変なWPカスタマイズの例を集めてみた。

特定のカスタムタクソノミーを持つ投稿以外のカスタムフィールド名を変更

たとえばバックアップ用途で使用する。

UPDATE `wp_postmeta` SET `meta_key` = 'hoge-after'
  WHERE `meta_key` = 'hoge-before'
    AND `post_id` NOT IN (
      SELECT `object_id` FROM `wp_term_relationships` WHERE `term_taxonomy_id` = 100
    );

ただ削除するだけであれば下記。

DELETE FROM `wp_postmeta`
  WHERE `meta_key` = 'hoge'
    AND `post_id` NOT IN (
      SELECT `object_id` FROM `wp_term_relationships` WHERE `term_taxonomy_id` = 100
    );

カテゴリーを階層を保って出力する関数

function outputTerms($taxonomy, $_parentTermID = 0) {
  $terms = get_terms($taxonomy, array(
    'parent' => $_parentTermID,
    'hierarchical' => 1,
    'hide_empty' => 0,
  ));
  if ($terms) {
    echo '<ul>';
    foreach($terms as $term) {
      echo '<li>';
      echo '<a href="' . get_category_link($term->term_id) . '">' . $term->name . '</a>';
      outputTerms($taxonomy, $term->term_id);
      echo '</li>';
    }
    echo '</ul>';
  }
}
outputTerms('category');

特定のタクソノミーを持つ投稿のURLを変更

add_action( 'pre_get_posts', function( $query ) {
  if ( is_admin() || ! $query->is_main_query() ) {
    return;
  }
  if ($query->is_post_type_archive('foo')) {
    $query->set('category_name', get_query_var('bar'));
  }
} );

add_filter( 'query_vars', function ( $public_query_vars ) {
  $public_query_vars[] = 'bar';
  return $public_query_vars;
} );

add_filter('rewrite_rules_array', function($rules){
  $new_rules = array(
    'baz/([^/]+)/?$' => 'index.php?post_type=foo&bar=$matches[1]',
    'baz/([^/]+)/page/([0-9]+)/?$' => 'index.php?post_type=foo&bar=$matches[1]&paged=$matches[2]',
  );
  return $new_rules + $rules;
});

// post_linkフィルターなども使用してURLを変更する

ACFで作ったタームのカスタムフィールドの数値順にタームを並び替え

function itemsList($taxonomy) {
  // 番号順に並び替え
  $terms = get_terms($taxonomy, array(
    'hide_empty' => 0,
  ));
  $orderList = array();
  foreach($terms as $term) {
    $value = get_field('hoge-priority', $taxonomy . '_' . $term->term_id);
    if (is_numeric($value)) {
      $value = (int)$value;
    } else {
      $value = 0;
    }
    $id = $term->term_id;
    $orderList[$id] = $value;
  }
  arsort($orderList, SORT_NUMERIC);
  foreach($orderList as $key => $value) {
    // outputItem関数で個別のtermオブジェクトを渡す
    outputItem(get_term($key, 'category'));
  }
}
itemsList('category');

親子関係のあるカテゴリーでリンクの階層をなくす

// https://example.com/category/parent/child/ -> https://example.com/category/child/
function my_term_link($termlink, $term, $taxonomy) {
  return ($taxonomy === 'category' ? home_url('/category/'. $term->slug . '/') : $termlink);
}
add_filter('term_link', 'my_term_link', 10, 3);

// ほんとはリライトルールも変更したほうがいい

カスタムタクソノミー のカスタムフィールド(get_option)などで取得される値を元にクエリを変更する

同じように単純にカスタムフィールドなんかで難しい場合は、投稿idのリストを取得してそのidのみをクエリにするなんかの処理がスマート。

// pre_get_postsで事前に取得してからクエリを発行
add_action('pre_get_posts', function($query) {
  if (!is_admin() && $query->is_main_query() && is_tax('foo', 100)) {
    $list = array();
    $allCategory = get_categories();
    foreach($allCategory as $cat) {
      $hasBar = get_field('bar', 'category_' . $cat->cat_ID);
      if ($hasBar) {
        $list[] = $cat->cat_ID;
      }
    }
    $query->set('category__not_in', $list);
  }
});

投稿のパーマリンクを変更

パーマリンクを http://example.com/?eid=xx 形式に変更したい場合は、以下のようにして parse_query フィルタを使うと良い。

参考:https://dogmap.jp/2011/04/21/change-category-link-to-different-link/

class add_permalink_to_different_link {
    function __construct(){
        add_filter('query_vars', array(&$this, 'add_query_vars'));
        add_action('parse_query', array(&$this, 'parse_query'));
        add_filter('post_link', array(&$this, 'post_link'), 10, 3);
    }
    public function add_query_vars($qvars) {
        $qvars[] = 'eid';
        return $qvars;
    }
    public function parse_query($query) {
        $post_id = (int) $query->query_vars['eid'];
        if ( !(empty($post_id) || $post_id === 0) ) {
            $url = get_permalink($post_id);
            if ( !empty($url) && $url !== FALSE ) {
                $query->query_vars["p"] = $post_id;
                $query->query["p"] = $post_id;
                $query->is_single = true;
                $query->is_singular = true;
                $query->is_home = false;
                $query->is_404 = false;
            } else {
                $query->set_404();
            }
        }
        return $query;
    }
    public function post_link($permalink, $post, $leavename) {
        return ($post->post_type === 'post' ? home_url('/?eid='.$post->ID) : $permalink);
    }
}
new add_permalink_to_different_link();

特定のカテゴリーがあるかどうかで投稿の順番を変える

add_action('pre_get_posts', function($query) {
  if (is_admin() || !$query->is_main_query()) {
    return;
  }
  // カテゴリーページ
  if (is_category()) {
    $catId = get_queried_object()->cat_ID;
    $target_list = array();

    // fooのbarがあれば、優先的に
    $target_query = new WP_Query(array(
      'cat' => $catId,
      'posts_per_page' => -1,
      'tax_query' => array(
        'relation' => 'AND',
        array(
          'taxonomy' => 'foo',
          'field' => 'slug',
          'terms' => 'bar',
          'operator' => 'NOT IN'
        ),
      ),
    ));
    if ( $target_query->have_posts() ) :
    while ( $target_query->have_posts() ) : $target_query->the_post();
      $target_list[] = get_the_ID();
    endwhile;
    endif;
    wp_reset_postdata();

    // fooのbazがあれば優先順位を下げる
    $target_query = new WP_Query(array(
      'cat' => $catId,
      'posts_per_page' => -1,
      'tax_query' => array(
        'relation' => 'AND',
        array(
          'taxonomy' => 'foo',
          'field' => 'slug',
          'terms' => 'baz',
          'operator' => 'IN'
        ),
      ),
    ));
    if ( $target_query->have_posts() ) :
    while ( $target_query->have_posts() ) : $target_query->the_post();
      $target_list[] = get_the_ID();
    endwhile;
    endif;
    wp_reset_postdata();

    $query->set('post__in', $target_list);
    $query->set('orderby', 'post__in');
  }
});

カテゴリーを他のポストタイプでも使用できるようにする

add_action('init', function() {
  register_taxonomy_for_object_type('category', 'hoge');
}, 10000);

カテゴリーページのパーマリンクを変更

参考:https://dogmap.jp/2011/04/21/change-category-link-to-different-link/

register_taxonomyを使えない場合で、カテゴリのリンクを http://example.com/?cid=xx 形式でも表示できるようにする。

class add_category_link_to_different_link {
    function __construct(){
        add_filter('query_vars', array(&$this, 'add_query_vars'));
        add_action('parse_query', array(&$this, 'parse_query'));
    }
    public function add_query_vars($qvars) {
        $qvars[] = 'cid';
        return $qvars;
    }
    public function parse_query($query) {
        $cat_id  = (int) $query->query_vars['cid'];
        if ( !(empty($cat_id) || $cat_id === 0) ) {
            $url = get_category_link($cat_id);
            if ( !empty($url) && $url !== FALSE ) {
                $query->query_vars["cat"] = $cat_id;
                $query->is_404 = false;
            } else {
                $query->set_404();
            }
        }
        return $query;
    }
}
new add_category_link_to_different_link();

カテゴリのリンクを http://example.com/cid/xx 形式に変更する場合。

class add_rewrite_rules{
    private $rule = null;
    private $query_var = null;
    function __construct($rule, $query_var) {
        $this->rule = $rule;
        $this->query_var = $query_var;
        add_filter('rewrite_rules_array', array(&$this, 'rewrite_rules_array'));
        add_action('init', array(&$this, 'init'));
    }
    public function init() {
        global $wp_rewrite;
        $rules = $wp_rewrite->wp_rewrite_rules();
        if (!isset($rules[$this->rule])) {
            $wp_rewrite->flush_rules();
        }
    }
    public function rewrite_rules_array($rules) {
        global $wp_rewrite;
        $new_rules[$this->rule] = $this->query_var;
        $rules = array_merge($new_rules, $rules);
        return $rules;
    }
}
global $wp_rewrite;
new add_rewrite_rules('^cid\/([0-9]+)$', $wp_rewrite->index . '?cat=$matches[1]');

特定の投稿タイプを含めるカスタムクエリ変数を追加

参考:https://chaika.hatenablog.com/entry/2014/10/10/200016
参考:https://qiita.com/shogo/items/403b8244ea39262ba132

// カスタムクエリ変数を追加
add_filter('query_vars', function($vars) {
  $vars[] = 'force-post-type';
  return $vars;
});

function my_posts_per_page($query) {
  if(is_main_query() && is_search() && !is_admin()) {
    $query->set( 'post_type', get_query_var('force-post-type', 'post') );
  }
}
add_action( 'pre_get_posts', 'my_posts_per_page' );

/**
 *
 * 検索対象を投稿かカスタムフィールドにするかの分岐
 *
 **/
function my_posy_search($search, $wp_query) {
  if ($wp_query->is_main_query() && $wp_query->is_search() && !is_admin()) {
    $q = $wp_query->query_vars;
    $n = null;
    if ($q['force-post-type'] === 'hoge') {
      $search .= ' AND post_type = \'hoge\'';
    } else {
      $search .= ' AND post_type = \'post\'';
    }
  }
  return $search;
}
add_filter('posts_search', 'my_posy_search', 10, 2);

特定の投稿タイプのみ編集を可能にするユーザーロール

参考:https://fixcode.jp/wordpress/wp-disabled-create_posts/

create_posts権限はregister_post_typeの時に決定するから特別に調整が必要みたい。

function change_post_types_cap() {
  global $wp_post_types;
  $target_post_types = array('post');
  foreach($target_post_types as $target_post_type) {
    // create_postsの権限を変更
    $cap = &$wp_post_types[$target_post_type]->cap;
    $cap->create_posts = "create_posts";
  }
  // create_posts権限を無効化(hogeグループ)
  $role = get_role( 'hoge' );
  $role->add_cap( 'create_posts', false );
}
add_action( 'init', 'change_post_types_cap' );

RSSを別ドメインにも許容

参考:https://stackoverflow.com/questions/12517039/how-to-add-cors-support-to-wordpress-rss2-feed

add_action( 'pre_get_posts', 'add_header_origin' );

function add_header_origin() {
    if (is_feed()){
        header( 'Access-Control-Allow-Origin: *' );
    }
}

構造化データのdatePublishedとdateModifiedを出力

echo get_date_from_gmt(get_post_time('c', true), 'c');
echo get_date_from_gmt(get_post_modified_time('c', true), 'c');

誰でも作成者にできるようにする

add_filter( 'wp_dropdown_users_args', 'add_subscribers_to_dropdown', 10, 2 );
function add_subscribers_to_dropdown( $query_args, $r ) {
  $query_args['who'] = '';
  return $query_args;
}