公開済の記事を指定日時で予約更新する

公開済みの投稿・ページの更新はよくあることです。そして、企業のサイト、特に上業企業の場合は「指定日時に更新内容を表示する」ことを要求されたります。WordPress では予約投稿ができるので、未来の日時を指定して[公開]! ・・・はい、記事が表示されなくなれました。この機能は「公開予定日時になったら公開する」ので、それまでは「非公開」にされてしまうのです。さぁ、困ったぞ。WordPress では普通にやってもできなさそうだ。そもそもマジ CMS じゃねぇんだから無茶言うなって話だぜ。WordPress には無理なのか?!Matt にお願いすれば何とかなるのか?!もう WordPress のロゴを消したりしないから何とかしてー!
はい、なんとかします。看板の XTREME STUNTS はダテじゃないってことを教えてやるぜ。ただ少しイレギュラーなことをしますので、そこは大目に見てください。Matt もそう言ってますし。言ってませんか。

元ネタは、フォーラムの 既投稿済み記事の更新 です。以前にも同様のトピックがあったようで、やはり需要はあるわけですね。目的に合わせて適材適所なツールを選択するのがプロだろ、ぁあん?なんてかっこいいことウチよう言われへんので WordPress でやります。コレと決めたら何としてでもソレを貫くのが男です。プロである前に一人の男として、もういいですか。

設計

SE の仕事です。上流工程でしっかり設計できれば後はスムーズにプロジェクトが進みます。客先で3日間徹夜とか当たり前ですよね。

  1. リビジョンに更新予約日時情報を付加する。
  2. 最新版から初版まで順に辿って 更新予約日時<=現在日時 となった記事の内容を現在の記事として表示する。

完璧な設計ですね。具体的には下流にやらせることにして、僕たちはとっとと飲みに行きましょう。
1.はカスタムフィールドを使います。カスタムフィールドは最新版にしか存在しないのが WordPress 2.9.1 現在の掟ですので、これを破ります。大目に見てください。2.のようにしておくと「あ、間違えた。」ってときに更に編集&更新されても、更新予約日時が同じなら最新版が得られます。

実装

前置きが長くなりましたが、徹夜なので許してください。以下を functions.php に追加して、ループ内で echo my_get_content() と書けばうまいことやってくれます。既投稿済み記事の更新の適用方法 にお応えして、公開済&更新予約日時がない記事についてはそのまま表示するようにしました。実装的にはたいしたことはしてないので、説明は省略するぜ。必要ならコメントしてね。テキトウに回答するし。

$fu_key = 'futureupdate';

function my_get_content(){
  global $post, $fu_key;

  $now = date('Y/m/d H:i');
  $update = get_post_meta($post->ID, $fu_key, true);
  if(!$update || ($update && $update <= $now))
    return get_the_content();

  $args = array(
    'order' => 'DESC',
    'orderby' => 'ID',
    'post_parent' => $post->ID,
    'post_type' => 'revision',
    'post_status' => 'inherit',
    'meta_key' => $fu_key,
    'meta_value' => $now,
    'meta_compare' => '<='
 );
  if($revisions = get_children($args))
    foreach($revisions as $revision)
      return $revision->post_content;

  return 'No content.';
}
//meta_box追加
function my_meta_futureupdate_box(){
  add_meta_box('my_meta_futureupdate_box', '更新予定日時の指定', 
    'my_meta_futureupdate_html', 'post', 'normal', 'high');
  add_meta_box('my_meta_futureupdate_box', '更新予定日時の指定', 
    'my_meta_futureupdate_html', 'page', 'normal', 'high');
}
function my_meta_futureupdate_html($post, $box){
  global $fu_key;

  $value = get_post_meta($post->ID, $fu_key, true);
  if(!$value) $value = '';
  echo '<input type="hidden" name="my_meta_futureupdate_nonce" id="my_meta_futureupdate_nonce" 
        value="'.wp_create_nonce(get_bloginfo('template_url') . $fu_key).'" />'."\n"
     . '<div><label for="futureupdate">更新予定日時(YYYY/MM/DD HH:II)</label>'."\n"
     . '<input type="text" name="futureupdate" value="'. $value  .'" size="50" /></div>'."\n";
}
function my_meta_futureupdate_update($post_id){
  global $fu_key;

  if(!wp_verify_nonce( $_POST['my_meta_futureupdate_nonce'], get_bloginfo('template_url') . $fu_key)){
    return $post_id;
  }
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
    return $post_id;

  if('page' == $_POST['post_type']){
    if(!current_user_can('edit_page', $post_id))
      return $post_id;
  }else{
    if(!current_user_can('edit_post', $post_id))
      return $post_id;
  }

  if($parent_id = wp_is_post_revision($post_id)){
    $old = get_post_meta($parent_id, $fu_key, true);
    if($old)
      update_metadata('post', $post_id, $fu_key, $old);
  }else{
  if(isset($_POST[$fu_key]))
    update_metadata('post', $post_id, $fu_key, $_POST[$fu_key]);
  }
}
add_action('admin_menu', 'my_meta_futureupdate_box');
add_action('save_post', 'my_meta_futureupdate_update');

振り返ってみればなんて事無い案件ですけど、やってみるまではモヤモヤしますね。そりゃ SE のギャラは良いわけだ、という結論で OK ?

参照:フォーラム
動作確認バージョン
  • WordPress 2.9.1

30 Comments

  • hiro hiro

    突然の問い合わせで失礼いたします。

    上記の「公開済の記事を指定日時で予約更新する」を利用させて頂きたく、設置をしようと
    試みましたが、私のレベルでは具体的な方法が今一つ分かりません。誠に恐縮ですが、お教えいただきたくお願いいたします。

    1、上記の構文はfunctions.phpの最終部分の

    function _cleanup_header_comment($str) {
    return trim(preg_replace(“/\s*(?:\*\/|\?>).*/”, ”, $str));
    }

    の次の行に挿入することでよいのでしょうか。

    2、「ループ内で echo my_get_content() と書けば」とは具体的にwordpressのどの部分に書けばよいのでしょうか。(挿入または、上書きの部分をお教えいただきたくお願いいたします。)

    ちなみに、wordpressのバージョンは2.9.2です。テンプレートはKtai Styleです。

    よろしくお願いいたします。

    • kz kz

      1.はい、そこでOKです。
      2.通常は index.php や single.php で本文を表示している the_content() の部分を置換します。Ktai Style だと ks_content() を置換、ですがうまくいくかどうかは不明です。

  • hiro hiro

    hiroです。ご回答ありがとうございました。お礼が遅くなりました。申し訳ありませんでした。

    お教えいただいた、functions.phpの最後尾 ?>の前に挿入しましたがエラーになってしまいログインできませんでした。

    先にお伝えしたfunctions.phpの最後尾の構文は古いほうのバージョンの構文でした。申し訳ありませんでした。現在のwordpressバージョン2.9.2のfunctions.phpの構文は変わってしまっているようです。

    恐れ入ります、バージョン2.9.2の対処の仕方がありましたらお教え頂きたく存じます。
    度々で恐縮ですが、よろしくお願いいたします。

  • hiro hiro

    hiroです。「公開済の記事を指定日時で予約更新する」でWordpress2.9.2に設置ごエラーになってしまう件でお尋ねしましたが、具体的なエラーメッセージをお知らせしたほうが良いかと思い、送らせていただきます。エラーは以下のようになります。よろしくお願いいたします。

    Fatal error: Call to undefined function add_action() in /export/sd08/www/jp/r/e/gmoserver/5/3/sd0106053/●●●●●.com/wordpress/wp-includes/functions.php on line 3709

  • kz kz

    functions.php の < ?php と ?> の間ならどこでもOKですよ。
    っていうか、functions.php と言ってるのは
    コアファイルの wp-includes/functions.php じゃなくて
    ご使用になってるテーマのフォルダ内にある functions.php ですよん。

  • hiro hiro

    hiroです。教えて頂いた「テーマのフォルダ内にある functions.php」の設定でエラーにならずにログインできるようになり、更新も出来るようになりました。
    ありがとうございました。

    しかし既投稿記事を書き換え、予約更新を設定すると、既投稿済みの記事が表示されません。予約設定時刻には、書き換えた投稿内容に更新され、予約更新されます。

    対応方法がありましたら、お教えいただきたく存じます。
    度々のお願いで恐縮ですが、どうぞよろしくお願いいたします。

    • kz kz

      既投稿記事は、まず「更新予約日時」に過去の日付を入れて更新してください。
      で、本文を編集して「更新予約日時」に未来の日付を入れて更新してください。
      参照:フォーラム の下から3つめ。

  • hiro hiro

    hiroです。色々とありがとうございます。今更なのですが、「公開済の記事を指定日時で予約更新する」を設置した際、meta_box追加によって、「更新予定日時の指定」の項目が編集画面上に表示されるのでしょうか。であれば、私の設置したサイトの編集画面には表示されませんので、その辺から間違っているかもしれません。

    PCのテーマは「default」、ktai-styleのテーマは「green」を使わせて頂いてます。
    「default」のfunctions.phpには多数のがあり何箇所か設置してみました上手くいきません、また「green」には該当するfunctions.phpが見つけられず、対応がわかりません。

    誠に恐縮ですが、再度ご指導いただけないでしょうか。よろしくお願いいたします。

  • hiro hiro

    文中 が抜けていました。失礼いたしました。正しくは

    「default」のfunctions.phpには多数のがあり何箇所か設置してみましたが上手くいきません、また「green」には該当するfunctions.phpが見つけられず、対応がわかりません。

    です。よろしくお願いいたします。

    • kz kz

      「更新予約日時」は管理画面の投稿の編集時に出てくるメタボックスです。出てこないなら何か間違ってますが、何を間違ってるかまではわからないです。
      Ktai Style のテーマ「green」は関係ないです、ご安心を。
      「default」のfunctions.php の一行目の一文字目から <?php ?> と自分で書いて、その中に本記事のコードを挿れてください。
      何ヶ所も入れると動かないので、他の場所に挿したコードは削除してください。
      <?php と ?> は「この中にPHPのコードを書きますよ」という印です。

  • hiro hiro

    hiroです。お世話になります。ありがとうございます。
    教えて頂いたように作業しているつもりですが、なかなか上手く動作しません。

    >「default」のfunctions.php の一行目の一文字目から と自分で書いて、その中に本記事のコードを挿れてください。

    については、やはり設置後「更新予約日時」は管理画面の投稿には表示されず、「抜粋」のボックスが文字化けします。

    自分の作業で間違っている部分があるかもしれませんので、もうしばらく色々とやってみます。今後ともよろしくお願いいたします。

  • kz kz

    一時的に kz 用管理アカウントを作っていただければ見てみますよー

  • hiro hiro

    ありがとうございます。問い合わせフォームよりご連絡させていただきます。

  • hiro hiro

    おかげさまで無事「公開済の記事を指定日時で予約更新する」機能が使えるようになりました。
    操作が簡単で、大変扱いやすく助かっております。ありがとうございました。
    また、お世話になる機会があるかも知れませんが、ぜひよろしくお願いいたします。

    • kz kz

      お役に立ててナニヨリです。こちらこそヨロシクです。

  • junysb3 junysb3

    公開済の記事を指定日時で予約更新する  |  wpxtreme: http://bit.ly/dMKti4

  • WPメモ:公開済の記事を指定日時で予約更新する方法 http://bit.ly/dZ7Lck

  • ロジャヒ ロジャヒ

    こんにちは。この方法を実装してうまく作動していますが、echoを使っているためショートコードが全部効かなくなってしまいました(テキストのまま表示されます)。ショートコードを効かせるのにはどうすればよろしいでしょうか?

    ヒントでも教えていただければ嬉しいです。

    よろしくお願い致します。

    • kz kz

      return $revision->post_content;

      return apply_filters( ‘the_content’, $revision->post_content );
      に変更すると良い気がします◎

  • ロジャヒ ロジャヒ

    なるほど!フィルタをかけるのを忘れてました。
    見事に直りました。ありがとうございます。

    • タケ タケ

      突然の書き込み失礼します。
      ページの更新予約をしたいと、こちらのコードを参考にさせていただきました。
      しかし、実は以前の担当が結構なカスタマイズをやってまして、
      そもそもWordPress初心者にとっては四苦八苦でした。
      やっとこ固定ページの特定テンプレートのみ適用することはできました。
      更新予約をするとその時間にきちんと更新されます。
      ただ、更新前、つまり既存のデータが表示されません。
      いろいろテストしてみたところ、
      if($revisions = get_children($args))
      foreach($revisions as $revision)
      return apply_filters(the_content(),$revision->page_content);
      この部分には、必ず通っているようです。
      何を確認すればよいのかすら分かりません。
      お忙しい中恐縮ですが、ご教授いただけませんでしょうか。

  • これしかないのかー。ぐはー。 http://t.co/PQpWph9F

  • WordPress3.3系はメディアアップローダがD&D対応になったのか。あとは固定ページの修正公開予約が出来ればCMSとしても充分なんだけどな。今のところこれしかない。http://t.co/fngTYPcj

  • http://andcarinsurancequotes.com http://andcarinsurancequotes.com

    I got what you mean,bookmarked, very decent website.

  • @take_it02 ソレはコレ的なアレですか?? http://t.co/UYgHNFou

  • kzyz kzyz

    このページのコードを元にプラグインを作ってみました!
    そのままでは今のバージョン(3.3)では動作しないようでしたので、
    いろいろ変更して動くようにしてみました。
    UI等も変更してますので、もしよろしければ試してみてください。
    https://github.com/kzyz/future-update

    • kz kz

      オオォォォ!!ステキ!オープンソース万歳!!

  • [for:nibushibu+tips@gmail.com]

  • むずすぎ。。/公開済の記事を指定日時で予約更新する  |  wpxtreme http://t.co/70BPo2Fuku

  • むずすぎ。。/公開済の記事を指定日時で予約更新する  |  wpxtreme