[WordPress] [CDN] CDN を前面に置いた時にプレビューを正常に表示させるための fix

CDN を前面に置いた時に WordPress ダッシュボードで表示される URL に投稿の更新日付を含ませて、強制的に no cache の状態で表示させるための fix

<?php
/*
Plugin Name: CloudFront Preview Fix
Plugin URI:
Description: WPログイン時にパーマリンクに記事変更日付を含み、プレビューが最新になるようにする
Version: 0.5
Author:
Author URI:
*/
add_action( 'init', function(){
$cf_fix = cloudfront_preview_fix::get_instance();
$cf_fix->add_hook();
});
class cloudfront_preview_fix{
private static $instance;
private function __construct() {}
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
$c = __CLASS__;
self::$instance = new $c();
}
return self::$instance;
}
public function add_hook() {
add_action( 'template_redirect', array($this, 'template_redirect') );
add_filter( 'post_link', array($this, 'post_link_fix'), 10, 3 );
add_filter( 'preview_post_link', array($this, 'preview_post_link_fix'), 10, 2 );
add_filter( 'the_guid', array($this,'the_guid') );
add_filter( 'sanitize_file_name', array($this,'sanitizeFileName') );
}
public function template_redirect() {
if ( is_user_logged_in() ) {
nocache_headers();
}
}
public function post_link_fix( $permalink, $post, $leavename ){
if ( !is_user_logged_in() || !is_admin() || is_feed() ) {
return $permalink;
}
$post = get_post( $post );
$post_time =
isset($post->post_modified)
? date('YmdHis', strtotime($post->post_modified))
: current_time('YmdHis');
$permalink = add_query_arg( 'post_date', $post_time, $permalink );
return $permalink;
}
public function preview_post_link_fix( $permalink, $post ){
if ( is_feed() ) {
return $permalink;
}
$post = get_post( $post );
$preview_time = current_time('YmdHis');
$permalink = add_query_arg( 'preview_time', $preview_time, $permalink );
return $permalink;
}
public function the_guid($guid) {
$guid = preg_replace( '#\?post_date=[\d]+#', '', $guid );
return $guid;
}
public function sanitizeFileName( $filename ){
$info = pathinfo($filename);
$ext = empty($info['extension']) ? '' : '.' . $info['extension'];
$name = basename($filename, $ext);
$finalFileName = $name.'-'.current_time('YmdHis');
return $finalFileName.$ext;
}
}

[WordPress] git 管理しているテーマで git のコミットIDをバージョン番号として使用するサンプル

<?php
$version = 'default';
$stylesheet_dir = get_stylesheet_directory();
if ( file_exists( $stylesheet_dir.'/.git/HEAD' ) ) {
$head = explode(' ', trim(file_get_contents($stylesheet_dir.'/.git/HEAD')) );
if ( isset($head[1]) && file_exists($stylesheet_dir.'/.git/'.$head[1]) ) {
$version = trim(file_get_contents($stylesheet_dir.'/.git/'.$head[1]));
}
}
define( 'THEME_VERSION', $version );

view raw
gistfile1.php
hosted with ❤ by GitHub

[wp-cli] サブディレクトリにインストールされている WordPress の一覧を取得する

#!/bin/sh
find /var/www/vhosts/ -maxdepth 2 -type f -name wp-config.php | while read thisfile; do
wp_path=${thisfile%/*}
echo "***** ${wp_path}"
wp_version=`wp –path=${wp_path} core version`
wp_home=`wp –path=${wp_path} eval "echo home_url();"`
echo "${wp_home} : ${wp_version}"
done;

view raw
gistfile1.sh
hosted with ❤ by GitHub

while ループ内で wp core update とかをすれば、一撃ですべての WordPress をアップデートできるよ

wp-cron の呼び出しをコントロールする

アクセス数が多いサイトだと、wp-cron.php へのアクセスが逆にネックになる事もあります。
参考:DISABLE_WP_CRONをしてもNginx Cache Controllerプラグインがwp-cron.phpにリクエストし続ける件 – エロサイトの作り方

そんなとき、僕は Nginx で wp-cron.php へのリクエストを完全に遮断して

location = /wp-cron.php {
    return 403;
}

サーバで、Nginx の実行ユーザで cron を設定

$ sudo crontab -u nginx -e
*/5 * * * * /usr/bin/php /path/to/wordpress/wp-cron.php

って感じすかね。

[Nginx][WordPress] WordPress リバースプロキシキャッシュ用の nginx.conf

/etc/nginx/php-fpm

try_files $uri =404;

expires        off;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass   unix:/var/run/php-fpm.sock;
fastcgi_index  index.php;
fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
include        fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_busy_buffers_size 32k;
fastcgi_temp_file_write_size 256k;

/etc/nginx/conf.d/default.conf

upstream backend {
  server unix:/var/run/nginx-backend.sock;
}

# reverse proxy
server {
    listen      80 default;
    server_name _;
    root        /path/to/wordpress;
    index       index.html index.htm;
    charset     utf-8;

    access_log  /var/log/nginx/access.log  main;
    error_log   /var/log/nginx/error.log;

    location ~ /\. { deny all; access_log /dev/null; log_not_found off; }

    rewrite /wp-admin$ $scheme://$host$uri/ permanent;

    set $do_not_cache 0;
    if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
        set $do_not_cache 1;
    }
    if ($request_method = POST) {
        set $do_not_cache 1;
    }

    location / {
        try_files $uri @wordpress;

        # Pass all .php files onto a php-fpm/php-fcgi server.
        location ~ \.php$ {
            include /etc/nginx/php-fpm;
        }
    }

    location @wordpress {
        proxy_no_cache     $do_not_cache;
        proxy_cache_bypass $do_not_cache;

        proxy_redirect     off;
        proxy_cache        czone;
        proxy_cache_key    "$scheme://$host$request_uri";
        proxy_cache_valid  200 10m;
        proxy_cache_valid  404 5m;
        proxy_pass     http://backend;
    }

    # 404
    error_page 404 @not_found;
    location @not_found {
        internal;
        rewrite ^ /404;
    }
}

# backend
server {
    listen      unix:/var/run/nginx-backend.sock default;
    server_name _;
    root        /path/to/wordpress;
    index       index.php index.html index.htm;

    access_log  /var/log/nginx/backend.access.log main;

    keepalive_timeout 25;
    port_in_redirect  off;

    gzip              off;
    gzip_vary         off;

    # This order might seem weird - this is attempted to match last if rules below fail.
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # Pass all .php files onto a php-fpm/php-fcgi server.
    location ~ \.php$ {
        set $proxy_https '';
        if ( $http_x_forwarded_proto = 'https' ) {
            set $proxy_https 'on';
        }

        include /etc/nginx/php-fpm;
        fastcgi_param  REMOTE_ADDR      $http_x_real_ip;
        fastcgi_param  HTTPS            $proxy_https  if_not_empty;
        fastcgi_pass_header "X-Accel-Redirect";
        fastcgi_pass_header "X-Accel-Buffering";
        fastcgi_pass_header "X-Accel-Charset";
        fastcgi_pass_header "X-Accel-Expires";
        fastcgi_pass_header "X-Accel-Limit-Rate";
    }
}

Re: How do I extend fetch_feed timeout?

As a quick fix I just went straight for the SimplePie code that the WordPress code is wrapping around.

$feed = new SimplePie();
$feed->set_feed_url('http://rss.betfair.com/RSS.aspx?format=rss&sportID=7');
$feed->set_timeout(30); // set to 30 seconds
$feed->set_item_limit(40);
$feed->set_stupidly_fast(true);
$feed->enable_cache(true);
$feed->set_cache_duration(200);
$feed->init();
$feed->handle_content_type();

WordPress › Support » How do I extend fetch_feed timeout?

WordPress の fetch_feed() 関数でタイムアウト値を延ばす方法をググったらサポートのこの回答が出てきたんだけど、wp-includes/feed.php 眺めたら、アクションフックがあったので、こっちで対応できるねというお話。

add_action('wp_feed_options', function(&$feed, $url){
    $feed->set_timeout(30); // set to 30 seconds
}, 10, 2);

今日の教訓:ググる前にソースを見よう。

[Nginx][WordPress] Nginx で WordPress の管理画面に BASIC 認証をかける ( ただし admin-ajax.php にはかけない )

location ~* /wp-login\.php|/wp-admin/((?!(admin-ajax\.php|css/|js/)).)*$ {
index index.php index.html index.htm;
# Basic認証のメッセージ
auth_basic "Please enter your ID and password";
# .htpasswd ファイルのパス
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
location ~ .*\.php$ {
try_files $uri =404;
proxy_pass http://backend;
}
}

view raw
gistfile1.txt
hosted with ❤ by GitHub

proxy_pass 使用してるんで、これはリバプロ側の設定です。
バックエンド側とか、そもそもリバプロ建てないって時は if ($request_filename ~ .*\.php) { } の中をよしなに変更してください。