PluginProbe
WP Ultimate Post Grid / 1.7.2
WP Ultimate Post Grid v1.7.2
4.1.1 trunk 1.5 1.6 1.7 1.7.1 1.7.2 1.8 1.9 2.0 2.1 2.2 2.3 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.2 3.0.0 3.3.0 3.4.0 3.5.0 3.6.0 3.7.0 All 32 releases
wp-ultimate-post-grid / vendor / vafpress / classes / metabox.php

metabox.php in WP Ultimate Post Grid 1.7.2, at vendor/vafpress/classes/metabox.php

770 lines 17.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Extended version of WPAlchemy Class
5 * so that it can process metabox using an array specification
6 * and compatible with all Vafpress Framework Option Controls.
7 */
8
9 /////////////////////////////////////////
10 // Include original WPAlchemy Class //
11 /////////////////////////////////////////
12 if(!class_exists('WPAlchemy_MetaBox'))
13 {
14 require_once VP_FileSystem::instance()->resolve_path('includes', 'wpalchemy/MetaBox');
15 }
16
17 class VP_Metabox extends WPAlchemy_MetaBox
18 {
19
20 public static $pool = array();
21
22 public $is_dev_mode = false;
23
24 function __construct($arr)
25 {
26 if( !is_array($arr) and file_exists($arr) )
27 {
28 $arr = include $arr;
29 }
30 parent::__construct($arr);
31
32 // Modify title in dev mode
33 if( $this->is_dev_mode )
34 {
35 $this->title = __('[Development Mode] ', 'wp-ultimate-recipe') . $this->title;
36 }
37
38 if ($this->can_output() and VP_WP_Admin::is_post_or_page() )
39 {
40 // make sure metabox template loaded
41 if( !is_array($this->template) and file_exists($this->template) )
42 $this->template = include $this->template;
43 add_action( 'init', array( $this, 'register_fields' ) );
44 }
45
46 self::$pool[$this->id] = $this;
47 }
48
49 public function register_fields()
50 {
51 $loader = VP_WP_Loader::instance();
52 $loader->add_types( $this->get_field_types(), 'metabox' );
53 }
54
55 public static function get_pool()
56 {
57 return self::$pool;
58 }
59
60 public static function pool_can_output()
61 {
62 foreach (self::$pool as $mb)
63 {
64 if( $mb->can_output() )
65 {
66 return true;
67 }
68 }
69 return false;
70 }
71
72 public static function pool_supports_editor()
73 {
74 foreach (self::$pool as $mb)
75 {
76 if( $mb->supports_editor() )
77 {
78 return true;
79 }
80 }
81 return false;
82 }
83
84 public function supports_editor()
85 {
86 $post_type = self::_get_current_post_type();
87 $has_editor = post_type_supports( $post_type, 'editor' );
88 return $has_editor;
89 }
90
91 /**
92 * Used to setup the meta box content template
93 *
94 * @since 1.0
95 * @access private
96 * @see _init()
97 */
98 function _setup()
99 {
100 $this->in_template = TRUE;
101
102 // also make current post data available
103 global $post;
104
105 // shortcuts
106 $mb =& $this;
107 $metabox =& $this;
108 $id = $this->id;
109 $meta = $this->_meta(NULL, TRUE);
110
111 // make sure metabox template loaded
112 if( !is_array($this->template) and file_exists($this->template) )
113 {
114 $this->template = include $this->template;
115 }
116 else
117 {
118 $fields = $this->_enfactor($this->template);
119 $this->_enbind($fields);
120 $fields = $this->_endep($fields);
121
122 echo '<div class="vp-metabox">';
123 $this->_enview($fields);
124 echo '</div>';
125 }
126
127 // create a nonce for verification
128 echo '<input type="hidden" name="'. $this->id .'_nonce" value="' . wp_create_nonce($this->id) . '" />';
129
130 $this->in_template = FALSE;
131 }
132
133 // return all field types
134 function get_field_types()
135 {
136 $types = array();
137
138 if(!function_exists('inner_build'))
139 {
140 function inner_build($fields, &$types)
141 {
142 $rules = VP_Util_Config::instance()->load('dependencies', 'rules');
143 foreach ($fields as $field)
144 {
145 if($field['type'] == 'group')
146 {
147 inner_build($field['fields'], $types);
148 }
149 else
150 {
151 if( ! in_array($field['type'], $types) )
152 $types[] = $field['type'];
153 }
154 }
155 }
156 }
157
158 inner_build($this->template, $types);
159
160 return $types;
161 }
162
163 function _enfactor($arr)
164 {
165 $mb =& $this;
166 $fields = $arr;
167 $field_objects = array();
168
169 foreach ($fields as $field)
170 {
171 if($field['type'] == 'group' and $field['repeating'])
172 {
173 $field_objects[$field['name']] = $this->_enfactor_group($field, $mb, true);
174 }
175 else if($field['type'] == 'group' and !$field['repeating'])
176 {
177 $field_objects[$field['name']] = $this->_enfactor_group($field, $mb, false);
178 }
179 else
180 {
181 $field_objects[$field['name']] = $this->_enfactor_field($field, $mb);
182 }
183 }
184
185 return $field_objects;
186 }
187
188 function _enbind($fields)
189 {
190 foreach ($fields as $name => $field)
191 {
192 if(is_array($field))
193 {
194 foreach ($field['groups'] as $group)
195 {
196 $this->_enbind($group['childs']);
197 }
198 }
199 else
200 {
201 $bind = $field->get_binding();
202 $val = $field->get_value();
203 if(!empty($bind) and is_null($val))
204 {
205 $bind = explode('|', $bind);
206 $func = $bind[0];
207 $params = $bind[1];
208 $params = preg_split('/[\s,]+/', $params);
209 $values = array();
210 foreach ($params as $param)
211 {
212 if(array_key_exists($param, $fields))
213 {
214 $values[] = $fields[$param]->get_value();
215 }
216 }
217 $result = call_user_func_array($func, $values);
218
219 if(VP_Util_Reflection::is_multiselectable($field))
220 {
221 $result = (array) $result;
222 }
223 else
224 {
225 if(is_array($result))
226 {
227 $result = reset($result);
228 }
229 $result = (String) $result;
230 }
231 $field->set_value($result);
232 }
233 if($field instanceof VP_Control_FieldMulti)
234 {
235 $bind = $field->get_items_binding();
236 if(!empty($bind))
237 {
238 $bind = explode('|', $bind);
239 $func = $bind[0];
240 $params = $bind[1];
241 $params = preg_split('/[\s,]+/', $params);
242 $values = array();
243 foreach ($params as $param)
244 {
245 if(array_key_exists($param, $fields))
246 {
247 $values[] = $fields[$param]->get_value();
248 }
249 }
250 $items = call_user_func_array($func, $values);
251 $field->add_items_from_array($items);
252 }
253 }
254 }
255 }
256 }
257
258 function _endep($fields)
259 {
260
261 if(!function_exists('loop_fields'))
262 {
263 function loop_fields(&$fields)
264 {
265 foreach ($fields as &$field)
266 {
267 if(is_array($field))
268 {
269 foreach ($field['groups'] as &$group)
270 {
271 loop_fields($group['childs']);
272 }
273 }
274
275 $dependency = '';
276 if($field instanceof VP_Control_Field)
277 {
278 $dependency = $field->get_dependency();
279 if(!empty($dependency))
280 {
281 $dependency = explode('|', $dependency);
282 $func = $dependency[0];
283 $params = $dependency[1];
284 }
285 }
286 else
287 {
288 if(isset($field['dependency']))
289 {
290 if(!empty($field['dependency']))
291 {
292 $dependency = $field['dependency'];
293 $func = $dependency['function'];
294 $params = $dependency['field'];
295 }
296 }
297 }
298
299 if(!empty($dependency))
300 {
301 $params = preg_split('/[\s,]+/', $params);
302 $values = array();
303 foreach ($params as $param)
304 {
305 if(array_key_exists($param, $fields))
306 {
307 $values[] = $fields[$param]->get_value();
308 }
309 }
310 $result = call_user_func_array($func, $values);
311 if(!$result)
312 {
313 if($field instanceof VP_Control_Field)
314 {
315 $field->is_hidden(true);
316 if($field->is_hidden())
317 $field->add_container_extra_classes('vp-hide');
318
319 $field->add_container_extra_classes('vp-dep-inactive');
320 }
321 else
322 {
323 $field['is_hidden'] = true;
324 if($field['is_hidden'])
325 $field['container_extra_classes'][] = 'vp-hide';
326
327 $field['container_extra_classes'][] = 'vp-dep-inactive';
328 }
329 }
330 }
331 }
332 }
333 }
334
335 loop_fields($fields);
336
337 return $fields;
338 }
339
340 function _enfactor_field($field, $mb, $in_group = false)
341 {
342 $is_multi = VP_Util_Reflection::is_multiselectable($field['type']);
343
344 if( !$is_multi )
345 {
346 $mb->the_field($field['name']);
347 }
348 else
349 {
350 $mb->the_field($field['name'], WPALCHEMY_FIELD_HINT_CHECKBOX_MULTI);
351 }
352 $field['name'] = $mb->get_the_name();
353
354 // create the object
355 $make = VP_Util_Reflection::field_class_from_type($field['type']);
356 $vp_field = call_user_func("$make::withArray", $field);
357
358 // get value from mb
359 $value = $mb->get_the_value();
360 // get default from array
361 $default = $vp_field->get_default();
362
363 // if tocopy always assign default
364 if( $mb->is_parent_multi() and $mb->is_in_multi_last() )
365 {
366 $value = $default;
367 }
368 else
369 {
370 // if value is null and default exist, use default
371 if( is_null($value) and !is_null($default) and empty($this->meta) )
372 {
373 $value = $default;
374 }
375 // if not then set up value from mb
376 else
377 {
378 if( VP_Util_Reflection::is_multiselectable($field['type']) )
379 {
380 if( !is_array($value) )
381 $value = array( $value );
382 }
383 }
384 }
385 $vp_field->set_value($value);
386
387 if (!$in_group)
388 {
389 $vp_field->add_container_extra_classes(array('vp-meta-single'));
390 }
391
392 return $vp_field;
393 }
394
395 function _enfactor_group($field, $mb, $repeating)
396 {
397 $ignore = array('type', 'length', 'fields');
398 $groups = array();
399 $indexed_name = '';
400 $level = null;
401 if($repeating)
402 {
403 while($mb->have_fields_and_multi($field['name']))
404 {
405 if ($indexed_name === '') $indexed_name = $mb->get_the_loop_group_id();
406 if (is_null($level)) $level = $mb->get_the_loop_level();
407 $fields = array();
408 foreach ($field['fields'] as $f)
409 {
410 if($f['type'] === 'group')
411 $fields[$f['name']] = $this->_enfactor_group($f, $mb, $f['repeating']);
412 else
413 $fields[$f['name']] = $this->_enfactor_field($f, $mb, true);
414 }
415 $groups[] = array(
416 'name' => $mb->get_the_loop_group_name(true),
417 'childs' => $fields
418 );
419 }
420 }
421 else
422 {
423 $length = isset($field['length']) ? $field['length'] : 1;
424 while($mb->have_fields($field['name'], $length))
425 {
426 if ($indexed_name === '') $indexed_name = $mb->get_the_loop_group_id();
427 if (is_null($level)) $level = $mb->get_the_loop_level();
428 $fields = array();
429 foreach ($field['fields'] as $f)
430 {
431 if($f['type'] === 'group')
432 $fields[$f['name']] = $this->_enfactor_group($f, $mb, $f['repeating']);
433 else
434 $fields[$f['name']] = $this->_enfactor_field($f, $mb, true);
435 }
436 $groups[] = array(
437 'name' => $mb->get_the_loop_group_name(true),
438 'childs' => $fields
439 );
440 }
441 }
442 // assign groups
443 $group['groups'] = $groups;
444 $group['indexed_name'] = $indexed_name;
445 $group['level'] = $level;
446
447 // assign other information
448 $keys = array_keys($field);
449 foreach ($keys as $key)
450 {
451 if(!in_array($key, $ignore))
452 {
453 $group[$key] = $field[$key];
454 }
455 }
456
457 // sortable
458 if(isset($group['sortable']) and $group['sortable'])
459 $group['container_extra_classes'][] = 'vp-sortable';
460
461 return $group;
462 }
463
464 function _enview($fields)
465 {
466 foreach ($fields as $name => $field)
467 {
468 if( is_array($field) and $field['repeating'] )
469 {
470 echo $this->_render_repeating_group($field);
471 }
472 else if( is_array($field) and !$field['repeating'] )
473 {
474 echo $this->_render_group($field);
475 }
476 else
477 {
478 echo $this->_render_field($field);
479 }
480 }
481 }
482
483 function _render_field($field)
484 {
485 return $field->render();
486 }
487
488 function _render_group($group)
489 {
490 $name = $group['name'];
491 $uid = $group['indexed_name'];
492 $oddity = ($group['level'] % 2 === 0) ? 'even' : 'odd';
493 $dependency = isset($group['dependency']) ? $group['dependency']['function'] . '|' . $group['dependency']['field'] : '';
494
495 $html = '';
496 $html .= '<div id="wpa_loop-' . $uid
497 . '" class="vp-wpa-loop level-' . $oddity . ' wpa_loop wpa_loop-' . $name . ' vp-fixed-loop vp-meta-group'
498 . (isset($group['container_extra_classes']) ? (' ' . implode(' ', $group['container_extra_classes'])) : '')
499 . '"'
500 . VP_Util_Text::return_if_exists(isset($dependency) ? $dependency : '', 'data-vp-dependency="%s"')
501 . '>';
502
503 $icon = '';
504 if(isset($group['sortable']) and $group['sortable'])
505 $icon = '<i class="fa fa-move"></i> ';
506
507 foreach ($group['groups'] as $g)
508 {
509 $is_first = false;
510 if ($g === reset($group['groups'])){ $is_first = true;}
511
512 $html .= '<div id="'. $g['name'] .'" class="vp-wpa-group wpa_group wpa_group-' . $name . '">';
513 $html .= '<div class="vp-wpa-group-heading"><a href="#" class="vp-wpa-group-title">' . $icon . $group['title'] . '</a></div>';
514 $html .= '<div class="vp-controls' . ((!$is_first) ? ' vp-hide' : '') . '">';
515
516 foreach ($g['childs'] as $f)
517 {
518
519 if( is_array($f) and $f['repeating'] )
520 $html .= $this->_render_repeating_group($f);
521 else if( is_array($f) and !$f['repeating'] )
522 $html .= $this->_render_group($f);
523 else
524 $html .= $this->_render_field($f);
525 }
526
527 $html .= '</div>';
528 $html .= '</div>';
529 }
530
531 $html .= '</div>';
532
533 return $html;
534 }
535
536 function _render_repeating_group($group)
537 {
538 $name = $group['name'];
539 $uid = $group['indexed_name'];
540 $oddity = ($group['level'] % 2 === 0) ? 'even' : 'odd';
541 $dependency = isset($group['dependency']) ? $group['dependency']['function'] . '|' . $group['dependency']['field'] : '';
542
543 $html = '';
544 $html .= '<div id="wpa_loop-' . $uid
545 . '" class="vp-wpa-loop level-' . $oddity . ' wpa_loop wpa_loop-' . $name . ' vp-repeating-loop vp-meta-group'
546 . (isset($group['container_extra_classes']) ? (' ' . implode(' ', $group['container_extra_classes'])) : '')
547 . '"'
548 . VP_Util_Text::return_if_exists(isset($dependency) ? $dependency : '', 'data-vp-dependency="%s"')
549 . '>';
550
551 $icon = '';
552 if(isset($group['sortable']) and $group['sortable'])
553 $icon = '<i class="fa fa-move"></i> ';
554
555 foreach ($group['groups'] as $g)
556 {
557 $class = '';
558 $is_first = false;
559 $is_last = false;
560 if ($g === end($group['groups'])){ $is_last = true; $class = ' last tocopy';}
561 if ($g === reset($group['groups'])){ $is_first = true; $class = ' first';}
562
563 $html .= '<div id="'. $g['name'] .'" class="vp-wpa-group wpa_group wpa_group-' . $name . $class . '">';
564 $html .= '<div class="vp-wpa-group-heading"><a href="#" class="vp-wpa-group-title">' . $icon . $group['title'] . '</a><a href="#" class="dodelete vp-wpa-group-remove" title="'. __('Remove', 'wp-ultimate-recipe') .'"><i class="fa fa-times"></i> '. __('Remove', 'wp-ultimate-recipe') .'</a></div>';
565 $html .= '<div class="vp-controls' . ((!$is_first) ? ' vp-hide' : '') . '">';
566 if ($g === end($group['groups']))
567 {
568 $tocopy = $g['name'] . '[tocopy]';
569 $html .= '<input type="hidden" class="tocopy-hidden" name="' . $tocopy . '" value="1">';
570 }
571 foreach ($g['childs'] as $f)
572 {
573
574 if( is_array($f) and $f['repeating'] )
575 $html .= $this->_render_repeating_group($f);
576 else if( is_array($f) and !$f['repeating'] )
577 $html .= $this->_render_group($f);
578 else
579 $html .= $this->_render_field($f);
580 }
581 $html .= '</div>';
582 $html .= '</div>';
583 }
584
585 $html .= '<div class="vp-wpa-group-add">';
586 $html .= '<a href="#" class="button button-large docopy-' . $name . '">'. __('Add More', 'wp-ultimate-recipe') . ' ' . $group['title'] . '</a>';
587 $html .= '</div>';
588
589 $html .= '</div>';
590
591 return $html;
592 }
593
594 function _save($post_id)
595 {
596 // skip saving if dev mode is on
597 if($this->is_dev_mode)
598 return;
599
600 $real_post_id = isset($_POST['post_ID']) ? $_POST['post_ID'] : NULL ;
601
602 // check autosave
603 if (defined('DOING_AUTOSAVE') AND DOING_AUTOSAVE AND !$this->autosave) return $post_id;
604
605 // make sure data came from our meta box, verify nonce
606 $nonce = isset($_POST[$this->id.'_nonce']) ? $_POST[$this->id.'_nonce'] : NULL ;
607 if (!wp_verify_nonce($nonce, $this->id)) return $post_id;
608
609 // check user permissions
610 if ($_POST['post_type'] == 'page')
611 {
612 if (!current_user_can('edit_page', $post_id)) return $post_id;
613 }
614 else
615 {
616 if (!current_user_can('edit_post', $post_id)) return $post_id;
617 }
618
619 // authentication passed, save data
620 $new_data = isset( $_POST[$this->id] ) ? $_POST[$this->id] : NULL ;
621
622 // clean to copy and reset array indexes
623 $this->_clean_tocopy($new_data);
624
625 if (empty($new_data))
626 {
627 $new_data = NULL;
628 }
629
630 // filter: save
631 if ($this->has_filter('save'))
632 {
633 $new_data = $this->apply_filters('save', $new_data, $real_post_id);
634
635 /**
636 * halt saving
637 * @since 1.3.4
638 */
639 if (FALSE === $new_data) return $post_id;
640
641 $this->_clean_tocopy($new_data);
642 }
643
644 // get current fields, use $real_post_id (checked for in both modes)
645 $current_fields = get_post_meta($real_post_id, $this->id . '_fields', TRUE);
646
647 if ($this->mode == WPALCHEMY_MODE_EXTRACT)
648 {
649 $new_fields = array();
650
651 if (is_array($new_data))
652 {
653 foreach ($new_data as $k => $v)
654 {
655 $field = $this->prefix . $k;
656
657 array_push($new_fields,$field);
658
659 $new_value = $new_data[$k];
660
661 if (is_null($new_value))
662 {
663 delete_post_meta($post_id, $field);
664 }
665 else
666 {
667 update_post_meta($post_id, $field, $new_value);
668 }
669 }
670 }
671
672 $diff_fields = array_diff((array)$current_fields,$new_fields);
673
674 if (is_array($diff_fields))
675 {
676 foreach ($diff_fields as $field)
677 {
678 delete_post_meta($post_id,$field);
679 }
680 }
681
682 delete_post_meta($post_id, $this->id . '_fields');
683
684 if ( ! empty($new_fields))
685 {
686 add_post_meta($post_id,$this->id . '_fields', $new_fields, TRUE);
687 }
688
689 // keep data tidy, delete values if previously using WPALCHEMY_MODE_ARRAY
690 delete_post_meta($post_id, $this->id);
691 }
692 else
693 {
694 if (is_null($new_data))
695 {
696 delete_post_meta($post_id, $this->id);
697 }
698 else
699 {
700 update_post_meta($post_id, $this->id, $new_data);
701 }
702
703 // keep data tidy, delete values if previously using WPALCHEMY_MODE_EXTRACT
704 if (is_array($current_fields))
705 {
706 foreach ($current_fields as $field)
707 {
708 delete_post_meta($post_id, $field);
709 }
710
711 delete_post_meta($post_id, $this->id . '_fields');
712 }
713 }
714
715 // action: save
716 if ($this->has_action('save'))
717 {
718 $this->do_action('save', $new_data, $real_post_id);
719 }
720
721 return $post_id;
722 }
723
724 private function _clean_tocopy(&$arr)
725 {
726 if(is_array($arr))
727 {
728 foreach ($arr as $key => $value)
729 {
730 if(is_array($value))
731 {
732 $this->_clean_tocopy($arr[$key]);
733 if(array_key_exists('tocopy', $value))
734 {
735 unset($arr[$key]);
736 }
737 }
738 }
739 if (!count($arr))
740 {
741 $arr = array();
742 }
743 else
744 {
745 $keys = array_keys($arr);
746
747 $is_numeric = TRUE;
748
749 foreach ($keys as $key)
750 {
751 if (!is_numeric($key))
752 {
753 $is_numeric = FALSE;
754 break;
755 }
756 }
757
758 if ($is_numeric)
759 {
760 $arr = array_values($arr);
761 }
762 }
763 }
764 }
765
766 }
767
768 /**
769 * EOF
770 */