Completed
Pull Request — 2.x (#4569)
by Scott Kingsley
04:42
created

PodsField_Pick::data()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 40
Code Lines 20

Duplication

Lines 5
Ratio 12.5 %

Importance

Changes 0
Metric Value
cc 5
eloc 20
nc 8
nop 6
dl 5
loc 40
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @package Pods\Fields
5
 */
6
class PodsField_Pick extends PodsField {
7
8
	/**
9
	 * {@inheritdoc}
10
	 */
11
	public static $group = 'Relationships / Media';
12
13
	/**
14
	 * {@inheritdoc}
15
	 */
16
	public static $type = 'pick';
17
18
	/**
19
	 * {@inheritdoc}
20
	 */
21
	public static $label = 'Relationship';
22
23
	/**
24
	 * {@inheritdoc}
25
	 */
26
	protected static $api = false;
27
28
	/**
29
	 * Available Related Objects.
30
	 *
31
	 * @var array
32
	 * @since 2.3
33
	 */
34
	public static $related_objects = array();
35
36
	/**
37
	 * Custom Related Objects
38
	 *
39
	 * @var array
40
	 * @since 2.3
41
	 */
42
	public static $custom_related_objects = array();
43
44
	/**
45
	 * Data used during validate / save to avoid extra queries.
46
	 *
47
	 * @var array
48
	 * @since 2.3
49
	 */
50
	public static $related_data = array();
51
52
	/**
53
	 * Data used during input method (mainly for autocomplete).
54
	 *
55
	 * @var array
56
	 * @since 2.3
57
	 */
58
	public static $field_data = array();
59
60
	/**
61
	 * Saved array of simple relationship names.
62
	 *
63
	 * @var array
64
	 * @since 2.5
65
	 */
66
	private static $names_simple = null;
67
68
	/**
69
	 * Saved array of relationship names
70
	 *
71
	 * @var array
72
	 * @since 2.5
73
	 */
74
	private static $names_related = null;
75
76
	/**
77
	 * Saved array of bidirectional relationship names
78
	 *
79
	 * @var array
80
	 * @since 2.5
81
	 */
82
	private static $names_bidirectional = null;
83
84
	/**
85
	 * {@inheritdoc}
86
	 */
87
	public function setup() {
88
89
		self::$label = __( 'Relationship', 'pods' );
90
	}
91
92
	/**
93
	 * {@inheritdoc}
94
	 */
95
	public function admin_init() {
96
97
		// AJAX for Relationship lookups.
98
		add_action( 'wp_ajax_pods_relationship', array( $this, 'admin_ajax_relationship' ) );
99
		add_action( 'wp_ajax_nopriv_pods_relationship', array( $this, 'admin_ajax_relationship' ) );
100
101
		// Handle modal input.
102
		add_action( 'edit_form_top', array( $this, 'admin_modal_input' ) );
103
		add_action( 'show_user_profile', array( $this, 'admin_modal_input' ) );
104
		add_action( 'edit_user_profile', array( $this, 'admin_modal_input' ) );
105
		add_action( 'edit_category_form', array( $this, 'admin_modal_input' ) );
106
		add_action( 'edit_link_category_form', array( $this, 'admin_modal_input' ) );
107
		add_action( 'edit_tag_form', array( $this, 'admin_modal_input' ) );
108
		add_action( 'add_tag_form', array( $this, 'admin_modal_input' ) );
109
		add_action( 'pods_meta_box_pre', array( $this, 'admin_modal_input' ) );
110
111
		// Handle modal saving.
112
		add_filter( 'redirect_post_location', array( $this, 'admin_modal_bail_post_redirect' ), 10, 2 );
113
		add_action( 'load-edit-tags.php', array( $this, 'admin_modal_bail_term_action' ) );
114
		add_action( 'load-categories.php', array( $this, 'admin_modal_bail_term_action' ) );
115
		add_action( 'load-edit-link-categories.php', array( $this, 'admin_modal_bail_term_action' ) );
116
		add_action( 'personal_options_update', array( $this, 'admin_modal_bail_user_action' ) );
117
		add_action( 'user_register', array( $this, 'admin_modal_bail_user_action' ) );
118
		add_action( 'pods_api_processed_form', array( $this, 'admin_modal_bail_pod' ), 10, 3 );
119
120
	}
121
122
	/**
123
	 * {@inheritdoc}
124
	 */
125
	public function options() {
126
127
		$options = array(
128
			static::$type . '_format_type'    => array(
129
				'label'      => __( 'Selection Type', 'pods' ),
130
				'help'       => __( 'help', 'pods' ),
131
				'default'    => 'single',
132
				'type'       => 'pick',
133
				'data'       => array(
134
					'single' => __( 'Single Select', 'pods' ),
135
					'multi'  => __( 'Multiple Select', 'pods' ),
136
				),
137
				'dependency' => true,
138
			),
139
			static::$type . '_format_single'  => array(
140
				'label'      => __( 'Format', 'pods' ),
141
				'help'       => __( 'help', 'pods' ),
142
				'depends-on' => array( static::$type . '_format_type' => 'single' ),
143
				'default'    => 'dropdown',
144
				'type'       => 'pick',
145
				'data'       => apply_filters(
146
					'pods_form_ui_field_pick_format_single_options', array(
147
						'dropdown'     => __( 'Drop Down', 'pods' ),
148
						'radio'        => __( 'Radio Buttons', 'pods' ),
149
						'autocomplete' => __( 'Autocomplete', 'pods' ),
150
						'list'         => __( 'List view', 'pods' ),
151
					)
152
				),
153
				'dependency' => true,
154
			),
155
			static::$type . '_format_multi'   => array(
156
				'label'      => __( 'Format', 'pods' ),
157
				'help'       => __( 'help', 'pods' ),
158
				'depends-on' => array( static::$type . '_format_type' => 'multi' ),
159
				'default'    => 'checkbox',
160
				'type'       => 'pick',
161
				'data'       => apply_filters(
162
					'pods_form_ui_field_pick_format_multi_options', array(
163
						'checkbox'     => __( 'Checkboxes', 'pods' ),
164
						'multiselect'  => __( 'Multi Select', 'pods' ),
165
						'autocomplete' => __( 'Autocomplete', 'pods' ),
166
						'list'         => __( 'List view', 'pods' ),
167
					)
168
				),
169
				'dependency' => true,
170
			),
171
			static::$type . '_allow_add_new'  => array(
172
				'label'       => __( 'Allow Add New', 'pods' ),
173
				'help'        => __( 'Allow new related records to be created in a modal window', 'pods' ),
174
				'wildcard-on' => array(
175
					static::$type . '_object' => array( '^post-type-(?!(custom-css|customize-changeset)).*$', '^taxonomy-.*$', '^user$', '^pod-.*$' ),
176
				),
177
				'type'        => 'boolean',
178
				'default'     => 1,
179
			),
180
			static::$type . '_taggable'       => array(
181
				'label'       => __( 'Taggable', 'pods' ),
182
				'help'        => __( 'Allow new values to be inserted when using an Autocomplete field', 'pods' ),
183
				'excludes-on' => array(
184
					static::$type . '_format_single' => array( 'dropdown', 'radio', 'list' ),
185
					static::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'list' ),
186
					static::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
187
				),
188
				'type'        => 'boolean',
189
				'default'     => 0,
190
			),
191
			static::$type . '_show_icon'      => array(
192
				'label'       => __( 'Show Icons', 'pods' ),
193
				'excludes-on' => array(
194
					static::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
195
					static::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'autocomplete' ),
196
					static::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
197
				),
198
				'type'        => 'boolean',
199
				'default'     => 1,
200
			),
201
			static::$type . '_show_edit_link' => array(
202
				'label'       => __( 'Show Edit Links', 'pods' ),
203
				'excludes-on' => array(
204
					static::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
205
					static::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'autocomplete' ),
206
					static::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
207
				),
208
				'type'        => 'boolean',
209
				'default'     => 1,
210
			),
211
			static::$type . '_show_view_link' => array(
212
				'label'       => __( 'Show View Links', 'pods' ),
213
				'excludes-on' => array(
214
					static::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
215
					static::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'autocomplete' ),
216
					static::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
217
				),
218
				'type'        => 'boolean',
219
				'default'     => 1,
220
			),
221
			static::$type . '_select_text'    => array(
222
				'label'      => __( 'Default Select Text', 'pods' ),
223
				'help'       => __( 'This is the text use for the default "no selection" dropdown item, if empty, it will default to "-- Select One --"', 'pods' ),
224
				'depends-on' => array(
225
					static::$type . '_format_type'   => 'single',
226
					static::$type . '_format_single' => 'dropdown',
227
				),
228
				'default'    => '',
229
				'type'       => 'text',
230
			),
231
			static::$type . '_limit'          => array(
232
				'label'      => __( 'Selection Limit', 'pods' ),
233
				'help'       => __( 'help', 'pods' ),
234
				'depends-on' => array( static::$type . '_format_type' => 'multi' ),
235
				'default'    => 0,
236
				'type'       => 'number',
237
			),
238
			static::$type . '_table_id'       => array(
239
				'label'      => __( 'Table ID Column', 'pods' ),
240
				'help'       => __( 'You must provide the ID column name for the table, this will be used to keep track of the relationship', 'pods' ),
241
				'depends-on' => array( static::$type . '_object' => 'table' ),
242
				'required'   => 1,
243
				'default'    => '',
244
				'type'       => 'text',
245
			),
246
			static::$type . '_table_index'    => array(
247
				'label'      => __( 'Table Index Column', 'pods' ),
248
				'help'       => __( 'You must provide the index column name for the table, this may optionally also be the ID column name', 'pods' ),
249
				'depends-on' => array( static::$type . '_object' => 'table' ),
250
				'required'   => 1,
251
				'default'    => '',
252
				'type'       => 'text',
253
			),
254
			static::$type . '_display'        => array(
255
				'label'       => __( 'Display Field in Selection List', 'pods' ),
256
				'help'        => __( 'Provide the name of a field on the related object to reference, example: {@post_title}', 'pods' ),
257
				'excludes-on' => array(
258
					static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
259
				),
260
				'default'     => '',
261
				'type'        => 'text',
262
			),
263
			static::$type . '_user_role'      => array(
264
				'label'            => __( 'Limit list to Role(s)', 'pods' ),
265
				'help'             => __( 'help', 'pods' ),
266
				'depends-on'       => array( static::$type . '_object' => 'user' ),
267
				'default'          => '',
268
				'type'             => 'pick',
269
				'pick_object'      => 'role',
270
				'pick_format_type' => 'multi',
271
			),
272
			static::$type . '_where'          => array(
273
				'label'       => __( 'Customized <em>WHERE</em>', 'pods' ),
274
				'help'        => __( 'help', 'pods' ),
275
				'excludes-on' => array(
276
					static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
277
				),
278
				'default'     => '',
279
				'type'        => 'text',
280
			),
281
			static::$type . '_orderby'        => array(
282
				'label'       => __( 'Customized <em>ORDER BY</em>', 'pods' ),
283
				'help'        => __( 'help', 'pods' ),
284
				'excludes-on' => array(
285
					static::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
286
				),
287
				'default'     => '',
288
				'type'        => 'text',
289
			),
290
			static::$type . '_groupby'        => array(
291
				'label'       => __( 'Customized <em>GROUP BY</em>', 'pods' ),
292
				'help'        => __( 'help', '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
		);
300
301
		$post_type_pick_objects = array();
302
303
		foreach ( get_post_types( '', 'names' ) as $post_type ) {
304
			$post_type_pick_objects[] = 'post-type_' . $post_type;
305
		}
306
307
		$options[ static::$type . '_post_status' ] = array(
308
			'name'             => 'post_status',
309
			'label'            => __( 'Post Status', 'pods' ),
310
			'help'             => __( 'help', 'pods' ),
311
			'type'             => 'pick',
312
			'pick_object'      => 'post-status',
313
			'pick_format_type' => 'multi',
314
			'default'          => 'publish',
315
			'depends-on'       => array(
316
				static::$type . '_object' => $post_type_pick_objects,
317
			),
318
		);
319
320
		return $options;
321
322
	}
323
324
	/**
325
	 * Register a related object.
326
	 *
327
	 * @param string $name    Object name.
328
	 * @param string $label   Object label.
329
	 * @param array  $options Object options.
330
	 *
331
	 * @return array|boolean Object array or false if unsuccessful
332
	 * @since 2.3
333
	 */
334
	public function register_related_object( $name, $label, $options = null ) {
335
336
		if ( empty( $name ) || empty( $label ) ) {
337
			return false;
338
		}
339
340
		$related_object = array(
341
			'label'         => $label,
342
			'group'         => 'Custom Relationships',
343
			'simple'        => true,
344
			'bidirectional' => false,
345
			'data'          => array(),
346
			'data_callback' => null,
347
		);
348
349
		$related_object = array_merge( $related_object, $options );
350
351
		self::$custom_related_objects[ $name ] = $related_object;
352
353
		return true;
354
355
	}
356
357
	/**
358
	 * Setup related objects.
359
	 *
360
	 * @param boolean $force Whether to force refresh of related objects.
361
	 *
362
	 * @return bool True when data has been loaded
363
	 * @since 2.3
364
	 */
365
	public function setup_related_objects( $force = false ) {
366
367
		$new_data_loaded = false;
368
369
		if ( ! $force && empty( self::$related_objects ) ) {
370
			// Only load transient if we aren't forcing a refresh.
371
			self::$related_objects = pods_transient_get( 'pods_related_objects' );
372
373
			if ( false !== self::$related_objects ) {
374
				$new_data_loaded = true;
375
			}
376
		} elseif ( $force ) {
377
			// If we are rebuilding, make sure we start with a clean slate.
378
			self::$related_objects = array();
379
		}
380
381
		if ( empty( self::$related_objects ) ) {
382
			// Do a complete build of related_objects.
383
			$new_data_loaded = true;
384
385
			// Custom simple relationship lists.
386
			self::$related_objects['custom-simple'] = array(
387
				'label'  => __( 'Simple (custom defined list)', 'pods' ),
388
				'group'  => __( 'Custom', 'pods' ),
389
				'simple' => true,
390
			);
391
392
			// Pods options.
393
			$pod_options = array();
394
395
			// Include PodsMeta if not already included.
396
			pods_meta();
397
398
			// Advanced Content Types for relationships.
399
			$_pods = PodsMeta::$advanced_content_types;
400
401 View Code Duplication
			foreach ( $_pods as $pod ) {
402
				$pod_options[ $pod['name'] ] = $pod['label'] . ' (' . $pod['name'] . ')';
403
			}
404
405
			// Settings pods for relationships.
406
			$_pods = PodsMeta::$settings;
407
408 View Code Duplication
			foreach ( $_pods as $pod ) {
409
				$pod_options[ $pod['name'] ] = $pod['label'] . ' (' . $pod['name'] . ')';
410
			}
411
412
			asort( $pod_options );
413
414
			foreach ( $pod_options as $pod => $label ) {
415
				self::$related_objects[ 'pod-' . $pod ] = array(
416
					'label'         => $label,
417
					'group'         => __( 'Pods', 'pods' ),
418
					'bidirectional' => true,
419
				);
420
			}
421
422
			// Post Types for relationships.
423
			$post_types = get_post_types();
424
			asort( $post_types );
425
426
			$ignore = array( 'attachment', 'revision', 'nav_menu_item' );
427
428 View Code Duplication
			foreach ( $post_types as $post_type => $label ) {
429
				if ( in_array( $post_type, $ignore, true ) || empty( $post_type ) ) {
430
					unset( $post_types[ $post_type ] );
431
432
					continue;
433
				} elseif ( 0 === strpos( $post_type, '_pods_' ) && apply_filters( 'pods_pick_ignore_internal', true ) ) {
434
					unset( $post_types[ $post_type ] );
435
436
					continue;
437
				}
438
439
				$post_type = get_post_type_object( $post_type );
440
441
				self::$related_objects[ 'post_type-' . $post_type->name ] = array(
442
					'label'         => $post_type->label . ' (' . $post_type->name . ')',
443
					'group'         => __( 'Post Types', 'pods' ),
444
					'bidirectional' => true,
445
				);
446
			}
447
448
			// Taxonomies for relationships.
449
			$taxonomies = get_taxonomies();
450
			asort( $taxonomies );
451
452
			$ignore = array( 'nav_menu', 'post_format' );
453
454 View Code Duplication
			foreach ( $taxonomies as $taxonomy => $label ) {
455
				/**
456
				 * Prevent ability to extend core Pods content types.
457
				 *
458
				 * @param bool $ignore_internal Default is true, when set to false Pods internal content types can not be extended.
459
				 *
460
				 * @since 2.3.19
461
				 */
462
				$ignore_internal = apply_filters( 'pods_pick_ignore_internal', true );
463
464
				if ( in_array( $taxonomy, $ignore, true ) || empty( $taxonomy ) ) {
465
					unset( $taxonomies[ $taxonomy ] );
466
467
					continue;
468
				} elseif ( 0 === strpos( $taxonomy, '_pods_' ) && $ignore_internal ) {
469
					unset( $taxonomies[ $taxonomy ] );
470
471
					continue;
472
				}
473
474
				$taxonomy = get_taxonomy( $taxonomy );
475
476
				self::$related_objects[ 'taxonomy-' . $taxonomy->name ] = array(
477
					'label'         => $taxonomy->label . ' (' . $taxonomy->name . ')',
478
					'group'         => __( 'Taxonomies', 'pods' ),
479
					'bidirectional' => true,
480
				);
481
			}//end foreach
482
483
			// Other WP Objects for relationships.
484
			self::$related_objects['user'] = array(
485
				'label'         => __( 'Users', 'pods' ),
486
				'group'         => __( 'Other WP Objects', 'pods' ),
487
				'bidirectional' => true,
488
			);
489
490
			self::$related_objects['role'] = array(
491
				'label'         => __( 'User Roles', 'pods' ),
492
				'group'         => __( 'Other WP Objects', 'pods' ),
493
				'simple'        => true,
494
				'data_callback' => array( $this, 'data_roles' ),
495
			);
496
497
			self::$related_objects['capability'] = array(
498
				'label'         => __( 'User Capabilities', 'pods' ),
499
				'group'         => __( 'Other WP Objects', 'pods' ),
500
				'simple'        => true,
501
				'data_callback' => array( $this, 'data_capabilities' ),
502
			);
503
504
			self::$related_objects['media'] = array(
505
				'label'         => __( 'Media', 'pods' ),
506
				'group'         => __( 'Other WP Objects', 'pods' ),
507
				'bidirectional' => true,
508
			);
509
510
			self::$related_objects['comment'] = array(
511
				'label'         => __( 'Comments', 'pods' ),
512
				'group'         => __( 'Other WP Objects', 'pods' ),
513
				'bidirectional' => true,
514
			);
515
516
			self::$related_objects['image-size'] = array(
517
				'label'         => __( 'Image Sizes', 'pods' ),
518
				'group'         => __( 'Other WP Objects', 'pods' ),
519
				'simple'        => true,
520
				'data_callback' => array( $this, 'data_image_sizes' ),
521
			);
522
523
			self::$related_objects['nav_menu'] = array(
524
				'label' => __( 'Navigation Menus', 'pods' ),
525
				'group' => __( 'Other WP Objects', 'pods' ),
526
			);
527
528
			self::$related_objects['post_format'] = array(
529
				'label' => __( 'Post Formats', 'pods' ),
530
				'group' => __( 'Other WP Objects', 'pods' ),
531
			);
532
533
			self::$related_objects['post-status'] = array(
534
				'label'         => __( 'Post Status', 'pods' ),
535
				'group'         => __( 'Other WP Objects', 'pods' ),
536
				'simple'        => true,
537
				'data_callback' => array( $this, 'data_post_stati' ),
538
			);
539
540
			do_action( 'pods_form_ui_field_pick_related_objects_other' );
541
542
			self::$related_objects['country'] = array(
543
				'label'         => __( 'Countries', 'pods' ),
544
				'group'         => __( 'Predefined Lists', 'pods' ),
545
				'simple'        => true,
546
				'data_callback' => array( $this, 'data_countries' ),
547
			);
548
549
			self::$related_objects['us_state'] = array(
550
				'label'         => __( 'US States', 'pods' ),
551
				'group'         => __( 'Predefined Lists', 'pods' ),
552
				'simple'        => true,
553
				'data_callback' => array( $this, 'data_us_states' ),
554
			);
555
556
			self::$related_objects['ca_province'] = array(
557
				'label'         => __( 'CA Provinces', 'pods' ),
558
				'group'         => __( 'Predefined Lists', 'pods' ),
559
				'simple'        => true,
560
				'data_callback' => array( $this, 'data_ca_provinces' ),
561
			);
562
563
			self::$related_objects['days_of_week'] = array(
564
				'label'         => __( 'Calendar - Days of Week', 'pods' ),
565
				'group'         => __( 'Predefined Lists', 'pods' ),
566
				'simple'        => true,
567
				'data_callback' => array( $this, 'data_days_of_week' ),
568
			);
569
570
			self::$related_objects['months_of_year'] = array(
571
				'label'         => __( 'Calendar - Months of Year', 'pods' ),
572
				'group'         => __( 'Predefined Lists', 'pods' ),
573
				'simple'        => true,
574
				'data_callback' => array( $this, 'data_months_of_year' ),
575
			);
576
577
			do_action( 'pods_form_ui_field_pick_related_objects_predefined' );
578
579
			if ( did_action( 'init' ) ) {
580
				pods_transient_set( 'pods_related_objects', self::$related_objects );
581
			}
582
		}//end if
583
584
		/**
585
		 * Allow custom related objects to be defined
586
		 */
587
		do_action( 'pods_form_ui_field_pick_related_objects_custom' );
588
589
		foreach ( self::$custom_related_objects as $object => $related_object ) {
590
			if ( ! isset( self::$related_objects[ $object ] ) ) {
591
				$new_data_loaded = true;
592
593
				self::$related_objects[ $object ] = $related_object;
594
			}
595
		}
596
597
		return $new_data_loaded;
598
599
	}
600
601
	/**
602
	 * Return available related objects
603
	 *
604
	 * @param boolean $force Whether to force refresh of related objects.
605
	 *
606
	 * @return array Field selection array
607
	 * @since 2.3
608
	 */
609
	public function related_objects( $force = false ) {
610
611
		if ( $this->setup_related_objects( $force ) || null === self::$names_related ) {
612
			$related_objects = array();
613
614
			foreach ( self::$related_objects as $related_object_name => $related_object ) {
615
				if ( ! isset( $related_objects[ $related_object['group'] ] ) ) {
616
					$related_objects[ $related_object['group'] ] = array();
617
				}
618
619
				$related_objects[ $related_object['group'] ][ $related_object_name ] = $related_object['label'];
620
			}
621
622
			self::$names_related = (array) apply_filters( 'pods_form_ui_field_pick_related_objects', $related_objects );
623
		}
624
625
		return self::$names_related;
626
627
	}
628
629
	/**
630
	 * Return available simple object names
631
	 *
632
	 * @return array Simple object names
633
	 * @since 2.3
634
	 */
635 View Code Duplication
	public function simple_objects() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
636
637
		if ( $this->setup_related_objects() || null === self::$names_simple ) {
638
			$simple_objects = array();
639
640
			foreach ( self::$related_objects as $object => $related_object ) {
641
				if ( ! isset( $related_object['simple'] ) || ! $related_object['simple'] ) {
642
					continue;
643
				}
644
645
				$simple_objects[] = $object;
646
			}
647
648
			self::$names_simple = (array) apply_filters( 'pods_form_ui_field_pick_simple_objects', $simple_objects );
649
		}
650
651
		return self::$names_simple;
652
653
	}
654
655
	/**
656
	 * Return available bidirectional object names
657
	 *
658
	 * @return array Bidirectional object names
659
	 * @since 2.3.4
660
	 */
661 View Code Duplication
	public function bidirectional_objects() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
662
663
		if ( $this->setup_related_objects() || null === self::$names_bidirectional ) {
664
			$bidirectional_objects = array();
665
666
			foreach ( self::$related_objects as $object => $related_object ) {
667
				if ( ! isset( $related_object['bidirectional'] ) || ! $related_object['bidirectional'] ) {
668
					continue;
669
				}
670
671
				$bidirectional_objects[] = $object;
672
			}
673
674
			self::$names_bidirectional = (array) apply_filters( 'pods_form_ui_field_pick_bidirectional_objects', $bidirectional_objects );
675
		}
676
677
		return self::$names_bidirectional;
678
679
	}
680
681
	/**
682
	 * {@inheritdoc}
683
	 */
684
	public function schema( $options = null ) {
685
686
		$schema = false;
687
688
		$simple_tableless_objects = $this->simple_objects();
689
690
		if ( in_array( pods_v( static::$type . '_object', $options ), $simple_tableless_objects, true ) ) {
691
			$schema = 'LONGTEXT';
692
		}
693
694
		return $schema;
695
696
	}
697
698
	/**
699
	 * {@inheritdoc}
700
	 */
701
	public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
702
703
		$fields = null;
704
705
		if ( is_object( $pod ) && isset( $pod->fields ) ) {
706
			/**
707
			 * @var $pod Pods Pods object.
708
			 */
709
			$fields = $pod->fields;
710
711 View Code Duplication
			if ( ! empty( $pod->pod_data['object_fields'] ) ) {
712
				$fields = array_merge( $fields, $pod->pod_data['object_fields'] );
713
			}
714 View Code Duplication
		} elseif ( is_array( $pod ) && isset( $pod['fields'] ) ) {
715
			$fields = $pod['fields'];
716
717
			if ( ! empty( $pod['object_fields'] ) ) {
718
				$fields = array_merge( $fields, $pod['object_fields'] );
719
			}
720
		}
721
722
		return pods_serial_comma(
723
			$value, array(
724
				'field'  => $name,
725
				'fields' => $fields,
726
			)
727
		);
728
729
	}
730
731
	/**
732
	 * {@inheritdoc}
733
	 */
734
	public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
735
736
		$options = (array) $options;
737
738
		$type = pods_v( 'type', $options, static::$type );
739
740
		$args = compact( array_keys( get_defined_vars() ) );
741
		$args = (object) $args;
742
743
		wp_enqueue_script( 'pods-dfv' );
744
745
		wp_enqueue_style( 'pods-select2' );
746
		wp_enqueue_script( 'pods-select2' );
747
748
		$this->render_input_script( $args );
749
750
		/**
751
		 * @todo Support custom integrations.
752
		 *
753
		 * 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' )
754
		 * Run the action 'pods_form_ui_field_pick_input'
755
		 * Pass the arguments: $name, $value, $options, $pod, $id
756
		 */
757
758
	}
759
760
	/**
761
	 * {@inheritdoc}
762
	 */
763
	public function build_dfv_field_options( $options, $args ) {
764
765
		$options['grouped'] = 1;
766
767 View Code Duplication
		if ( empty( $options[ $args->type . '_object' ] ) ) {
768
			$options[ $args->type . '_object' ] = '';
769
		}
770
771 View Code Duplication
		if ( empty( $options[ $args->type . '_val' ] ) ) {
772
			$options[ $args->type . '_val' ] = '';
773
		}
774
775
		$options['table_info'] = array();
776
777
		$custom = pods_v( $args->type . '_custom', $options, false );
778
779
		$custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $args->name, $args->value, $options, $args->pod, $args->id );
780
781
		$ajax = false;
782
783
		if ( ( 'custom-simple' !== pods_v( $args->type . '_object', $options ) || empty( $custom ) ) && '' !== pods_v( $args->type . '_object', $options, '', true ) ) {
784
			$ajax = true;
785
		}
786
787
		if ( ! empty( self::$field_data ) && self::$field_data['id'] === $options['id'] ) {
788
			$ajax = (boolean) self::$field_data['autocomplete'];
789
		}
790
791
		$ajax = apply_filters( 'pods_form_ui_field_pick_ajax', $ajax, $args->name, $args->value, $options, $args->pod, $args->id );
792
793
		if ( 0 === (int) pods_v( $args->type . '_ajax', $options, 1 ) ) {
794
			$ajax = false;
795
		}
796
797
		$options[ $args->type . '_ajax' ] = (int) $ajax;
798
799
		$format_type = pods_v( $args->type . '_format_type', $options, 'single', true );
800
801
		$limit = 1;
802
803
		if ( 'single' === $format_type ) {
804
			$format_single = pods_v( $args->type . '_format_single', $options, 'dropdown', true );
805
806 View Code Duplication
			if ( 'dropdown' === $format_single ) {
807
				$options['view_name'] = 'select';
808
			} elseif ( 'radio' === $format_single ) {
809
				$options['view_name'] = 'radio';
810
			} elseif ( 'autocomplete' === $format_single ) {
811
				$options['view_name'] = 'select2';
812
			} elseif ( 'list' === $format_single ) {
813
				$options['view_name'] = 'list';
814
			} else {
815
				$options['view_name'] = $format_single;
816
			}
817
		} elseif ( 'multi' === $format_type ) {
818
			$format_multi = pods_v( $args->type . '_format_multi', $options, 'checkbox', true );
819
820
			if ( ! empty( $args->value ) && ! is_array( $args->value ) ) {
821
				$args->value = explode( ',', $args->value );
822
			}
823
824 View Code Duplication
			if ( 'checkbox' === $format_multi ) {
825
				$options['view_name'] = 'checkbox';
826
			} elseif ( 'multiselect' === $format_multi ) {
827
				$options['view_name'] = 'select';
828
			} elseif ( 'autocomplete' === $format_multi ) {
829
				$options['view_name'] = 'select2';
830
			} elseif ( 'list' === $format_multi ) {
831
				$options['view_name'] = 'list';
832
			} else {
833
				$options['view_name'] = $format_multi;
834
			}
835
836
			$limit = 0;
837
838
			if ( ! empty( $options[ $args->type . '_limit' ] ) ) {
839
				$limit = absint( $options[ $args->type . '_limit' ] );
840
			}
841
		} else {
842
			$options['view_name'] = $format_type;
843
		}//end if
844
845
		$options[ $args->type . '_limit' ] = $limit;
846
847
		$options['ajax_data'] = $this->build_dfv_autocomplete_ajax_data( $options, $args, $ajax );
848
849
		/**
850
		 * Allow overriding some of the Select2 options used in the JS init.
851
		 *
852
		 * @param array|null $select2_overrides Override options for Select2/SelectWoo.
853
		 *
854
		 * @since 2.7
855
		 */
856
		$options['select2_overrides'] = apply_filters( 'pods_pick_select2_overrides', null );
857
858
		return $options;
859
860
	}
861
862
	/**
863
	 * Build DFV autocomplete AJAX data.
864
	 *
865
	 * @param array  $options DFV options.
866
	 * @param object $args    {
867
	 *  Field information arguments.
868
	 *
869
	 *     @type string     $name    Field name.
870
	 *     @type string     $type    Field type.
871
	 *     @type array      $options Field options.
872
	 *     @type mixed      $value   Current value.
873
	 *     @type array      $pod     Pod information.
874
	 *     @type int|string $id      Current item ID.
875
	 * }
876
	 * @param bool   $ajax    True if ajax mode should be used.
877
	 *
878
	 * @return array
879
	 */
880
	public function build_dfv_autocomplete_ajax_data( $options, $args, $ajax = false ) {
881
882
		if ( is_object( $args->pod ) ) {
883
			$pod_id = (int) $args->pod->pod_id;
884
		} else {
885
			$pod_id = 0;
886
		}
887
888
		$field_id = (int) $options['id'];
889
890
		$id = (int) $args->id;
891
892
		if ( is_user_logged_in() ) {
893
			$uid = 'user_' . get_current_user_id();
894
		} else {
895
			$uid = @session_id();
896
		}
897
898
		$uri_hash = wp_create_nonce( 'pods_uri_' . $_SERVER['REQUEST_URI'] );
899
900
		$field_nonce = wp_create_nonce( 'pods_relationship_' . $pod_id . '_' . $uid . '_' . $uri_hash . '_' . $field_id );
901
902
		// Values can be overridden via the `pods_field_dfv_data` filter in $data['fieldConfig']['ajax_data'].
903
		return array(
904
			'ajax'                 => $ajax,
905
			'delay'                => 300,
906
			'minimum_input_length' => 1,
907
			'pod'                  => $pod_id,
908
			'field'                => $field_id,
909
			'id'                   => $id,
910
			'uri'                  => $uri_hash,
911
			'_wpnonce'             => $field_nonce,
912
		);
913
914
	}
915
916
	/**
917
	 * {@inheritdoc}
918
	 */
919
	public function build_dfv_field_config( $args ) {
920
921
		$config = parent::build_dfv_field_config( $args );
922
923
		if ( ! isset( $config['optgroup'] ) ) {
924
			$config['optgroup'] = false;
925
		}
926
927
		/**
928
		 * Filter on whether to allow modals to be used on the front of the site (in an non-admin area).
929
		 *
930
		 * @param boolean $show_on_front
931
		 * @param array $config
932
		 * @param array $args
933
		 *
934
		 * @since 2.7
935
		 */
936
		$show_on_front = apply_filters( 'pods_ui_dfv_pick_modals_show_on_front', false, $config, $args );
937
938
		/**
939
		 * Filter on whether to allow nested modals to be used (modals within modals).
940
		 *
941
		 * @param boolean $allow_nested_modals
942
		 * @param array $config
943
		 * @param array $args
944
		 *
945
		 * @since 2.7
946
		 */
947
		$allow_nested_modals = apply_filters( 'pods_ui_dfv_pick_modals_allow_nested', false, $config, $args );
948
949
		// Disallow add/edit outside the admin and when we're already in a modal
950
		if ( ( ! $show_on_front && ! is_admin() ) || ( ! $allow_nested_modals && pods_is_modal_window() ) ) {
951
			$config[ $args->type . '_allow_add_new' ]  = false;
952
			$config[ $args->type . '_show_edit_link' ] = false;
953
		}
954
955
		$iframe = array(
956
			'src'        => '',
957
			'url'        => '',
958
			'query_args' => array(),
959
		);
960
961
		// Set the file name and args based on the content type of the relationship
962
		switch ( $args->options['pick_object'] ) {
963
			case 'post_type':
964
				if ( ! empty( $args->options['pick_val'] ) ) {
965
					$post_type_obj = get_post_type_object( $args->options['pick_val'] );
966
967
					if ( $post_type_obj && current_user_can( $post_type_obj->cap->create_posts ) ) {
968
						$iframe['url']        = admin_url( 'post-new.php' );
969
						$iframe['query_args'] = array(
970
							'post_type' => $args->options['pick_val'],
971
						);
972
					}
973
				}
974
975
				break;
976
977
			case 'taxonomy':
978
				/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
979
				 * @todo Fix add new modal issues
980
				if ( ! empty( $args->options['pick_val'] ) ) {
981
					$taxonomy_obj = get_taxonomy( $args->options['pick_val'] );
982
983
					if ( $taxonomy_obj && current_user_can( $taxonomy_obj->cap->edit_terms ) ) {
984
						$iframe['url']  = admin_url( 'edit-tags.php' );
985
						$iframe['query_args'] = array(
986
							'taxonomy' => $args->options['pick_val'],
987
						);
988
					}
989
				}
990
				*/
991
992
				break;
993
994
			case 'user':
995
				if ( current_user_can( 'create_users' ) ) {
996
					$iframe['url'] = admin_url( 'user-new.php' );
997
				}
998
999
				break;
1000
1001
			case 'pod':
1002
				if ( ! empty( $args->options['pick_val'] ) ) {
1003
					if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
1004
						$iframe['url']        = admin_url( 'admin.php' );
1005
						$iframe['query_args'] = array(
1006
							'page'   => 'pods-manage-' . $args->options['pick_val'],
1007
							'action' => 'add',
1008
						);
1009
1010
					}
1011
				}
1012
1013
				break;
1014
		}//end switch
1015
1016
		// Potential valid modal target if we've set the file name
1017
		if ( ! empty( $iframe['url'] ) ) {
1018
			// @todo: Replace string literal with defined constant
1019
			$iframe['query_args']['pods_modal'] = 1;
1020
1021
			// Add args we always need
1022
			$iframe['src'] = add_query_arg( $iframe['query_args'], $iframe['url'] );
1023
		}
1024
1025
		$iframe['title_add']  = sprintf( __( '%s: Add New', 'pods' ), $args->options['label'] );
1026
		$iframe['title_edit'] = sprintf( __( '%s: Edit', 'pods' ), $args->options['label'] );
1027
1028
		/**
1029
		 * Allow filtering iframe configuration
1030
		 *
1031
		 * @param array $iframe
1032
		 * @param array $config
1033
		 * @param array $args
1034
		 *
1035
		 * @since 2.7
1036
		 */
1037
		$iframe = apply_filters( 'pods_ui_dfv_pick_modals_iframe', $iframe, $config, $args );
1038
1039
		if ( ! empty( $iframe['src'] ) ) {
1040
			// We extend wp.media.view.Modal for modal add/edit, we must ensure we load the template for it
1041
			wp_enqueue_media();
1042
1043
		}
1044
1045
		$config['iframe_src']        = $iframe['src'];
1046
		$config['iframe_title_add']  = $iframe['title_add'];
1047
		$config['iframe_title_edit'] = $iframe['title_edit'];
1048
1049
		return $config;
1050
1051
	}
1052
1053
	/**
1054
	 * {@inheritdoc}
1055
	 */
1056
	public function build_dfv_field_item_data( $args ) {
1057
1058
		$args->options['supports_thumbnails'] = null;
1059
1060
		$item_data = array();
1061
1062
		if ( ! empty( $args->options['data'] ) ) {
1063
			$item_data = $this->build_dfv_field_item_data_recurse( $args->options['data'], $args );
1064
		}
1065
1066
		return $item_data;
1067
1068
	}
1069
1070
	/**
1071
	 * Loop through relationship data and expand item data with additional information for DFV.
1072
	 *
1073
	 * @param array  $data    Item data to expand.
1074
	 * @param object $args    {
1075
	 *      Field information arguments.
1076
	 *
1077
	 *     @type string     $name    Field name.
1078
	 *     @type string     $type    Field type.
1079
	 *     @type array      $options Field options.
1080
	 *     @type mixed      $value   Current value.
1081
	 *     @type array      $pod     Pod information.
1082
	 *     @type int|string $id      Current item ID.
1083
	 * }
1084
	 *
1085
	 * @return array
1086
	 */
1087
	public function build_dfv_field_item_data_recurse( $data, $args ) {
1088
1089
		$item_data = array();
1090
1091
		foreach ( $data as $item_id => $item_title ) {
1092
			if ( is_array( $item_title ) ) {
1093
				$args->options['optgroup'] = true;
1094
1095
				$item_data[] = array(
1096
					'label'      => $item_id,
1097
					'collection' => $this->build_dfv_field_item_data_recurse( $item_title, $args ),
1098
				);
1099
			} else {
1100
				// Key by item_id temporarily to be able to sort based on $args->value
1101
				$item_data[ $item_id ] = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args );
1102
			}
1103
		}
1104
1105
		// Maintain any saved sort order from $args->value
1106
		if ( is_array( $args->value ) && 1 < count( $args->value ) && $this->is_autocomplete( $args->options ) ) {
1107
			$item_data = array_replace( $args->value, $item_data );
1108
		}
1109
1110
		// Convert from associative to numeric array
1111
		$item_data = array_values( $item_data );
1112
1113
		return $item_data;
1114
1115
	}
1116
1117
	/**
1118
	 * Loop through relationship data and expand item data with additional information for DFV.
1119
	 *
1120
	 * @param int|string $item_id    Item ID.
1121
	 * @param string     $item_title Item title.
1122
	 * @param object     $args       {
1123
	 *      Field information arguments.
1124
	 *
1125
	 *     @type string      $name    Field name.
1126
	 *     @type string      $type    Field type.
1127
	 *     @type array       $options Field options.
1128
	 *     @type mixed       $value   Current value.
1129
	 *     @type array       $pod     Pod information.
1130
	 *     @type int|string  $id      Current item ID.
1131
	 * }
1132
	 *
1133
	 * @return array
1134
	 */
1135
	public function build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args ) {
1136
1137
		$use_dashicon = false;
1138
		$icon         = '';
1139
		$img_icon     = '';
1140
		$edit_link    = '';
1141
		$link         = '';
1142
1143
		if ( ! isset( $args->options['supports_thumbnails'] ) ) {
1144
			$args->options['supports_thumbnails'] = null;
1145
		}
1146
1147
		switch ( $args->options['pick_object'] ) {
1148
			case 'post_type':
1149
				$item_id = (int) $item_id;
1150
1151
				if ( null === $args->options['supports_thumbnails'] && ! empty( $args->options['pick_val'] ) ) {
1152
					$args->options['supports_thumbnails'] = post_type_supports( $args->options['pick_val'], 'thumbnail' );
1153
				}
1154
1155
				if ( true === $args->options['supports_thumbnails'] ) {
1156
					$post_thumbnail_id = get_post_thumbnail_id( $item_id );
1157
1158
					if ( $post_thumbnail_id ) {
1159
						$thumb = wp_get_attachment_image_src( $post_thumbnail_id, 'thumbnail', false );
1160
					}
1161
1162
					if ( ! empty( $thumb[0] ) ) {
1163
						$img_icon = $thumb[0];
1164
					}
1165
				}
1166
1167
				if ( empty( $img_icon ) ) {
1168
1169
					// Default icon for posts.
1170
					$icon = 'dashicons-admin-post';
1171
1172
					// Post type icons.
1173
					$post_type = (array) get_post_type_object( get_post_type( $item_id ) );
1174
1175
					if ( ! empty( $post_type['menu_icon'] ) ) {
1176
						// Post specific icon.
1177
						$icon = $post_type['menu_icon'];
1178
					} elseif ( isset( $post_type['name'] ) && 'page' ) {
1179
						switch ( $post_type['name'] ) {
1180
							case 'page':
1181
								// Default for pages.
1182
								$icon = 'dashicons-admin-page';
1183
								break;
1184
							case 'attachment':
1185
								// Default for attachments.
1186
								$icon = 'dashicons-admin-media';
1187
								break;
1188
						}
1189
					}
1190
				}//end if
1191
1192
				$edit_link = get_edit_post_link( $item_id, 'raw' );
1193
1194
				$link = get_permalink( $item_id );
1195
1196
				break;
1197
1198
			case 'taxonomy':
1199
				$item_id = (int) $item_id;
1200
1201
				if ( ! empty( $args->options['pick_val'] ) ) {
1202
1203
					// Default icon for taxonomy.
1204
					$icon = 'dashicons-category';
1205
1206
					// Change icon for non-hierarchical taxonomies.
1207
					$taxonomy = get_term( $item_id );
1208
					if ( isset( $taxonomy->taxonomy ) ) {
1209
						$taxonomy = (array) get_taxonomy( $taxonomy->taxonomy );
1210
						if ( isset( $taxonomy['hierarchical'] ) && ! $taxonomy['hierarchical'] ) {
1211
							$icon = 'dashicons-tag';
1212
						}
1213
					}
1214
1215
					$edit_link = get_edit_term_link( $item_id, $args->options['pick_val'] );
1216
1217
					$link = get_term_link( $item_id, $args->options['pick_val'] );
1218
				}
1219
1220
				break;
1221
1222
			case 'user':
1223
				$item_id = (int) $item_id;
1224
1225
				$args->options['supports_thumbnails'] = true;
1226
1227
				$icon     = 'dashicons-admin-users';
1228
				$img_icon = get_avatar_url( $item_id, array( 'size' => 150 ) );
1229
1230
				$edit_link = get_edit_user_link( $item_id );
1231
1232
				$link = get_author_posts_url( $item_id );
1233
1234
				break;
1235
1236
			case 'comment':
1237
				$item_id = (int) $item_id;
1238
1239
				$args->options['supports_thumbnails'] = true;
1240
1241
				$icon     = 'dashicons-admin-comments';
1242
				$img_icon = get_avatar_url( get_comment( $item_id ), array( 'size' => 150 ) );
1243
1244
				$edit_link = get_edit_comment_link( $item_id );
1245
1246
				$link = get_comment_link( $item_id );
1247
1248
				break;
1249
1250
			case 'pod':
1251
				$item_id = (int) $item_id;
1252
1253
				if ( ! empty( $args->options['pick_val'] ) ) {
1254
1255
					$icon = 'dashicons-pods';
1256
1257
					if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
1258
						$file_name  = 'admin.php';
1259
						$query_args = array(
1260
							'page'   => 'pods-manage-' . $args->options['pick_val'],
1261
							'action' => 'edit',
1262
							'id'     => $item_id,
1263
						);
1264
1265
						$edit_link = add_query_arg( $query_args, admin_url( $file_name ) );
1266
					}
1267
1268
					// @todo Add $link support
1269
					$link = '';
1270
				}
1271
1272
				break;
1273
		}//end switch
1274
1275
		// Image icons always overwrite default icons
1276
		if ( ! empty( $img_icon ) ) {
1277
			$icon = $img_icon;
1278
		}
1279
1280
		// Parse icon type
1281
		if ( 'none' === $icon || 'div' === $icon ) {
1282
			$icon         = '';
1283
			$use_dashicon = true;
1284
		} elseif ( 0 === strpos( $icon, 'data:image/svg+xml;base64,' ) ) {
1285
			$icon         = esc_attr( $icon );
1286
			$use_dashicon = false;
1287
		} elseif ( 0 === strpos( $icon, 'dashicons-' ) ) {
1288
			$icon         = sanitize_html_class( $icon );
1289
			$use_dashicon = true;
1290
		}
1291
1292
		// Support modal editing
1293
		if ( ! empty( $edit_link ) ) {
1294
			// @todo: Replace string literal with defined constant
1295
			$edit_link = add_query_arg( array( 'pods_modal' => '1' ), $edit_link );
1296
		}
1297
1298
		// Determine if this is a selected item
1299
		$selected = false;
1300
1301
		if ( is_array( $args->value ) ) {
1302
			if ( isset( $args->value[ $item_id ] ) ) {
1303
				$selected = true;
1304
			} elseif ( in_array( $item_id, $args->value, true ) ) {
1305
				$selected = true;
1306
			}
1307
		} elseif ( (string) $item_id === (string) $args->value ) {
1308
			$selected = true;
1309
		}
1310
1311
		$item = array(
1312
			'id'           => $item_id,
1313
			'use_dashicon' => $use_dashicon,
1314
			'icon'         => $icon,
1315
			'name'         => $item_title,
1316
			'edit_link'    => $edit_link,
1317
			'link'         => $link,
1318
			'selected'     => $selected,
1319
		);
1320
1321
		return $item;
1322
1323
	}
1324
1325
	/**
1326
	 * {@inheritdoc}
1327
	 */
1328
	public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1329
1330
		if ( empty( self::$api ) ) {
1331
			self::$api = pods_api();
1332
		}
1333
1334
		$simple_tableless_objects = $this->simple_objects();
1335
1336
		$related_pick_limit  = 0;
1337
		$related_field       = false;
1338
		$related_pod         = false;
1339
		$current_related_ids = false;
1340
1341
		// Bidirectional relationship requirement checks
1342
		$related_object = pods_v( static::$type . '_object', $options, '' );
1343
		// pod, post_type, taxonomy, etc..
1344
		$related_val = pods_v( static::$type . '_val', $options, $related_object, null, true );
1345
		// pod name, post type name, taxonomy name, etc..
1346
		if ( empty( $related_val ) ) {
1347
			$related_val = $related_object;
1348
		}
1349
1350
		$related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1351
1352
		$options['id'] = (int) $options['id'];
1353
1354
		if ( ! isset( self::$related_data[ $options['id'] ] ) || empty( self::$related_data[ $options['id'] ] ) ) {
1355
			self::$related_data[ $options['id'] ] = array();
1356
		}
1357
1358
		if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1359
			$related_pod = self::$api->load_pod(
1360
				array(
1361
					'name'       => $related_val,
1362
					'table_info' => false,
1363
				), false
1364
			);
1365
1366
			if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1367
				$related_field = false;
1368
1369
				// Ensure sister_id exists on related Pod.
1370 View Code Duplication
				foreach ( $related_pod['fields'] as $related_pod_field ) {
1371
					if ( 'pick' === $related_pod_field['type'] && $related_sister_id === $related_pod_field['id'] ) {
1372
						$related_field = $related_pod_field;
1373
1374
						break;
1375
					}
1376
				}
1377
1378
				if ( ! empty( $related_field ) ) {
1379
					$current_ids = self::$api->lookup_related_items( $fields[ $name ]['id'], $pod['id'], $id, $fields[ $name ], $pod );
1380
1381
					self::$related_data[ $options['id'] ]['current_ids'] = $current_ids;
1382
1383
					$value_ids = $value;
1384
1385
					// Convert values from a comma-separated string into an array.
1386
					if ( ! is_array( $value_ids ) ) {
1387
						$value_ids = explode( ',', $value_ids );
1388
					}
1389
1390
					$value_ids = array_unique( array_filter( $value_ids ) );
1391
1392
					// Get ids to remove.
1393
					$remove_ids = array_diff( $current_ids, $value_ids );
1394
1395
					$related_required   = (boolean) pods_v( 'required', $related_field['options'], 0 );
1396
					$related_pick_limit = (int) pods_v( static::$type . '_limit', $related_field['options'], 0 );
1397
1398
					if ( 'single' === pods_v( static::$type . '_format_type', $related_field['options'] ) ) {
1399
						$related_pick_limit = 1;
1400
					}
1401
1402
					// Validate Required fields.
1403
					if ( $related_required && ! empty( $remove_ids ) ) {
1404
						foreach ( $remove_ids as $related_id ) {
1405
							$bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1406
1407
							self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] = $bidirectional_ids;
1408
1409
							if ( empty( $bidirectional_ids ) || ( in_array( (int) $id, $bidirectional_ids, true ) && 1 === count( $bidirectional_ids ) ) ) {
1410
								return sprintf( __( 'The %1$s field is required and cannot be removed by the %2$s field', 'pods' ), $related_field['label'], $options['label'] );
1411
							}
1412
						}
1413
					}
1414
				} else {
1415
					$related_pod = false;
1416
				}//end if
1417
			} else {
1418
				$related_pod = false;
1419
			}//end if
1420
		}//end if
1421
1422
		if ( empty( self::$related_data[ $options['id'] ] ) ) {
1423
			unset( self::$related_data[ $options['id'] ] );
1424
		} else {
1425
			self::$related_data[ $options['id'] ]['related_pod']        = $related_pod;
1426
			self::$related_data[ $options['id'] ]['related_field']      = $related_field;
1427
			self::$related_data[ $options['id'] ]['related_pick_limit'] = $related_pick_limit;
1428
1429
			$pick_limit = (int) pods_v( static::$type . '_limit', $options['options'], 0 );
1430
1431
			if ( 'single' === pods_v( static::$type . '_format_type', $options['options'] ) ) {
1432
				$pick_limit = 1;
1433
			}
1434
1435
			$related_field['id'] = (int) $related_field['id'];
1436
1437
			if ( ! isset( self::$related_data[ $related_field['id'] ] ) || empty( self::$related_data[ $related_field['id'] ] ) ) {
1438
				self::$related_data[ $related_field['id'] ] = array(
1439
					'related_pod'        => $pod,
1440
					'related_field'      => $options,
1441
					'related_pick_limit' => $pick_limit,
1442
				);
1443
			}
1444
		}//end if
1445
1446
		return true;
1447
1448
	}
1449
1450
	/**
1451
	 * {@inheritdoc}
1452
	 */
1453
	public function save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
1454
1455
		if ( empty( self::$api ) ) {
1456
			self::$api = pods_api();
1457
		}
1458
1459
		$options['id'] = (int) $options['id'];
1460
1461
		if ( ! isset( self::$related_data[ $options['id'] ] ) ) {
1462
			return;
1463
		}
1464
1465
		$related_pod        = self::$related_data[ $options['id'] ]['related_pod'];
1466
		$related_field      = self::$related_data[ $options['id'] ]['related_field'];
1467
		$related_pick_limit = self::$related_data[ $options['id'] ]['related_pick_limit'];
1468
1469
		// Bidirectional relationship updates.
1470
		if ( ! empty( $related_field ) ) {
1471
			// Don't use no conflict mode unless this isn't the current pod type.
1472
			$no_conflict = true;
1473
1474
			if ( $related_pod['type'] !== $pod['type'] ) {
1475
				$no_conflict = pods_no_conflict_check( $related_pod['type'] );
1476
			}
1477
1478
			if ( ! $no_conflict ) {
1479
				pods_no_conflict_on( $related_pod['type'] );
1480
			}
1481
1482
			$value = array_filter( $value );
1483
1484
			foreach ( $value as $related_id ) {
1485
				if ( isset( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) && ! empty( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) ) {
1486
					$bidirectional_ids = self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ];
1487
				} else {
1488
					$bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1489
				}
1490
1491
				$bidirectional_ids = array_filter( $bidirectional_ids );
1492
1493
				if ( empty( $bidirectional_ids ) ) {
1494
					$bidirectional_ids = array();
1495
				}
1496
1497
				$remove_ids = array();
1498
1499
				if ( 0 < $related_pick_limit && ! empty( $bidirectional_ids ) && ! in_array( $id, $bidirectional_ids, true ) ) {
1500
					$total_bidirectional_ids = count( $bidirectional_ids );
1501
1502
					while ( $related_pick_limit <= $total_bidirectional_ids ) {
1503
						$remove_ids[] = (int) array_pop( $bidirectional_ids );
1504
1505
						$total_bidirectional_ids = count( $bidirectional_ids );
1506
					}
1507
				}
1508
1509
				// Remove this item from related items no longer related to.
1510
				$remove_ids = array_unique( array_filter( $remove_ids ) );
1511
1512
				if ( ! in_array( $id, $bidirectional_ids, true ) ) {
1513
					// Add to related items.
1514
					$bidirectional_ids[] = $id;
1515
				} elseif ( empty( $remove_ids ) ) {
1516
					// Nothing to change.
1517
					continue;
1518
				}
1519
1520
				self::$api->save_relationships( $related_id, $bidirectional_ids, $related_pod, $related_field );
1521
1522
				if ( ! empty( $remove_ids ) ) {
1523
					self::$api->delete_relationships( $remove_ids, $related_id, $pod, $options );
1524
				}
1525
			}//end foreach
1526
1527
			if ( ! $no_conflict ) {
1528
				pods_no_conflict_off( $related_pod['type'] );
1529
			}
1530
		}//end if
1531
1532
	}
1533
1534
	/**
1535
	 * Delete the value from the DB
1536
	 *
1537
	 * @param int|null    $id      Item ID.
1538
	 * @param string|null $name    Field name.
1539
	 * @param array|null  $options Field options.
1540
	 * @param array|null  $pod     Pod options.
1541
	 *
1542
	 * @since 2.3
1543
	 */
1544
	public function delete( $id = null, $name = null, $options = null, $pod = null ) {
1545
1546
		if ( empty( self::$api ) ) {
1547
			self::$api = pods_api();
1548
		}
1549
1550
		$simple_tableless_objects = $this->simple_objects();
1551
1552
		// Bidirectional relationship requirement checks.
1553
		$related_object = pods_v( static::$type . '_object', $options, '' );
1554
		// pod, post_type, taxonomy, etc..
1555
		$related_val = pods_v( static::$type . '_val', $options, $related_object, true );
1556
		// pod name, post type name, taxonomy name, etc..
1557
		$related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1558
1559
		if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1560
			$related_pod = self::$api->load_pod(
1561
				array(
1562
					'name'       => $related_val,
1563
					'table_info' => false,
1564
				), false
1565
			);
1566
1567
			if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1568
				$related_field = false;
1569
1570
				// Ensure sister_id exists on related Pod.
1571 View Code Duplication
				foreach ( $related_pod['fields'] as $related_pod_field ) {
1572
					if ( 'pick' === $related_pod_field['type'] && (int) $related_sister_id === (int) $related_pod_field['id'] ) {
1573
						$related_field = $related_pod_field;
1574
1575
						break;
1576
					}
1577
				}
1578
1579
				if ( ! empty( $related_field ) ) {
1580
					$values = self::$api->lookup_related_items( $options['id'], $pod['id'], $id, $options, $pod );
1581
1582
					if ( ! empty( $values ) ) {
1583
						$no_conflict = pods_no_conflict_check( $related_pod['type'] );
1584
1585
						if ( ! $no_conflict ) {
1586
							pods_no_conflict_on( $related_pod['type'] );
1587
						}
1588
1589
						self::$api->delete_relationships( $values, $id, $related_pod, $related_field );
1590
1591
						if ( ! $no_conflict ) {
1592
							pods_no_conflict_off( $related_pod['type'] );
1593
						}
1594
					}
1595
				}
1596
			}//end if
1597
		}//end if
1598
1599
	}
1600
1601
	/**
1602
	 * {@inheritdoc}
1603
	 */
1604
	public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
1605
1606
		$value = $this->simple_value( $name, $value, $options, $pod, $id );
1607
1608
		return $this->display( $value, $name, $options, $pod, $id );
1609
1610
	}
1611
1612
	/**
1613
	 * Get the data from the field.
1614
	 *
1615
	 * @param string            $name    The name of the field.
1616
	 * @param string|array|null $value   The value of the field.
1617
	 * @param array|null        $options Field options.
1618
	 * @param array|null        $pod     Pod data.
1619
	 * @param int|null          $id      Item ID.
1620
	 * @param boolean           $in_form Whether we are in form context.
1621
	 *
1622
	 * @return array Array of possible field data
1623
	 *
1624
	 * @since 2.0
1625
	 */
1626
	public function data( $name, $value = null, $options = null, $pod = null, $id = null, $in_form = true ) {
1627
1628 View Code Duplication
		if ( isset( $options['options'] ) ) {
1629
			$options = array_merge( $options, $options['options'] );
1630
1631
			unset( $options['options'] );
1632
		}
1633
1634
		$data = pods_v( 'data', $options, null, true );
1635
1636
		$object_params = array(
1637
			// The name of the field.
1638
			'name'    => $name,
1639
			// The value of the field.
1640
			'value'   => $value,
1641
			// Field options.
1642
			'options' => $options,
1643
			// Pod data.
1644
			'pod'     => $pod,
1645
			// Item ID.
1646
			'id'      => $id,
1647
			// Data context.
1648
			'context' => 'data',
1649
		);
1650
1651
		if ( null !== $data ) {
1652
			$data = (array) $data;
1653
		} else {
1654
			$data = $this->get_object_data( $object_params );
1655
		}
1656
1657
		if ( 'single' === pods_v( static::$type . '_format_type', $options, 'single' ) && 'dropdown' === pods_v( static::$type . '_format_single', $options, 'dropdown' ) ) {
1658
			$data = array( '' => pods_v( static::$type . '_select_text', $options, __( '-- Select One --', 'pods' ), true ) ) + $data;
1659
		}
1660
1661
		$data = apply_filters( 'pods_field_pick_data', $data, $name, $value, $options, $pod, $id );
1662
1663
		return $data;
1664
1665
	}
1666
1667
	/**
1668
	 * Convert a simple value to the correct value
1669
	 *
1670
	 * @param string            $name    The name of the field.
1671
	 * @param string|array|null $value   The value of the field.
1672
	 * @param array|null        $options Field options.
1673
	 * @param array|null        $pod     Pod data.
1674
	 * @param int|null          $id      Item ID.
1675
	 * @param boolean           $raw     Whether to return the raw list of keys (true) or convert to key=>value (false).
1676
	 *
1677
	 * @return mixed Corrected value
1678
	 */
1679
	public function simple_value( $name, $value = null, $options = null, $pod = null, $id = null, $raw = false ) {
1680
1681
		if ( in_array( pods_v( static::$type . '_object', $options ), self::simple_objects(), true ) ) {
1682 View Code Duplication
			if ( isset( $options['options'] ) ) {
1683
				$options = array_merge( $options, $options['options'] );
1684
1685
				unset( $options['options'] );
1686
			}
1687
1688
			if ( ! is_array( $value ) && 0 < strlen( $value ) ) {
1689
				$simple = @json_decode( $value, true );
1690
1691
				if ( is_array( $simple ) ) {
1692
					$value = $simple;
1693
				}
1694
			}
1695
1696
			$data = pods_v( 'data', $options, null, true );
1697
1698
			$object_params = array(
1699
				// The name of the field.
1700
				'name'    => $name,
1701
				// The value of the field.
1702
				'value'   => $value,
1703
				// Field options.
1704
				'options' => $options,
1705
				// Pod data.
1706
				'pod'     => $pod,
1707
				// Item ID.
1708
				'id'      => $id,
1709
				// Data context.
1710
				'context' => 'simple_value',
1711
			);
1712
1713
			if ( null === $data ) {
1714
				$data = $this->get_object_data( $object_params );
1715
			}
1716
1717
			$data = (array) $data;
1718
1719
			$key = 0;
1720
1721
			if ( is_array( $value ) ) {
1722
				if ( ! empty( $data ) ) {
1723
					$val = array();
1724
1725
					foreach ( $value as $k => $v ) {
1726
						if ( isset( $data[ $v ] ) ) {
1727
							if ( false === $raw ) {
1728
								$k = $v;
1729
								$v = $data[ $v ];
1730
							}
1731
1732
							$val[ $k ] = $v;
1733
						}
1734
					}
1735
1736
					$value = $val;
1737
				}
1738
			} elseif ( isset( $data[ $value ] ) && false === $raw ) {
1739
				$key   = $value;
1740
				$value = $data[ $value ];
1741
			}//end if
1742
1743
			$single_multi = pods_v( static::$type . '_format_type', $options, 'single' );
1744
1745
			if ( 'multi' === $single_multi ) {
1746
				$limit = (int) pods_v( static::$type . '_limit', $options, 0 );
1747
			} else {
1748
				$limit = 1;
1749
			}
1750
1751
			if ( is_array( $value ) && 0 < $limit ) {
1752
				if ( 1 === $limit ) {
1753
					$value = current( $value );
1754
				} else {
1755
					$value = array_slice( $value, 0, $limit, true );
1756
				}
1757
			} elseif ( ! is_array( $value ) && null !== $value && 0 < strlen( $value ) ) {
1758
				if ( 1 !== $limit || ( true === $raw && 'multi' === $single_multi ) ) {
1759
					$value = array(
1760
						$key => $value,
1761
					);
1762
				}
1763
			}
1764
		}//end if
1765
1766
		return $value;
1767
1768
	}
1769
1770
	/**
1771
	 * Get the label from a pick value.
1772
	 *
1773
	 * @param string            $name    The name of the field.
1774
	 * @param string|array|null $value   The value of the field.
1775
	 * @param array|null        $options Field options.
1776
	 * @param array|null        $pod     Pod data.
1777
	 * @param int|null          $id      Item ID.
1778
	 *
1779
	 * @return string
1780
	 *
1781
	 * @since 2.2
1782
	 */
1783
	public function value_to_label( $name, $value = null, $options = null, $pod = null, $id = null ) {
1784
1785 View Code Duplication
		if ( isset( $options['options'] ) ) {
1786
			$options = array_merge( $options, $options['options'] );
1787
1788
			unset( $options['options'] );
1789
		}
1790
1791
		$data = pods_v( 'data', $options, null, true );
1792
1793
		$object_params = array(
1794
			// The name of the field.
1795
			'name'    => $name,
1796
			// The value of the field.
1797
			'value'   => $value,
1798
			// Field options.
1799
			'options' => $options,
1800
			// Pod data.
1801
			'pod'     => $pod,
1802
			// Item ID.
1803
			'id'      => $id,
1804
			// Data context.
1805
			'context' => 'value_to_label',
1806
		);
1807
1808
		if ( null !== $data ) {
1809
			$data = (array) $data;
1810
		} else {
1811
			$data = $this->get_object_data( $object_params );
1812
		}
1813
1814
		$labels = array();
1815
1816
		$check_value = $value;
1817
1818
		foreach ( $check_value as $check_k => $check_v ) {
0 ignored issues
show
Bug introduced by
The expression $check_value of type string|array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1819
			$check_value[ $check_k ] = (string) $check_v;
1820
		}
1821
1822
		foreach ( $data as $v => $l ) {
0 ignored issues
show
Bug introduced by
The expression $data of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1823
			if ( ! in_array( (string) $l, $labels, true ) && ( (string) $value === (string) $v || ( is_array( $value ) && in_array( (string) $v, $value, true ) ) ) ) {
1824
				$labels[] = (string) $l;
1825
			}
1826
		}
1827
1828
		$labels = apply_filters( 'pods_field_pick_value_to_label', $labels, $name, $value, $options, $pod, $id );
1829
1830
		$labels = pods_serial_comma( $labels );
1831
1832
		return $labels;
1833
1834
	}
1835
1836
	/**
1837
	 * Get available items from a relationship field.
1838
	 *
1839
	 * @param array|string $field         Field array or field name.
1840
	 * @param array        $options       Field options array overrides.
1841
	 * @param array        $object_params Additional get_object_data options.
1842
	 *
1843
	 * @return array An array of available items from a relationship field
1844
	 */
1845
	public function get_field_data( $field, $options = array(), $object_params = array() ) {
1846
1847
		// Handle field array overrides.
1848
		if ( is_array( $field ) ) {
1849
			$options = array_merge( $field, $options );
1850
		}
1851
1852
		// Get field name from array.
1853
		$field = pods_v( 'name', $options, $field, true );
1854
1855
		// Field name or options not set.
1856
		if ( empty( $field ) || empty( $options ) ) {
1857
			return array();
1858
		}
1859
1860
		// Options normalization.
1861
		$options = array_merge( $options, pods_v( 'options', $options, array(), true ) );
1862
1863
		// Setup object params.
1864
		$object_params = array_merge(
1865
			array(
1866
				// The name of the field.
1867
				'name'    => $field,
1868
				// Field options.
1869
				'options' => $options,
1870
			), $object_params
1871
		);
1872
1873
		// Get data override.
1874
		$data = pods_v( 'data', $options, null, true );
1875
1876
		if ( null !== $data ) {
1877
			// Return data override.
1878
			$data = (array) $data;
1879
		} else {
1880
			// Get object data.
1881
			$data = $this->get_object_data( $object_params );
1882
		}
1883
1884
		return $data;
1885
1886
	}
1887
1888
	/**
1889
	 * Get data from relationship objects.
1890
	 *
1891
	 * @param array $object_params Object data parameters.
1892
	 *
1893
	 * @return array|bool Object data
1894
	 */
1895
	public function get_object_data( $object_params = null ) {
1896
1897
		/**
1898
		 * @var $wpdb wpdb
1899
		 */
1900
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1901
1902
		$object_params = array_merge(
1903
			array(
1904
				// The name of the field.
1905
				'name'        => '',
1906
				// The value of the field.
1907
				'value'       => '',
1908
				// Field options.
1909
				'options'     => array(),
1910
				// Pod data.
1911
				'pod'         => '',
1912
				// Item ID.
1913
				'id'          => '',
1914
				// Data context.
1915
				'context'     => '',
1916
				// Data parameters.
1917
				'data_params' => array(
1918
					// Query being searched.
1919
					'query' => '',
1920
				),
1921
				// Page number of results to get.
1922
				'page'        => 1,
1923
				// How many data items to limit to (autocomplete defaults to 30, set to -1 or 1+ to override).
1924
				'limit'       => 0,
1925
			), $object_params
1926
		);
1927
1928
		$object_params['options']     = (array) $object_params['options'];
1929
		$object_params['data_params'] = (array) $object_params['data_params'];
1930
1931
		$name         = $object_params['name'];
1932
		$value        = $object_params['value'];
1933
		$options      = $object_params['options'];
1934
		$pod          = $object_params['pod'];
1935
		$id           = $object_params['id'];
1936
		$context      = $object_params['context'];
1937
		$data_params  = $object_params['data_params'];
1938
		$page         = min( 1, (int) $object_params['page'] );
1939
		$limit        = (int) $object_params['limit'];
1940
		$autocomplete = false;
1941
1942 View Code Duplication
		if ( isset( $options['options'] ) ) {
1943
			$options = array_merge( $options, $options['options'] );
1944
1945
			unset( $options['options'] );
1946
		}
1947
1948
		$data  = apply_filters( 'pods_field_pick_object_data', null, $name, $value, $options, $pod, $id, $object_params );
1949
		$items = array();
1950
1951
		if ( ! isset( $options[ static::$type . '_object' ] ) ) {
1952
			$data = pods_v( 'data', $options, array(), true );
1953
		}
1954
1955
		$simple = false;
1956
1957
		if ( null === $data ) {
1958
			$data = array();
1959
1960
			if ( 'custom-simple' === $options[ static::$type . '_object' ] ) {
1961
				$custom = pods_v( static::$type . '_custom', $options, '' );
1962
1963
				$custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $name, $value, $options, $pod, $id, $object_params );
1964
1965
				if ( ! empty( $custom ) ) {
1966
					if ( ! is_array( $custom ) ) {
1967
						$data = array();
1968
1969
						$custom = explode( "\n", trim( $custom ) );
1970
1971
						foreach ( $custom as $custom_value ) {
1972
							$custom_label = explode( '|', $custom_value );
1973
1974
							if ( empty( $custom_label ) ) {
1975
								continue;
1976
							}
1977
1978
							if ( 1 === count( $custom_label ) ) {
1979
								$custom_label = $custom_value;
1980
							} else {
1981
								$custom_value = $custom_label[0];
1982
								$custom_label = $custom_label[1];
1983
							}
1984
1985
							$custom_value = trim( (string) $custom_value );
1986
							$custom_label = trim( (string) $custom_label );
1987
1988
							$data[ $custom_value ] = $custom_label;
1989
						}
1990
					} else {
1991
						$data = $custom;
1992
					}//end if
1993
1994
					$simple = true;
1995
				}//end if
1996
			} 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'] ) ) {
1997
				$data = self::$related_objects[ $options[ static::$type . '_object' ] ]['data'];
1998
1999
				$simple = true;
2000
			} 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'] ) ) {
2001
				$data = call_user_func_array(
2002
					self::$related_objects[ $options[ static::$type . '_object' ] ]['data_callback'], array(
2003
						$name,
2004
						$value,
2005
						$options,
2006
						$pod,
2007
						$id,
2008
					)
2009
				);
2010
2011 View Code Duplication
				if ( 'data' === $context ) {
2012
					self::$field_data = array(
2013
						'field'        => $name,
2014
						'id'           => $options['id'],
2015
						'autocomplete' => false,
2016
					);
2017
				}
2018
2019
				$simple = true;
2020
2021
				// Cache data from callback.
2022
				if ( ! empty( $data ) ) {
2023
					self::$related_objects[ $options[ static::$type . '_object' ] ]['data'] = $data;
2024
				}
2025
			} elseif ( 'simple_value' !== $context ) {
2026
				$pick_val = pods_v( static::$type . '_val', $options );
2027
2028
				if ( 'table' === pods_v( static::$type . '_object', $options ) ) {
2029
					$pick_val = pods_v( static::$type . '_table', $options, $pick_val, true );
2030
				}
2031
2032 View Code Duplication
				if ( '__current__' === $pick_val ) {
2033
					if ( is_object( $pod ) ) {
2034
						$pick_val = $pod->pod;
2035
					} elseif ( is_array( $pod ) ) {
2036
						$pick_val = $pod['name'];
2037
					} elseif ( 0 < strlen( $pod ) ) {
2038
						$pick_val = $pod;
2039
					}
2040
				}
2041
2042
				$options['table_info'] = pods_api()->get_table_info( pods_v( static::$type . '_object', $options ), $pick_val, null, null, $object_params );
2043
2044
				$search_data = pods_data();
2045
				$search_data->table( $options['table_info'] );
2046
2047
				if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) && isset( $options['table_info']['pod']['name'] ) ) {
2048
					$search_data->pod    = $options['table_info']['pod']['name'];
2049
					$search_data->fields = $options['table_info']['pod']['fields'];
2050
				}
2051
2052
				$params = array(
2053
					'select'     => "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`",
2054
					'table'      => $search_data->table,
2055
					'where'      => pods_v( static::$type . '_where', $options, (array) $options['table_info']['where_default'], true ),
2056
					'orderby'    => pods_v( static::$type . '_orderby', $options, null, true ),
2057
					'groupby'    => pods_v( static::$type . '_groupby', $options, null, true ),
2058
					'pagination' => false,
2059
					'search'     => false,
2060
				);
2061
2062
				if ( in_array( $options[ static::$type . '_object' ], array( 'site', 'network' ), true ) ) {
2063
					$params['select'] .= ', `t`.`path`';
2064
				}
2065
2066
				if ( ! empty( $params['where'] ) && (array) $options['table_info']['where_default'] !== $params['where'] ) {
2067
					$params['where'] = pods_evaluate_tags( $params['where'], true );
2068
				}
2069
2070
				if ( empty( $params['where'] ) || ( ! is_array( $params['where'] ) && '' === trim( $params['where'] ) ) ) {
2071
					$params['where'] = array();
2072
				} elseif ( ! is_array( $params['where'] ) ) {
2073
					$params['where'] = (array) $params['where'];
2074
				}
2075
2076
				if ( 'value_to_label' === $context ) {
2077
					$params['where'][] = "`t`.`{$search_data->field_id}` = " . number_format( $value, 0, '', '' );
2078
				}
2079
2080
				$display = trim( pods_v( static::$type . '_display', $options ), ' {@}' );
2081
2082
				if ( 0 < strlen( $display ) ) {
2083
					if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) ) {
2084
						if ( isset( $options['table_info']['pod']['object_fields'] ) && isset( $options['table_info']['pod']['object_fields'][ $display ] ) ) {
2085
							$search_data->field_index = $display;
2086
2087
							$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
2088
						} elseif ( isset( $options['table_info']['pod']['fields'][ $display ] ) ) {
2089
							$search_data->field_index = $display;
2090
2091
							if ( 'table' === $options['table_info']['pod']['storage'] && ! in_array(
2092
								$options['table_info']['pod']['type'], array(
2093
									'pod',
2094
									'table',
2095
								), true
2096
							)
2097
							) {
2098
								$params['select'] = "`t`.`{$search_data->field_id}`, `d`.`{$search_data->field_index}`";
2099
							} elseif ( 'meta' === $options['table_info']['pod']['storage'] ) {
2100
								$params['select'] = "`t`.`{$search_data->field_id}`, `{$search_data->field_index}`.`meta_value` AS {$search_data->field_index}";
2101
							} else {
2102
								$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
2103
							}
2104
						}//end if
2105
					} elseif ( isset( $options['table_info']['object_fields'] ) && isset( $options['table_info']['object_fields'][ $display ] ) ) {
2106
						$search_data->field_index = $display;
2107
2108
						$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
2109
					}//end if
2110
				}//end if
2111
2112
				$autocomplete = $this->is_autocomplete( $options );
2113
2114
				$hierarchy = false;
2115
2116 View Code Duplication
				if ( 'data' === $context && ! $autocomplete ) {
2117
					if ( 'single' === pods_v( static::$type . '_format_type', $options, 'single' ) && in_array(
2118
						pods_v( static::$type . '_format_single', $options, 'dropdown' ), array(
2119
							'dropdown',
2120
							'radio',
2121
						), true
2122
					)
2123
					) {
2124
						$hierarchy = true;
2125
					} elseif ( 'multi' === pods_v( static::$type . '_format_type', $options, 'single' ) && in_array(
2126
						pods_v( static::$type . '_format_multi', $options, 'checkbox' ), array(
2127
							'multiselect',
2128
							'checkbox',
2129
						), true
2130
					)
2131
					) {
2132
						$hierarchy = true;
2133
					}
2134
				}
2135
2136
				if ( $hierarchy && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
2137
					$params['select'] .= ', ' . $options['table_info']['field_parent_select'];
2138
				}
2139
2140
				if ( $autocomplete ) {
2141
					if ( 0 === $limit ) {
2142
						$limit = 30;
2143
					}
2144
2145
					$params['limit'] = apply_filters( 'pods_form_ui_field_pick_autocomplete_limit', $limit, $name, $value, $options, $pod, $id, $object_params );
2146
2147
					if ( is_array( $value ) && $params['limit'] < count( $value ) ) {
2148
						$params['limit'] = count( $value );
2149
					}
2150
2151
					$params['page'] = $page;
2152
2153
					if ( 'admin_ajax_relationship' === $context ) {
2154
						$lookup_where = array(
2155
							$search_data->field_index => "`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'",
2156
						);
2157
2158
						// @todo Hook into WPML for each table
2159
						if ( $wpdb->users === $search_data->table ) {
2160
							$lookup_where['display_name'] = "`t`.`display_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2161
							$lookup_where['user_login']   = "`t`.`user_login` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2162
							$lookup_where['user_email']   = "`t`.`user_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2163
						} elseif ( $wpdb->posts === $search_data->table ) {
2164
							$lookup_where['post_title']   = "`t`.`post_title` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2165
							$lookup_where['post_name']    = "`t`.`post_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2166
							$lookup_where['post_content'] = "`t`.`post_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2167
							$lookup_where['post_excerpt'] = "`t`.`post_excerpt` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2168
						} elseif ( $wpdb->terms === $search_data->table ) {
2169
							$lookup_where['name'] = "`t`.`name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2170
							$lookup_where['slug'] = "`t`.`slug` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2171
						} elseif ( $wpdb->comments === $search_data->table ) {
2172
							$lookup_where['comment_content']      = "`t`.`comment_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2173
							$lookup_where['comment_author']       = "`t`.`comment_author` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2174
							$lookup_where['comment_author_email'] = "`t`.`comment_author_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2175
						}
2176
2177
						$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 );
2178
2179
						if ( ! empty( $lookup_where ) ) {
2180
							$params['where'][] = implode( ' OR ', $lookup_where );
2181
						}
2182
2183
						$orderby   = array();
2184
						$orderby[] = "(`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%' ) DESC";
2185
2186
						$pick_orderby = pods_v( static::$type . '_orderby', $options, null, true );
2187
2188
						if ( 0 < strlen( $pick_orderby ) ) {
2189
							$orderby[] = $pick_orderby;
2190
						}
2191
2192
						$orderby[] = "`t`.`{$search_data->field_index}`";
2193
						$orderby[] = "`t`.`{$search_data->field_id}`";
2194
2195
						$params['orderby'] = $orderby;
2196
					}//end if
2197
				} elseif ( 0 < $limit ) {
2198
					$params['limit'] = $limit;
2199
					$params['page']  = $page;
2200
				}//end if
2201
2202
				$extra = '';
2203
2204
				if ( $wpdb->posts === $search_data->table ) {
2205
					$extra = ', `t`.`post_type`';
2206
				} elseif ( $wpdb->terms === $search_data->table ) {
2207
					$extra = ', `tt`.`taxonomy`';
2208
				} elseif ( $wpdb->comments === $search_data->table ) {
2209
					$extra = ', `t`.`comment_type`';
2210
				}
2211
2212
				$params['select'] .= $extra;
2213
2214
				if ( 'user' === pods_v( static::$type . '_object', $options ) ) {
2215
					$roles = pods_v( static::$type . '_user_role', $options );
2216
2217
					if ( ! empty( $roles ) ) {
2218
						$where = array();
2219
2220
						foreach ( (array) $roles as $role ) {
2221
							if ( empty( $role ) || ( pods_clean_name( $role ) !== $role && sanitize_title( $role ) !== $role ) ) {
2222
								continue;
2223
							}
2224
2225
							$where[] = $wpdb->base_prefix . ( ( is_multisite() && ! is_main_site() ) ? get_current_blog_id() . '_' : '' ) . 'capabilities.meta_value LIKE "%\"' . pods_sanitize_like( $role ) . '\"%"';
2226
						}
2227
2228
						if ( ! empty( $where ) ) {
2229
							$params['where'][] = implode( ' OR ', $where );
2230
						}
2231
					}
2232
				}
2233
2234
				$results = $search_data->select( $params );
2235
2236
				if ( $autocomplete && $params['limit'] < $search_data->total_found() ) {
2237
					if ( ! empty( $value ) ) {
2238
						$ids = $value;
2239
2240
						if ( is_array( $ids ) && isset( $ids[0] ) && is_array( $ids[0] ) ) {
2241
							$ids = wp_list_pluck( $ids, $search_data->field_id );
2242
						}
2243
2244
						if ( is_array( $ids ) ) {
2245
							$ids = implode( ', ', $ids );
2246
						}
2247
2248
						if ( is_array( $params['where'] ) ) {
2249
							$params['where'] = implode( ' AND ', $params['where'] );
2250
						}
2251
						if ( ! empty( $params['where'] ) ) {
2252
							$params['where'] .= ' AND ';
2253
						}
2254
2255
						$params['where'] .= "`t`.`{$search_data->field_id}` IN ( {$ids} )";
2256
2257
						$results = $search_data->select( $params );
2258
					}//end if
2259
				} else {
2260
					$autocomplete = false;
2261
				}//end if
2262
2263 View Code Duplication
				if ( 'data' === $context ) {
2264
					self::$field_data = array(
2265
						'field'        => $name,
2266
						'id'           => $options['id'],
2267
						'autocomplete' => $autocomplete,
2268
					);
2269
				}
2270
2271
				if ( $hierarchy && ! $autocomplete && ! empty( $results ) && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
2272
					$select_args = array(
2273
						'id'     => $options['table_info']['field_id'],
2274
						'index'  => $options['table_info']['field_index'],
2275
						'parent' => $options['table_info']['field_parent'],
2276
					);
2277
2278
					$results = pods_hierarchical_select( $results, $select_args );
2279
				}
2280
2281
				$ids = array();
2282
2283
				if ( ! empty( $results ) ) {
2284
					$display_filter = pods_v( 'display_filter', pods_v( 'options', pods_v( $search_data->field_index, $search_data->pod_data['object_fields'] ) ) );
2285
2286
					foreach ( $results as $result ) {
2287
						$result = get_object_vars( $result );
2288
2289
						if ( ! isset( $result[ $search_data->field_id ], $result[ $search_data->field_index ] ) ) {
2290
							continue;
2291
						}
2292
2293
						$result[ $search_data->field_index ] = trim( $result[ $search_data->field_index ] );
2294
2295
						$object      = '';
2296
						$object_type = '';
2297
2298
						if ( $wpdb->posts === $search_data->table && isset( $result['post_type'] ) ) {
2299
							$object      = $result['post_type'];
2300
							$object_type = 'post_type';
2301
						} elseif ( $wpdb->terms === $search_data->table && isset( $result['taxonomy'] ) ) {
2302
							$object      = $result['taxonomy'];
2303
							$object_type = 'taxonomy';
2304
						}
2305
2306
						if ( 0 < strlen( $display_filter ) ) {
2307
							$display_filter_args = pods_v( 'display_filter_args', pods_v( 'options', pods_v( $search_data->field_index, $search_data->pod_data['object_fields'] ) ) );
2308
2309
							$filter_args = array(
2310
								$display_filter,
2311
								$result[ $search_data->field_index ],
2312
							);
2313
2314
							if ( ! empty( $display_filter_args ) ) {
2315
								foreach ( (array) $display_filter_args as $display_filter_arg ) {
2316
									if ( isset( $result[ $display_filter_arg ] ) ) {
2317
										$filter_args[] = $result[ $display_filter_arg ];
2318
									}
2319
								}
2320
							}
2321
2322
							$result[ $search_data->field_index ] = call_user_func_array( 'apply_filters', $filter_args );
2323
						}
2324
2325
						if ( in_array( $options[ static::$type . '_object' ], array( 'site', 'network' ), true ) ) {
2326
							$result[ $search_data->field_index ] = $result[ $search_data->field_index ] . $result['path'];
2327
						} elseif ( '' === $result[ $search_data->field_index ] ) {
2328
							$result[ $search_data->field_index ] = '(No Title)';
2329
						}
2330
2331
						if ( 'admin_ajax_relationship' === $context ) {
2332
							$items[] = $this->build_dfv_field_item_data_recurse_item( $result[ $search_data->field_id ], $result[ $search_data->field_index ], (object) $object_params );
2333
						} else {
2334
							$data[ $result[ $search_data->field_id ] ] = $result[ $search_data->field_index ];
2335
						}
2336
2337
						$ids[] = $result[ $search_data->field_id ];
2338
					}//end foreach
2339
				}//end if
2340
			}//end if
2341
2342
			if ( $simple && 'admin_ajax_relationship' === $context ) {
2343
				$found_data = array();
2344
2345
				foreach ( $data as $k => $v ) {
2346
					if ( false !== stripos( $v, $data_params['query'] ) || false !== stripos( $k, $data_params['query'] ) ) {
2347
						$found_data[ $k ] = $v;
2348
					}
2349
				}
2350
2351
				$data = $found_data;
2352
			}
2353
		}//end if
2354
2355
		if ( 'admin_ajax_relationship' === $context ) {
2356
			if ( empty( $items ) && ! empty( $data ) ) {
2357
				foreach ( $data as $k => $v ) {
2358
					$items[] = array(
2359
						'id'   => $k,
2360
						'text' => $v,
2361
					);
2362
				}
2363
			}
2364
2365
			$data = $items;
2366
		}
2367
2368
		return $data;
2369
2370
	}
2371
2372
	/**
2373
	 * Check if field is autocomplete enabled.
2374
	 *
2375
	 * @param array $options Field options.
2376
	 *
2377
	 * @return bool
2378
	 */
2379
	public function is_autocomplete( $options ) {
2380
2381
		$autocomplete = false;
2382
2383 View Code Duplication
		if ( 'single' === pods_v( static::$type . '_format_type', $options, 'single' ) ) {
2384
			if ( in_array( pods_v( static::$type . '_format_single', $options, 'dropdown' ), array( 'autocomplete', 'list' ), true ) ) {
2385
				$autocomplete = true;
2386
			}
2387
		} elseif ( 'multi' === pods_v( static::$type . '_format_type', $options, 'single' ) ) {
2388
			if ( in_array( pods_v( static::$type . '_format_multi', $options, 'checkbox' ), array( 'autocomplete', 'list' ), true ) ) {
2389
				$autocomplete = true;
2390
			}
2391
		}
2392
2393
		return $autocomplete;
2394
	}
2395
2396
	/**
2397
	 * Handle autocomplete AJAX.
2398
	 *
2399
	 * @since 2.3
2400
	 */
2401
	public function admin_ajax_relationship() {
2402
2403
		pods_session_start();
2404
2405
		// Sanitize input.
2406
		// @codingStandardsIgnoreLine
2407
		$params = pods_unslash( (array) $_POST );
2408
2409 View Code Duplication
		foreach ( $params as $key => $value ) {
2410
			if ( 'action' === $key ) {
2411
				continue;
2412
			}
2413
2414
			unset( $params[ $key ] );
2415
2416
			$params[ str_replace( '_podsfix_', '', $key ) ] = $value;
2417
		}
2418
2419
		$params = (object) $params;
2420
2421
		$uid = @session_id();
2422
2423
		if ( is_user_logged_in() ) {
2424
			$uid = 'user_' . get_current_user_id();
2425
		}
2426
2427
		$nonce_check = 'pods_relationship_' . (int) $params->pod . '_' . $uid . '_' . $params->uri . '_' . (int) $params->field;
2428
2429 View Code Duplication
		if ( ! isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, $nonce_check ) ) {
2430
			pods_error( __( 'Unauthorized request', 'pods' ), PodsInit::$admin );
2431
		}
2432
2433
		if ( empty( self::$api ) ) {
2434
			self::$api = pods_api();
2435
		}
2436
2437
		$pod   = self::$api->load_pod( array( 'id' => (int) $params->pod ) );
2438
		$field = self::$api->load_field(
2439
			array(
2440
				'id'         => (int) $params->field,
2441
				'table_info' => true,
2442
			)
2443
		);
2444
		$id    = (int) $params->id;
2445
2446
		$limit = 15;
2447
2448
		if ( isset( $params->limit ) ) {
2449
			$limit = (int) $params->limit;
2450
		}
2451
2452
		$page = 1;
2453
2454
		if ( isset( $params->page ) ) {
2455
			$page = (int) $params->page;
2456
		}
2457
2458
		if ( ! isset( $params->query ) || '' === trim( $params->query ) ) {
2459
			pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
2460 View Code Duplication
		} elseif ( empty( $pod ) || empty( $field ) || (int) $pod['id'] !== (int) $field['pod_id'] || ! isset( $pod['fields'][ $field['name'] ] ) ) {
2461
			pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
2462
		} elseif ( 'pick' !== $field['type'] || empty( $field['table_info'] ) ) {
2463
			pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
2464
		} elseif ( 'single' === pods_v( static::$type . '_format_type', $field ) && 'autocomplete' === pods_v( static::$type . '_format_single', $field ) ) {
2465
			pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
2466
		} elseif ( 'multi' === pods_v( static::$type . '_format_type', $field ) && 'autocomplete' === pods_v( static::$type . '_format_multi', $field ) ) {
2467
			pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
2468
		}
2469
2470
		$object_params = array(
2471
			// The name of the field.
2472
			'name'        => $field['name'],
2473
			// The value of the field.
2474
			'value'       => null,
2475
			// Field options.
2476
			'options'     => array_merge( $field, $field['options'] ),
2477
			// Pod data.
2478
			'pod'         => $pod,
2479
			// Item ID.
2480
			'id'          => $id,
2481
			// Data context.
2482
			'context'     => 'admin_ajax_relationship',
2483
			'data_params' => $params,
2484
			'page'        => $page,
2485
			'limit'       => $limit,
2486
		);
2487
2488
		$pick_data = apply_filters( 'pods_field_pick_data_ajax', null, $field['name'], null, $field, $pod, $id );
2489
2490
		if ( null !== $pick_data ) {
2491
			$items = $pick_data;
2492
		} else {
2493
			$items = $this->get_object_data( $object_params );
2494
		}
2495
2496
		if ( ! empty( $items ) && isset( $items[0] ) && ! is_array( $items[0] ) ) {
2497
			$new_items = array();
2498
2499
			foreach ( $items as $id => $text ) {
2500
				$new_items[] = array(
2501
					'id'    => $id,
2502
					'text'  => $text,
2503
					'image' => '',
2504
				);
2505
			}
2506
2507
			$items = $new_items;
2508
		}
2509
2510
		$items = apply_filters( 'pods_field_pick_data_ajax_items', $items, $field['name'], null, $field, $pod, $id );
2511
2512
		$items = array(
2513
			'results' => $items,
2514
		);
2515
2516
		wp_send_json( $items );
2517
2518
		die();
2519
		// KBAI!
2520
	}
2521
2522
	/**
2523
	 * Data callback for Post Stati.
2524
	 *
2525
	 * @param string|null       $name    The name of the field.
2526
	 * @param string|array|null $value   The value of the field.
2527
	 * @param array|null        $options Field options.
2528
	 * @param array|null        $pod     Pod data.
2529
	 * @param int|null          $id      Item ID.
2530
	 *
2531
	 * @return array
2532
	 *
2533
	 * @since 2.3
2534
	 */
2535
	public function data_post_stati( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2536
2537
		$data = array();
2538
2539
		$post_stati = get_post_stati( array(), 'objects' );
2540
2541
		foreach ( $post_stati as $post_status ) {
2542
			$data[ $post_status->name ] = $post_status->label;
2543
		}
2544
2545
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2546
2547
	}
2548
2549
	/**
2550
	 * Data callback for User Roles.
2551
	 *
2552
	 * @param string|null       $name    The name of the field.
2553
	 * @param string|array|null $value   The value of the field.
2554
	 * @param array|null        $options Field options.
2555
	 * @param array|null        $pod     Pod data.
2556
	 * @param int|null          $id      Item ID.
2557
	 *
2558
	 * @return array
2559
	 *
2560
	 * @since 2.3
2561
	 */
2562
	public function data_roles( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2563
2564
		$data = array();
2565
2566
		global $wp_roles;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
2567
2568
		foreach ( $wp_roles->role_objects as $key => $role ) {
2569
			$data[ $key ] = $wp_roles->role_names[ $key ];
2570
		}
2571
2572
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2573
2574
	}
2575
2576
	/**
2577
	 * Data callback for User Capabilities.
2578
	 *
2579
	 * @param string|null       $name    The name of the field.
2580
	 * @param string|array|null $value   The value of the field.
2581
	 * @param array|null        $options Field options.
2582
	 * @param array|null        $pod     Pod data.
2583
	 * @param int|null          $id      Item ID.
2584
	 *
2585
	 * @return array
2586
	 *
2587
	 * @since 2.3
2588
	 */
2589
	public function data_capabilities( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2590
2591
		$data = array();
2592
2593
		global $wp_roles;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
2594
2595
		$default_caps = array(
2596
			'activate_plugins',
2597
			'add_users',
2598
			'create_users',
2599
			'delete_others_pages',
2600
			'delete_others_posts',
2601
			'delete_pages',
2602
			'delete_plugins',
2603
			'delete_posts',
2604
			'delete_private_pages',
2605
			'delete_private_posts',
2606
			'delete_published_pages',
2607
			'delete_published_posts',
2608
			'delete_users',
2609
			'edit_dashboard',
2610
			'edit_files',
2611
			'edit_others_pages',
2612
			'edit_others_posts',
2613
			'edit_pages',
2614
			'edit_plugins',
2615
			'edit_posts',
2616
			'edit_private_pages',
2617
			'edit_private_posts',
2618
			'edit_published_pages',
2619
			'edit_published_posts',
2620
			'edit_theme_options',
2621
			'edit_themes',
2622
			'edit_users',
2623
			'import',
2624
			'install_plugins',
2625
			'install_themes',
2626
			'list_users',
2627
			'manage_categories',
2628
			'manage_links',
2629
			'manage_options',
2630
			'moderate_comments',
2631
			'promote_users',
2632
			'publish_pages',
2633
			'publish_posts',
2634
			'read',
2635
			'read_private_pages',
2636
			'read_private_posts',
2637
			'remove_users',
2638
			'switch_themes',
2639
			'unfiltered_html',
2640
			'unfiltered_upload',
2641
			'update_core',
2642
			'update_plugins',
2643
			'update_themes',
2644
			'upload_files',
2645
		);
2646
2647
		$role_caps = array();
2648
2649 View Code Duplication
		foreach ( $wp_roles->role_objects as $key => $role ) {
2650
			if ( is_array( $role->capabilities ) ) {
2651
				foreach ( $role->capabilities as $cap => $grant ) {
2652
					$role_caps[ $cap ] = $cap;
2653
				}
2654
			}
2655
		}
2656
2657
		$role_caps = array_unique( $role_caps );
2658
2659
		$capabilities = array_merge( $default_caps, $role_caps );
2660
2661
		// To support Members filters.
2662
		$capabilities = apply_filters( 'members_get_capabilities', $capabilities );
2663
2664
		$capabilities = apply_filters( 'pods_roles_get_capabilities', $capabilities );
2665
2666
		sort( $capabilities );
2667
2668
		$capabilities = array_unique( $capabilities );
2669
2670
		global $wp_roles;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
2671
2672
		foreach ( $capabilities as $capability ) {
2673
			$data[ $capability ] = $capability;
2674
		}
2675
2676
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2677
2678
	}
2679
2680
	/**
2681
	 * Data callback for Image Sizes.
2682
	 *
2683
	 * @param string|null       $name    The name of the field.
2684
	 * @param string|array|null $value   The value of the field.
2685
	 * @param array|null        $options Field options.
2686
	 * @param array|null        $pod     Pod data.
2687
	 * @param int|null          $id      Item ID.
2688
	 *
2689
	 * @return array
2690
	 *
2691
	 * @since 2.3
2692
	 */
2693 View Code Duplication
	public function data_image_sizes( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2694
2695
		$data = array();
2696
2697
		$image_sizes = get_intermediate_image_sizes();
2698
2699
		foreach ( $image_sizes as $image_size ) {
2700
			$data[ $image_size ] = ucwords( str_replace( '-', ' ', $image_size ) );
2701
		}
2702
2703
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2704
2705
	}
2706
2707
	/**
2708
	 * Data callback for Countries.
2709
	 *
2710
	 * @param string|null       $name    The name of the field.
2711
	 * @param string|array|null $value   The value of the field.
2712
	 * @param array|null        $options Field options.
2713
	 * @param array|null        $pod     Pod data.
2714
	 * @param int|null          $id      Item ID.
2715
	 *
2716
	 * @return array
2717
	 *
2718
	 * @since 2.3
2719
	 */
2720
	public function data_countries( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2721
2722
		$data = array(
2723
			'AF' => __( 'Afghanistan' ),
2724
			'AL' => __( 'Albania' ),
2725
			'DZ' => __( 'Algeria' ),
2726
			'AS' => __( 'American Samoa' ),
2727
			'AD' => __( 'Andorra' ),
2728
			'AO' => __( 'Angola' ),
2729
			'AI' => __( 'Anguilla' ),
2730
			'AQ' => __( 'Antarctica' ),
2731
			'AG' => __( 'Antigua and Barbuda' ),
2732
			'AR' => __( 'Argentina' ),
2733
			'AM' => __( 'Armenia' ),
2734
			'AW' => __( 'Aruba' ),
2735
			'AU' => __( 'Australia' ),
2736
			'AT' => __( 'Austria' ),
2737
			'AZ' => __( 'Azerbaijan' ),
2738
			'BS' => __( 'Bahamas' ),
2739
			'BH' => __( 'Bahrain' ),
2740
			'BD' => __( 'Bangladesh' ),
2741
			'BB' => __( 'Barbados' ),
2742
			'BY' => __( 'Belarus' ),
2743
			'BE' => __( 'Belgium' ),
2744
			'BZ' => __( 'Belize' ),
2745
			'BJ' => __( 'Benin' ),
2746
			'BM' => __( 'Bermuda' ),
2747
			'BT' => __( 'Bhutan' ),
2748
			'BO' => __( 'Bolivia' ),
2749
			'BA' => __( 'Bosnia and Herzegovina' ),
2750
			'BW' => __( 'Botswana' ),
2751
			'BV' => __( 'Bouvet Island' ),
2752
			'BR' => __( 'Brazil' ),
2753
			'BQ' => __( 'British Antarctic Territory' ),
2754
			'IO' => __( 'British Indian Ocean Territory' ),
2755
			'VG' => __( 'British Virgin Islands' ),
2756
			'BN' => __( 'Brunei' ),
2757
			'BG' => __( 'Bulgaria' ),
2758
			'BF' => __( 'Burkina Faso' ),
2759
			'BI' => __( 'Burundi' ),
2760
			'KH' => __( 'Cambodia' ),
2761
			'CM' => __( 'Cameroon' ),
2762
			'CA' => __( 'Canada' ),
2763
			'CT' => __( 'Canton and Enderbury Islands' ),
2764
			'CV' => __( 'Cape Verde' ),
2765
			'KY' => __( 'Cayman Islands' ),
2766
			'CF' => __( 'Central African Republic' ),
2767
			'TD' => __( 'Chad' ),
2768
			'CL' => __( 'Chile' ),
2769
			'CN' => __( 'China' ),
2770
			'CX' => __( 'Christmas Island' ),
2771
			'CC' => __( 'Cocos [Keeling] Islands' ),
2772
			'CO' => __( 'Colombia' ),
2773
			'KM' => __( 'Comoros' ),
2774
			'CG' => __( 'Congo - Brazzaville' ),
2775
			'CD' => __( 'Congo - Kinshasa' ),
2776
			'CK' => __( 'Cook Islands' ),
2777
			'CR' => __( 'Costa Rica' ),
2778
			'HR' => __( 'Croatia' ),
2779
			'CU' => __( 'Cuba' ),
2780
			'CY' => __( 'Cyprus' ),
2781
			'CZ' => __( 'Czech Republic' ),
2782
			'CI' => __( 'Côte d’Ivoire' ),
2783
			'DK' => __( 'Denmark' ),
2784
			'DJ' => __( 'Djibouti' ),
2785
			'DM' => __( 'Dominica' ),
2786
			'DO' => __( 'Dominican Republic' ),
2787
			'NQ' => __( 'Dronning Maud Land' ),
2788
			'DD' => __( 'East Germany' ),
2789
			'EC' => __( 'Ecuador' ),
2790
			'EG' => __( 'Egypt' ),
2791
			'SV' => __( 'El Salvador' ),
2792
			'GQ' => __( 'Equatorial Guinea' ),
2793
			'ER' => __( 'Eritrea' ),
2794
			'EE' => __( 'Estonia' ),
2795
			'ET' => __( 'Ethiopia' ),
2796
			'FK' => __( 'Falkland Islands' ),
2797
			'FO' => __( 'Faroe Islands' ),
2798
			'FJ' => __( 'Fiji' ),
2799
			'FI' => __( 'Finland' ),
2800
			'FR' => __( 'France' ),
2801
			'GF' => __( 'French Guiana' ),
2802
			'PF' => __( 'French Polynesia' ),
2803
			'TF' => __( 'French Southern Territories' ),
2804
			'FQ' => __( 'French Southern and Antarctic Territories' ),
2805
			'GA' => __( 'Gabon' ),
2806
			'GM' => __( 'Gambia' ),
2807
			'GE' => __( 'Georgia' ),
2808
			'DE' => __( 'Germany' ),
2809
			'GH' => __( 'Ghana' ),
2810
			'GI' => __( 'Gibraltar' ),
2811
			'GR' => __( 'Greece' ),
2812
			'GL' => __( 'Greenland' ),
2813
			'GD' => __( 'Grenada' ),
2814
			'GP' => __( 'Guadeloupe' ),
2815
			'GU' => __( 'Guam' ),
2816
			'GT' => __( 'Guatemala' ),
2817
			'GG' => __( 'Guernsey' ),
2818
			'GN' => __( 'Guinea' ),
2819
			'GW' => __( 'Guinea-Bissau' ),
2820
			'GY' => __( 'Guyana' ),
2821
			'HT' => __( 'Haiti' ),
2822
			'HM' => __( 'Heard Island and McDonald Islands' ),
2823
			'HN' => __( 'Honduras' ),
2824
			'HK' => __( 'Hong Kong SAR China' ),
2825
			'HU' => __( 'Hungary' ),
2826
			'IS' => __( 'Iceland' ),
2827
			'IN' => __( 'India' ),
2828
			'ID' => __( 'Indonesia' ),
2829
			'IR' => __( 'Iran' ),
2830
			'IQ' => __( 'Iraq' ),
2831
			'IE' => __( 'Ireland' ),
2832
			'IM' => __( 'Isle of Man' ),
2833
			'IL' => __( 'Israel' ),
2834
			'IT' => __( 'Italy' ),
2835
			'JM' => __( 'Jamaica' ),
2836
			'JP' => __( 'Japan' ),
2837
			'JE' => __( 'Jersey' ),
2838
			'JT' => __( 'Johnston Island' ),
2839
			'JO' => __( 'Jordan' ),
2840
			'KZ' => __( 'Kazakhstan' ),
2841
			'KE' => __( 'Kenya' ),
2842
			'KI' => __( 'Kiribati' ),
2843
			'KW' => __( 'Kuwait' ),
2844
			'KG' => __( 'Kyrgyzstan' ),
2845
			'LA' => __( 'Laos' ),
2846
			'LV' => __( 'Latvia' ),
2847
			'LB' => __( 'Lebanon' ),
2848
			'LS' => __( 'Lesotho' ),
2849
			'LR' => __( 'Liberia' ),
2850
			'LY' => __( 'Libya' ),
2851
			'LI' => __( 'Liechtenstein' ),
2852
			'LT' => __( 'Lithuania' ),
2853
			'LU' => __( 'Luxembourg' ),
2854
			'MO' => __( 'Macau SAR China' ),
2855
			'MK' => __( 'Macedonia' ),
2856
			'MG' => __( 'Madagascar' ),
2857
			'MW' => __( 'Malawi' ),
2858
			'MY' => __( 'Malaysia' ),
2859
			'MV' => __( 'Maldives' ),
2860
			'ML' => __( 'Mali' ),
2861
			'MT' => __( 'Malta' ),
2862
			'MH' => __( 'Marshall Islands' ),
2863
			'MQ' => __( 'Martinique' ),
2864
			'MR' => __( 'Mauritania' ),
2865
			'MU' => __( 'Mauritius' ),
2866
			'YT' => __( 'Mayotte' ),
2867
			'FX' => __( 'Metropolitan France' ),
2868
			'MX' => __( 'Mexico' ),
2869
			'FM' => __( 'Micronesia' ),
2870
			'MI' => __( 'Midway Islands' ),
2871
			'MD' => __( 'Moldova' ),
2872
			'MC' => __( 'Monaco' ),
2873
			'MN' => __( 'Mongolia' ),
2874
			'ME' => __( 'Montenegro' ),
2875
			'MS' => __( 'Montserrat' ),
2876
			'MA' => __( 'Morocco' ),
2877
			'MZ' => __( 'Mozambique' ),
2878
			'MM' => __( 'Myanmar [Burma]' ),
2879
			'NA' => __( 'Namibia' ),
2880
			'NR' => __( 'Nauru' ),
2881
			'NP' => __( 'Nepal' ),
2882
			'NL' => __( 'Netherlands' ),
2883
			'AN' => __( 'Netherlands Antilles' ),
2884
			'NT' => __( 'Neutral Zone' ),
2885
			'NC' => __( 'New Caledonia' ),
2886
			'NZ' => __( 'New Zealand' ),
2887
			'NI' => __( 'Nicaragua' ),
2888
			'NE' => __( 'Niger' ),
2889
			'NG' => __( 'Nigeria' ),
2890
			'NU' => __( 'Niue' ),
2891
			'NF' => __( 'Norfolk Island' ),
2892
			'KP' => __( 'North Korea' ),
2893
			'VD' => __( 'North Vietnam' ),
2894
			'MP' => __( 'Northern Mariana Islands' ),
2895
			'NO' => __( 'Norway' ),
2896
			'OM' => __( 'Oman' ),
2897
			'PC' => __( 'Pacific Islands Trust Territory' ),
2898
			'PK' => __( 'Pakistan' ),
2899
			'PW' => __( 'Palau' ),
2900
			'PS' => __( 'Palestinian Territories' ),
2901
			'PA' => __( 'Panama' ),
2902
			'PZ' => __( 'Panama Canal Zone' ),
2903
			'PG' => __( 'Papua New Guinea' ),
2904
			'PY' => __( 'Paraguay' ),
2905
			'YD' => __( "People's Democratic Republic of Yemen" ),
2906
			'PE' => __( 'Peru' ),
2907
			'PH' => __( 'Philippines' ),
2908
			'PN' => __( 'Pitcairn Islands' ),
2909
			'PL' => __( 'Poland' ),
2910
			'PT' => __( 'Portugal' ),
2911
			'PR' => __( 'Puerto Rico' ),
2912
			'QA' => __( 'Qatar' ),
2913
			'RO' => __( 'Romania' ),
2914
			'RU' => __( 'Russia' ),
2915
			'RW' => __( 'Rwanda' ),
2916
			'RE' => __( 'Réunion' ),
2917
			'BL' => __( 'Saint Barthélemy' ),
2918
			'SH' => __( 'Saint Helena' ),
2919
			'KN' => __( 'Saint Kitts and Nevis' ),
2920
			'LC' => __( 'Saint Lucia' ),
2921
			'MF' => __( 'Saint Martin' ),
2922
			'PM' => __( 'Saint Pierre and Miquelon' ),
2923
			'VC' => __( 'Saint Vincent and the Grenadines' ),
2924
			'WS' => __( 'Samoa' ),
2925
			'SM' => __( 'San Marino' ),
2926
			'SA' => __( 'Saudi Arabia' ),
2927
			'SN' => __( 'Senegal' ),
2928
			'RS' => __( 'Serbia' ),
2929
			'CS' => __( 'Serbia and Montenegro' ),
2930
			'SC' => __( 'Seychelles' ),
2931
			'SL' => __( 'Sierra Leone' ),
2932
			'SG' => __( 'Singapore' ),
2933
			'SK' => __( 'Slovakia' ),
2934
			'SI' => __( 'Slovenia' ),
2935
			'SB' => __( 'Solomon Islands' ),
2936
			'SO' => __( 'Somalia' ),
2937
			'ZA' => __( 'South Africa' ),
2938
			'GS' => __( 'South Georgia and the South Sandwich Islands' ),
2939
			'KR' => __( 'South Korea' ),
2940
			'ES' => __( 'Spain' ),
2941
			'LK' => __( 'Sri Lanka' ),
2942
			'SD' => __( 'Sudan' ),
2943
			'SR' => __( 'Suriname' ),
2944
			'SJ' => __( 'Svalbard and Jan Mayen' ),
2945
			'SZ' => __( 'Swaziland' ),
2946
			'SE' => __( 'Sweden' ),
2947
			'CH' => __( 'Switzerland' ),
2948
			'SY' => __( 'Syria' ),
2949
			'ST' => __( 'São Tomé and Príncipe' ),
2950
			'TW' => __( 'Taiwan' ),
2951
			'TJ' => __( 'Tajikistan' ),
2952
			'TZ' => __( 'Tanzania' ),
2953
			'TH' => __( 'Thailand' ),
2954
			'TL' => __( 'Timor-Leste' ),
2955
			'TG' => __( 'Togo' ),
2956
			'TK' => __( 'Tokelau' ),
2957
			'TO' => __( 'Tonga' ),
2958
			'TT' => __( 'Trinidad and Tobago' ),
2959
			'TN' => __( 'Tunisia' ),
2960
			'TR' => __( 'Turkey' ),
2961
			'TM' => __( 'Turkmenistan' ),
2962
			'TC' => __( 'Turks and Caicos Islands' ),
2963
			'TV' => __( 'Tuvalu' ),
2964
			'UM' => __( 'U.S. Minor Outlying Islands' ),
2965
			'PU' => __( 'U.S. Miscellaneous Pacific Islands' ),
2966
			'VI' => __( 'U.S. Virgin Islands' ),
2967
			'UG' => __( 'Uganda' ),
2968
			'UA' => __( 'Ukraine' ),
2969
			'SU' => __( 'Union of Soviet Socialist Republics' ),
2970
			'AE' => __( 'United Arab Emirates' ),
2971
			'GB' => __( 'United Kingdom' ),
2972
			'US' => __( 'United States' ),
2973
			'ZZ' => __( 'Unknown or Invalid Region' ),
2974
			'UY' => __( 'Uruguay' ),
2975
			'UZ' => __( 'Uzbekistan' ),
2976
			'VU' => __( 'Vanuatu' ),
2977
			'VA' => __( 'Vatican City' ),
2978
			'VE' => __( 'Venezuela' ),
2979
			'VN' => __( 'Vietnam' ),
2980
			'WK' => __( 'Wake Island' ),
2981
			'WF' => __( 'Wallis and Futuna' ),
2982
			'EH' => __( 'Western Sahara' ),
2983
			'YE' => __( 'Yemen' ),
2984
			'ZM' => __( 'Zambia' ),
2985
			'ZW' => __( 'Zimbabwe' ),
2986
			'AX' => __( 'Åland Islands' ),
2987
		);
2988
2989
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2990
2991
	}
2992
2993
	/**
2994
	 * Data callback for US States.
2995
	 *
2996
	 * @param string|null       $name    The name of the field.
2997
	 * @param string|array|null $value   The value of the field.
2998
	 * @param array|null        $options Field options.
2999
	 * @param array|null        $pod     Pod data.
3000
	 * @param int|null          $id      Item ID.
3001
	 *
3002
	 * @return array
3003
	 *
3004
	 * @since 2.3
3005
	 */
3006
	public function data_us_states( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3007
3008
		$data = array(
3009
			'AL' => __( 'Alabama' ),
3010
			'AK' => __( 'Alaska' ),
3011
			'AZ' => __( 'Arizona' ),
3012
			'AR' => __( 'Arkansas' ),
3013
			'CA' => __( 'California' ),
3014
			'CO' => __( 'Colorado' ),
3015
			'CT' => __( 'Connecticut' ),
3016
			'DE' => __( 'Delaware' ),
3017
			'DC' => __( 'District Of Columbia' ),
3018
			'FL' => __( 'Florida' ),
3019
			'GA' => __( 'Georgia' ),
3020
			'HI' => __( 'Hawaii' ),
3021
			'ID' => __( 'Idaho' ),
3022
			'IL' => __( 'Illinois' ),
3023
			'IN' => __( 'Indiana' ),
3024
			'IA' => __( 'Iowa' ),
3025
			'KS' => __( 'Kansas' ),
3026
			'KY' => __( 'Kentucky' ),
3027
			'LA' => __( 'Louisiana' ),
3028
			'ME' => __( 'Maine' ),
3029
			'MD' => __( 'Maryland' ),
3030
			'MA' => __( 'Massachusetts' ),
3031
			'MI' => __( 'Michigan' ),
3032
			'MN' => __( 'Minnesota' ),
3033
			'MS' => __( 'Mississippi' ),
3034
			'MO' => __( 'Missouri' ),
3035
			'MT' => __( 'Montana' ),
3036
			'NE' => __( 'Nebraska' ),
3037
			'NV' => __( 'Nevada' ),
3038
			'NH' => __( 'New Hampshire' ),
3039
			'NJ' => __( 'New Jersey' ),
3040
			'NM' => __( 'New Mexico' ),
3041
			'NY' => __( 'New York' ),
3042
			'NC' => __( 'North Carolina' ),
3043
			'ND' => __( 'North Dakota' ),
3044
			'OH' => __( 'Ohio' ),
3045
			'OK' => __( 'Oklahoma' ),
3046
			'OR' => __( 'Oregon' ),
3047
			'PA' => __( 'Pennsylvania' ),
3048
			'RI' => __( 'Rhode Island' ),
3049
			'SC' => __( 'South Carolina' ),
3050
			'SD' => __( 'South Dakota' ),
3051
			'TN' => __( 'Tennessee' ),
3052
			'TX' => __( 'Texas' ),
3053
			'UT' => __( 'Utah' ),
3054
			'VT' => __( 'Vermont' ),
3055
			'VA' => __( 'Virginia' ),
3056
			'WA' => __( 'Washington' ),
3057
			'WV' => __( 'West Virginia' ),
3058
			'WI' => __( 'Wisconsin' ),
3059
			'WY' => __( 'Wyoming' ),
3060
		);
3061
3062
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
3063
3064
	}
3065
3066
	/**
3067
	 * Data callback for CA Provinces.
3068
	 *
3069
	 * @param string|null       $name    The name of the field.
3070
	 * @param string|array|null $value   The value of the field.
3071
	 * @param array|null        $options Field options.
3072
	 * @param array|null        $pod     Pod data.
3073
	 * @param int|null          $id      Item ID.
3074
	 *
3075
	 * @return array
3076
	 *
3077
	 * @since 2.3
3078
	 */
3079
	public function data_ca_provinces( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3080
3081
		$data = array(
3082
			'AB' => __( 'Alberta' ),
3083
			'BC' => __( 'British Columbia' ),
3084
			'MB' => __( 'Manitoba' ),
3085
			'NB' => __( 'New Brunswick' ),
3086
			'NL' => __( 'Newfoundland and Labrador' ),
3087
			'NT' => __( 'Northwest Territories' ),
3088
			'NS' => __( 'Nova Scotia' ),
3089
			'NU' => __( 'Nunavut' ),
3090
			'ON' => __( 'Ontario' ),
3091
			'PE' => __( 'Prince Edward Island' ),
3092
			'QC' => __( 'Quebec' ),
3093
			'SK' => __( 'Saskatchewan' ),
3094
			'YT' => __( 'Yukon' ),
3095
		);
3096
3097
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
3098
3099
	}
3100
3101
	/**
3102
	 * Data callback for US States.
3103
	 *
3104
	 * @param string|null       $name    The name of the field.
3105
	 * @param string|array|null $value   The value of the field.
3106
	 * @param array|null        $options Field options.
3107
	 * @param array|null        $pod     Pod data.
3108
	 * @param int|null          $id      Item ID.
3109
	 *
3110
	 * @return array
3111
	 *
3112
	 * @since 2.3
3113
	 */
3114
	public function data_days_of_week( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3115
3116
		/**
3117
		 * @var WP_Locale
3118
		 */
3119
		global $wp_locale;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
3120
3121
		return $wp_locale->weekday;
3122
3123
	}
3124
3125
	/**
3126
	 * Data callback for US States.
3127
	 *
3128
	 * @param string|null       $name    The name of the field.
3129
	 * @param string|array|null $value   The value of the field.
3130
	 * @param array|null        $options Field options.
3131
	 * @param array|null        $pod     Pod data.
3132
	 * @param int|null          $id      Item ID.
3133
	 *
3134
	 * @return array
3135
	 *
3136
	 * @since 2.3
3137
	 */
3138
	public function data_months_of_year( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
3139
3140
		/**
3141
		 * @var WP_Locale
3142
		 */
3143
		global $wp_locale;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
3144
3145
		return $wp_locale->month;
3146
3147
	}
3148
3149
	/**
3150
	 * Add our modal input to the form so we can track whether we're in our modal during saving or not.
3151
	 */
3152
	public function admin_modal_input() {
3153
3154
		if ( ! pods_is_modal_window() ) {
3155
			return;
3156
		}
3157
3158
		echo '<input name="pods_modal" type="hidden" value="1" />';
3159
3160
	}
3161
3162
	/**
3163
	 * Bail to send new saved data back to our modal handler.
3164
	 *
3165
	 * @param int    $item_id    Item ID.
3166
	 * @param string $item_title Item title.
3167
	 * @param object $field_args Field arguments.
3168
	 */
3169
	public function admin_modal_bail( $item_id, $item_title, $field_args ) {
3170
3171
		$model_data = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $field_args );
3172
		?>
3173
			<script type="text/javascript">
3174
				window.parent.jQuery( window.parent ).trigger(
3175
					'dfv:modal:update',
3176
					<?php echo wp_json_encode( $model_data, JSON_HEX_TAG ); ?>
3177
				);
3178
			</script>
3179
		<?php
3180
3181
		die();
3182
3183
	}
3184
3185
	/**
3186
	 * Bail to send new saved data back to our modal handler.
3187
	 *
3188
	 * @param int    $item_id    Item ID.
3189
	 * @param string $item_title Item title.
3190
	 * @param object $field_args Field arguments.
3191
	 */
3192
	public function admin_modal_bail_JSON( $item_id, $item_title, $field_args ) {
3193
3194
		$model_data = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $field_args );
3195
		echo wp_json_encode( $model_data, JSON_HEX_TAG );
3196
3197
		die();
3198
	}
3199
3200
	/**
3201
	 * Bail on Post save redirect for Admin modal.
3202
	 *
3203
	 * @param string $location The destination URL.
3204
	 * @param int    $post_id  The post ID.
3205
	 *
3206
	 * @return string
3207
	 */
3208
	public function admin_modal_bail_post_redirect( $location, $post_id ) {
3209
3210
		if ( ! pods_is_modal_window() ) {
3211
			return $location;
3212
		}
3213
3214
		$post_title = get_the_title( $post_id );
3215
3216
		$field_args = (object) array(
3217
			'options' => array(
3218
				'pick_object' => 'post_type',
3219
				'pick_val'    => get_post_type( $post_id ),
3220
			),
3221
			'value'   => array(
3222
				$post_id => $post_title,
3223
			),
3224
		);
3225
3226
		$this->admin_modal_bail( $post_id, $post_title, $field_args );
3227
3228
		return $location;
3229
3230
	}
3231
3232
	/**
3233
	 * Hook into term updating process to bail on redirect.
3234
	 */
3235
	public function admin_modal_bail_term_action() {
3236
3237
		if ( ! pods_is_modal_window() ) {
3238
			return;
3239
		}
3240
3241
		add_action( 'created_term', array( $this, 'admin_modal_bail_term' ), 10, 3 );
3242
		add_action( 'edited_term', array( $this, 'admin_modal_bail_term' ), 10, 3 );
3243
3244
	}
3245
3246
	/**
3247
	 * Bail on Term save redirect for Admin modal.
3248
	 *
3249
	 * @param int    $term_id  Term ID.
3250
	 * @param int    $tt_id    Term taxonomy ID.
3251
	 * @param string $taxonomy Taxonomy slug.
3252
	 */
3253
	public function admin_modal_bail_term( $term_id, $tt_id, $taxonomy ) {
3254
3255
		if ( ! pods_is_modal_window() ) {
3256
			return;
3257
		}
3258
3259
		$term = get_term( $term_id );
3260
3261
		if ( ! $term || is_wp_error( $term ) ) {
3262
			return;
3263
		}
3264
3265
		$field_args = (object) array(
3266
			'options' => array(
3267
				'pick_object' => 'taxonomy',
3268
				'pick_val'    => $term->taxonomy,
3269
			),
3270
			'value'   => array(
3271
				$term->term_id => $term->name,
3272
			),
3273
		);
3274
3275
		$this->admin_modal_bail( $term->term_id, $term->name, $field_args );
3276
3277
	}
3278
3279
	/**
3280
	 * Hook into user updating process to bail on redirect.
3281
	 */
3282
	public function admin_modal_bail_user_action() {
3283
3284
		if ( ! pods_is_modal_window() ) {
3285
			return;
3286
		}
3287
3288
		add_filter( 'wp_redirect', array( $this, 'admin_modal_bail_user_redirect' ) );
3289
3290
	}
3291
3292
	/**
3293
	 * Bail on User save redirect for Admin modal.
3294
	 *
3295
	 * @param string $location The destination URL.
3296
	 *
3297
	 * @return string
3298
	 */
3299
	public function admin_modal_bail_user_redirect( $location ) {
3300
3301
		if ( ! pods_is_modal_window() ) {
3302
			return $location;
3303
		}
3304
3305
		global $user_id;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
3306
3307
		$user = get_userdata( $user_id );
3308
3309
		if ( ! $user || is_wp_error( $user ) ) {
3310
			return $location;
3311
		}
3312
3313
		$field_args = (object) array(
3314
			'options' => array(
3315
				'pick_object' => 'user',
3316
				'pick_val'    => '',
3317
			),
3318
			'value'   => array(
3319
				$user->ID => $user->display_name,
3320
			),
3321
		);
3322
3323
		$this->admin_modal_bail( $user->ID, $user->display_name, $field_args );
3324
3325
		return $location;
3326
3327
	}
3328
3329
	/**
3330
	 * Bail on Pod item save for Admin modal.
3331
	 *
3332
	 * @param int       $id     Item ID.
3333
	 * @param array     $params save_pod_item parameters.
3334
	 * @param null|Pods $obj    Pod object (if set).
3335
	 */
3336
	public function admin_modal_bail_pod( $id, $params, $obj ) {
3337
3338
		if ( ! pods_is_modal_window() ) {
3339
			return;
3340
		}
3341
3342
		if ( ! $obj ) {
3343
			$obj = pods( $params['pod'] );
3344
		}
3345
3346
		if ( ! $obj || ! $obj->fetch( $id ) ) {
3347
			return;
3348
		}
3349
3350
		$item_id    = $obj->id();
3351
		$item_title = $obj->index();
3352
3353
		$field_args = (object) array(
3354
			'options' => array(
3355
				'pick_object' => $obj->pod_data['type'],
3356
				'pick_val'    => $obj->pod,
3357
			),
3358
			'value'   => array(
3359
				$obj->id() => $item_title,
3360
			),
3361
		);
3362
3363
		$this->admin_modal_bail_JSON( $item_id, $item_title, $field_args );
3364
3365
	}
3366
3367
}
3368