
固定ページや投稿、カスタム投稿タイプなどにカスタムフィールドを持たせることがよくあります。
入力の手間が省け、htmlの知識がない人でも簡単に高機能なWebレイアウトを作ることができとても便利です。
ところが、カスタムフィールド管理のプラグインでCustom Field Suiteを使うと、「プレビュー」(「更新」せずに表示を確認できる機能)ができない、という問題があります。
そこで今回は、Custom Field Suiteを使ったカスタムフィールドを持つページの「プレビュー」を表示する方法のご紹介。
まずプラグインを作り、有効にします。
(作り方の基礎が知りたければWordPressのプラグインを作成する(初級)を参考にしてください。)
<?php
/*
Plugin Name: Custom field suite preview bug fix
Author: kaiza
Plugin URI:
Description: Custom field suite preview bug fix
Version: 0.1.0
Author URI:
*/
$cfs_fix = new Custom_Field_Suite_Preview();
class Custom_Field_Suite_Preview {
function __construct(){
add_action('plugins_loaded', array($this, 'plugins_loaded'));
}
public function plugins_loaded(){
add_action('cfs_init', array($this, 'cfs_init'), 0);
add_action('wp_insert_post', array($this, 'wp_insert_post'));
add_filter('get_post_metadata', array($this, 'get_post_metadata'), 10, 4 );
add_shortcode('cfs_get', function($p){
extract(shortcode_atts(array(
'key' => false,
'id' => 0,
'format' => array(),
), $p));
return self::get($key, $id, $format);
});
}
public function get($key, $id = 0, $format = array()){
global $cfs;
if (intval($this->get_preview_id($id))) {
return $cfs->get($key, $this->get_preview_id($id), $format);
} elseif ($id = $this->get_preview_id(get_the_ID())) {
return $cfs->get($key, $id, $format);
} else {
return $cfs->get($key, get_the_ID(), $format);
}
}
public function cfs_init(){
if (isset($_POST['wp-preview']) && $_POST['wp-preview'] === 'dopreview') {
global $cfs;
remove_action('cfs_init', array($cfs->form, 'init'));
}
}
public function get_preview_id( $post_id ){
global $post;
$preview_id = 0;
if (isset($post->ID) && intval($post->ID) === intval($post_id) && is_preview()
&& $preview = wp_get_post_autosave($post->ID)) {
$preview_id = $preview->ID;
}
return $preview_id;
}
public function get_post_metadata( $return, $post_id, $meta_key, $single ) {
if ($preview_id = $this->get_preview_id($post_id)) {
if ($post_id !== $preview_id) {
$return = get_post_meta($preview_id, $meta_key, $single);
}
}
return $return;
}
public function wp_insert_post($post_ID){
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (defined('DOING_AJAX') && DOING_AJAX) {
return;
}
if (wp_is_post_revision($post_ID)) {
global $wpdb;
global $cfs;
$wpdb->query($wpdb->prepare(
"DELETE FROM $wpdb->postmeta WHERE post_id = %d",
$post_ID
));
$cfs->form->session = new cfs_session();
$session = $cfs->form->session->get();
$field_groups = array();
if (isset($session['field_groups'])) {
$field_groups = $session['field_groups'];
}
foreach ($field_groups as $key => $val) {
$field_groups[$key] = (int) $val;
}
$options = array(
'format' => 'input',
'field_groups' => $field_groups
);
//ユーザーさんからいただいた改善案にもとづき、修正しています。
if(!empty($_POST['cfs']['input'])) {
$cfs->save($_POST['cfs']['input'], array('ID' => $post_ID), $options);
}
//元のコード $cfs->save($_POST['cfs']['input'], array('ID' => $post_ID), $options);
$post_metas = array('meta');
foreach ( $post_metas as $post_meta ) {
foreach ( $_POST[$post_meta] as $meta_id => $meta_arr ) {
add_metadata('post', $post_ID, $meta_arr['key'], $meta_arr['value']);
}
}
}
}
}
これで、「プレビュー」が押されたときに、Custom Field Suiteで作ったカスタムフィールドの値を自動セーブします。
今度は表示側(page.phpなど)です。
自動セーブされた値を取得するために、Custom Field Suiteの関数は使わず、WordPress標準のget_post_meta関数を使ってカスタムフィールドを読み込むようにします。
<? php
//画像の読み込み
$image1 = get_post_meta($post->ID, 'image1', true);
$image1 = content_url().'/uploads/'.get_post_meta($image1, '_wp_attached_file', true);
//テキストの読み込み
$text1 = get_post_meta($post->ID, 'text1', true);
//繰り返しフィールドの読み込み
$repeat1_fields = get_post_meta($post->ID, 'repeat1', false);
$count_total = count($repeat1_fields );
$count_total = $count_total/2; //同じ値が2つ登録されるので1つだけ取り出すための調整式
$repeat_fields = array();
for($i = 0; $i < $count_total; $i++){
$repeat_fields[$i]['repeat1']=$repeat1_fields[$i];
}
//ユーザーさんからいただいた改善案では、次のような書き方もでき、
//これだと即時の更新ができるそうです。
if(is_preview()) {
$id = get_preview_id(get_the_ID());
} else {
$id = $post->ID;
}
$program_cfs = CFS()->get(false,$id);
$image1 = $program_cfs['image1'];
$text1 = $program_cfs['text1'];
//ただし、繰り返しフィールドの読み込みがこれでできるのか調べていないので、一応、当方のコードも上述のまま残しておきます。
?>
テキスト表示
<?php echo $text1; ?>
画像表示
<img src="<?php echo $image1; ?>" >
繰り返しフィールドの表示
foreach ($repeat_fields as $repeat_field) {
echo $repeat_field['repeat1'].'<br>';
}
これでプレビュー表示されます。
※ ただし、これをしても、2回に1回しか変更した内容が反映されたページは表示されません。
2回に1回は変更前の“今公開されているページ”がプレビューとして現れます。
なぜそうなるかまでは突き止められませんでした。
ちなみに私たちが普段使っているカスタムフィールド管理用プラグイン Advanced Custom Fieldsでも同じ現象が起きます。。
あしからず。
WordPressカスタマイズ事例やウェブ制作ノウハウの新着情報、お役立ち情報を
リアルタイムにメルマガ配信!