PluginProbe
Smart Custom Fields / 1.0.3
Smart Custom Fields v1.0.3
1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.7.0 2.0.0 2.0.1 2.1.0 2.1.1 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 All 68 releases
smart-custom-fields / smart-custom-fields.php

smart-custom-fields.php in Smart Custom Fields 1.0.3, at smart-custom-fields.php

492 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin name: Smart Custom Fields
4 * Plugin URI: https://github.com/inc2734/smart-custom-fields/
5 * Description: Smart Custom Fields is a simple plugin that management custom fields.
6 * Version: 1.0.3
7 * Author: Takashi Kitajima
8 * Author URI: http://2inc.org
9 * Created: October 9, 2014
10 * Modified: OJanuary 6, 2015
11 * Text Domain: smart-custom-fields
12 * Domain Path: /languages/
13 * License: GPLv2
14 * License URI: http://www.gnu.org/licenses/gpl-2.0.html
15 */
16 class Smart_Custom_Fields {
17
18 /**
19 * post_custom 格納用
20 * 何度も関数呼び出ししなくて良いように保存
21 */
22 protected $post_custom = array();
23
24 /**
25 * repeat_multiple_data
26 * 何度も関数呼び出ししなくて良いように保存
27 */
28 protected $repeat_multiple_data = array();
29
30 /**
31 * fields
32 * 各フォーム部品のオブジェクトを格納する�
33 �列
34 */
35 protected $fields = array();
36
37 /**
38 * __construct
39 */
40 public function __construct() {
41 require_once plugin_dir_path( __FILE__ ) . 'classes/class.config.php';
42 add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
43 register_uninstall_hook( __FILE__, array( __CLASS__, 'uninstall' ) );
44 }
45
46 /**
47 * plugins_loaded
48 */
49 public function plugins_loaded() {
50 do_action( SCF_Config::PREFIX . 'load' );
51 require_once plugin_dir_path( __FILE__ ) . 'classes/class.field-base.php';
52 require_once plugin_dir_path( __FILE__ ) . 'classes/class.settings.php';
53 require_once plugin_dir_path( __FILE__ ) . 'classes/class.revisions.php';
54 require_once plugin_dir_path( __FILE__ ) . 'classes/class.scf.php';
55 new Smart_Custom_Fields_Settings();
56 new Smart_Custom_Fields_Revisions();
57 new SCF();
58
59 foreach ( glob( plugin_dir_path( __FILE__ ) . 'classes/fields/*.php' ) as $form_item ) {
60 include_once $form_item;
61 $basename = basename( $form_item, '.php' );
62 $classname = preg_replace( '/^class\.field\-(.+)$/', 'Smart_Custom_Fields_Field_$1', $basename );
63 if ( class_exists( $classname ) ) {
64 new $classname();
65 }
66 }
67
68 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
69 add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
70 add_action( 'save_post', array( $this, 'save_post' ) );
71 }
72
73 /**
74 * uninstall
75 */
76 public static function uninstall() {
77 $cf_posts = get_posts( array(
78 'post_type' => SCF_Config::NAME,
79 'posts_per_page' => -1,
80 'post_status' => 'any',
81 ) );
82 foreach ( $cf_posts as $post ) {
83 wp_delete_post( $post->ID, true );
84 }
85 delete_post_meta_by_key( SCF_Config::PREFIX . 'repeat-multiple-data' );
86 }
87
88 /**
89 * admin_enqueue_scripts
90 * @param string $hook
91 */
92 public function admin_enqueue_scripts( $hook ) {
93 if ( in_array( $hook, array( 'post-new.php', 'post.php' ) ) ) {
94 $post_type = get_post_type();
95 $settings = SCF::get_settings( $post_type );
96
97 if ( empty( $settings ) )
98 return;
99
100 wp_enqueue_style(
101 SCF_Config::PREFIX . 'editor',
102 plugin_dir_url( __FILE__ ) . 'css/editor.css'
103 );
104 wp_enqueue_media();
105 wp_enqueue_script(
106 SCF_Config::PREFIX . 'editor',
107 plugin_dir_url( __FILE__ ) . 'js/editor.js',
108 array( 'jquery' ),
109 null,
110 true
111 );
112 wp_localize_script( SCF_Config::PREFIX . 'editor', 'smart_cf_uploader', array(
113 'image_uploader_title' => esc_html__( 'Image setting', 'smart-custom-fields' ),
114 'file_uploader_title' => esc_html__( 'File setting', 'smart-custom-fields' ),
115 ) );
116 }
117 }
118
119 /**
120 * add_meta_boxes
121 * 投稿画面にカスタムフィールドを表示
122 * @param stirng $post_type
123 * @param object $post
124 */
125 public function add_meta_boxes( $post_type, $post ) {
126 $cf_posts = SCF::get_settings_posts( $post_type );
127 foreach ( $cf_posts as $post ) {
128 setup_postdata( $post );
129 $settings = get_post_meta( $post->ID, SCF_Config::PREFIX . 'setting', true );
130 if ( !$settings )
131 continue;
132 add_meta_box(
133 SCF_Config::PREFIX . 'custom-field-' . $post->ID,
134 $post->post_title,
135 array( $this, 'display_meta_box' ),
136 $post_type,
137 'normal',
138 'default',
139 $settings
140 );
141 wp_reset_postdata();
142 }
143 }
144
145 /**
146 * display_meta_box
147 * @param object $post
148 * @param array $setings カスタムフィールドの設定�
149
150 */
151 public function display_meta_box( $post, $settings ) {
152 $_settings = SCF::get_settings( get_post_type() );
153 $groups = $_settings[$settings['id']];
154 $tables = $this->get_tables( $post->ID, $groups );
155
156 printf( '<div class="%s">', esc_attr( SCF_Config::PREFIX . 'meta-box' ) );
157 $index = 0;
158 foreach ( $tables as $group_key => $group ) {
159 $btn_repeat = '';
160 $is_repeat = ( isset( $group['repeat'] ) && $group['repeat'] === true ) ? true : false;
161 if ( $is_repeat ) {
162 if ( $index === 0 ) {
163 printf(
164 '<div class="%s">',
165 esc_attr( SCF_Config::PREFIX . 'meta-box-repeat-tables' )
166 );
167 $this->display_tr( $post->ID, $is_repeat, $group['fields'] );
168 }
169 }
170
171 $this->display_tr( $post->ID, $is_repeat, $group['fields'], $index );
172
173 // ループの場合は添字をカウントアップ
174 // ループを抜けたらカウントをもとに戻す
175 if ( $is_repeat &&
176 isset( $tables[$group_key + 1 ]['group-name'] ) &&
177 $tables[$group_key + 1 ]['group-name'] === $group['group-name'] ) {
178 $index ++;
179 } else {
180 $index = 0;
181 }
182 if ( $is_repeat && $index === 0 ) {
183 echo '</div>';
184 }
185 }
186 printf( '</div>' );
187 wp_nonce_field( SCF_Config::NAME . '-fields', SCF_Config::PREFIX . 'fields-nonce' );
188 }
189
190 /**
191 * save_post
192 * @param int $post_id
193 */
194 public function save_post( $post_id ) {
195 if ( !isset( $_POST[SCF_Config::PREFIX . 'fields-nonce'] ) ) {
196 return;
197 }
198 if ( !wp_verify_nonce( $_POST[SCF_Config::PREFIX . 'fields-nonce'], SCF_Config::NAME . '-fields' ) ) {
199 return;
200 }
201 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
202 return;
203 }
204 if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ){
205 return;
206 }
207 if ( !isset( $_POST[SCF_Config::NAME] ) ) {
208 return;
209 }
210
211 // 繰り返しフィールドのチェックボックスは、普通のチェックボックスと混ざって
212 // 判別できなくなるのでわかるように保存しておく
213 $repeat_multiple_data = array();
214
215 // チェックボックスが未�
216 �力のときは "" がくるので、それは保存しないように判別
217 $multiple_data_fields = array();
218
219 $post_type = get_post_type();
220 $settings = SCF::get_settings( $post_type );
221 foreach ( $settings as $setting ) {
222 foreach ( $setting as $group ) {
223 $is_repeat = ( isset( $group['repeat'] ) && $group['repeat'] === true ) ? true : false;
224 foreach ( $group['fields'] as $field ) {
225 delete_post_meta( $post_id, $field['name'] );
226
227 if ( $field['allow-multiple-data'] ) {
228 $multiple_data_fields[] = $field['name'];
229 }
230
231 if ( $is_repeat && $field['allow-multiple-data'] ) {
232 $repeat_multiple_data_fields = $_POST[SCF_Config::NAME][$field['name']];
233 foreach ( $repeat_multiple_data_fields as $values ) {
234 if ( is_array( $values ) ) {
235 $repeat_multiple_data[$field['name']][] = count( $values );
236 } else {
237 $repeat_multiple_data[$field['name']][] = 0;
238 }
239 }
240 }
241 }
242 }
243 }
244 delete_post_meta( $post_id, SCF_Config::PREFIX . 'repeat-multiple-data' );
245 if ( $repeat_multiple_data ) {
246 update_post_meta( $post_id, SCF_Config::PREFIX . 'repeat-multiple-data', $repeat_multiple_data );
247 }
248
249 foreach ( $_POST[SCF_Config::NAME] as $name => $values ) {
250 foreach ( $values as $value ) {
251 if ( in_array( $name, $multiple_data_fields ) && $value === '' )
252 continue;
253 if ( !is_array( $value ) ) {
254 $this->add_post_meta( $post_id, $name, $value );
255 } else {
256 foreach ( $value as $val ) {
257 $this->add_post_meta( $post_id, $name, $val );
258 }
259 }
260 }
261 }
262 }
263
264 /**
265 * add_post_meta
266 * @param int $post_id
267 * @param string $name
268 * @param mixed $value
269 */
270 protected function add_post_meta( $post_id, $name, $value ) {
271 do_action( SCF_Config::PREFIX . '-before-save-post', $post_id, $name, $value );
272 $is_valid = apply_filters( SCF_Config::PREFIX . '-validate-save-post', true, $post_id, $name, $value );
273 if ( $is_valid ) {
274 add_post_meta( $post_id, $name, $value );
275 }
276 do_action( SCF_Config::PREFIX . '-after-save-post', $post_id, $name, $value );
277 }
278
279 /**
280 * get_post_custom
281 * @param int $post_id
282 * @return array
283 */
284 protected function get_post_custom( $post_id ) {
285 $post_custom = $this->post_custom;
286 if ( empty( $post_custom ) ) {
287 $post_custom = get_post_custom( $post_id );
288 if ( empty( $post_custom ) ) {
289 return array();
290 }
291 $this->post_custom = $post_custom;
292 }
293 return $this->post_custom;
294 }
295
296 /**
297 * get_repeat_multiple_data
298 * @param int $post_id
299 * @return array $this->repeat_multiple_data
300 */
301 protected function get_repeat_multiple_data( $post_id ) {
302 $repeat_multiple_data = $this->repeat_multiple_data;
303 if ( empty( $repeat_multiple_data ) ) {
304 $repeat_multiple_data = get_post_meta( $post_id, SCF_Config::PREFIX . 'repeat-multiple-data', true );
305 if ( empty( $repeat_multiple_data ) ) {
306 return array();
307 }
308 if ( is_serialized( $repeat_multiple_data ) ) {
309 $repeat_multiple_data = maybe_unserialize( $repeat_multiple_data );
310 }
311 $this->repeat_multiple_data = $repeat_multiple_data;
312 }
313 return $this->repeat_multiple_data;
314 }
315
316 /**
317 * get_tables
318 * カスタムフィールドを出力するための�
319 �列を生成
320 * @param array $groups カスタムフィールド設定ページで保存した設定
321 * @return array $tables カスタムフィールド表示用のテーブルを出力するための�
322 �列
323 */
324 protected function get_tables( $post_id, $groups ) {
325 $post_custom = $this->get_post_custom( $post_id );
326 $repeat_multiple_data = $this->get_repeat_multiple_data( $post_id );
327 $tables = array();
328 foreach ( $groups as $group ) {
329 // ループのときは、ループの分だけグループを追加する
330 // ループだけどループがないとき(新規登録時とか)は1つだけ�
331 �れる
332 if ( isset( $group['repeat'] ) && $group['repeat'] === true ) {
333 $loop_count = 1;
334 foreach ( $group['fields'] as $field ) {
335 if ( isset( $post_custom[$field['name']] ) && is_array( $post_custom[$field['name']] ) ) {
336 $post_meta = $post_custom[$field['name']];
337 $post_meta_count = count( $post_meta );
338 // 同名のカスタムフィールドが複数のとき(チェックボックス or ループ)
339 if ( $post_meta_count > 1 ) {
340 // チェックボックスの場合
341 if ( is_array( $repeat_multiple_data ) && array_key_exists( $field['name'], $repeat_multiple_data ) ) {
342 $repeat_multiple_data_count = count( $repeat_multiple_data[$field['name']] );
343 if ( $loop_count < $repeat_multiple_data_count )
344 $loop_count = $repeat_multiple_data_count;
345 }
346 // チェックボックス以外
347 else {
348 if ( $loop_count < $post_meta_count )
349 $loop_count = $post_meta_count;
350 }
351 }
352 }
353 }
354 if ( $loop_count >= 1 ) {
355 for ( $i = $loop_count; $i > 0; $i -- ) {
356 $tables[] = $group;
357 }
358 continue;
359 }
360 }
361 $tables[] = $group;
362 }
363 return $tables;
364 }
365
366 /**
367 * get_multiple_data_field_value
368 * @param int $post_id
369 * @param string $field_name
370 * @param int $index
371 * @return array or null
372 */
373 protected function get_multiple_data_field_value( $post_id, $field_name, $index ) {
374 $post_custom = $this->get_post_custom( $post_id );
375 $repeat_multiple_data = $this->get_repeat_multiple_data( $post_id );
376 $value = null;
377 if ( isset( $post_custom[$field_name] ) && is_array( $post_custom[$field_name] ) ) {
378 $value = $post_custom[$field_name];
379 // ループのとき
380 if ( is_array( $repeat_multiple_data ) && array_key_exists( $field_name, $repeat_multiple_data ) ) {
381 $now_num = 0;
382 if ( isset( $repeat_multiple_data[$field_name][$index] ) ) {
383 $now_num = $repeat_multiple_data[$field_name][$index];
384 }
385
386 // 自分($index)より前の個数の合計が指す index が start
387 $_temp = array_slice( $repeat_multiple_data[$field_name], 0, $index );
388 $sum = array_sum( $_temp );
389 $start = $sum;
390
391 $value = null;
392 if ( $now_num ) {
393 $value = array_slice( $post_custom[$field_name], $start, $now_num );
394 }
395 }
396 }
397 return $value;
398 }
399
400 /**
401 * get_single_data_field_value
402 * @param int $post_id
403 * @param string $field_name
404 * @param int $index
405 * @return string or null
406 */
407 protected function get_single_data_field_value( $post_id, $field_name, $index ) {
408 $post_custom = $this->get_post_custom( $post_id );
409 $value = null;
410 if ( isset( $post_custom[$field_name][$index] ) ) {
411 $value = $post_custom[$field_name][$index];
412 }
413 return $value;
414 }
415
416 /**
417 * display_tr
418 * @param int $post_id
419 * @param bool $is_repeat
420 * @param array $fields
421 * @param int, null $index
422 */
423 protected function display_tr( $post_id, $is_repeat, $fields, $index = null ) {
424 $btn_repeat = '';
425 if ( $is_repeat ) {
426 $btn_repeat = sprintf( '<span class="%s"></span>', esc_attr( SCF_Config::PREFIX . 'icon-handle' ) );
427 $btn_repeat .= '<span class="button btn-add-repeat-group">+</span>';
428 $btn_repeat .= ' <span class="button btn-remove-repeat-group">-</span>';
429 }
430
431 $style = '';
432 if ( is_null( $index ) ) {
433 $style = 'style="display: none;"';
434 }
435
436 printf(
437 '<div class="%s" %s>%s<table>',
438 esc_attr( SCF_Config::PREFIX . 'meta-box-table' ),
439 $style,
440 $btn_repeat
441 );
442
443 foreach ( $fields as $field ) {
444 $field_label = $field['label'];
445 if ( !$field_label ) {
446 $field_label = $field['name'];
447 }
448
449 // 複数値許可フィールドのとき
450 $post_status = get_post_status( $post_id );
451 if ( $field['allow-multiple-data'] ) {
452 $value = array();
453 if ( !SCF::is_empty( $field['default'] ) && ( $post_status === 'auto-draft' || is_null( $index ) ) ) {
454 $value = SCF::get_field_instance( $field['type'] )->get_choices( $field['default'] );
455 }
456 $_value = $this->get_multiple_data_field_value( $post_id, $field['name'], $index );
457 }
458 // 複数不値許可フィールドのとき
459 else {
460 $value = '';
461 if ( $post_status === 'auto-draft' || is_null( $index ) ) {
462 if ( !SCF::is_empty( $field['default'] ) ) {
463 $value = $field['default'];
464 }
465 }
466 $_value = $this->get_single_data_field_value( $post_id, $field['name'], $index );
467 }
468 if ( !is_null( $_value ) ) {
469 $value = $_value;
470 }
471
472 $notes = '';
473 if ( !empty( $field['notes'] ) ) {
474 $notes = sprintf(
475 '<p class="description">%s</p>',
476 esc_html( $field['notes'] )
477 );
478 }
479
480 $form_field = SCF::get_field_instance( $field['type'] )->get_field( $field, $index, $value );
481 printf(
482 '<tr><th>%s</th><td>%s%s</td></tr>',
483 esc_html( $field_label ),
484 $form_field,
485 $notes
486 );
487 }
488 echo '</table></div>';
489 }
490 }
491 new Smart_Custom_Fields();
492