PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.7.31.4
Pods – Custom Content Types and Fields v2.7.31.4
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / classes / fields / pick.php
pods / classes / fields Last commit date
avatar.php 2 days ago boolean.php 2 days ago code.php 2 days ago color.php 2 days ago comment.php 2 days ago currency.php 2 days ago date.php 2 days ago datetime.php 2 days ago email.php 2 days ago file.php 2 days ago html.php 2 days ago link.php 2 days ago number.php 2 days ago oembed.php 2 days ago paragraph.php 2 days ago password.php 2 days ago phone.php 2 days ago pick.php 2 days ago slug.php 2 days ago taxonomy.php 2 days ago text.php 2 days ago time.php 2 days ago website.php 2 days ago wysiwyg.php 2 days ago
pick.php
3577 lines
1 <?php
2
3 // Don't load directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 die( '-1' );
6 }
7
8 /**
9 * @package Pods\Fields
10 */
11 class PodsField_Pick extends PodsField {
12
13 /**
14 * {@inheritdoc}
15 */
16 public static $group = 'Relationships / Media';
17
18 /**
19 * {@inheritdoc}
20 */
21 public static $type = 'pick';
22
23 /**
24 * {@inheritdoc}
25 */
26 public static $label = 'Relationship';
27
28 /**
29 * {@inheritdoc}
30 */
31 protected static $api = false;
32
33 /**
34 * Available Related Objects.
35 *
36 * @var array
37 * @since 2.3.0
38 */
39 public static $related_objects = array();
40
41 /**
42 * Custom Related Objects
43 *
44 * @var array
45 * @since 2.3.0
46 */
47 public static $custom_related_objects = array();
48
49 /**
50 * Data used during validate / save to avoid extra queries.
51 *
52 * @var array
53 * @since 2.3.0
54 */
55 public static $related_data = array();
56
57 /**
58 * Data used during input method (mainly for autocomplete).
59 *
60 * @var array
61 * @since 2.3.0
62 */
63 public static $field_data = array();
64
65 /**
66 * Saved array of simple relationship names.
67 *
68 * @var array
69 * @since 2.5.0
70 */
71 private static $names_simple = null;
72
73 /**
74 * Saved array of relationship names
75 *
76 * @var array
77 * @since 2.5.0
78 */
79 private static $names_related = null;
80
81 /**
82 * Saved array of bidirectional relationship names
83 *
84 * @var array
85 * @since 2.5.0
86 */
87 private static $names_bidirectional = null;
88
89 /**
90 * {@inheritdoc}
91 */
92 public function setup() {
93
94 self::$label = __( 'Relationship', 'pods' );
95 }
96
97 /**
98 * {@inheritdoc}
99 */
100 public function admin_init() {
101
102 // AJAX for Relationship lookups.
103 add_action( 'wp_ajax_pods_relationship', array( $this, 'admin_ajax_relationship' ) );
104 add_action( 'wp_ajax_nopriv_pods_relationship', array( $this, 'admin_ajax_relationship' ) );
105
106 // Handle modal input.
107 add_action( 'pods_meta_box_pre', array( $this, 'admin_modal_input' ) );
108 add_action( 'edit_form_top', array( $this, 'admin_modal_input' ) );
109 add_action( 'show_user_profile', array( $this, 'admin_modal_input' ) );
110 add_action( 'edit_user_profile', array( $this, 'admin_modal_input' ) );
111
112 // Hook into every taxonomy form.
113 $taxonomies = get_taxonomies();
114
115 foreach ( $taxonomies as $taxonomy ) {
116 if ( $taxonomy instanceof WP_Term ) {
117 $taxonomy = $taxonomy->name;
118 }
119
120 add_action( $taxonomy . '_add_form', array( $this, 'admin_modal_input' ) );
121 add_action( $taxonomy . '_edit_form', array( $this, 'admin_modal_input' ) );
122 }
123
124 // Handle modal saving.
125 add_filter( 'redirect_post_location', array( $this, 'admin_modal_bail_post_redirect' ), 10, 2 );
126 add_action( 'load-edit-tags.php', array( $this, 'admin_modal_bail_term_action' ) );
127 add_action( 'load-categories.php', array( $this, 'admin_modal_bail_term_action' ) );
128 add_action( 'load-edit-link-categories.php', array( $this, 'admin_modal_bail_term_action' ) );
129 add_action( 'personal_options_update', array( $this, 'admin_modal_bail_user_action' ) );
130 add_action( 'user_register', array( $this, 'admin_modal_bail_user_action' ) );
131 add_action( 'pods_api_processed_form', array( $this, 'admin_modal_bail_pod' ), 10, 3 );
132
133 }
134
135 /**
136 * {@inheritdoc}
137 */
138 public function options() {
139
140 $options = array(
141 static::$type . '_format_type' => array(
142 'label' => __( 'Selection Type', 'pods' ),
143 'help' => __( 'help', 'pods' ),
144 'default' => 'single',
145 'type' => 'pick',
146 'data' => array(
147 'single' => __( 'Single Select', 'pods' ),
148 'multi' => __( 'Multiple Select', 'pods' ),
149 ),
150 'dependency' => true,
151 ),
152 static::$type . '_format_single' => array(
153 'label' => __( 'Format', 'pods' ),
154 'help' => __( 'help', 'pods' ),
155 'depends-on' => array( static::$type . '_format_type' => 'single' ),
156 'default' => 'dropdown',
157 'type' => 'pick',
158 'data' => apply_filters(
159 'pods_form_ui_field_pick_format_single_options', array(
160 'dropdown' => __( 'Drop Down', 'pods' ),
161 'radio' => __( 'Radio Buttons', 'pods' ),
162 'autocomplete' => __( 'Autocomplete', 'pods' ),
163 'list' => __( 'List view', 'pods' ),
164 )
165 ),
166 'dependency' => true,
167 ),
168 static::$type . '_format_multi' => array(
169 'label' => __( 'Format', 'pods' ),
170 'help' => __( 'help', 'pods' ),
171 'depends-on' => array( static::$type . '_format_type' => 'multi' ),
172 'default' => 'checkbox',
173 'type' => 'pick',
174 'data' => apply_filters(
175 'pods_form_ui_field_pick_format_multi_options', array(
176 'checkbox' => __( 'Checkboxes', 'pods' ),
177 'multiselect' => __( 'Multi Select', 'pods' ),
178 'autocomplete' => __( 'Autocomplete', 'pods' ),
179 'list' => __( 'List view', 'pods' ),
180 )
181 ),
182 'dependency' => true,
183 ),
184 static::$type . '_display_format_multi' => array(
185 'label' => __( 'Display Format', 'pods' ),
186 'help' => __( 'Used as format for front-end display', 'pods' ),
187 'depends-on' => array( static::$type . '_format_type' => 'multi' ),
188 'default' => 'default',
189 'type' => 'pick',
190 'data' => array(
191 'default' => __( 'Item 1, Item 2, and Item 3', 'pods' ),
192 'non_serial' => __( 'Item 1, Item 2 and Item 3', 'pods' ),
193 'custom' => __( 'Custom separator (without "and")', 'pods' ),
194 ),
195 'dependency' => true,
196 ),
197 static::$type . '_display_format_separator' => array(
198 'label' => __( 'Display Format Separator', 'pods' ),
199 'help' => __( 'Used as separator for front-end display. This also turns off the "and" portion of the formatting.', 'pods' ),
200 'depends-on' => array(
201 static::$type . '_display_format_multi' => 'custom',
202 static::$type . '_format_type' => 'multi',
203 ),
204 'default' => ', ',
205 'type' => 'text',
206 ),
207 static::$type . '_allow_add_new' => array(
208 'label' => __( 'Allow Add New', 'pods' ),
209 'help' => __( 'Allow new related records to be created in a modal window', 'pods' ),
210 'wildcard-on' => array(
211 static::$type . '_object' => array( '^post-type-(?!(custom-css|customize-changeset)).*$', '^taxonomy-.*$', '^user$', '^pod-.*$' ),
212 ),
213 'type' => 'boolean',
214 'default' => 1,
215 ),
216 static::$type . '_taggable' => array(
217 'label' => __( 'Taggable', 'pods' ),
218 'help' => __( 'Allow new values to be inserted when using an Autocomplete field', 'pods' ),
219 'excludes-on' => array(
220 static::$type . '_format_single' => array( 'dropdown', 'radio', 'list' ),
221 static::$type . '_format_multi' => array( 'checkbox', 'multiselect', 'list' ),
222 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
223 ),
224 'type' => 'boolean',
225 'default' => 0,
226 ),
227 static::$type . '_show_icon' => array(
228 'label' => __( 'Show Icons', 'pods' ),
229 'excludes-on' => array(
230 static::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
231 static::$type . '_format_multi' => array( 'checkbox', 'multiselect', 'autocomplete' ),
232 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
233 ),
234 'type' => 'boolean',
235 'default' => 1,
236 ),
237 static::$type . '_show_edit_link' => array(
238 'label' => __( 'Show Edit Links', 'pods' ),
239 'excludes-on' => array(
240 static::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
241 static::$type . '_format_multi' => array( 'checkbox', 'multiselect', 'autocomplete' ),
242 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
243 ),
244 'type' => 'boolean',
245 'default' => 1,
246 ),
247 static::$type . '_show_view_link' => array(
248 'label' => __( 'Show View Links', 'pods' ),
249 'excludes-on' => array(
250 static::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
251 static::$type . '_format_multi' => array( 'checkbox', 'multiselect', 'autocomplete' ),
252 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
253 ),
254 'type' => 'boolean',
255 'default' => 1,
256 ),
257 static::$type . '_select_text' => array(
258 'label' => __( 'Default Select Text', 'pods' ),
259 'help' => __( 'This is the text use for the default "no selection" dropdown item, if empty, it will default to "-- Select One --"', 'pods' ),
260 'depends-on' => array(
261 static::$type . '_format_type' => 'single',
262 static::$type . '_format_single' => 'dropdown',
263 ),
264 'default' => '',
265 'type' => 'text',
266 ),
267 static::$type . '_limit' => array(
268 'label' => __( 'Selection Limit', 'pods' ),
269 'help' => __( 'help', 'pods' ),
270 'depends-on' => array( static::$type . '_format_type' => 'multi' ),
271 'default' => 0,
272 'type' => 'number',
273 ),
274 static::$type . '_table_id' => array(
275 'label' => __( 'Table ID Column', 'pods' ),
276 'help' => __( 'You must provide the ID column name for the table, this will be used to keep track of the relationship', 'pods' ),
277 'depends-on' => array( static::$type . '_object' => 'table' ),
278 'required' => 1,
279 'default' => '',
280 'type' => 'text',
281 ),
282 static::$type . '_table_index' => array(
283 'label' => __( 'Table Index Column', 'pods' ),
284 'help' => __( 'You must provide the index column name for the table, this may optionally also be the ID column name', 'pods' ),
285 'depends-on' => array( static::$type . '_object' => 'table' ),
286 'required' => 1,
287 'default' => '',
288 'type' => 'text',
289 ),
290 static::$type . '_display' => array(
291 'label' => __( 'Display Field in Selection List', 'pods' ),
292 'help' => __( 'Provide the name of a field on the related object to reference, example: {@post_title}', 'pods' ),
293 'excludes-on' => array(
294 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
295 ),
296 'default' => '',
297 'type' => 'text',
298 ),
299 static::$type . '_user_role' => array(
300 'label' => __( 'Limit list to Role(s)', 'pods' ),
301 'help' => __( 'help', 'pods' ),
302 'depends-on' => array( static::$type . '_object' => 'user' ),
303 'default' => '',
304 'type' => 'pick',
305 'pick_object' => 'role',
306 'pick_format_type' => 'multi',
307 ),
308 static::$type . '_where' => array(
309 'label' => __( 'Customized <em>WHERE</em>', 'pods' ),
310 'help' => __( 'help', 'pods' ),
311 'excludes-on' => array(
312 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
313 ),
314 'default' => '',
315 'type' => 'text',
316 ),
317 static::$type . '_orderby' => array(
318 'label' => __( 'Customized <em>ORDER BY</em>', 'pods' ),
319 'help' => __( 'help', 'pods' ),
320 'excludes-on' => array(
321 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
322 ),
323 'default' => '',
324 'type' => 'text',
325 ),
326 static::$type . '_groupby' => array(
327 'label' => __( 'Customized <em>GROUP BY</em>', 'pods' ),
328 'help' => __( 'help', 'pods' ),
329 'excludes-on' => array(
330 static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
331 ),
332 'default' => '',
333 'type' => 'text',
334 ),
335 );
336
337 $post_type_pick_objects = array();
338
339 foreach ( get_post_types( '', 'names' ) as $post_type ) {
340 $post_type_pick_objects[] = 'post-type_' . $post_type;
341 }
342
343 $options[ static::$type . '_post_status' ] = array(
344 'name' => 'post_status',
345 'label' => __( 'Post Status', 'pods' ),
346 'help' => __( 'help', 'pods' ),
347 'type' => 'pick',
348 'pick_object' => 'post-status',
349 'pick_format_type' => 'multi',
350 'default' => 'publish',
351 'depends-on' => array(
352 static::$type . '_object' => $post_type_pick_objects,
353 ),
354 );
355
356 return $options;
357
358 }
359
360 /**
361 * Register a related object.
362 *
363 * @param string $name Object name.
364 * @param string $label Object label.
365 * @param array $options Object options.
366 *
367 * @return array|boolean Object array or false if unsuccessful
368 * @since 2.3.0
369 */
370 public function register_related_object( $name, $label, $options = null ) {
371
372 if ( empty( $name ) || empty( $label ) ) {
373 return false;
374 }
375
376 $related_object = array(
377 'label' => $label,
378 'group' => 'Custom Relationships',
379 'simple' => true,
380 'bidirectional' => false,
381 'data' => array(),
382 'data_callback' => null,
383 );
384
385 $related_object = array_merge( $related_object, $options );
386
387 self::$custom_related_objects[ $name ] = $related_object;
388
389 return true;
390
391 }
392
393 /**
394 * Setup related objects.
395 *
396 * @param boolean $force Whether to force refresh of related objects.
397 *
398 * @return bool True when data has been loaded
399 * @since 2.3.0
400 */
401 public function setup_related_objects( $force = false ) {
402
403 $new_data_loaded = false;
404
405 if ( ! $force && empty( self::$related_objects ) ) {
406 // Only load transient if we aren't forcing a refresh.
407 self::$related_objects = pods_transient_get( 'pods_related_objects' );
408
409 if ( false !== self::$related_objects ) {
410 $new_data_loaded = true;
411 }
412 } elseif ( $force ) {
413 // If we are rebuilding, make sure we start with a clean slate.
414 self::$related_objects = array();
415 }
416
417 if ( empty( self::$related_objects ) ) {
418 // Do a complete build of related_objects.
419 $new_data_loaded = true;
420
421 // Custom simple relationship lists.
422 self::$related_objects['custom-simple'] = array(
423 'label' => __( 'Simple (custom defined list)', 'pods' ),
424 'group' => __( 'Custom', 'pods' ),
425 'simple' => true,
426 );
427
428 // Pods options.
429 $pod_options = array();
430
431 // Include PodsMeta if not already included.
432 pods_meta();
433
434 // Advanced Content Types for relationships.
435 $_pods = PodsMeta::$advanced_content_types;
436
437 foreach ( $_pods as $pod ) {
438 $pod_options[ $pod['name'] ] = $pod['label'] . ' (' . $pod['name'] . ')';
439 }
440
441 // Settings pods for relationships.
442 $_pods = PodsMeta::$settings;
443
444 foreach ( $_pods as $pod ) {
445 $pod_options[ $pod['name'] ] = $pod['label'] . ' (' . $pod['name'] . ')';
446 }
447
448 asort( $pod_options );
449
450 foreach ( $pod_options as $pod => $label ) {
451 self::$related_objects[ 'pod-' . $pod ] = array(
452 'label' => $label,
453 'group' => __( 'Pods', 'pods' ),
454 'bidirectional' => true,
455 );
456 }
457
458 // Post Types for relationships.
459 $post_types = get_post_types();
460 asort( $post_types );
461
462 $ignore = array( 'attachment', 'revision', 'nav_menu_item' );
463
464 foreach ( $post_types as $post_type => $label ) {
465 $post_type = (string) $post_type;
466
467 if ( in_array( $post_type, $ignore, true ) || empty( $post_type ) ) {
468 unset( $post_types[ $post_type ] );
469
470 continue;
471 } elseif ( 0 === strpos( $post_type, '_pods_' ) && apply_filters( 'pods_pick_ignore_internal', true ) ) {
472 unset( $post_types[ $post_type ] );
473
474 continue;
475 }
476
477 $post_type = get_post_type_object( $post_type );
478
479 self::$related_objects[ 'post_type-' . $post_type->name ] = array(
480 'label' => $post_type->label . ' (' . $post_type->name . ')',
481 'group' => __( 'Post Types', 'pods' ),
482 'bidirectional' => true,
483 );
484 }
485
486 // Taxonomies for relationships.
487 $taxonomies = get_taxonomies();
488 asort( $taxonomies );
489
490 $ignore = array( 'nav_menu', 'post_format' );
491
492 foreach ( $taxonomies as $taxonomy => $label ) {
493 $taxonomy = (string) $taxonomy;
494
495 /**
496 * Prevent ability to extend core Pods content types.
497 *
498 * @param bool $ignore_internal Default is true, when set to false Pods internal content types can not be extended.
499 *
500 * @since 2.3.19
501 */
502 $ignore_internal = apply_filters( 'pods_pick_ignore_internal', true );
503
504 if ( in_array( $taxonomy, $ignore, true ) || empty( $taxonomy ) ) {
505 unset( $taxonomies[ $taxonomy ] );
506
507 continue;
508 } elseif ( 0 === strpos( $taxonomy, '_pods_' ) && $ignore_internal ) {
509 unset( $taxonomies[ $taxonomy ] );
510
511 continue;
512 }
513
514 $taxonomy = get_taxonomy( $taxonomy );
515
516 self::$related_objects[ 'taxonomy-' . $taxonomy->name ] = array(
517 'label' => $taxonomy->label . ' (' . $taxonomy->name . ')',
518 'group' => __( 'Taxonomies', 'pods' ),
519 'bidirectional' => true,
520 );
521 }//end foreach
522
523 // Other WP Objects for relationships.
524 self::$related_objects['user'] = array(
525 'label' => __( 'Users', 'pods' ),
526 'group' => __( 'Other WP Objects', 'pods' ),
527 'bidirectional' => true,
528 );
529
530 self::$related_objects['role'] = array(
531 'label' => __( 'User Roles', 'pods' ),
532 'group' => __( 'Other WP Objects', 'pods' ),
533 'simple' => true,
534 'data_callback' => array( $this, 'data_roles' ),
535 );
536
537 self::$related_objects['capability'] = array(
538 'label' => __( 'User Capabilities', 'pods' ),
539 'group' => __( 'Other WP Objects', 'pods' ),
540 'simple' => true,
541 'data_callback' => array( $this, 'data_capabilities' ),
542 );
543
544 self::$related_objects['media'] = array(
545 'label' => __( 'Media', 'pods' ),
546 'group' => __( 'Other WP Objects', 'pods' ),
547 'bidirectional' => true,
548 );
549
550 self::$related_objects['comment'] = array(
551 'label' => __( 'Comments', 'pods' ),
552 'group' => __( 'Other WP Objects', 'pods' ),
553 'bidirectional' => true,
554 );
555
556 self::$related_objects['image-size'] = array(
557 'label' => __( 'Image Sizes', 'pods' ),
558 'group' => __( 'Other WP Objects', 'pods' ),
559 'simple' => true,
560 'data_callback' => array( $this, 'data_image_sizes' ),
561 );
562
563 self::$related_objects['nav_menu'] = array(
564 'label' => __( 'Navigation Menus', 'pods' ),
565 'group' => __( 'Other WP Objects', 'pods' ),
566 );
567
568 self::$related_objects['post_format'] = array(
569 'label' => __( 'Post Formats', 'pods' ),
570 'group' => __( 'Other WP Objects', 'pods' ),
571 );
572
573 self::$related_objects['post-status'] = array(
574 'label' => __( 'Post Status', 'pods' ),
575 'group' => __( 'Other WP Objects', 'pods' ),
576 'simple' => true,
577 'data_callback' => array( $this, 'data_post_stati' ),
578 );
579
580 do_action( 'pods_form_ui_field_pick_related_objects_other' );
581
582 self::$related_objects['country'] = array(
583 'label' => __( 'Countries', 'pods' ),
584 'group' => __( 'Predefined Lists', 'pods' ),
585 'simple' => true,
586 'data_callback' => array( $this, 'data_countries' ),
587 );
588
589 self::$related_objects['us_state'] = array(
590 'label' => __( 'US States', 'pods' ),
591 'group' => __( 'Predefined Lists', 'pods' ),
592 'simple' => true,
593 'data_callback' => array( $this, 'data_us_states' ),
594 );
595
596 self::$related_objects['ca_province'] = array(
597 'label' => __( 'CA Provinces', 'pods' ),
598 'group' => __( 'Predefined Lists', 'pods' ),
599 'simple' => true,
600 'data_callback' => array( $this, 'data_ca_provinces' ),
601 );
602
603 self::$related_objects['days_of_week'] = array(
604 'label' => __( 'Calendar - Days of Week', 'pods' ),
605 'group' => __( 'Predefined Lists', 'pods' ),
606 'simple' => true,
607 'data_callback' => array( $this, 'data_days_of_week' ),
608 );
609
610 self::$related_objects['months_of_year'] = array(
611 'label' => __( 'Calendar - Months of Year', 'pods' ),
612 'group' => __( 'Predefined Lists', 'pods' ),
613 'simple' => true,
614 'data_callback' => array( $this, 'data_months_of_year' ),
615 );
616
617 do_action( 'pods_form_ui_field_pick_related_objects_predefined' );
618
619 if ( did_action( 'init' ) ) {
620 pods_transient_set( 'pods_related_objects', self::$related_objects );
621 }
622 }//end if
623
624 /**
625 * Allow custom related objects to be defined
626 */
627 do_action( 'pods_form_ui_field_pick_related_objects_custom' );
628
629 foreach ( self::$custom_related_objects as $object => $related_object ) {
630 if ( ! isset( self::$related_objects[ $object ] ) ) {
631 $new_data_loaded = true;
632
633 self::$related_objects[ $object ] = $related_object;
634 }
635 }
636
637 return $new_data_loaded;
638
639 }
640
641 /**
642 * Return available related objects
643 *
644 * @param boolean $force Whether to force refresh of related objects.
645 *
646 * @return array Field selection array
647 * @since 2.3.0
648 */
649 public function related_objects( $force = false ) {
650
651 if ( $this->setup_related_objects( $force ) || null === self::$names_related ) {
652 $related_objects = array();
653
654 foreach ( self::$related_objects as $related_object_name => $related_object ) {
655 if ( ! isset( $related_objects[ $related_object['group'] ] ) ) {
656 $related_objects[ $related_object['group'] ] = array();
657 }
658
659 $related_objects[ $related_object['group'] ][ $related_object_name ] = $related_object['label'];
660 }
661
662 self::$names_related = (array) apply_filters( 'pods_form_ui_field_pick_related_objects', $related_objects );
663 }
664
665 return self::$names_related;
666
667 }
668
669 /**
670 * Return available simple object names
671 *
672 * @return array Simple object names
673 * @since 2.3.0
674 */
675 public function simple_objects() {
676
677 if ( $this->setup_related_objects() || null === self::$names_simple ) {
678 $simple_objects = array();
679
680 foreach ( self::$related_objects as $object => $related_object ) {
681 if ( ! isset( $related_object['simple'] ) || ! $related_object['simple'] ) {
682 continue;
683 }
684
685 $simple_objects[] = $object;
686 }
687
688 self::$names_simple = (array) apply_filters( 'pods_form_ui_field_pick_simple_objects', $simple_objects );
689 }
690
691 return self::$names_simple;
692
693 }
694
695 /**
696 * Return available bidirectional object names
697 *
698 * @return array Bidirectional object names
699 * @since 2.3.4
700 */
701 public function bidirectional_objects() {
702
703 if ( $this->setup_related_objects() || null === self::$names_bidirectional ) {
704 $bidirectional_objects = array();
705
706 foreach ( self::$related_objects as $object => $related_object ) {
707 if ( ! isset( $related_object['bidirectional'] ) || ! $related_object['bidirectional'] ) {
708 continue;
709 }
710
711 $bidirectional_objects[] = $object;
712 }
713
714 self::$names_bidirectional = (array) apply_filters( 'pods_form_ui_field_pick_bidirectional_objects', $bidirectional_objects );
715 }
716
717 return self::$names_bidirectional;
718
719 }
720
721 /**
722 * {@inheritdoc}
723 */
724 public function schema( $options = null ) {
725
726 $schema = false;
727
728 $simple_tableless_objects = $this->simple_objects();
729
730 if ( in_array( pods_v( static::$type . '_object', $options ), $simple_tableless_objects, true ) ) {
731 $schema = 'LONGTEXT';
732 }
733
734 return $schema;
735
736 }
737
738 /**
739 * {@inheritdoc}
740 */
741 public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
742
743 $fields = null;
744
745 if ( is_object( $pod ) && isset( $pod->fields ) ) {
746 /**
747 * @var $pod Pods Pods object.
748 */
749 $fields = $pod->fields;
750
751 if ( ! empty( $pod->pod_data['object_fields'] ) ) {
752 $fields = array_merge( $fields, $pod->pod_data['object_fields'] );
753 }
754 } elseif ( is_array( $pod ) && isset( $pod['fields'] ) ) {
755 $fields = $pod['fields'];
756
757 if ( ! empty( $pod['object_fields'] ) ) {
758 $fields = array_merge( $fields, $pod['object_fields'] );
759 }
760 }
761
762 $args = array(
763 'field' => $name,
764 'fields' => $fields,
765 );
766
767 $display_format = pods_v( static::$type . '_display_format_multi', $options, 'default' );
768
769 if ( 'non_serial' === $display_format ) {
770 $args['serial'] = false;
771 }
772
773 if ( 'custom' === $display_format ) {
774 $args['serial'] = false;
775
776 $separator = pods_v( static::$type . '_display_format_separator', $options, ', ' );
777 if ( ! empty( $separator ) ) {
778 $args['separator'] = $separator;
779
780 // Replicate separator behavior.
781 $args['and'] = $args['separator'];
782 }
783 }
784
785 return pods_serial_comma( $value, $args );
786 }
787
788 /**
789 * {@inheritdoc}
790 */
791 public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
792
793 $options = (array) $options;
794
795 $type = pods_v( 'type', $options, static::$type );
796
797 $args = compact( array_keys( get_defined_vars() ) );
798 $args = (object) $args;
799
800 wp_enqueue_script( 'pods-dfv' );
801
802 wp_enqueue_style( 'pods-select2' );
803 wp_enqueue_script( 'pods-select2' );
804
805 $this->render_input_script( $args );
806
807 /**
808 * @todo Support custom integrations.
809 *
810 * Run the action 'pods_form_ui_field_pick_input_' . pods_v( static::$type . '_format_type', $options, 'single' ) . '_' . pods_v( static::$type . '_format_multi', $options, 'checkbox' )
811 * Run the action 'pods_form_ui_field_pick_input'
812 * Pass the arguments: $name, $value, $options, $pod, $id
813 */
814
815 }
816
817 /**
818 * {@inheritdoc}
819 */
820 public function build_dfv_field_options( $options, $args ) {
821
822 $options['grouped'] = 1;
823
824 if ( empty( $options[ $args->type . '_object' ] ) ) {
825 $options[ $args->type . '_object' ] = '';
826 }
827
828 if ( empty( $options[ $args->type . '_val' ] ) ) {
829 $options[ $args->type . '_val' ] = '';
830 }
831
832 $options['table_info'] = array();
833
834 $custom = pods_v( $args->type . '_custom', $options, false );
835
836 $custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $args->name, $args->value, $options, $args->pod, $args->id );
837
838 $ajax = false;
839
840 if ( $this->can_ajax( $args->type, $options ) ) {
841 $ajax = true;
842
843 if ( ! empty( self::$field_data ) && self::$field_data['id'] === $options['id'] ) {
844 $ajax = (boolean) self::$field_data['autocomplete'];
845 }
846 }
847
848 $ajax = apply_filters( 'pods_form_ui_field_pick_ajax', $ajax, $args->name, $args->value, $options, $args->pod, $args->id );
849
850 if ( 0 === (int) pods_v( $args->type . '_ajax', $options, 1 ) ) {
851 $ajax = false;
852 }
853
854 $options[ $args->type . '_ajax' ] = (int) $ajax;
855
856 $format_type = pods_v( $args->type . '_format_type', $options, 'single', true );
857
858 $limit = 1;
859
860 if ( 'single' === $format_type ) {
861 $format_single = pods_v( $args->type . '_format_single', $options, 'dropdown', true );
862
863 if ( 'dropdown' === $format_single ) {
864 $options['view_name'] = 'select';
865 } elseif ( 'radio' === $format_single ) {
866 $options['view_name'] = 'radio';
867 } elseif ( 'autocomplete' === $format_single ) {
868 $options['view_name'] = 'select2';
869 } elseif ( 'list' === $format_single ) {
870 $options['view_name'] = 'list';
871 } else {
872 $options['view_name'] = $format_single;
873 }
874 } elseif ( 'multi' === $format_type ) {
875 $format_multi = pods_v( $args->type . '_format_multi', $options, 'checkbox', true );
876
877 if ( ! empty( $args->value ) && ! is_array( $args->value ) ) {
878 $args->value = explode( ',', $args->value );
879 }
880
881 if ( 'checkbox' === $format_multi ) {
882 $options['view_name'] = 'checkbox';
883 } elseif ( 'multiselect' === $format_multi ) {
884 $options['view_name'] = 'select';
885 } elseif ( 'autocomplete' === $format_multi ) {
886 $options['view_name'] = 'select2';
887 } elseif ( 'list' === $format_multi ) {
888 $options['view_name'] = 'list';
889 } else {
890 $options['view_name'] = $format_multi;
891 }
892
893 $limit = 0;
894
895 if ( ! empty( $options[ $args->type . '_limit' ] ) ) {
896 $limit = absint( $options[ $args->type . '_limit' ] );
897 }
898 } else {
899 $options['view_name'] = $format_type;
900 }//end if
901
902 $options[ $args->type . '_limit' ] = $limit;
903
904 $options['ajax_data'] = $this->build_dfv_autocomplete_ajax_data( $options, $args, $ajax );
905
906 /**
907 * Allow overriding some of the Select2 options used in the JS init.
908 *
909 * @param array|null $select2_overrides Override options for Select2/SelectWoo.
910 *
911 * @since 2.7.0
912 */
913 $options['select2_overrides'] = apply_filters( 'pods_pick_select2_overrides', null );
914
915 return $options;
916
917 }
918
919 /**
920 * Build DFV autocomplete AJAX data.
921 *
922 * @param array $options DFV options.
923 * @param object $args {
924 * Field information arguments.
925 *
926 * @type string $name Field name.
927 * @type string $type Field type.
928 * @type array $options Field options.
929 * @type mixed $value Current value.
930 * @type array $pod Pod information.
931 * @type int|string $id Current item ID.
932 * }
933 * @param bool $ajax True if ajax mode should be used.
934 *
935 * @return array
936 */
937 public function build_dfv_autocomplete_ajax_data( $options, $args, $ajax = false ) {
938
939 if ( is_object( $args->pod ) ) {
940 $pod_id = (int) $args->pod->pod_id;
941 } else {
942 $pod_id = 0;
943 }
944
945 $field_id = (int) $options['id'];
946
947 $id = (int) $args->id;
948
949 if ( is_user_logged_in() ) {
950 $uid = 'user_' . get_current_user_id();
951 } else {
952 $uid = pods_session_id();
953 }
954
955 $uri_hash = wp_create_nonce( 'pods_uri_' . $_SERVER['REQUEST_URI'] );
956
957 $field_nonce = wp_create_nonce( 'pods_relationship_' . $pod_id . '_' . $uid . '_' . $uri_hash . '_' . $field_id );
958
959 // Values can be overridden via the `pods_field_dfv_data` filter in $data['fieldConfig']['ajax_data'].
960 return array(
961 'ajax' => $ajax,
962 'delay' => 300,
963 'minimum_input_length' => 1,
964 'pod' => $pod_id,
965 'field' => $field_id,
966 'id' => $id,
967 'uri' => $uri_hash,
968 '_wpnonce' => $field_nonce,
969 );
970
971 }
972
973 /**
974 * {@inheritdoc}
975 */
976 public function build_dfv_field_config( $args ) {
977
978 $config = parent::build_dfv_field_config( $args );
979
980 if ( ! isset( $config['optgroup'] ) ) {
981 $config['optgroup'] = false;
982 }
983
984 /**
985 * Filter on whether to allow modals to be used on the front of the site (in an non-admin area).
986 *
987 * @param boolean $show_on_front
988 * @param array $config
989 * @param array $args
990 *
991 * @since 2.7.0
992 */
993 $show_on_front = apply_filters( 'pods_ui_dfv_pick_modals_show_on_front', false, $config, $args );
994
995 /**
996 * Filter on whether to allow nested modals to be used (modals within modals).
997 *
998 * @param boolean $allow_nested_modals
999 * @param array $config
1000 * @param array $args
1001 *
1002 * @since 2.7.0
1003 */
1004 $allow_nested_modals = apply_filters( 'pods_ui_dfv_pick_modals_allow_nested', false, $config, $args );
1005
1006 // Disallow add/edit outside the admin and when we're already in a modal
1007 if ( ( ! $show_on_front && ! is_admin() ) || ( ! $allow_nested_modals && pods_is_modal_window() ) ) {
1008 $config[ $args->type . '_allow_add_new' ] = false;
1009 $config[ $args->type . '_show_edit_link' ] = false;
1010 }
1011
1012 $iframe = array(
1013 'src' => '',
1014 'url' => '',
1015 'query_args' => array(),
1016 );
1017
1018 // Set the file name and args based on the content type of the relationship
1019 switch ( $args->options['pick_object'] ) {
1020 case 'post_type':
1021 if ( ! empty( $args->options['pick_val'] ) ) {
1022 $post_type_obj = get_post_type_object( $args->options['pick_val'] );
1023
1024 if ( $post_type_obj && current_user_can( $post_type_obj->cap->create_posts ) ) {
1025 $iframe['url'] = admin_url( 'post-new.php' );
1026 $iframe['query_args'] = array(
1027 'post_type' => $args->options['pick_val'],
1028 );
1029 }
1030 }
1031
1032 // Determine the default icon to use for this post type,
1033 // default to the dashicon for posts
1034 $config[ 'default_icon' ] = 'dashicons-admin-post';
1035
1036 // Any custom specified menu icon gets priority
1037 $post_type = get_post_type_object( $args->options[ 'pick_val' ] );
1038 if ( ! empty( $post_type->menu_icon ) ) {
1039 $config[ 'default_icon' ] = $post_type->menu_icon;
1040
1041 // Page and attachment have their own dashicons
1042 } elseif ( isset( $post_type->name ) ) {
1043 switch ( $post_type->name ) {
1044 case 'page':
1045 // Default for pages.
1046 $config[ 'default_icon' ] = 'dashicons-admin-page';
1047 break;
1048 case 'attachment':
1049 // Default for attachments.
1050 $config[ 'default_icon' ] = 'dashicons-admin-media';
1051 break;
1052 }
1053 }
1054
1055 break;
1056
1057 case 'taxonomy':
1058 /*
1059 * @todo Fix add new modal issues
1060 if ( ! empty( $args->options['pick_val'] ) ) {
1061 $taxonomy_obj = get_taxonomy( $args->options['pick_val'] );
1062
1063 if ( $taxonomy_obj && current_user_can( $taxonomy_obj->cap->edit_terms ) ) {
1064 $iframe['url'] = admin_url( 'edit-tags.php' );
1065 $iframe['query_args'] = array(
1066 'taxonomy' => $args->options['pick_val'],
1067 );
1068 }
1069 }
1070 */
1071
1072 break;
1073
1074 case 'user':
1075 if ( current_user_can( 'create_users' ) ) {
1076 $iframe['url'] = admin_url( 'user-new.php' );
1077 }
1078
1079 break;
1080
1081 case 'pod':
1082 if ( ! empty( $args->options['pick_val'] ) ) {
1083 if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
1084 $iframe['url'] = admin_url( 'admin.php' );
1085 $iframe['query_args'] = array(
1086 'page' => 'pods-manage-' . $args->options['pick_val'],
1087 'action' => 'add',
1088 );
1089
1090 }
1091 }
1092
1093 break;
1094 }//end switch
1095
1096 // Potential valid modal target if we've set the file name
1097 if ( ! empty( $iframe['url'] ) ) {
1098 // @todo: Replace string literal with defined constant
1099 $iframe['query_args']['pods_modal'] = 1;
1100
1101 // Add args we always need
1102 $iframe['src'] = add_query_arg( $iframe['query_args'], $iframe['url'] );
1103 }
1104
1105 $iframe['title_add'] = sprintf( __( '%s: Add New', 'pods' ), $args->options['label'] );
1106 $iframe['title_edit'] = sprintf( __( '%s: Edit', 'pods' ), $args->options['label'] );
1107
1108 /**
1109 * Allow filtering iframe configuration
1110 *
1111 * @param array $iframe
1112 * @param array $config
1113 * @param array $args
1114 *
1115 * @since 2.7.0
1116 */
1117 $iframe = apply_filters( 'pods_ui_dfv_pick_modals_iframe', $iframe, $config, $args );
1118
1119 if ( ! empty( $iframe['src'] ) ) {
1120 // We extend wp.media.view.Modal for modal add/edit, we must ensure we load the template for it
1121 wp_enqueue_media();
1122
1123 }
1124
1125 $config['iframe_src'] = $iframe['src'];
1126 $config['iframe_title_add'] = $iframe['title_add'];
1127 $config['iframe_title_edit'] = $iframe['title_edit'];
1128
1129 return $config;
1130
1131 }
1132
1133 /**
1134 * {@inheritdoc}
1135 */
1136 public function build_dfv_field_item_data( $args ) {
1137
1138 $args->options['supports_thumbnails'] = null;
1139
1140 $item_data = array();
1141
1142 if ( ! empty( $args->options['data'] ) ) {
1143 $item_data = $this->build_dfv_field_item_data_recurse( $args->options['data'], $args );
1144 }
1145
1146 return $item_data;
1147
1148 }
1149
1150 /**
1151 * Loop through relationship data and expand item data with additional information for DFV.
1152 *
1153 * @param array $data Item data to expand.
1154 * @param object $args {
1155 * Field information arguments.
1156 *
1157 * @type string $name Field name.
1158 * @type string $type Field type.
1159 * @type array $options Field options.
1160 * @type mixed $value Current value.
1161 * @type array $pod Pod information.
1162 * @type int|string $id Current item ID.
1163 * }
1164 *
1165 * @return array
1166 */
1167 public function build_dfv_field_item_data_recurse( $data, $args ) {
1168
1169 $item_data = array();
1170
1171 foreach ( $data as $item_id => $item_title ) {
1172 if ( is_array( $item_title ) ) {
1173 $args->options['optgroup'] = true;
1174
1175 $item_data[] = array(
1176 'label' => $item_id,
1177 'collection' => $this->build_dfv_field_item_data_recurse( $item_title, $args ),
1178 );
1179 } else {
1180 // Key by item_id temporarily to be able to sort based on $args->value
1181 $item_data[ $item_id ] = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args );
1182 }
1183 }
1184
1185 // Maintain any saved sort order from $args->value
1186 if ( is_array( $args->value ) && 1 < count( $args->value ) && $this->is_autocomplete( $args->options ) ) {
1187 $item_data = array_replace( $args->value, $item_data );
1188 }
1189
1190 // Convert from associative to numeric array
1191 $item_data = array_values( $item_data );
1192
1193 return $item_data;
1194
1195 }
1196
1197 /**
1198 * Loop through relationship data and expand item data with additional information for DFV.
1199 *
1200 * @param int|string $item_id Item ID.
1201 * @param string $item_title Item title.
1202 * @param object $args {
1203 * Field information arguments.
1204 *
1205 * @type string $name Field name.
1206 * @type string $type Field type.
1207 * @type array $options Field options.
1208 * @type mixed $value Current value.
1209 * @type array $pod Pod information.
1210 * @type int|string $id Current item ID.
1211 * }
1212 *
1213 * @return array
1214 */
1215 public function build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args ) {
1216
1217 $icon = '';
1218 $img_icon = '';
1219 $edit_link = '';
1220 $link = '';
1221
1222 if ( ! isset( $args->options['supports_thumbnails'] ) ) {
1223 $args->options['supports_thumbnails'] = null;
1224 }
1225
1226 switch ( $args->options['pick_object'] ) {
1227 case 'post_type':
1228 if ( null === $args->options['supports_thumbnails'] && ! empty( $args->options['pick_val'] ) ) {
1229 $args->options['supports_thumbnails'] = post_type_supports( $args->options['pick_val'], 'thumbnail' );
1230 }
1231
1232 if ( true === $args->options['supports_thumbnails'] ) {
1233 $post_thumbnail_id = get_post_thumbnail_id( $item_id );
1234
1235 if ( $post_thumbnail_id ) {
1236 $thumb = wp_get_attachment_image_src( $post_thumbnail_id, 'thumbnail', false );
1237 }
1238
1239 if ( ! empty( $thumb[0] ) ) {
1240 $img_icon = $thumb[0];
1241 }
1242 }
1243
1244 if ( empty( $img_icon ) ) {
1245
1246 // Default icon for posts.
1247 $icon = 'dashicons-admin-post';
1248
1249 // Post type icons.
1250 $post_type = (array) get_post_type_object( get_post_type( $item_id ) );
1251
1252 if ( ! empty( $post_type['menu_icon'] ) ) {
1253 // Post specific icon.
1254 $icon = $post_type['menu_icon'];
1255 } elseif ( isset( $post_type['name'] ) && 'page' ) {
1256 switch ( $post_type['name'] ) {
1257 case 'page':
1258 // Default for pages.
1259 $icon = 'dashicons-admin-page';
1260 break;
1261 case 'attachment':
1262 // Default for attachments.
1263 $icon = 'dashicons-admin-media';
1264 break;
1265 }
1266 }
1267 }//end if
1268
1269 $edit_link = get_edit_post_link( $item_id, 'raw' );
1270
1271 $link = get_permalink( $item_id );
1272
1273 break;
1274
1275 case 'taxonomy':
1276 if ( ! empty( $args->options['pick_val'] ) ) {
1277
1278 // Default icon for taxonomy.
1279 $icon = 'dashicons-category';
1280
1281 // Change icon for non-hierarchical taxonomies.
1282 $taxonomy = get_term( $item_id );
1283 if ( isset( $taxonomy->taxonomy ) ) {
1284 $taxonomy = (array) get_taxonomy( $taxonomy->taxonomy );
1285 if ( isset( $taxonomy['hierarchical'] ) && ! $taxonomy['hierarchical'] ) {
1286 $icon = 'dashicons-tag';
1287 }
1288 }
1289
1290 $edit_link = get_edit_term_link( $item_id, $args->options['pick_val'] );
1291
1292 $link = get_term_link( $item_id, $args->options['pick_val'] );
1293 }
1294
1295 break;
1296
1297 case 'user':
1298 $args->options['supports_thumbnails'] = true;
1299
1300 $icon = 'dashicons-admin-users';
1301 $img_icon = get_avatar_url( $item_id, array( 'size' => 150 ) );
1302
1303 $edit_link = get_edit_user_link( $item_id );
1304
1305 $link = get_author_posts_url( $item_id );
1306
1307 break;
1308
1309 case 'comment':
1310 $args->options['supports_thumbnails'] = true;
1311
1312 $icon = 'dashicons-admin-comments';
1313 $img_icon = get_avatar_url( get_comment( $item_id ), array( 'size' => 150 ) );
1314
1315 $edit_link = get_edit_comment_link( $item_id );
1316
1317 $link = get_comment_link( $item_id );
1318
1319 break;
1320
1321 case 'pod':
1322 if ( ! empty( $args->options['pick_val'] ) ) {
1323
1324 $icon = 'dashicons-pods';
1325
1326 if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
1327 $file_name = 'admin.php';
1328 $query_args = array(
1329 'page' => 'pods-manage-' . $args->options['pick_val'],
1330 'action' => 'edit',
1331 'id' => $item_id,
1332 );
1333
1334 $edit_link = add_query_arg( $query_args, admin_url( $file_name ) );
1335 }
1336
1337 // @todo Add $link support
1338 $link = '';
1339 }
1340
1341 break;
1342 }//end switch
1343
1344 // Image icons always overwrite default icons
1345 if ( ! empty( $img_icon ) ) {
1346 $icon = (string) $img_icon;
1347 }
1348
1349 // Parse icon type
1350 if ( 'none' === $icon || 'div' === $icon ) {
1351 $icon = '';
1352 } elseif ( 0 === strpos( $icon, 'dashicons-' ) ) {
1353 $icon = sanitize_html_class( $icon );
1354 }
1355
1356 // #5740 Check for WP_Error object.
1357 if ( ! is_string( $link ) ) {
1358 $link = '';
1359 }
1360
1361 // Support modal editing
1362 if ( ! empty( $edit_link ) ) {
1363 // @todo: Replace string literal with defined constant
1364 $edit_link = add_query_arg( array( 'pods_modal' => '1' ), $edit_link );
1365 }
1366
1367 // Determine if this is a selected item.
1368 // Issue history for setting selected: #4753, #4892, #5014.
1369 $selected = false;
1370
1371 $values = array();
1372
1373 // If we have values, let's cast them.
1374 if ( ! empty( $args->value ) ) {
1375 // The value may be a single non-array value.
1376 $values = (array) $args->value;
1377 }
1378
1379 // Cast values in array as string.
1380 $values = array_map( 'strval', $values );
1381
1382 // If the value array has keys as IDs, let's check for matches from the keys first.
1383 if ( ! isset( $values[0] ) ) {
1384 // Get values from keys.
1385 $key_values = array_keys( $values );
1386
1387 // Cast key values in array as string.
1388 $key_values = array_map( 'strval', $key_values );
1389
1390 // Let's check to see if the current $item_id matches any key values.
1391 if ( in_array( (string) $item_id, $key_values, true ) ) {
1392 $selected = true;
1393 }
1394 }
1395
1396 // If we do not have a key match, the normal values may still match.
1397 if ( ! $selected ) {
1398 // Let's check to see if the current $item_id matches any values.
1399 if ( in_array( (string) $item_id, $values, true ) ) {
1400 $selected = true;
1401 }
1402 }
1403
1404 $item = array(
1405 'id' => null !== $item_id ? html_entity_decode( esc_html( $item_id ), ENT_COMPAT ) : '',
1406 'icon' => null !== $icon ? esc_attr( (string) $icon ) : '',
1407 'name' => null !== $item_title ? wp_strip_all_tags( html_entity_decode( $item_title, ENT_COMPAT ) ) : '',
1408 'edit_link' => null !== $edit_link ? html_entity_decode( esc_url( $edit_link ), ENT_COMPAT ) : '',
1409 'link' => null !== $link ? html_entity_decode( esc_url( $link ), ENT_COMPAT ) : '',
1410 'selected' => $selected,
1411 );
1412
1413 return $item;
1414
1415 }
1416
1417 /**
1418 * {@inheritdoc}
1419 */
1420 public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1421 $validate = parent::validate( $value, $name, $options, $fields, $pod, $id, $params );
1422
1423 $errors = array();
1424
1425 if ( is_array( $validate ) ) {
1426 $errors = $validate;
1427 }
1428
1429 if ( empty( self::$api ) ) {
1430 self::$api = pods_api();
1431 }
1432
1433 $simple_tableless_objects = $this->simple_objects();
1434
1435 $related_pick_limit = 0;
1436 $related_field = false;
1437 $related_pod = false;
1438 $current_related_ids = false;
1439
1440 // Bidirectional relationship requirement checks
1441 $related_object = pods_v( static::$type . '_object', $options, '' );
1442 // pod, post_type, taxonomy, etc..
1443 $related_val = pods_v( static::$type . '_val', $options, $related_object, null, true );
1444 // pod name, post type name, taxonomy name, etc..
1445 if ( empty( $related_val ) ) {
1446 $related_val = $related_object;
1447 }
1448
1449 $related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1450
1451 $options['id'] = (int) $options['id'];
1452
1453 if ( ! isset( self::$related_data[ $options['id'] ] ) || empty( self::$related_data[ $options['id'] ] ) ) {
1454 self::$related_data[ $options['id'] ] = array();
1455 }
1456
1457 if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1458 $related_pod = self::$api->load_pod(
1459 array(
1460 'name' => $related_val,
1461 'table_info' => false,
1462 ), false
1463 );
1464
1465 if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1466 $related_field = false;
1467
1468 // Ensure sister_id exists on related Pod.
1469 foreach ( $related_pod['fields'] as $related_pod_field ) {
1470 if ( 'pick' === $related_pod_field['type'] && $related_sister_id === $related_pod_field['id'] ) {
1471 $related_field = $related_pod_field;
1472
1473 break;
1474 }
1475 }
1476
1477 if ( ! empty( $related_field ) ) {
1478 $current_ids = self::$api->lookup_related_items( $fields[ $name ]['id'], $pod['id'], $id, $fields[ $name ], $pod );
1479
1480 self::$related_data[ $options['id'] ]['current_ids'] = $current_ids;
1481
1482 $value_ids = $value;
1483
1484 // Convert values from a comma-separated string into an array.
1485 if ( ! is_array( $value_ids ) ) {
1486 $value_ids = explode( ',', $value_ids );
1487 }
1488
1489 $value_ids = array_unique( array_filter( $value_ids ) );
1490
1491 // Get ids to remove.
1492 $remove_ids = array_diff( $current_ids, $value_ids );
1493
1494 $related_required = (boolean) pods_v( 'required', $related_field['options'], 0 );
1495 $related_pick_limit = (int) pods_v( static::$type . '_limit', $related_field['options'], 0 );
1496
1497 if ( 'single' === pods_v( static::$type . '_format_type', $related_field['options'] ) ) {
1498 $related_pick_limit = 1;
1499 }
1500
1501 // Validate Required fields.
1502 if ( $related_required && ! empty( $remove_ids ) ) {
1503 foreach ( $remove_ids as $related_id ) {
1504 $bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1505
1506 self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] = $bidirectional_ids;
1507
1508 if ( empty( $bidirectional_ids ) || ( in_array( (int) $id, $bidirectional_ids, true ) && 1 === count( $bidirectional_ids ) ) ) {
1509 // Translators: %1$s and %2$s stand for field labels.
1510 $errors[] = sprintf( esc_html__( 'The %1$s field is required and cannot be removed by the %2$s field', 'pods' ), $related_field['label'], $options['label'] );
1511 return $errors;
1512 }
1513 }
1514 }
1515 } else {
1516 $related_pod = false;
1517 }//end if
1518 } else {
1519 $related_pod = false;
1520 }//end if
1521 }//end if
1522
1523 if ( empty( self::$related_data[ $options['id'] ] ) ) {
1524 unset( self::$related_data[ $options['id'] ] );
1525 } else {
1526 self::$related_data[ $options['id'] ]['related_pod'] = $related_pod;
1527 self::$related_data[ $options['id'] ]['related_field'] = $related_field;
1528 self::$related_data[ $options['id'] ]['related_pick_limit'] = $related_pick_limit;
1529
1530 $pick_limit = (int) pods_v( static::$type . '_limit', $options['options'], 0 );
1531
1532 if ( 'single' === pods_v( static::$type . '_format_type', $options['options'] ) ) {
1533 $pick_limit = 1;
1534 }
1535
1536 $related_field['id'] = (int) $related_field['id'];
1537
1538 if ( ! isset( self::$related_data[ $related_field['id'] ] ) || empty( self::$related_data[ $related_field['id'] ] ) ) {
1539 self::$related_data[ $related_field['id'] ] = array(
1540 'related_pod' => $pod,
1541 'related_field' => $options,
1542 'related_pick_limit' => $pick_limit,
1543 );
1544 }
1545 }//end if
1546
1547 if ( ! empty( $errors ) ) {
1548 return $errors;
1549 }
1550
1551 return $validate;
1552
1553 }
1554
1555 /**
1556 * {@inheritdoc}
1557 */
1558 public function save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
1559
1560 if ( empty( self::$api ) ) {
1561 self::$api = pods_api();
1562 }
1563
1564 $options['id'] = (int) $options['id'];
1565
1566 if ( ! isset( self::$related_data[ $options['id'] ] ) ) {
1567 return;
1568 }
1569
1570 $related_pod = self::$related_data[ $options['id'] ]['related_pod'];
1571 $related_field = self::$related_data[ $options['id'] ]['related_field'];
1572 $related_pick_limit = self::$related_data[ $options['id'] ]['related_pick_limit'];
1573
1574 // Bidirectional relationship updates.
1575 if ( ! empty( $related_field ) ) {
1576 // Don't use no conflict mode unless this isn't the current pod type.
1577 $no_conflict = true;
1578
1579 if ( $related_pod['type'] !== $pod['type'] ) {
1580 $no_conflict = pods_no_conflict_check( $related_pod['type'] );
1581 }
1582
1583 if ( ! $no_conflict ) {
1584 pods_no_conflict_on( $related_pod['type'] );
1585 }
1586
1587 $value = array_filter( $value );
1588
1589 foreach ( $value as $related_id ) {
1590 if ( isset( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) && ! empty( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) ) {
1591 $bidirectional_ids = self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ];
1592 } else {
1593 $bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1594 }
1595
1596 $bidirectional_ids = array_filter( $bidirectional_ids );
1597
1598 if ( empty( $bidirectional_ids ) ) {
1599 $bidirectional_ids = array();
1600 }
1601
1602 $remove_ids = array();
1603
1604 if ( 0 < $related_pick_limit && ! empty( $bidirectional_ids ) && ! in_array( $id, $bidirectional_ids, true ) ) {
1605 $total_bidirectional_ids = count( $bidirectional_ids );
1606
1607 while ( $related_pick_limit <= $total_bidirectional_ids ) {
1608 $remove_ids[] = (int) array_pop( $bidirectional_ids );
1609
1610 $total_bidirectional_ids = count( $bidirectional_ids );
1611 }
1612 }
1613
1614 // Remove this item from related items no longer related to.
1615 $remove_ids = array_unique( array_filter( $remove_ids ) );
1616
1617 if ( ! in_array( $id, $bidirectional_ids, true ) ) {
1618 // Add to related items.
1619 $bidirectional_ids[] = $id;
1620 } elseif ( empty( $remove_ids ) ) {
1621 // Nothing to change.
1622 continue;
1623 }
1624
1625 self::$api->save_relationships( $related_id, $bidirectional_ids, $related_pod, $related_field );
1626
1627 if ( ! empty( $remove_ids ) ) {
1628 self::$api->delete_relationships( $remove_ids, $related_id, $pod, $options );
1629 }
1630 }//end foreach
1631
1632 if ( ! $no_conflict ) {
1633 pods_no_conflict_off( $related_pod['type'] );
1634 }
1635 }//end if
1636
1637 }
1638
1639 /**
1640 * Delete the value from the DB
1641 *
1642 * @param int|null $id Item ID.
1643 * @param string|null $name Field name.
1644 * @param array|null $options Field options.
1645 * @param array|null $pod Pod options.
1646 *
1647 * @since 2.3.0
1648 */
1649 public function delete( $id = null, $name = null, $options = null, $pod = null ) {
1650
1651 if ( empty( self::$api ) ) {
1652 self::$api = pods_api();
1653 }
1654
1655 $simple_tableless_objects = $this->simple_objects();
1656
1657 // Bidirectional relationship requirement checks.
1658 $related_object = pods_v( static::$type . '_object', $options, '' );
1659 // pod, post_type, taxonomy, etc..
1660 $related_val = pods_v( static::$type . '_val', $options, $related_object, true );
1661 // pod name, post type name, taxonomy name, etc..
1662 $related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1663
1664 if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1665 $related_pod = self::$api->load_pod(
1666 array(
1667 'name' => $related_val,
1668 'table_info' => false,
1669 ), false
1670 );
1671
1672 if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1673 $related_field = false;
1674
1675 // Ensure sister_id exists on related Pod.
1676 foreach ( $related_pod['fields'] as $related_pod_field ) {
1677 if ( 'pick' === $related_pod_field['type'] && (int) $related_sister_id === (int) $related_pod_field['id'] ) {
1678 $related_field = $related_pod_field;
1679
1680 break;
1681 }
1682 }
1683
1684 if ( ! empty( $related_field ) ) {
1685 $values = self::$api->lookup_related_items( $options['id'], $pod['id'], $id, $options, $pod );
1686
1687 if ( ! empty( $values ) ) {
1688 $no_conflict = pods_no_conflict_check( $related_pod['type'] );
1689
1690 if ( ! $no_conflict ) {
1691 pods_no_conflict_on( $related_pod['type'] );
1692 }
1693
1694 self::$api->delete_relationships( $values, $id, $related_pod, $related_field );
1695
1696 if ( ! $no_conflict ) {
1697 pods_no_conflict_off( $related_pod['type'] );
1698 }
1699 }
1700 }
1701 }//end if
1702 }//end if
1703
1704 }
1705
1706 /**
1707 * {@inheritdoc}
1708 */
1709 public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
1710
1711 $value = $this->simple_value( $name, $value, $options, $pod, $id );
1712
1713 return $this->display( $value, $name, $options, $pod, $id );
1714
1715 }
1716
1717 /**
1718 * {@inheritdoc}
1719 */
1720 public function data( $name, $value = null, $options = null, $pod = null, $id = null, $in_form = true ) {
1721
1722 if ( isset( $options['options'] ) ) {
1723 $options = array_merge( $options, $options['options'] );
1724
1725 unset( $options['options'] );
1726 }
1727
1728 $data = pods_v( 'data', $options, null, true );
1729
1730 $object_params = array(
1731 // The name of the field.
1732 'name' => $name,
1733 // The value of the field.
1734 'value' => $value,
1735 // Field options.
1736 'options' => $options,
1737 // Pod data.
1738 'pod' => $pod,
1739 // Item ID.
1740 'id' => $id,
1741 // Data context.
1742 'context' => 'data',
1743 );
1744
1745 if ( null !== $data ) {
1746 $data = (array) $data;
1747 } else {
1748 $data = $this->get_object_data( $object_params );
1749 }
1750
1751 if ( 'single' === pods_v( static::$type . '_format_type', $options, 'single' ) && 'dropdown' === pods_v( static::$type . '_format_single', $options, 'dropdown' ) ) {
1752 $data = array( '' => pods_v( static::$type . '_select_text', $options, __( '-- Select One --', 'pods' ), true ) ) + $data;
1753 }
1754
1755 $data = apply_filters( 'pods_field_pick_data', $data, $name, $value, $options, $pod, $id );
1756
1757 return $data;
1758
1759 }
1760
1761 /**
1762 * Convert a simple value to the correct value
1763 *
1764 * @param string $name The name of the field.
1765 * @param string|array|null $value The value of the field.
1766 * @param array|null $options Field options.
1767 * @param array|null $pod Pod data.
1768 * @param int|null $id Item ID.
1769 * @param boolean $raw Whether to return the raw list of keys (true) or convert to key=>value (false).
1770 *
1771 * @return mixed Corrected value
1772 */
1773 public function simple_value( $name, $value = null, $options = null, $pod = null, $id = null, $raw = false ) {
1774
1775 if ( in_array( pods_v( static::$type . '_object', $options ), self::simple_objects(), true ) ) {
1776 if ( isset( $options['options'] ) ) {
1777 $options = array_merge( $options, $options['options'] );
1778
1779 unset( $options['options'] );
1780 }
1781
1782 if ( ! is_array( $value ) && 0 < strlen( $value ) ) {
1783 $simple = @json_decode( $value, true );
1784
1785 if ( is_array( $simple ) ) {
1786 $value = $simple;
1787 }
1788 }
1789
1790 $data = pods_v( 'data', $options, null, true );
1791
1792 $object_params = array(
1793 // The name of the field.
1794 'name' => $name,
1795 // The value of the field.
1796 'value' => $value,
1797 // Field options.
1798 'options' => $options,
1799 // Pod data.
1800 'pod' => $pod,
1801 // Item ID.
1802 'id' => $id,
1803 // Data context.
1804 'context' => 'simple_value',
1805 );
1806
1807 if ( null === $data ) {
1808 $data = $this->get_object_data( $object_params );
1809 }
1810
1811 $data = (array) $data;
1812
1813 $key = 0;
1814
1815 if ( is_array( $value ) ) {
1816 if ( ! empty( $data ) ) {
1817 $val = array();
1818
1819 foreach ( $value as $k => $v ) {
1820 if ( isset( $data[ $v ] ) ) {
1821 if ( false === $raw ) {
1822 $k = $v;
1823 $v = $data[ $v ];
1824 }
1825
1826 $val[ $k ] = $v;
1827 }
1828 }
1829
1830 $value = $val;
1831 }
1832 } elseif ( isset( $data[ $value ] ) && false === $raw ) {
1833 $key = $value;
1834 $value = $data[ $value ];
1835 }//end if
1836
1837 $single_multi = pods_v( static::$type . '_format_type', $options, 'single' );
1838
1839 if ( 'multi' === $single_multi ) {
1840 $limit = (int) pods_v( static::$type . '_limit', $options, 0 );
1841 } else {
1842 $limit = 1;
1843 }
1844
1845 if ( is_array( $value ) && 0 < $limit ) {
1846 if ( 1 === $limit ) {
1847 $value = current( $value );
1848 } else {
1849 $value = array_slice( $value, 0, $limit, true );
1850 }
1851 } elseif ( ! is_array( $value ) && null !== $value && 0 < strlen( $value ) ) {
1852 if ( 1 !== $limit || ( true === $raw && 'multi' === $single_multi ) ) {
1853 $value = array(
1854 $key => $value,
1855 );
1856 }
1857 }
1858 }//end if
1859
1860 return $value;
1861
1862 }
1863
1864 /**
1865 * Get the label from a pick value.
1866 *
1867 * @param string $name The name of the field.
1868 * @param string|array|null $value The value of the field.
1869 * @param array|null $options Field options.
1870 * @param array|null $pod Pod data.
1871 * @param int|null $id Item ID.
1872 *
1873 * @return string
1874 *
1875 * @since 2.2.0
1876 */
1877 public function value_to_label( $name, $value = null, $options = null, $pod = null, $id = null ) {
1878
1879 if ( isset( $options['options'] ) ) {
1880 $options = array_merge( $options, $options['options'] );
1881
1882 unset( $options['options'] );
1883 }
1884
1885 $data = pods_v( 'data', $options, null, true );
1886
1887 $object_params = array(
1888 // The name of the field.
1889 'name' => $name,
1890 // The value of the field.
1891 'value' => $value,
1892 // Field options.
1893 'options' => $options,
1894 // Pod data.
1895 'pod' => $pod,
1896 // Item ID.
1897 'id' => $id,
1898 // Data context.
1899 'context' => 'value_to_label',
1900 );
1901
1902 if ( null !== $data ) {
1903 $data = (array) $data;
1904 } else {
1905 $data = $this->get_object_data( $object_params );
1906 }
1907
1908 $labels = array();
1909
1910 foreach ( $data as $v => $l ) {
1911 if ( ! in_array( (string) $l, $labels, true ) && ( (string) $value === (string) $v || ( is_array( $value ) && in_array( (string) $v, $value, true ) ) ) ) {
1912 $labels[] = (string) $l;
1913 }
1914 }
1915
1916 $labels = apply_filters( 'pods_field_pick_value_to_label', $labels, $name, $value, $options, $pod, $id );
1917
1918 $labels = pods_serial_comma( $labels );
1919
1920 return $labels;
1921
1922 }
1923
1924 /**
1925 * Get available items from a relationship field.
1926 *
1927 * @param array|string $field Field array or field name.
1928 * @param array $options Field options array overrides.
1929 * @param array $object_params Additional get_object_data options.
1930 *
1931 * @return array An array of available items from a relationship field
1932 */
1933 public function get_field_data( $field, $options = array(), $object_params = array() ) {
1934
1935 // Handle field array overrides.
1936 if ( is_array( $field ) ) {
1937 $options = array_merge( $field, $options );
1938 }
1939
1940 // Get field name from array.
1941 $field = pods_v( 'name', $options, $field, true );
1942
1943 // Field name or options not set.
1944 if ( empty( $field ) || empty( $options ) ) {
1945 return array();
1946 }
1947
1948 // Options normalization.
1949 $options = array_merge( $options, pods_v( 'options', $options, array(), true ) );
1950
1951 // Setup object params.
1952 $object_params = array_merge(
1953 array(
1954 // The name of the field.
1955 'name' => $field,
1956 // Field options.
1957 'options' => $options,
1958 ), $object_params
1959 );
1960
1961 // Get data override.
1962 $data = pods_v( 'data', $options, null, true );
1963
1964 if ( null !== $data ) {
1965 // Return data override.
1966 $data = (array) $data;
1967 } else {
1968 // Get object data.
1969 $data = $this->get_object_data( $object_params );
1970 }
1971
1972 return $data;
1973
1974 }
1975
1976 /**
1977 * Get data from relationship objects.
1978 *
1979 * @param array $object_params Object data parameters.
1980 *
1981 * @return array|bool Object data
1982 */
1983 public function get_object_data( $object_params = null ) {
1984
1985 /**
1986 * @var $wpdb wpdb
1987 */
1988 global $wpdb;
1989
1990 $object_params = array_merge(
1991 array(
1992 // The name of the field.
1993 'name' => '',
1994 // The value of the field.
1995 'value' => '',
1996 // Field options.
1997 'options' => array(),
1998 // Pod data.
1999 'pod' => '',
2000 // Item ID.
2001 'id' => '',
2002 // Data context.
2003 'context' => '',
2004 // Data parameters.
2005 'data_params' => array(
2006 // Query being searched.
2007 'query' => '',
2008 ),
2009 // Page number of results to get.
2010 'page' => 1,
2011 // How many data items to limit to (autocomplete defaults to 30, set to -1 or 1+ to override).
2012 'limit' => 0,
2013 ), $object_params
2014 );
2015
2016 /**
2017 * Overwrite parameters used by PodsField_Pick::get_object_data.
2018 *
2019 * @since 2.7.21
2020 *
2021 * @param array $object_params {
2022 * Get object parameters
2023 *
2024 * @type string $name Field name.
2025 * @type mixed $value Current value.
2026 * @type array $options Field options.
2027 * @type array $pod Pod data.
2028 * @type int|string $id Current item ID.
2029 * @type string $context Data context.
2030 * @type array $data_params Data parameters.
2031 * @type int $page Page number of results to get.
2032 * @type int $limit How many data items to limit to (autocomplete defaults to 30, set to -1 or 1+ to override).
2033 * }
2034 */
2035 $object_params = apply_filters( 'pods_field_pick_object_data_params', $object_params );
2036
2037 $object_params['options'] = (array) $object_params['options'];
2038 $object_params['data_params'] = (array) $object_params['data_params'];
2039
2040 $name = $object_params['name'];
2041 $value = $object_params['value'];
2042 $options = $object_params['options'];
2043 $pod = $object_params['pod'];
2044 $id = $object_params['id'];
2045 $context = $object_params['context'];
2046 $data_params = $object_params['data_params'];
2047 $page = min( 1, (int) $object_params['page'] );
2048 $limit = (int) $object_params['limit'];
2049 $autocomplete = false;
2050
2051 if ( isset( $options['options'] ) ) {
2052 $options = array_merge( $options, $options['options'] );
2053
2054 unset( $options['options'] );
2055 }
2056
2057 $data = apply_filters( 'pods_field_pick_object_data', null, $name, $value, $options, $pod, $id, $object_params );
2058 $items = array();
2059
2060 if ( ! isset( $options[ static::$type . '_object' ] ) ) {
2061 $data = pods_v( 'data', $options, array(), true );
2062 }
2063
2064 $simple = false;
2065
2066 if ( null === $data ) {
2067 $data = array();
2068
2069 if ( 'custom-simple' === $options[ static::$type . '_object' ] ) {
2070 $custom = pods_v( static::$type . '_custom', $options, '' );
2071
2072 $custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $name, $value, $options, $pod, $id, $object_params );
2073
2074 if ( ! empty( $custom ) ) {
2075 if ( ! is_array( $custom ) ) {
2076 $data = array();
2077
2078 $custom = explode( "\n", trim( $custom ) );
2079
2080 foreach ( $custom as $custom_value ) {
2081 $custom_label = explode( '|', $custom_value );
2082
2083 if ( empty( $custom_label ) ) {
2084 continue;
2085 }
2086
2087 if ( 1 === count( $custom_label ) ) {
2088 $custom_label = $custom_value;
2089 } else {
2090 $custom_value = $custom_label[0];
2091 $custom_label = $custom_label[1];
2092 }
2093
2094 $custom_value = trim( (string) $custom_value );
2095 $custom_label = trim( (string) $custom_label );
2096
2097 $data[ $custom_value ] = $custom_label;
2098 }
2099 } else {
2100 $data = $custom;
2101 }//end if
2102
2103 $simple = true;
2104 }//end if
2105 } elseif ( isset( self::$related_objects[ $options[ static::$type . '_object' ] ] ) && isset( self::$related_objects[ $options[ static::$type . '_object' ] ]['data'] ) && ! empty( self::$related_objects[ $options[ static::$type . '_object' ] ]['data'] ) ) {
2106 $data = self::$related_objects[ $options[ static::$type . '_object' ] ]['data'];
2107
2108 $simple = true;
2109 } elseif ( isset( self::$related_objects[ $options[ static::$type . '_object' ] ] ) && isset( self::$related_objects[ $options[ static::$type . '_object' ] ]['data_callback'] ) && is_callable( self::$related_objects[ $options[ static::$type . '_object' ] ]['data_callback'] ) ) {
2110 $data = call_user_func_array(
2111 self::$related_objects[ $options[ static::$type . '_object' ] ]['data_callback'], array(
2112 $name,
2113 $value,
2114 $options,
2115 $pod,
2116 $id,
2117 )
2118 );
2119
2120 if ( 'data' === $context ) {
2121 self::$field_data = array(
2122 'field' => $name,
2123 'id' => $options['id'],
2124 'autocomplete' => false,
2125 );
2126 }
2127
2128 $simple = true;
2129
2130 // Cache data from callback.
2131 if ( ! empty( $data ) ) {
2132 self::$related_objects[ $options[ static::$type . '_object' ] ]['data'] = $data;
2133 }
2134 } elseif ( 'simple_value' !== $context ) {
2135 $pick_val = pods_v( static::$type . '_val', $options );
2136
2137 if ( 'table' === pods_v( static::$type . '_object', $options ) ) {
2138 $pick_val = pods_v( static::$type . '_table', $options, $pick_val, true );
2139 }
2140
2141 if ( '__current__' === $pick_val ) {
2142 if ( is_object( $pod ) ) {
2143 $pick_val = $pod->pod;
2144 } elseif ( is_array( $pod ) ) {
2145 $pick_val = $pod['name'];
2146 } elseif ( 0 < strlen( $pod ) ) {
2147 $pick_val = $pod;
2148 }
2149 }
2150
2151 $options['table_info'] = pods_api()->get_table_info( pods_v( static::$type . '_object', $options ), $pick_val, null, null, $object_params );
2152
2153 $search_data = pods_data();
2154 $search_data->table( $options['table_info'] );
2155
2156 $default_field_index = $search_data->field_index;
2157
2158 if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) && isset( $options['table_info']['pod']['name'] ) ) {
2159 $search_data->pod = $options['table_info']['pod']['name'];
2160 $search_data->fields = $options['table_info']['pod']['fields'];
2161 }
2162
2163 $params = array(
2164 'select' => "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`",
2165 'table' => $search_data->table,
2166 'where' => pods_v( static::$type . '_where', $options, null, true ),
2167 'orderby' => pods_v( static::$type . '_orderby', $options, null, true ),
2168 'groupby' => pods_v( static::$type . '_groupby', $options, null, true ),
2169 'pagination' => false,
2170 'search' => false,
2171 );
2172
2173 $access_args = array();
2174 $access_params = (object) array(
2175 'from' => 'pick/get_object_data',
2176 );
2177
2178 if ( ! empty( $pick_object ) && ! empty( $pick_val ) ) {
2179 $access_args['object_type'] = $pick_object;
2180 $access_args['object_name'] = $pick_val;
2181 }
2182
2183 // Determine whether pick_where fragment is allowed.
2184 if ( $params['where'] && ! pods_access_sql_fragment_is_allowed( $params['where'], 'WHERE', $access_args, $access_params ) ) {
2185 /*
2186 * Don't default to empty, default to a false check so it doesn't return unexpected data that wasn't intended.
2187 *
2188 * Returning no results is better than more results than intended for security purposes.
2189 */
2190 $params['where'] = '0=1';
2191 }
2192
2193 // Determine whether pick_orderby fragment is allowed.
2194 if ( $params['orderby'] && ! pods_access_sql_fragment_is_allowed( $params['orderby'], 'ORDER BY', $access_args, $access_params ) ) {
2195 $params['orderby'] = null;
2196 }
2197
2198 // Determine whether pick_having fragment is allowed.
2199 if ( $params['having'] && ! pods_access_sql_fragment_is_allowed( $params['having'], 'HAVING', $access_args, $access_params ) ) {
2200 /*
2201 * Don't default to empty, default to a false check so it doesn't return unexpected data that wasn't intended.
2202 *
2203 * Returning no results is better than more results than intended for security purposes.
2204 */
2205 $params['having'] = '0=1';
2206 }
2207
2208 // Determine whether pick_orderby fragment is allowed.
2209 if ( $params['groupby'] && ! pods_access_sql_fragment_is_allowed( $params['groupby'], 'GROUP BY', $access_args, $access_params ) ) {
2210 $params['groupby'] = null;
2211 }
2212
2213 if ( null === $params['where'] ) {
2214 $params['where'] = (array) $options['table_info']['where_default'];
2215 }
2216
2217 if ( in_array( $options[ static::$type . '_object' ], array( 'site', 'network' ), true ) ) {
2218 $params['select'] .= ', `t`.`path`';
2219 }
2220
2221 if ( ! empty( $params['where'] ) && (array) $options['table_info']['where_default'] !== $params['where'] ) {
2222 $params['where'] = pods_evaluate_tags( $params['where'], true );
2223 }
2224
2225 if ( empty( $params['where'] ) || ( ! is_array( $params['where'] ) && '' === trim( $params['where'] ) ) ) {
2226 $params['where'] = array();
2227 } elseif ( ! is_array( $params['where'] ) ) {
2228 $params['where'] = (array) $params['where'];
2229 }
2230
2231 if ( 'value_to_label' === $context ) {
2232 $params['where'][] = "`t`.`{$search_data->field_id}` = " . number_format( $value, 0, '', '' );
2233 }
2234
2235 $display = trim( pods_v( static::$type . '_display', $options ), ' {@}' );
2236
2237 if ( 0 < strlen( $display ) ) {
2238 if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) ) {
2239 if ( isset( $options['table_info']['pod']['object_fields'] ) && isset( $options['table_info']['pod']['object_fields'][ $display ] ) ) {
2240 $search_data->field_index = $display;
2241
2242 $params['select'] .= ", `t`.`{$search_data->field_index}`";
2243 } else {
2244 $search_data->field_index = sanitize_key( $display );
2245
2246 if ( isset( $options['table_info']['pod']['fields'][ $display ] ) && 'table' === $options['table_info']['pod']['storage'] && ! in_array(
2247 $options['table_info']['pod']['type'], array(
2248 'pod',
2249 'table',
2250 ), true
2251 )
2252 ) {
2253 $params['select'] .= ", `d`.`{$search_data->field_index}`";
2254 } elseif ( 'meta' === $options['table_info']['pod']['storage'] ) {
2255 $params['select'] .= ", `{$search_data->field_index}`.`meta_value` AS {$search_data->field_index}";
2256 } else {
2257 $params['select'] .= ", `t`.`{$search_data->field_index}`";
2258 }
2259 }//end if
2260 } elseif ( isset( $options['table_info']['object_fields'] ) && isset( $options['table_info']['object_fields'][ $display ] ) ) {
2261 $search_data->field_index = $display;
2262
2263 $params['select'] .= ", `t`.`{$search_data->field_index}`";
2264 }//end if
2265 }//end if
2266
2267 $autocomplete = $this->is_autocomplete( $options );
2268
2269 $hierarchy = false;
2270
2271 if ( 'data' === $context && ! $autocomplete ) {
2272 if ( 'single' === pods_v( static::$type . '_format_type', $options, 'single' ) && in_array(
2273 pods_v( static::$type . '_format_single', $options, 'dropdown' ), array(
2274 'dropdown',
2275 'radio',
2276 ), true
2277 )
2278 ) {
2279 $hierarchy = true;
2280 } elseif ( 'multi' === pods_v( static::$type . '_format_type', $options, 'single' ) && in_array(
2281 pods_v( static::$type . '_format_multi', $options, 'checkbox' ), array(
2282 'multiselect',
2283 'checkbox',
2284 ), true
2285 ) ) {
2286 $hierarchy = true;
2287 }
2288 }
2289
2290 if ( $hierarchy && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
2291 $params['select'] .= ', ' . $options['table_info']['field_parent_select'];
2292 }
2293
2294 if ( $autocomplete ) {
2295 if ( 0 === $limit ) {
2296 $limit = 30;
2297 }
2298
2299 $params['limit'] = apply_filters( 'pods_form_ui_field_pick_autocomplete_limit', $limit, $name, $value, $options, $pod, $id, $object_params );
2300
2301 if ( is_array( $value ) && $params['limit'] < count( $value ) ) {
2302 $params['limit'] = count( $value );
2303 }
2304
2305 $params['page'] = $page;
2306
2307 if ( 'admin_ajax_relationship' === $context ) {
2308 $lookup_where = array(
2309 $search_data->field_index => "`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'",
2310 );
2311
2312 // @todo Hook into WPML for each table
2313 if ( $wpdb->users === $search_data->table ) {
2314 $lookup_where['display_name'] = "`t`.`display_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2315 $lookup_where['user_login'] = "`t`.`user_login` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2316 $lookup_where['user_email'] = "`t`.`user_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2317 } elseif ( $wpdb->posts === $search_data->table ) {
2318 $lookup_where['post_title'] = "`t`.`post_title` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2319 $lookup_where['post_name'] = "`t`.`post_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2320 $lookup_where['post_content'] = "`t`.`post_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2321 $lookup_where['post_excerpt'] = "`t`.`post_excerpt` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2322 } elseif ( $wpdb->terms === $search_data->table ) {
2323 $lookup_where['name'] = "`t`.`name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2324 $lookup_where['slug'] = "`t`.`slug` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2325 } elseif ( $wpdb->comments === $search_data->table ) {
2326 $lookup_where['comment_content'] = "`t`.`comment_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2327 $lookup_where['comment_author'] = "`t`.`comment_author` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2328 $lookup_where['comment_author_email'] = "`t`.`comment_author_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2329 }
2330
2331 $lookup_where = apply_filters( 'pods_form_ui_field_pick_autocomplete_lookup', $lookup_where, $data_params['query'], $name, $value, $options, $pod, $id, $object_params, $search_data );
2332
2333 if ( ! empty( $lookup_where ) ) {
2334 $params['where'][] = implode( ' OR ', $lookup_where );
2335 }
2336
2337 $orderby = array();
2338 $orderby[] = "(`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%' ) DESC";
2339
2340 $pick_orderby = pods_v( static::$type . '_orderby', $options, null, true );
2341
2342 if ( 0 < strlen( $pick_orderby ) ) {
2343 $orderby[] = $pick_orderby;
2344 }
2345
2346 $orderby[] = "`t`.`{$search_data->field_index}`";
2347 $orderby[] = "`t`.`{$search_data->field_id}`";
2348
2349 $params['orderby'] = $orderby;
2350 }//end if
2351 } elseif ( 0 < $limit ) {
2352 $params['limit'] = $limit;
2353 $params['page'] = $page;
2354 }//end if
2355
2356 $extra = '';
2357
2358 if ( $wpdb->posts === $search_data->table ) {
2359 $extra = ', `t`.`post_type`';
2360 } elseif ( $wpdb->terms === $search_data->table ) {
2361 $extra = ', `tt`.`taxonomy`';
2362 } elseif ( $wpdb->comments === $search_data->table ) {
2363 $extra = ', `t`.`comment_type`';
2364 }
2365
2366 if ( '' !== $extra && false === strpos( (string) $params['select'], $extra ) ) {
2367 $params['select'] .= ', ' . $extra;
2368 }
2369
2370 if ( 'user' === pods_v( static::$type . '_object', $options ) ) {
2371 $roles = pods_v( static::$type . '_user_role', $options );
2372
2373 if ( ! empty( $roles ) ) {
2374 $where = array();
2375
2376 foreach ( (array) $roles as $role ) {
2377 if ( empty( $role ) || ( pods_clean_name( $role ) !== $role && sanitize_title( $role ) !== $role ) ) {
2378 continue;
2379 }
2380
2381 $prefix = $wpdb->base_prefix;
2382
2383 if ( is_multisite() && ! is_main_site() ) {
2384 $prefix .= get_current_blog_id() . '_';
2385 }
2386
2387 $where[] = $prefix . 'capabilities.meta_value LIKE "%\"' . pods_sanitize_like( $role ) . '\"%"';
2388 }
2389
2390 if ( ! empty( $where ) ) {
2391 $params['where'][] = implode( ' OR ', $where );
2392 }
2393 }//end if
2394 }//end if
2395
2396 if ( empty( $params['where'] ) ) {
2397 $params['where'] = null;
2398 }
2399
2400 $params['from'] = 'pick/get_object_data';
2401
2402 $results = $search_data->select( $params );
2403
2404 if ( $autocomplete && $params['limit'] < $search_data->total_found() ) {
2405 if ( ! empty( $value ) ) {
2406 $ids = $value;
2407
2408 if ( is_array( $ids ) && isset( $ids[0] ) && is_array( $ids[0] ) ) {
2409 $ids = wp_list_pluck( $ids, $search_data->field_id );
2410 }
2411
2412 if ( $params['limit'] < count( (array) $ids ) ) {
2413 $params['limit'] = count( (array) $ids );
2414 }
2415
2416 if ( is_array( $ids ) ) {
2417 $ids = implode( ', ', $ids );
2418 }
2419
2420 if ( is_array( $params['where'] ) ) {
2421 $params['where'] = implode( ' AND ', $params['where'] );
2422 }
2423 if ( ! empty( $params['where'] ) ) {
2424 $params['where'] = '(' . $params['where'] . ') AND ';
2425 }
2426
2427 $params['where'] .= "`t`.`{$search_data->field_id}` IN ( {$ids} )";
2428
2429 $results = $search_data->select( $params );
2430 }//end if
2431 } else {
2432 $autocomplete = false;
2433 }//end if
2434
2435 if ( 'data' === $context ) {
2436 self::$field_data = array(
2437 'field' => $name,
2438 'id' => $options['id'],
2439 'autocomplete' => $autocomplete,
2440 );
2441 }
2442
2443 if ( $hierarchy && ! $autocomplete && ! empty( $results ) && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
2444 $select_args = array(
2445 'id' => $options['table_info']['field_id'],
2446 'index' => $options['table_info']['field_index'],
2447 'parent' => $options['table_info']['field_parent'],
2448 );
2449
2450 $results = pods_hierarchical_select( $results, $select_args );
2451 }
2452
2453 $ids = array();
2454
2455 if ( ! empty( $results ) ) {
2456 $display_filter = pods_v( 'display_filter', pods_v( 'options', pods_v( $search_data->field_index, $search_data->pod_data['object_fields'] ) ) );
2457
2458 foreach ( $results as $result ) {
2459 $result = get_object_vars( $result );
2460 $field_id = $search_data->field_id;
2461 $field_index = $search_data->field_index;
2462
2463 if ( ! isset( $result[ $field_index ] ) ) {
2464 $field_index = $default_field_index;
2465 }
2466 if ( ! isset( $result[ $field_id ], $result[ $field_index ] ) ) {
2467 continue;
2468 }
2469
2470 $result[ $field_index ] = trim( $result[ $field_index ] );
2471
2472 $object = '';
2473 $object_type = '';
2474
2475 if ( $wpdb->posts === $search_data->table && isset( $result['post_type'] ) ) {
2476 $object = $result['post_type'];
2477 $object_type = 'post_type';
2478 } elseif ( $wpdb->terms === $search_data->table && isset( $result['taxonomy'] ) ) {
2479 $object = $result['taxonomy'];
2480 $object_type = 'taxonomy';
2481 }
2482
2483 if ( 0 < strlen( $display_filter ) ) {
2484 $display_filter_args = pods_v( 'display_filter_args', pods_v( 'options', pods_v( $field_index, $search_data->pod_data['object_fields'] ) ) );
2485
2486 $filter_args = array(
2487 $display_filter,
2488 $result[ $field_index ],
2489 );
2490
2491 if ( ! empty( $display_filter_args ) ) {
2492 foreach ( (array) $display_filter_args as $display_filter_arg ) {
2493 if ( isset( $result[ $display_filter_arg ] ) ) {
2494 $filter_args[] = $result[ $display_filter_arg ];
2495 }
2496 }
2497 }
2498
2499 $result[ $field_index ] = call_user_func_array( 'apply_filters', $filter_args );
2500 }
2501
2502 if ( in_array( $options[ static::$type . '_object' ], array( 'site', 'network' ), true ) ) {
2503 $result[ $field_index ] = $result[ $field_index ] . $result['path'];
2504 } elseif ( '' === $result[ $field_index ] ) {
2505 $result[ $field_index ] = '(No Title)';
2506 }
2507
2508 if ( 'admin_ajax_relationship' === $context ) {
2509 $items[] = $this->build_dfv_field_item_data_recurse_item( $result[ $field_id ], $result[ $field_index ], (object) $object_params );
2510 } else {
2511 $data[ $result[ $field_id ] ] = $result[ $field_index ];
2512 }
2513
2514 $ids[] = $result[ $field_id ];
2515 }//end foreach
2516 }//end if
2517 }//end if
2518
2519 if ( $simple && 'admin_ajax_relationship' === $context ) {
2520 $found_data = array();
2521
2522 foreach ( $data as $k => $v ) {
2523 if ( false !== stripos( $v, $data_params['query'] ) || false !== stripos( $k, $data_params['query'] ) ) {
2524 $found_data[ $k ] = $v;
2525 }
2526 }
2527
2528 $data = $found_data;
2529 }
2530 }//end if
2531
2532 if ( 'admin_ajax_relationship' === $context ) {
2533 if ( empty( $items ) && ! empty( $data ) ) {
2534 foreach ( $data as $k => $v ) {
2535 $items[] = array(
2536 'id' => $k,
2537 'text' => $v,
2538 );
2539 }
2540 }
2541
2542 $data = $items;
2543 }
2544
2545 return $data;
2546
2547 }
2548
2549 /**
2550 * Check if field is autocomplete enabled.
2551 *
2552 * @param array $options Field options.
2553 *
2554 * @return bool
2555 *
2556 * @since 2.7.0
2557 */
2558 private function is_autocomplete( $options ) {
2559
2560 $autocomplete = false;
2561
2562 if ( 'single' === pods_v( static::$type . '_format_type', $options, 'single' ) ) {
2563 if ( in_array( pods_v( static::$type . '_format_single', $options, 'dropdown' ), array( 'autocomplete', 'list' ), true ) ) {
2564 $autocomplete = true;
2565 }
2566 } elseif ( 'multi' === pods_v( static::$type . '_format_type', $options, 'single' ) ) {
2567 if ( in_array( pods_v( static::$type . '_format_multi', $options, 'checkbox' ), array( 'autocomplete', 'list' ), true ) ) {
2568 $autocomplete = true;
2569 }
2570 }
2571
2572 return $autocomplete;
2573 }
2574
2575 /**
2576 * Check if a field type is a tableless text field type.
2577 *
2578 * @since 2.7.4
2579 *
2580 * @param string $type Field type.
2581 * @param array $options Field options.
2582 * @return bool True if the field type is a tableless text field type, false otherwise.
2583 */
2584 private function is_simple_tableless( $type, array $options ) {
2585 $field_object = pods_v( $type . '_object', $options );
2586
2587 return in_array( $field_object, PodsForm::simple_tableless_objects(), true );
2588 }
2589
2590 /**
2591 * Check if a field supports AJAX mode
2592 *
2593 * @param string $type Field type.
2594 * @param array $options Field options.
2595 *
2596 * @return bool
2597 * @since 2.7.4
2598 */
2599 private function can_ajax( $type, $options ) {
2600 return $this->is_autocomplete( $options ) && ! $this->is_simple_tableless( $type, $options );
2601 }
2602
2603
2604 /**
2605 * Handle autocomplete AJAX.
2606 *
2607 * @since 2.3.0
2608 */
2609 public function admin_ajax_relationship() {
2610
2611 pods_session_start();
2612
2613 // Sanitize input.
2614 // @codingStandardsIgnoreLine
2615 $params = pods_unslash( (array) $_POST );
2616
2617 foreach ( $params as $key => $value ) {
2618 if ( 'action' === $key ) {
2619 continue;
2620 }
2621
2622 unset( $params[ $key ] );
2623
2624 $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
2625 }
2626
2627 $params = (object) $params;
2628
2629 $uid = pods_session_id();
2630
2631 if ( is_user_logged_in() ) {
2632 $uid = 'user_' . get_current_user_id();
2633 }
2634
2635 $nonce_check = 'pods_relationship_' . (int) $params->pod . '_' . $uid . '_' . $params->uri . '_' . (int) $params->field;
2636
2637 if ( ! isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, $nonce_check ) ) {
2638 pods_error( __( 'Unauthorized request', 'pods' ), PodsInit::$admin );
2639 }
2640
2641 if ( empty( self::$api ) ) {
2642 self::$api = pods_api();
2643 }
2644
2645 $pod = self::$api->load_pod( array( 'id' => (int) $params->pod ) );
2646 $field = self::$api->load_field(
2647 array(
2648 'id' => (int) $params->field,
2649 'table_info' => true,
2650 )
2651 );
2652 $id = (int) $params->id;
2653
2654 $limit = 15;
2655
2656 if ( isset( $params->limit ) ) {
2657 $limit = (int) $params->limit;
2658 }
2659
2660 $page = 1;
2661
2662 if ( isset( $params->page ) ) {
2663 $page = (int) $params->page;
2664 }
2665
2666 if ( ! isset( $params->query ) || '' === trim( $params->query ) ) {
2667 pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
2668 } elseif ( empty( $pod ) || empty( $field ) || (int) $pod['id'] !== (int) $field['pod_id'] || ! isset( $pod['fields'][ $field['name'] ] ) ) {
2669 pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
2670 } elseif ( 'pick' !== $field['type'] || empty( $field['table_info'] ) ) {
2671 pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
2672 } elseif ( 'single' === pods_v( static::$type . '_format_type', $field ) && 'autocomplete' === pods_v( static::$type . '_format_single', $field ) ) {
2673 pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
2674 } elseif ( 'multi' === pods_v( static::$type . '_format_type', $field ) && 'autocomplete' === pods_v( static::$type . '_format_multi', $field ) ) {
2675 pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
2676 }
2677
2678 $object_params = array(
2679 // The name of the field.
2680 'name' => $field['name'],
2681 // The value of the field.
2682 'value' => null,
2683 // Field options.
2684 'options' => array_merge( $field, $field['options'] ),
2685 // Pod data.
2686 'pod' => $pod,
2687 // Item ID.
2688 'id' => $id,
2689 // Data context.
2690 'context' => 'admin_ajax_relationship',
2691 'data_params' => $params,
2692 'page' => $page,
2693 'limit' => $limit,
2694 );
2695
2696 $pick_data = apply_filters( 'pods_field_pick_data_ajax', null, $field['name'], null, $field, $pod, $id );
2697
2698 if ( null !== $pick_data ) {
2699 $items = $pick_data;
2700 } else {
2701 $items = $this->get_object_data( $object_params );
2702 }
2703
2704 if ( ! empty( $items ) && isset( $items[0] ) && ! is_array( $items[0] ) ) {
2705 $new_items = array();
2706
2707 foreach ( $items as $id => $text ) {
2708 $new_items[] = array(
2709 'id' => $id,
2710 'text' => $text,
2711 'image' => '',
2712 );
2713 }
2714
2715 $items = $new_items;
2716 }
2717
2718 $items = apply_filters( 'pods_field_pick_data_ajax_items', $items, $field['name'], null, $field, $pod, $id );
2719
2720 $items = array(
2721 'results' => $items,
2722 );
2723
2724 wp_send_json( $items );
2725
2726 die();
2727 // KBAI!
2728 }
2729
2730 /**
2731 * Data callback for Post Stati.
2732 *
2733 * @param string|null $name The name of the field.
2734 * @param string|array|null $value The value of the field.
2735 * @param array|null $options Field options.
2736 * @param array|null $pod Pod data.
2737 * @param int|null $id Item ID.
2738 *
2739 * @return array
2740 *
2741 * @since 2.3.0
2742 */
2743 public function data_post_stati( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2744
2745 $data = array();
2746
2747 $post_stati = get_post_stati( array(), 'objects' );
2748
2749 foreach ( $post_stati as $post_status ) {
2750 $data[ $post_status->name ] = $post_status->label;
2751 }
2752
2753 return apply_filters( 'pods_form_ui_field_pick_data_post_stati', $data, $name, $value, $options, $pod, $id );
2754
2755 }
2756
2757 /**
2758 * Data callback for User Roles.
2759 *
2760 * @param string|null $name The name of the field.
2761 * @param string|array|null $value The value of the field.
2762 * @param array|null $options Field options.
2763 * @param array|null $pod Pod data.
2764 * @param int|null $id Item ID.
2765 *
2766 * @return array
2767 *
2768 * @since 2.3.0
2769 */
2770 public function data_roles( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2771
2772 $data = array();
2773
2774 global $wp_roles;
2775
2776 foreach ( $wp_roles->role_objects as $key => $role ) {
2777 $data[ $key ] = $wp_roles->role_names[ $key ];
2778 }
2779
2780 return apply_filters( 'pods_form_ui_field_pick_data_roles', $data, $name, $value, $options, $pod, $id );
2781
2782 }
2783
2784 /**
2785 * Data callback for User Capabilities.
2786 *
2787 * @param string|null $name The name of the field.
2788 * @param string|array|null $value The value of the field.
2789 * @param array|null $options Field options.
2790 * @param array|null $pod Pod data.
2791 * @param int|null $id Item ID.
2792 *
2793 * @return array
2794 *
2795 * @since 2.3.0
2796 */
2797 public function data_capabilities( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2798
2799 $data = array();
2800
2801 global $wp_roles;
2802
2803 $default_caps = array(
2804 'activate_plugins',
2805 'add_users',
2806 'create_users',
2807 'delete_others_pages',
2808 'delete_others_posts',
2809 'delete_pages',
2810 'delete_plugins',
2811 'delete_posts',
2812 'delete_private_pages',
2813 'delete_private_posts',
2814 'delete_published_pages',
2815 'delete_published_posts',
2816 'delete_users',
2817 'edit_dashboard',
2818 'edit_files',
2819 'edit_others_pages',
2820 'edit_others_posts',
2821 'edit_pages',
2822 'edit_plugins',
2823 'edit_posts',
2824 'edit_private_pages',
2825 'edit_private_posts',
2826 'edit_published_pages',
2827 'edit_published_posts',
2828 'edit_theme_options',
2829 'edit_themes',
2830 'edit_users',
2831 'import',
2832 'install_plugins',
2833 'install_themes',
2834 'list_users',
2835 'manage_categories',
2836 'manage_links',
2837 'manage_options',
2838 'moderate_comments',
2839 'promote_users',
2840 'publish_pages',
2841 'publish_posts',
2842 'read',
2843 'read_private_pages',
2844 'read_private_posts',
2845 'remove_users',
2846 'switch_themes',
2847 'unfiltered_html',
2848 'unfiltered_upload',
2849 'update_core',
2850 'update_plugins',
2851 'update_themes',
2852 'upload_files',
2853 );
2854
2855 $role_caps = array();
2856
2857 foreach ( $wp_roles->role_objects as $key => $role ) {
2858 if ( is_array( $role->capabilities ) ) {
2859 foreach ( $role->capabilities as $cap => $grant ) {
2860 $role_caps[ $cap ] = $cap;
2861 }
2862 }
2863 }
2864
2865 $role_caps = array_unique( $role_caps );
2866
2867 $capabilities = array_merge( $default_caps, $role_caps );
2868
2869 // To support Members filters.
2870 $capabilities = apply_filters( 'members_get_capabilities', $capabilities );
2871
2872 $capabilities = apply_filters( 'pods_roles_get_capabilities', $capabilities );
2873
2874 sort( $capabilities );
2875
2876 $capabilities = array_unique( $capabilities );
2877
2878 global $wp_roles;
2879
2880 foreach ( $capabilities as $capability ) {
2881 $data[ $capability ] = $capability;
2882 }
2883
2884 return apply_filters( 'pods_form_ui_field_pick_data_capabilities', $data, $name, $value, $options, $pod, $id );
2885
2886 }
2887
2888 /**
2889 * Data callback for Image Sizes.
2890 *
2891 * @param string|null $name The name of the field.
2892 * @param string|array|null $value The value of the field.
2893 * @param array|null $options Field options.
2894 * @param array|null $pod Pod data.
2895 * @param int|null $id Item ID.
2896 *
2897 * @return array
2898 *
2899 * @since 2.3.0
2900 */
2901 public function data_image_sizes( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2902
2903 $data = array();
2904
2905 $image_sizes = get_intermediate_image_sizes();
2906
2907 foreach ( $image_sizes as $image_size ) {
2908 $data[ $image_size ] = ucwords( str_replace( '-', ' ', $image_size ) );
2909 }
2910
2911 return apply_filters( 'pods_form_ui_field_pick_data_image_sizes', $data, $name, $value, $options, $pod, $id );
2912
2913 }
2914
2915 /**
2916 * Data callback for Countries.
2917 *
2918 * @param string|null $name The name of the field.
2919 * @param string|array|null $value The value of the field.
2920 * @param array|null $options Field options.
2921 * @param array|null $pod Pod data.
2922 * @param int|null $id Item ID.
2923 *
2924 * @return array
2925 *
2926 * @since 2.3.0
2927 */
2928 public function data_countries( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2929
2930 $data = array(
2931 'AF' => __( 'Afghanistan' ),
2932 'AL' => __( 'Albania' ),
2933 'DZ' => __( 'Algeria' ),
2934 'AS' => __( 'American Samoa' ),
2935 'AD' => __( 'Andorra' ),
2936 'AO' => __( 'Angola' ),
2937 'AI' => __( 'Anguilla' ),
2938 'AQ' => __( 'Antarctica' ),
2939 'AG' => __( 'Antigua and Barbuda' ),
2940 'AR' => __( 'Argentina' ),
2941 'AM' => __( 'Armenia' ),
2942 'AW' => __( 'Aruba' ),
2943 'AU' => __( 'Australia' ),
2944 'AT' => __( 'Austria' ),
2945 'AZ' => __( 'Azerbaijan' ),
2946 'BS' => __( 'Bahamas' ),
2947 'BH' => __( 'Bahrain' ),
2948 'BD' => __( 'Bangladesh' ),
2949 'BB' => __( 'Barbados' ),
2950 'BY' => __( 'Belarus' ),
2951 'BE' => __( 'Belgium' ),
2952 'BZ' => __( 'Belize' ),
2953 'BJ' => __( 'Benin' ),
2954 'BM' => __( 'Bermuda' ),
2955 'BT' => __( 'Bhutan' ),
2956 'BO' => __( 'Bolivia' ),
2957 'BA' => __( 'Bosnia and Herzegovina' ),
2958 'BW' => __( 'Botswana' ),
2959 'BV' => __( 'Bouvet Island' ),
2960 'BR' => __( 'Brazil' ),
2961 'BQ' => __( 'British Antarctic Territory' ),
2962 'IO' => __( 'British Indian Ocean Territory' ),
2963 'VG' => __( 'British Virgin Islands' ),
2964 'BN' => __( 'Brunei' ),
2965 'BG' => __( 'Bulgaria' ),
2966 'BF' => __( 'Burkina Faso' ),
2967 'BI' => __( 'Burundi' ),
2968 'KH' => __( 'Cambodia' ),
2969 'CM' => __( 'Cameroon' ),
2970 'CA' => __( 'Canada' ),
2971 'CT' => __( 'Canton and Enderbury Islands' ),
2972 'CV' => __( 'Cape Verde' ),
2973 'KY' => __( 'Cayman Islands' ),
2974 'CF' => __( 'Central African Republic' ),
2975 'TD' => __( 'Chad' ),
2976 'CL' => __( 'Chile' ),
2977 'CN' => __( 'China' ),
2978 'CX' => __( 'Christmas Island' ),
2979 'CC' => __( 'Cocos [Keeling] Islands' ),
2980 'CO' => __( 'Colombia' ),
2981 'KM' => __( 'Comoros' ),
2982 'CG' => __( 'Congo - Brazzaville' ),
2983 'CD' => __( 'Congo - Kinshasa' ),
2984 'CK' => __( 'Cook Islands' ),
2985 'CR' => __( 'Costa Rica' ),
2986 'HR' => __( 'Croatia' ),
2987 'CU' => __( 'Cuba' ),
2988 'CY' => __( 'Cyprus' ),
2989 'CZ' => __( 'Czech Republic' ),
2990 'CI' => __( 'Côte d’Ivoire' ),
2991 'DK' => __( 'Denmark' ),
2992 'DJ' => __( 'Djibouti' ),
2993 'DM' => __( 'Dominica' ),
2994 'DO' => __( 'Dominican Republic' ),
2995 'NQ' => __( 'Dronning Maud Land' ),
2996 'DD' => __( 'East Germany' ),
2997 'EC' => __( 'Ecuador' ),
2998 'EG' => __( 'Egypt' ),
2999 'SV' => __( 'El Salvador' ),
3000 'GQ' => __( 'Equatorial Guinea' ),
3001 'ER' => __( 'Eritrea' ),
3002 'EE' => __( 'Estonia' ),
3003 'ET' => __( 'Ethiopia' ),
3004 'FK' => __( 'Falkland Islands' ),
3005 'FO' => __( 'Faroe Islands' ),
3006 'FJ' => __( 'Fiji' ),
3007 'FI' => __( 'Finland' ),
3008 'FR' => __( 'France' ),
3009 'GF' => __( 'French Guiana' ),
3010 'PF' => __( 'French Polynesia' ),
3011 'TF' => __( 'French Southern Territories' ),
3012 'FQ' => __( 'French Southern and Antarctic Territories' ),
3013 'GA' => __( 'Gabon' ),
3014 'GM' => __( 'Gambia' ),
3015 'GE' => __( 'Georgia' ),
3016 'DE' => __( 'Germany' ),
3017 'GH' => __( 'Ghana' ),
3018 'GI' => __( 'Gibraltar' ),
3019 'GR' => __( 'Greece' ),
3020 'GL' => __( 'Greenland' ),
3021 'GD' => __( 'Grenada' ),
3022 'GP' => __( 'Guadeloupe' ),
3023 'GU' => __( 'Guam' ),
3024 'GT' => __( 'Guatemala' ),
3025 'GG' => __( 'Guernsey' ),
3026 'GN' => __( 'Guinea' ),
3027 'GW' => __( 'Guinea-Bissau' ),
3028 'GY' => __( 'Guyana' ),
3029 'HT' => __( 'Haiti' ),
3030 'HM' => __( 'Heard Island and McDonald Islands' ),
3031 'HN' => __( 'Honduras' ),
3032 'HK' => __( 'Hong Kong SAR China' ),
3033 'HU' => __( 'Hungary' ),
3034 'IS' => __( 'Iceland' ),
3035 'IN' => __( 'India' ),
3036 'ID' => __( 'Indonesia' ),
3037 'IR' => __( 'Iran' ),
3038 'IQ' => __( 'Iraq' ),
3039 'IE' => __( 'Ireland' ),
3040 'IM' => __( 'Isle of Man' ),
3041 'IL' => __( 'Israel' ),
3042 'IT' => __( 'Italy' ),
3043 'JM' => __( 'Jamaica' ),
3044 'JP' => __( 'Japan' ),
3045 'JE' => __( 'Jersey' ),
3046 'JT' => __( 'Johnston Island' ),
3047 'JO' => __( 'Jordan' ),
3048 'KZ' => __( 'Kazakhstan' ),
3049 'KE' => __( 'Kenya' ),
3050 'KI' => __( 'Kiribati' ),
3051 'KW' => __( 'Kuwait' ),
3052 'KG' => __( 'Kyrgyzstan' ),
3053 'LA' => __( 'Laos' ),
3054 'LV' => __( 'Latvia' ),
3055 'LB' => __( 'Lebanon' ),
3056 'LS' => __( 'Lesotho' ),
3057 'LR' => __( 'Liberia' ),
3058 'LY' => __( 'Libya' ),
3059 'LI' => __( 'Liechtenstein' ),
3060 'LT' => __( 'Lithuania' ),
3061 'LU' => __( 'Luxembourg' ),
3062 'MO' => __( 'Macau SAR China' ),
3063 'MK' => __( 'Macedonia' ),
3064 'MG' => __( 'Madagascar' ),
3065 'MW' => __( 'Malawi' ),
3066 'MY' => __( 'Malaysia' ),
3067 'MV' => __( 'Maldives' ),
3068 'ML' => __( 'Mali' ),
3069 'MT' => __( 'Malta' ),
3070 'MH' => __( 'Marshall Islands' ),
3071 'MQ' => __( 'Martinique' ),
3072 'MR' => __( 'Mauritania' ),
3073 'MU' => __( 'Mauritius' ),
3074 'YT' => __( 'Mayotte' ),
3075 'FX' => __( 'Metropolitan France' ),
3076 'MX' => __( 'Mexico' ),
3077 'FM' => __( 'Micronesia' ),
3078 'MI' => __( 'Midway Islands' ),
3079 'MD' => __( 'Moldova' ),
3080 'MC' => __( 'Monaco' ),
3081 'MN' => __( 'Mongolia' ),
3082 'ME' => __( 'Montenegro' ),
3083 'MS' => __( 'Montserrat' ),
3084 'MA' => __( 'Morocco' ),
3085 'MZ' => __( 'Mozambique' ),
3086 'MM' => __( 'Myanmar [Burma]' ),
3087 'NA' => __( 'Namibia' ),
3088 'NR' => __( 'Nauru' ),
3089 'NP' => __( 'Nepal' ),
3090 'NL' => __( 'Netherlands' ),
3091 'AN' => __( 'Netherlands Antilles' ),
3092 'NT' => __( 'Neutral Zone' ),
3093 'NC' => __( 'New Caledonia' ),
3094 'NZ' => __( 'New Zealand' ),
3095 'NI' => __( 'Nicaragua' ),
3096 'NE' => __( 'Niger' ),
3097 'NG' => __( 'Nigeria' ),
3098 'NU' => __( 'Niue' ),
3099 'NF' => __( 'Norfolk Island' ),
3100 'KP' => __( 'North Korea' ),
3101 'VD' => __( 'North Vietnam' ),
3102 'MP' => __( 'Northern Mariana Islands' ),
3103 'NO' => __( 'Norway' ),
3104 'OM' => __( 'Oman' ),
3105 'PC' => __( 'Pacific Islands Trust Territory' ),
3106 'PK' => __( 'Pakistan' ),
3107 'PW' => __( 'Palau' ),
3108 'PS' => __( 'Palestinian Territories' ),
3109 'PA' => __( 'Panama' ),
3110 'PZ' => __( 'Panama Canal Zone' ),
3111 'PG' => __( 'Papua New Guinea' ),
3112 'PY' => __( 'Paraguay' ),
3113 'YD' => __( "People's Democratic Republic of Yemen" ),
3114 'PE' => __( 'Peru' ),
3115 'PH' => __( 'Philippines' ),
3116 'PN' => __( 'Pitcairn Islands' ),
3117 'PL' => __( 'Poland' ),
3118 'PT' => __( 'Portugal' ),
3119 'PR' => __( 'Puerto Rico' ),
3120 'QA' => __( 'Qatar' ),
3121 'RO' => __( 'Romania' ),
3122 'RU' => __( 'Russia' ),
3123 'RW' => __( 'Rwanda' ),
3124 'RE' => __( 'Réunion' ),
3125 'BL' => __( 'Saint Barthélemy' ),
3126 'SH' => __( 'Saint Helena' ),
3127 'KN' => __( 'Saint Kitts and Nevis' ),
3128 'LC' => __( 'Saint Lucia' ),
3129 'MF' => __( 'Saint Martin' ),
3130 'PM' => __( 'Saint Pierre and Miquelon' ),
3131 'VC' => __( 'Saint Vincent and the Grenadines' ),
3132 'WS' => __( 'Samoa' ),
3133 'SM' => __( 'San Marino' ),
3134 'SA' => __( 'Saudi Arabia' ),
3135 'SN' => __( 'Senegal' ),
3136 'RS' => __( 'Serbia' ),
3137 'CS' => __( 'Serbia and Montenegro' ),
3138 'SC' => __( 'Seychelles' ),
3139 'SL' => __( 'Sierra Leone' ),
3140 'SG' => __( 'Singapore' ),
3141 'SK' => __( 'Slovakia' ),
3142 'SI' => __( 'Slovenia' ),
3143 'SB' => __( 'Solomon Islands' ),
3144 'SO' => __( 'Somalia' ),
3145 'ZA' => __( 'South Africa' ),
3146 'GS' => __( 'South Georgia and the South Sandwich Islands' ),
3147 'KR' => __( 'South Korea' ),
3148 'ES' => __( 'Spain' ),
3149 'LK' => __( 'Sri Lanka' ),
3150 'SD' => __( 'Sudan' ),
3151 'SR' => __( 'Suriname' ),
3152 'SJ' => __( 'Svalbard and Jan Mayen' ),
3153 'SZ' => __( 'Swaziland' ),
3154 'SE' => __( 'Sweden' ),
3155 'CH' => __( 'Switzerland' ),
3156 'SY' => __( 'Syria' ),
3157 'ST' => __( 'São Tomé and Príncipe' ),
3158 'TW' => __( 'Taiwan' ),
3159 'TJ' => __( 'Tajikistan' ),
3160 'TZ' => __( 'Tanzania' ),
3161 'TH' => __( 'Thailand' ),
3162 'TL' => __( 'Timor-Leste' ),
3163 'TG' => __( 'Togo' ),
3164 'TK' => __( 'Tokelau' ),
3165 'TO' => __( 'Tonga' ),
3166 'TT' => __( 'Trinidad and Tobago' ),
3167 'TN' => __( 'Tunisia' ),
3168 'TR' => __( 'Turkey' ),
3169 'TM' => __( 'Turkmenistan' ),
3170 'TC' => __( 'Turks and Caicos Islands' ),
3171 'TV' => __( 'Tuvalu' ),
3172 'UM' => __( 'U.S. Minor Outlying Islands' ),
3173 'PU' => __( 'U.S. Miscellaneous Pacific Islands' ),
3174 'VI' => __( 'U.S. Virgin Islands' ),
3175 'UG' => __( 'Uganda' ),
3176 'UA' => __( 'Ukraine' ),
3177 'SU' => __( 'Union of Soviet Socialist Republics' ),
3178 'AE' => __( 'United Arab Emirates' ),
3179 'GB' => __( 'United Kingdom' ),
3180 'US' => __( 'United States' ),
3181 'ZZ' => __( 'Unknown or Invalid Region' ),
3182 'UY' => __( 'Uruguay' ),
3183 'UZ' => __( 'Uzbekistan' ),
3184 'VU' => __( 'Vanuatu' ),
3185 'VA' => __( 'Vatican City' ),
3186 'VE' => __( 'Venezuela' ),
3187 'VN' => __( 'Vietnam' ),
3188 'WK' => __( 'Wake Island' ),
3189 'WF' => __( 'Wallis and Futuna' ),
3190 'EH' => __( 'Western Sahara' ),
3191 'YE' => __( 'Yemen' ),
3192 'ZM' => __( 'Zambia' ),
3193 'ZW' => __( 'Zimbabwe' ),
3194 'AX' => __( '�
3195 land Islands' ),
3196 );
3197
3198 return apply_filters( 'pods_form_ui_field_pick_data_countries', $data, $name, $value, $options, $pod, $id );
3199
3200 }
3201
3202 /**
3203 * Data callback for US States.
3204 *
3205 * @param string|null $name The name of the field.
3206 * @param string|array|null $value The value of the field.
3207 * @param array|null $options Field options.
3208 * @param array|null $pod Pod data.
3209 * @param int|null $id Item ID.
3210 *
3211 * @return array
3212 *
3213 * @since 2.3.0
3214 */
3215 public function data_us_states( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3216
3217 $data = array(
3218 'AL' => __( 'Alabama' ),
3219 'AK' => __( 'Alaska' ),
3220 'AZ' => __( 'Arizona' ),
3221 'AR' => __( 'Arkansas' ),
3222 'CA' => __( 'California' ),
3223 'CO' => __( 'Colorado' ),
3224 'CT' => __( 'Connecticut' ),
3225 'DE' => __( 'Delaware' ),
3226 'DC' => __( 'District Of Columbia' ),
3227 'FL' => __( 'Florida' ),
3228 'GA' => __( 'Georgia' ),
3229 'HI' => __( 'Hawaii' ),
3230 'ID' => __( 'Idaho' ),
3231 'IL' => __( 'Illinois' ),
3232 'IN' => __( 'Indiana' ),
3233 'IA' => __( 'Iowa' ),
3234 'KS' => __( 'Kansas' ),
3235 'KY' => __( 'Kentucky' ),
3236 'LA' => __( 'Louisiana' ),
3237 'ME' => __( 'Maine' ),
3238 'MD' => __( 'Maryland' ),
3239 'MA' => __( 'Massachusetts' ),
3240 'MI' => __( 'Michigan' ),
3241 'MN' => __( 'Minnesota' ),
3242 'MS' => __( 'Mississippi' ),
3243 'MO' => __( 'Missouri' ),
3244 'MT' => __( 'Montana' ),
3245 'NE' => __( 'Nebraska' ),
3246 'NV' => __( 'Nevada' ),
3247 'NH' => __( 'New Hampshire' ),
3248 'NJ' => __( 'New Jersey' ),
3249 'NM' => __( 'New Mexico' ),
3250 'NY' => __( 'New York' ),
3251 'NC' => __( 'North Carolina' ),
3252 'ND' => __( 'North Dakota' ),
3253 'OH' => __( 'Ohio' ),
3254 'OK' => __( 'Oklahoma' ),
3255 'OR' => __( 'Oregon' ),
3256 'PA' => __( 'Pennsylvania' ),
3257 'RI' => __( 'Rhode Island' ),
3258 'SC' => __( 'South Carolina' ),
3259 'SD' => __( 'South Dakota' ),
3260 'TN' => __( 'Tennessee' ),
3261 'TX' => __( 'Texas' ),
3262 'UT' => __( 'Utah' ),
3263 'VT' => __( 'Vermont' ),
3264 'VA' => __( 'Virginia' ),
3265 'WA' => __( 'Washington' ),
3266 'WV' => __( 'West Virginia' ),
3267 'WI' => __( 'Wisconsin' ),
3268 'WY' => __( 'Wyoming' ),
3269 );
3270
3271 return apply_filters( 'pods_form_ui_field_pick_data_us_states', $data, $name, $value, $options, $pod, $id );
3272
3273 }
3274
3275 /**
3276 * Data callback for CA Provinces.
3277 *
3278 * @param string|null $name The name of the field.
3279 * @param string|array|null $value The value of the field.
3280 * @param array|null $options Field options.
3281 * @param array|null $pod Pod data.
3282 * @param int|null $id Item ID.
3283 *
3284 * @return array
3285 *
3286 * @since 2.3.0
3287 */
3288 public function data_ca_provinces( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3289
3290 $data = array(
3291 'AB' => __( 'Alberta' ),
3292 'BC' => __( 'British Columbia' ),
3293 'MB' => __( 'Manitoba' ),
3294 'NB' => __( 'New Brunswick' ),
3295 'NL' => __( 'Newfoundland and Labrador' ),
3296 'NT' => __( 'Northwest Territories' ),
3297 'NS' => __( 'Nova Scotia' ),
3298 'NU' => __( 'Nunavut' ),
3299 'ON' => __( 'Ontario' ),
3300 'PE' => __( 'Prince Edward Island' ),
3301 'QC' => __( 'Quebec' ),
3302 'SK' => __( 'Saskatchewan' ),
3303 'YT' => __( 'Yukon' ),
3304 );
3305
3306 return apply_filters( 'pods_form_ui_field_pick_data_ca_provinces', $data, $name, $value, $options, $pod, $id );
3307
3308 }
3309
3310 /**
3311 * Data callback for US States.
3312 *
3313 * @param string|null $name The name of the field.
3314 * @param string|array|null $value The value of the field.
3315 * @param array|null $options Field options.
3316 * @param array|null $pod Pod data.
3317 * @param int|null $id Item ID.
3318 *
3319 * @return array
3320 *
3321 * @since 2.3.0
3322 */
3323 public function data_days_of_week( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3324
3325 /**
3326 * @var WP_Locale
3327 */
3328 global $wp_locale;
3329
3330 return $wp_locale->weekday;
3331
3332 }
3333
3334 /**
3335 * Data callback for US States.
3336 *
3337 * @param string|null $name The name of the field.
3338 * @param string|array|null $value The value of the field.
3339 * @param array|null $options Field options.
3340 * @param array|null $pod Pod data.
3341 * @param int|null $id Item ID.
3342 *
3343 * @return array
3344 *
3345 * @since 2.3.0
3346 */
3347 public function data_months_of_year( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3348
3349 /**
3350 * @var WP_Locale
3351 */
3352 global $wp_locale;
3353
3354 return $wp_locale->month;
3355
3356 }
3357
3358 /**
3359 * Add our modal input to the form so we can track whether we're in our modal during saving or not.
3360 */
3361 public function admin_modal_input() {
3362
3363 if ( ! pods_is_modal_window() ) {
3364 return;
3365 }
3366
3367 echo '<input name="pods_modal" type="hidden" value="1" />';
3368
3369 }
3370
3371 /**
3372 * Bail to send new saved data back to our modal handler.
3373 *
3374 * @param int $item_id Item ID.
3375 * @param string $item_title Item title.
3376 * @param object $field_args Field arguments.
3377 */
3378 public function admin_modal_bail( $item_id, $item_title, $field_args ) {
3379
3380 $model_data = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $field_args );
3381 ?>
3382 <script type="text/javascript">
3383 window.parent.jQuery( window.parent ).trigger(
3384 'dfv:modal:update',
3385 <?php echo wp_json_encode( $model_data, JSON_HEX_TAG ); ?>
3386 );
3387 </script>
3388 <?php
3389
3390 die();
3391
3392 }
3393
3394 /**
3395 * Bail to send new saved data back to our modal handler.
3396 *
3397 * @param int $item_id Item ID.
3398 * @param string $item_title Item title.
3399 * @param object $field_args Field arguments.
3400 */
3401 public function admin_modal_bail_JSON( $item_id, $item_title, $field_args ) {
3402
3403 $model_data = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $field_args );
3404 echo wp_json_encode( $model_data, JSON_HEX_TAG );
3405
3406 die();
3407 }
3408
3409 /**
3410 * Bail on Post save redirect for Admin modal.
3411 *
3412 * @param string $location The destination URL.
3413 * @param int $post_id The post ID.
3414 *
3415 * @return string
3416 */
3417 public function admin_modal_bail_post_redirect( $location, $post_id ) {
3418
3419 if ( ! pods_is_modal_window() ) {
3420 return $location;
3421 }
3422
3423 $post_title = get_the_title( $post_id );
3424
3425 $field_args = (object) array(
3426 'options' => array(
3427 'pick_object' => 'post_type',
3428 'pick_val' => get_post_type( $post_id ),
3429 ),
3430 'value' => array(
3431 $post_id => $post_title,
3432 ),
3433 );
3434
3435 $this->admin_modal_bail( $post_id, $post_title, $field_args );
3436
3437 return $location;
3438
3439 }
3440
3441 /**
3442 * Hook into term updating process to bail on redirect.
3443 */
3444 public function admin_modal_bail_term_action() {
3445
3446 if ( ! pods_is_modal_window() ) {
3447 return;
3448 }
3449
3450 add_action( 'created_term', array( $this, 'admin_modal_bail_term' ), 10, 3 );
3451 add_action( 'edited_term', array( $this, 'admin_modal_bail_term' ), 10, 3 );
3452
3453 }
3454
3455 /**
3456 * Bail on Term save redirect for Admin modal.
3457 *
3458 * @param int $term_id Term ID.
3459 * @param int $tt_id Term taxonomy ID.
3460 * @param string $taxonomy Taxonomy slug.
3461 */
3462 public function admin_modal_bail_term( $term_id, $tt_id, $taxonomy ) {
3463
3464 if ( ! pods_is_modal_window() ) {
3465 return;
3466 }
3467
3468 $term = get_term( $term_id );
3469
3470 if ( ! $term || is_wp_error( $term ) ) {
3471 return;
3472 }
3473
3474 $field_args = (object) array(
3475 'options' => array(
3476 'pick_object' => 'taxonomy',
3477 'pick_val' => $term->taxonomy,
3478 ),
3479 'value' => array(
3480 $term->term_id => $term->name,
3481 ),
3482 );
3483
3484 $this->admin_modal_bail( $term->term_id, $term->name, $field_args );
3485
3486 }
3487
3488 /**
3489 * Hook into user updating process to bail on redirect.
3490 */
3491 public function admin_modal_bail_user_action() {
3492
3493 if ( ! pods_is_modal_window() ) {
3494 return;
3495 }
3496
3497 add_filter( 'wp_redirect', array( $this, 'admin_modal_bail_user_redirect' ) );
3498
3499 }
3500
3501 /**
3502 * Bail on User save redirect for Admin modal.
3503 *
3504 * @param string $location The destination URL.
3505 *
3506 * @return string
3507 */
3508 public function admin_modal_bail_user_redirect( $location ) {
3509
3510 if ( ! pods_is_modal_window() ) {
3511 return $location;
3512 }
3513
3514 global $user_id;
3515
3516 $user = get_userdata( $user_id );
3517
3518 if ( ! $user || is_wp_error( $user ) ) {
3519 return $location;
3520 }
3521
3522 $field_args = (object) array(
3523 'options' => array(
3524 'pick_object' => 'user',
3525 'pick_val' => '',
3526 ),
3527 'value' => array(
3528 $user->ID => $user->display_name,
3529 ),
3530 );
3531
3532 $this->admin_modal_bail( $user->ID, $user->display_name, $field_args );
3533
3534 return $location;
3535
3536 }
3537
3538 /**
3539 * Bail on Pod item save for Admin modal.
3540 *
3541 * @param int $id Item ID.
3542 * @param array $params save_pod_item parameters.
3543 * @param null|Pods $obj Pod object (if set).
3544 */
3545 public function admin_modal_bail_pod( $id, $params, $obj ) {
3546
3547 if ( ! pods_is_modal_window() ) {
3548 return;
3549 }
3550
3551 if ( ! $obj ) {
3552 $obj = pods( $params['pod'] );
3553 }
3554
3555 if ( ! $obj || ! $obj->fetch( $id ) ) {
3556 return;
3557 }
3558
3559 $item_id = $obj->id();
3560 $item_title = $obj->index();
3561
3562 $field_args = (object) array(
3563 'options' => array(
3564 'pick_object' => $obj->pod_data['type'],
3565 'pick_val' => $obj->pod,
3566 ),
3567 'value' => array(
3568 $obj->id() => $item_title,
3569 ),
3570 );
3571
3572 $this->admin_modal_bail_JSON( $item_id, $item_title, $field_args );
3573
3574 }
3575
3576 }
3577