サイトを1日止めたい

オンラインショップに限らずだけど、Snow Monkeyを使ったwebサイトを一時的にメンテナンスにさせたいときってどうしてますか?
以前オンラインショップを運営するお客さんから「全商品の価格や送料を変更することがあって、商品数もそこそこあるので、変更中に購入されたり、価格に誤入力があると怖いから、いったん止めたい。」という相談があった。
ま、たしかに商品数が多いと修整中に購入される可能性もゼロではない。その場合は1商品ずつ「下書き」にした状態で修整→確認して公開していけばいいんだけど、修整内容もサイトのプレビューで見たいという状況だったので、サイトを1日停止(メンテナンス状態に)することになった。
※サイトを止めて1日以内に全商品の価格、送料を変更、担当者がプレビューで二重チェックという流れ。

メンテナンスページを表示するのに手っ取り早いのが公式ディレクトリでの検索。そう、プラグインをインストールすること。
調べてみると、いくつか良さそうなものが見つかる。
代表的なものだと、日本語に翻訳されてるWP Maintenance ModeMaintenanceあたり?

こうしたプラグインを導入すれば、すごく簡単にメンテナンス状態になるけど、必要以上に高機能だったり、かゆいところに手が届かないこともあったりする。
例えば、ちょっとしたギミックを取り入れたいとか、サイトのデザインを踏襲したいとか、YouTube動画を見せたいとか、Webフォントを使いたいとか。。。
それに加えて、今回のようなケース(メンテナンス開始と公開(再開)時間の希望が深夜0時キッカリ)では、さらにプラグインを選定する条件も絞られてしまう。

どうやって対応するか。

プラグインがあるくらいなので「メンテナンスページへの切り替えを簡単にしたい!」という要望は少なくないはず。
ASP(いまはSaaSって言うべきか?)のショップシステムなどの多くは「閉店」する機能がついていて、トグルスイッチ1つで簡単にメンテナンスページに切り替えられるので、できるのが当たり前と思ってる人だっていると思う。

基本的に特殊なことを除いて、WordPressにできないことはないと思ってる派なので、調べればヒントは見つかるはず。

WordPressを長く使っていると特徴的な関数はなんとなく記憶していて、こういったケースの場合はwp_dieが応用できるんじゃないかな?とアタリをつけてみる。
世の中同じことを考えてる人って、たぶん最低でも300人くらいいると思っているので、英語の記事も探せばグッドアイディアやコードを見つけることもできるだろう。

この関数で検索をかけると、応用する方法が見つかる。たとえばここ。

この記事で紹介されているコードはこれ。

function quick_maintenance_mode() {
  if ( ! current_user_can( 'edit_themes' ) || ! is_user_logged_in() ) {
    wp_die( '<h1>只今メンテナンス中です</h1><p>申し訳ありませんが、暫くしてから再度アクセスをお願いします。<br />お急ぎの場合は、お手数ですが <a href="mailto:xxx@example.com">xxx@example.com</a> までご連絡ください。</p>' );  }
}
add_action( 'get_header', 'quick_maintenance_mode' );

条件分岐(if)にある! current_user_can( 'edit_themes' )は、テーマの編集権限を持っているユーザーは除外(!)、! is_user_logged_in()ログインしているユーザーは除外で、||はどちらかに当てはまる場合。
ん〜よくわからないけど、! is_user_logged_in()だけでもいいような気がする。どうなんでしょうかね?

で、このコードだと、エラーメッセージを1行程度に収まるように(HTMLで)差し替えはできるけど、ごっそり書くのは面倒そう。
my-snow-monkey.phpにごっそり書きたくないし、使いまわしも考えて、別ファイルとしてmy-snow-monkeyに置くようにする。

それとアクションフックget_headerも気になっていたので調べたら、実行するタイミングらしい。
今回の場合はメンテナンス画面にするので、とにかくサイトにアクセスしたら真っ先に表示させたいので、以下のSnow Monkeyサポートフォーラムの回答を参考にして、after_setup_themeを当てるのが良さそうだけど、ログインページもメンテナンス画面になってしまいそうなので、1つずつ検証しないとね。
でも、テーマやプラグインの開発者は、適材適所を知っているんだろうな。。。
どこで知るんだろう。そういうのって。。。

また、このトピックの回答でDRILL LANCERさんが回答してるrequire_onceを使えば、別のファイルを読ませることもできるのがわかる。

require_once plugin_dir_path( __FILE__ ) . 'inc/class-widget-appear-disappear.php';

My Snow Monkeyを使用する場合、plugin_dir_path( FILE ) .の部分は、
define( 'MY_SNOW_MONKEY_PATH', untrailingslashit( plugin_dir_path( FILE ) ) );(My Snow Monkey Ver.0.2.1の場合)
が用意されているので、

require_once MY_SNOW_MONKEY_PATH . '/xxxxxx.php';

と書けば、メンテナンス用のHTML(PHP)を読み込めるはず。

【補足】主要なアクションフックが実行される順番に関する参考記事

ねぇ、やたらと記事が長くない?

備忘録だから仕方ない。
どうやって解決したかのロジックも重要なのさ。

自分でもツッコむくらい長くなりそうなので、そろそろ本題に行きましょう。

最終的に書いたコード

上の説明にあったフックget_headerだと、Snow Monkeyのテーマが読み込まれるため、独自のHTMLに影響が出てしまった。
after_setup_themeの場合はログイン画面もメンテナンスページになってしまうので意味がない。
いくつか試してみて、template_redirectは影響が出なかったので、ひとまずこのカタチになった。

add_action(
	'template_redirect',
	function() {
	$now = wp_date( 'YmdHis' );
    if ( $now > '20210703000000' && $now < '20210703235959' ) {
      if ( !is_user_logged_in() ) {
        require_once MY_SNOW_MONKEY_PATH . '/maintenance.php';
        wp_die();
      }
    }
});
$now = wp_date( 'YmdHis' );
  if ( $now > '20210703000000' && $now < '20210703235959' ) {
   // 
  }
$now = wp_date( 'YmdHis' );

これで日時を取得、文字(数値)にして変数化。
YmdHisは想像つくと思うけど、これについては割愛。こういう記事を参考にしてね。
あ、ただ、WordPress 5.3から、wp_dateという関数が登場したのでコレを使うのが良いみたい。

if ( $now > '20210703000000' && $now < '20210703235959' ) {
   // 
}

ifには、2021年7月3日 0:00にメンテナンス画面になって2021年7月4日 0:00に公開するように条件を入れる。
YmdHisはもはや日時ではなく14桁のただの数値なので、希望の日時も同じく数値として入力、大きいか小さいかで条件にすればいい。

当然このままだとログインもログインしているユーザーについては、その対象日時の間に修整作業をしたり、プレビューできるようにするため、さらに条件を加えて対象からはずす。
!をつけて条件以外のものを条件とした。

if ( !is_user_logged_in() ) { //ログインユーザーではない場合
   // 
  }

で、条件に当てはまるときに実行するのがコレ

require_once MY_SNOW_MONKEY_PATH . '/maintenance.php';
  wp_die();

my-snow-monkeyのディレクトリにメンテナンス用の独自HTMLmaintenance.phpを置いた。
最後のwp_die();だけど、下記の記事にちょっと説明があるとおり「もうこれ以上は処理しないよ」という呪文なのでこうした。
使い方間違ってないかな???

表示させるmaintenance.phpは、簡単なHTMLならheadにCSSを書いてあげればいいし、少し構造が複雑なら、ディレクトリつくって分けてあげればいいと思う。
※外部JSやCSSにする場合は絶対パスかルートパスで指定する。

お客さん側でできるようにするなら

上で書いたコードはあくまでも応急処置。
お客さん側で簡単にコントロールできないので、その場合はプラグインにするなり、ACF Proのオプションページ機能+カスタムフィールドを使えばできなくもないと思う。

ずいぶんと長い記事になってしまったけど、やっていることはそれほど難しくないですね。
Snow Monkeyを使っているなら、このコードを流用できると思うので、ぜひ試してみてください。
ということで、今日はこのへんで。

コードがおかしかったら教えてください🙇‍

この記事を書いた人

GONSY

印刷会社のグラフィックデザイナーだった1998年に「会社案内」のHTML化をきっかけにWebの世界へ。
WordPressはMEから使っているけどプログラムスキルは一向に上がらない。WooCommerceは2018年から。忘れっぽくなってきたので、試したこと、実装方法を記録するためにブログをスタート。
最近、WordPress、WooCommerce、Snow Monkeyがおもしろいと感じるおじさん。