Completed
Pull Request — 2.x (#4187)
by Scott Kingsley
06:00
created

PodsField_Pick::build_dfv_field_options()   F

Complexity

Conditions 22
Paths 832

Size

Total Lines 87
Code Lines 53

Duplication

Lines 22
Ratio 25.29 %

Importance

Changes 0
Metric Value
cc 22
eloc 53
nc 832
nop 2
dl 22
loc 87
rs 2.2988
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
775
		do_action( 'pods_form_ui_field_pick_input', pods_v( self::$type . '_format_type', $options, 'single' ), $name, $value, $options, $pod, $id );
776
777
		// @todo Support custom integrations.
778
		do_action( 'pods_form_ui_field_pick_input', pods_v( self::$type . '_format_type', $options, 'single' ), $name, $value, $options, $pod, $id );
779
780
	}
781
782
	/**
783
	 * {@inheritdoc}
784
	 */
785
	public function build_dfv_field_options( $options, $args ) {
786
787
		$options['grouped'] = 1;
788
789
		if ( empty( $options[ $args->type . '_object' ] ) ) {
790
			$options[ $args->type . '_object' ] = '';
791
		}
792
793
		if ( empty( $options[ $args->type . '_val' ] ) ) {
794
			$options[ $args->type . '_val' ] = '';
795
		}
796
797
		$options['table_info'] = array();
798
799
		$custom = pods_v( $args->type . '_custom', $options, false );
800
801
		$custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $args->name, $args->value, $options, $args->pod, $args->id );
802
803
		$ajax = false;
804
805
		if ( ( 'custom-simple' !== pods_v( $args->type . '_object', $options ) || empty( $custom ) ) && '' !== pods_v( $args->type . '_object', $options, '', true ) ) {
806
			$ajax = true;
807
		}
808
809
		if ( ! empty( self::$field_data ) && self::$field_data['id'] === $options['id'] ) {
810
			$ajax = (boolean) self::$field_data['autocomplete'];
811
		}
812
813
		$ajax = apply_filters( 'pods_form_ui_field_pick_ajax', $ajax, $args->name, $args->value, $options, $args->pod, $args->id );
814
815
		if ( 0 === (int) pods_v( $args->type . '_ajax', $options, 1 ) ) {
816
			$ajax = false;
817
		}
818
819
		$options[ $args->type . '_ajax' ] = (int) $ajax;
820
821
		$format_type = pods_v( $args->type . '_format_type', $options, 'single', true );
822
823
		$limit = 1;
824
825
		if ( 'single' === $format_type ) {
826
			$format_single = pods_v( $args->type . '_format_single', $options, 'dropdown', true );
827
828 View Code Duplication
			if ( 'dropdown' === $format_single ) {
829
				$options['view_name'] = 'select';
830
			} elseif ( 'radio' === $format_single ) {
831
				$options['view_name'] = 'radio';
832
			} elseif ( 'autocomplete' === $format_single ) {
833
				$options['view_name'] = 'select2';
834
			} elseif ( 'list' === $format_single ) {
835
				$options['view_name'] = 'list';
836
			} else {
837
				$options['view_name'] = $format_single;
838
			}
839
		} elseif ( 'multi' === $format_type ) {
840
			$format_multi = pods_v( $args->type . '_format_multi', $options, 'checkbox', true );
841
842
			if ( ! empty( $args->value ) && ! is_array( $args->value ) ) {
843
				$args->value = explode( ',', $args->value );
844
			}
845
846 View Code Duplication
			if ( 'checkbox' === $format_multi ) {
847
				$options['view_name'] = 'checkbox';
848
			} elseif ( 'multiselect' === $format_multi ) {
849
				$options['view_name'] = 'select';
850
			} elseif ( 'autocomplete' === $format_multi ) {
851
				$options['view_name'] = 'select2';
852
			} elseif ( 'list' === $format_multi ) {
853
				$options['view_name'] = 'list';
854
			} else {
855
				$options['view_name'] = $format_multi;
856
			}
857
858
			$limit = 0;
859
860
			if ( ! empty( $options[ $args->type . '_limit' ] ) ) {
861
				$limit = absint( $options[ $args->type . '_limit' ] );
862
			}
863
		} else {
864
			$options['view_name'] = $format_type;
865
		}
866
867
		$options[ $args->type . '_limit' ] = $limit;
868
869
		return $options;
870
871
	}
872
873
	/**
874
	 * {@inheritdoc}
875
	 */
876
	public function build_dfv_field_config( $args ) {
877
878
		$config = parent::build_dfv_field_config( $args );
879
880
		if ( ! isset( $config['optgroup'] ) ) {
881
			$config['optgroup'] = false;
882
		}
883
884
		/**
885
		 * Filter on whether to allow modals to be used on the front of the site (in an non-admin area).
886
		 *
887
		 * @param boolean $show_on_front
888
		 *
889
		 * @since 2.7
890
		 */
891
		$show_on_front = apply_filters( 'pods_ui_dfv_pick_modals_show_on_front', false );
892
893
		/**
894
		 * Filter on whether to allow nested modals to be used (modals within modals).
895
		 *
896
		 * @param boolean $allow_nested_modals
897
		 *
898
		 * @since 2.7
899
		 */
900
		$allow_nested_modals = apply_filters( 'pods_ui_dfv_pick_modals_allow_nested', false );
901
902
		// Disallow add/edit outside the admin and when we're already in a modal
903
		if ( ( ! $show_on_front && ! is_admin() ) || ( ! $allow_nested_modals && pods_is_modal_window() ) ) {
904
			$config[ $args->type . '_allow_add_new' ]  = false;
905
			$config[ $args->type . '_show_edit_link' ] = false;
906
		}
907
908
		$file_name  = '';
909
		$query_args = array();
910
911
		// Set the file name and args based on the content type of the relationship
912
		switch ( $args->options['pick_object'] ) {
913
			case 'post_type':
914
				if ( ! empty( $args->options['pick_val'] ) ) {
915
					$post_type_obj = get_post_type_object( $args->options['pick_val'] );
916
917
					if ( $post_type_obj && current_user_can( $post_type_obj->cap->create_posts ) ) {
918
						$file_name  = 'post-new.php';
919
						$query_args = array(
920
							'post_type' => $args->options['pick_val'],
921
						);
922
					}
923
				}
924
925
				break;
926
927
			case 'taxonomy':
928
				// @todo Fix add new modal issues
929
				/*if ( ! empty( $args->options['pick_val'] ) ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% 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...
930
					$taxonomy_obj = get_taxonomy( $args->options['pick_val'] );
931
932
					if ( $taxonomy_obj && current_user_can( $taxonomy_obj->cap->edit_terms ) ) {
933
						$file_name  = 'edit-tags.php';
934
						$query_args = array(
935
							'taxonomy' => $args->options['pick_val'],
936
						);
937
					}
938
				}*/
939
940
				break;
941
942
			case 'user':
943
				if ( current_user_can( 'create_users' ) ) {
944
					$file_name  = 'user-new.php';
945
				}
946
947
				break;
948
949
			case 'pod':
950
				if ( ! empty( $args->options['pick_val'] ) ) {
951
					if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
952
						$file_name  = 'admin.php';
953
						$query_args = array(
954
							'page'   => 'pods-manage-' . $args->options['pick_val'],
955
							'action' => 'add',
956
						);
957
958
					}
959
				}
960
961
				break;
962
		}
963
964
		$iframe_src = '';
965
966
		if ( ! empty( $file_name ) ) {
967
			// @todo: Replace string literal with defined constant
968
			$query_args['pods_modal'] = 1;
969
970
			// Add args we always need
971
			$iframe_src = add_query_arg( $query_args, admin_url( $file_name ) );
972
		}
973
974
		$config['iframe_src']   = $iframe_src;
975
		$config['iframe_title_add'] = sprintf( __( '%s: Add New', 'pods' ), $args->options['label'] );
976
		$config['iframe_title_edit'] = sprintf( __( '%s: Edit', 'pods' ), $args->options['label'] );
977
978
		return $config;
979
980
	}
981
982
	/**
983
	 * {@inheritdoc}
984
	 */
985
	public function build_dfv_field_item_data( $args ) {
986
987
		$args->options['supports_thumbnails'] = null;
988
989
		$item_data = array();
990
991
		if ( ! empty( $args->options['data'] ) ) {
992
			$item_data = $this->build_dfv_field_item_data_recurse( $args->options['data'], $args );
993
		}
994
995
		return $item_data;
996
997
	}
998
999
	/**
1000
	 * Loop through relationship data and expand item data with additional information for DFV.
1001
	 *
1002
	 * @param array     $data    Item data to expand.
1003
	 * @param object    $args    {
1004
	 *                           Field information arguments.
1005
	 *
1006
	 * @type string     $name    Field name
1007
	 * @type string     $type    Field type
1008
	 * @type array      $options Field options
1009
	 * @type mixed      $value   Current value
1010
	 * @type array      $pod     Pod information
1011
	 * @type int|string $id      Current item ID
1012
	 * }
1013
	 *
1014
	 * @return array
1015
	 */
1016
	public function build_dfv_field_item_data_recurse( $data, $args ) {
1017
1018
		$item_data = array();
1019
1020
		foreach ( $data as $item_id => $item_title ) {
1021
			if ( is_array( $item_title ) ) {
1022
				$args->options['optgroup'] = true;
1023
1024
				$item_data[] = array(
1025
					'label'      => $item_id,
1026
					'collection' => $this->build_dfv_field_item_data_recurse( $item_title, $args ),
1027
				);
1028
			} else {
1029
				$item_data[] = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args );
1030
			}
1031
		}
1032
1033
		return $item_data;
1034
1035
	}
1036
1037
	/**
1038
	 * Loop through relationship data and expand item data with additional information for DFV.
1039
	 *
1040
	 * @param int|string $item_id
1041
	 * @param string     $item_title
1042
	 * @param object     $args    {
1043
	 *                            Field information arguments.
1044
	 *
1045
	 * @type string      $name    Field name
1046
	 * @type string      $type    Field type
1047
	 * @type array       $options Field options
1048
	 * @type mixed       $value   Current value
1049
	 * @type array       $pod     Pod information
1050
	 * @type int|string  $id      Current item ID
1051
	 * }
1052
	 *
1053
	 * @return array
1054
	 */
1055
	public function build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args ) {
1056
1057
		$use_dashicon = false;
1058
		$icon         = '';
1059
		$img_icon     = '';
1060
		$edit_link    = '';
1061
		$link         = '';
1062
1063
		if ( ! isset( $args->options['supports_thumbnails'] ) ) {
1064
			$args->options['supports_thumbnails'] = null;
1065
		}
1066
1067
		switch ( $args->options['pick_object'] ) {
1068
			case 'post_type':
1069
				$item_id = (int) $item_id;
1070
1071
				if ( null === $args->options['supports_thumbnails'] && ! empty( $args->options['pick_val'] ) ) {
1072
					$args->options['supports_thumbnails'] = post_type_supports( $args->options['pick_val'], 'thumbnail' );
1073
				}
1074
1075
				if ( true === $args->options['supports_thumbnails'] ) {
1076
					$post_thumbnail_id = get_post_thumbnail_id( $item_id );
1077
1078
					if ( $post_thumbnail_id ) {
1079
						$thumb = wp_get_attachment_image_src( $post_thumbnail_id, 'thumbnail', false );
1080
					}
1081
1082
					if ( ! empty( $thumb[0] ) ) {
1083
						$img_icon = $thumb[0];
1084
					}
1085
				}
1086
1087
				if ( empty( $img_icon ) ) {
1088
1089
					// Default icon for posts.
1090
					$icon = 'dashicons-admin-post';
1091
1092
					// Post type icons.
1093
					$post_type = (array) get_post_type_object( get_post_type( $item_id ) );
1094
1095
					if ( ! empty( $post_type['menu_icon'] ) ) {
1096
						// Post specific icon.
1097
						$icon = $post_type['menu_icon'];
1098
					} elseif ( isset( $post_type['name'] ) && 'page' ) {
1099
						switch ( $post_type['name'] ) {
1100
							case 'page':
1101
								// Default for pages.
1102
								$icon = 'dashicons-admin-page';
1103
							break;
1104
							case 'attachment':
1105
								// Default for attachments.
1106
								$icon = 'dashicons-admin-media';
1107
							break;
1108
						}
1109
					}
1110
				}
1111
1112
				$edit_link = get_edit_post_link( $item_id, 'raw' );
1113
1114
				$link = get_permalink( $item_id );
1115
1116
				break;
1117
1118
			case 'taxonomy':
1119
				$item_id = (int) $item_id;
1120
1121
				if ( ! empty( $args->options['pick_val'] ) ) {
1122
1123
					// Default icon for taxonomy.
1124
					$icon = 'dashicons-category';
1125
1126
					// Change icon for non-hierarchical taxonomies.
1127
					$taxonomy = get_term( $item_id );
1128
					if ( isset( $taxonomy->taxonomy ) ) {
1129
						$taxonomy = (array) get_taxonomy( $taxonomy->taxonomy );
1130
						if ( isset( $taxonomy['hierarchical'] ) && ! $taxonomy['hierarchical'] ) {
1131
							$icon = 'dashicons-tag';
1132
						}
1133
					}
1134
1135
					$edit_link = get_edit_term_link( $item_id, $args->options['pick_val'] );
1136
1137
					$link = get_term_link( $item_id, $args->options['pick_val'] );
1138
				}
1139
1140
				break;
1141
1142
			case 'user':
1143
				$item_id = (int) $item_id;
1144
1145
				$args->options['supports_thumbnails'] = true;
1146
1147
				$icon = 'dashicons-admin-users';
1148
				$img_icon = get_avatar_url( $item_id, array( 'size' => 150 ) );
1149
1150
				$edit_link = get_edit_user_link( $item_id );
1151
1152
				$link = get_author_posts_url( $item_id );
1153
1154
				break;
1155
1156
			case 'comment':
1157
				$item_id = (int) $item_id;
1158
1159
				$args->options['supports_thumbnails'] = true;
1160
1161
				$icon = 'dashicons-admin-comments';
1162
				$img_icon = get_avatar_url( get_comment( $item_id ), array( 'size' => 150 ) );
1163
1164
				$edit_link = get_edit_comment_link( $item_id );
1165
1166
				$link = get_comment_link( $item_id );
1167
1168
				break;
1169
1170
			case 'pod':
1171
				$item_id = (int) $item_id;
1172
1173
				if ( ! empty( $args->options['pick_val'] ) ) {
1174
1175
					$icon = 'dashicons-pods';
1176
1177
					if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
1178
						$file_name  = 'admin.php';
1179
						$query_args = array(
1180
							'page'   => 'pods-manage-' . $args->options['pick_val'],
1181
							'action' => 'edit',
1182
							'id'     => $item_id,
1183
						);
1184
1185
						$edit_link = add_query_arg( $query_args, admin_url( $file_name ) );
1186
					}
1187
1188
					// @todo Add $link support
1189
					$link = '';
1190
				}
1191
1192
				break;
1193
		}
1194
1195
		// Image icons always overwrite default icons
1196
		if ( ! empty( $img_icon ) ) {
1197
			$icon = $img_icon;
1198
		}
1199
1200
		// Parse icon type
1201
		if ( 'none' === $icon || 'div' === $icon ) {
1202
			$icon = '';
1203
			$use_dashicon = true;
1204
		} elseif ( 0 === strpos( $icon, 'data:image/svg+xml;base64,' ) ) {
1205
			$icon = esc_attr( $icon );
1206
			$use_dashicon = false;
1207
		} elseif ( 0 === strpos( $icon, 'dashicons-' ) ) {
1208
			$icon = sanitize_html_class( $icon );
1209
			$use_dashicon = true;
1210
		}
1211
1212
		// Support modal editing
1213
		if ( ! empty( $edit_link ) ) {
1214
			// @todo: Replace string literal with defined constant
1215
			$edit_link = add_query_arg( array( 'pods_modal' => '1' ), $edit_link );
1216
		}
1217
1218
		// Determine if this is a selected item
1219
		$selected = false;
1220
1221
		if ( is_array( $args->value ) ) {
1222
			if ( isset( $args->value[ $item_id ] ) ) {
1223
				$selected = true;
1224
			} elseif ( in_array( $item_id, $args->value, true ) ) {
1225
				$selected = true;
1226
			}
1227
		} elseif ( $item_id === $args->value ) {
1228
			$selected = true;
1229
		}
1230
1231
		$item = array(
1232
			'id'           => $item_id,
1233
			'use_dashicon' => $use_dashicon,
1234
			'icon'         => $icon,
1235
			'name'         => $item_title,
1236
			'edit_link'    => $edit_link,
1237
			'link'         => $link,
1238
			'selected'     => $selected,
1239
		);
1240
1241
		return $item;
1242
1243
	}
1244
1245
	/**
1246
	 * {@inheritdoc}
1247
	 */
1248
	public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1249
1250
		if ( empty( self::$api ) ) {
1251
			self::$api = pods_api();
1252
		}
1253
1254
		$simple_tableless_objects = $this->simple_objects();
1255
1256
		$related_pick_limit = 0;
1257
		$related_field      = $related_pod = $current_related_ids = false;
1258
1259
		// Bidirectional relationship requirement checks
1260
		$related_object = pods_v( self::$type . '_object', $options, '' ); // pod, post_type, taxonomy, etc..
1261
		$related_val    = pods_v( self::$type . '_val', $options, $related_object, null, true ); // pod name, post type name, taxonomy name, etc..
1262
		if ( empty( $related_val ) ) {
1263
			$related_val = $related_object;
1264
		}
1265
1266
		$related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1267
1268
		$options['id'] = (int) $options['id'];
1269
1270
		if ( ! isset( self::$related_data[ $options['id'] ] ) || empty( self::$related_data[ $options['id'] ] ) ) {
1271
			self::$related_data[ $options['id'] ] = array();
1272
		}
1273
1274
		if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1275
			$related_pod = self::$api->load_pod( array( 'name' => $related_val, 'table_info' => false ), false );
1276
1277
			if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1278
				$related_field = false;
1279
1280
				// Ensure sister_id exists on related Pod.
1281 View Code Duplication
				foreach ( $related_pod['fields'] as $related_pod_field ) {
1282
					if ( 'pick' === $related_pod_field['type'] && $related_sister_id === $related_pod_field['id'] ) {
1283
						$related_field = $related_pod_field;
1284
1285
						break;
1286
					}
1287
				}
1288
1289
				if ( ! empty( $related_field ) ) {
1290
					$current_ids = self::$api->lookup_related_items( $fields[ $name ]['id'], $pod['id'], $id, $fields[ $name ], $pod );
1291
1292
					self::$related_data[ $options['id'] ]['current_ids'] = $current_ids;
1293
1294
					$value_ids = $value;
1295
1296
					// Convert values from a comma-separated string into an array.
1297
					if ( ! is_array( $value_ids ) ) {
1298
						$value_ids = explode( ',', $value_ids );
1299
					}
1300
1301
					$value_ids = array_unique( array_filter( $value_ids ) );
1302
1303
					// Get ids to remove.
1304
					$remove_ids = array_diff( $current_ids, $value_ids );
1305
1306
					$related_required   = (boolean) pods_v( 'required', $related_field['options'], 0 );
1307
					$related_pick_limit = (int) pods_v( self::$type . '_limit', $related_field['options'], 0 );
1308
1309
					if ( 'single' === pods_v( self::$type . '_format_type', $related_field['options'] ) ) {
1310
						$related_pick_limit = 1;
1311
					}
1312
1313
					// Validate Required fields.
1314
					if ( $related_required && ! empty( $remove_ids ) ) {
1315
						foreach ( $remove_ids as $related_id ) {
1316
							$bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1317
1318
							self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] = $bidirectional_ids;
1319
1320
							if ( empty( $bidirectional_ids ) || ( in_array( (int) $id, $bidirectional_ids, true ) && 1 === count( $bidirectional_ids ) ) ) {
1321
								return sprintf( __( 'The %1$s field is required and cannot be removed by the %2$s field', 'pods' ), $related_field['label'], $options['label'] );
1322
							}
1323
						}
1324
					}
1325
				} else {
1326
					$related_pod = false;
1327
				}
1328
			} else {
1329
				$related_pod = false;
1330
			}
1331
		}
1332
1333
		if ( empty( self::$related_data[ $options['id'] ] ) ) {
1334
			unset( self::$related_data[ $options['id'] ] );
1335
		} else {
1336
			self::$related_data[ $options['id'] ]['related_pod']        = $related_pod;
1337
			self::$related_data[ $options['id'] ]['related_field']      = $related_field;
1338
			self::$related_data[ $options['id'] ]['related_pick_limit'] = $related_pick_limit;
1339
1340
			$pick_limit = (int) pods_v( self::$type . '_limit', $options['options'], 0 );
1341
1342
			if ( 'single' === pods_v( self::$type . '_format_type', $options['options'] ) ) {
1343
				$pick_limit = 1;
1344
			}
1345
1346
			$related_field['id'] = (int) $related_field['id'];
1347
1348
			if ( ! isset( self::$related_data[ $related_field['id'] ] ) || empty( self::$related_data[ $related_field['id'] ] ) ) {
1349
				self::$related_data[ $related_field['id'] ] = array(
1350
					'related_pod'        => $pod,
1351
					'related_field'      => $options,
1352
					'related_pick_limit' => $pick_limit,
1353
				);
1354
			}
1355
		}
1356
1357
		return true;
1358
1359
	}
1360
1361
	/**
1362
	 * {@inheritdoc}
1363
	 */
1364
	public function save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
1365
1366
		if ( empty( self::$api ) ) {
1367
			self::$api = pods_api();
1368
		}
1369
1370
		$options['id'] = (int) $options['id'];
1371
1372
		if ( ! isset( self::$related_data[ $options['id'] ] ) ) {
1373
			return;
1374
		}
1375
1376
		$related_pod        = self::$related_data[ $options['id'] ]['related_pod'];
1377
		$related_field      = self::$related_data[ $options['id'] ]['related_field'];
1378
		$related_pick_limit = self::$related_data[ $options['id'] ]['related_pick_limit'];
1379
1380
		// Bidirectional relationship updates.
1381
		if ( ! empty( $related_field ) ) {
1382
			// Don't use no conflict mode unless this isn't the current pod type.
1383
			$no_conflict = true;
1384
1385
			if ( $related_pod['type'] !== $pod['type'] ) {
1386
				$no_conflict = pods_no_conflict_check( $related_pod['type'] );
1387
			}
1388
1389
			if ( ! $no_conflict ) {
1390
				pods_no_conflict_on( $related_pod['type'] );
1391
			}
1392
1393
			$value = array_filter( $value );
1394
1395
			foreach ( $value as $related_id ) {
1396
				if ( isset( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) && ! empty( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) ) {
1397
					$bidirectional_ids = self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ];
1398
				} else {
1399
					$bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1400
				}
1401
1402
				$bidirectional_ids = array_filter( $bidirectional_ids );
1403
1404
				if ( empty( $bidirectional_ids ) ) {
1405
					$bidirectional_ids = array();
1406
				}
1407
1408
				$remove_ids = array();
1409
1410
				if ( 0 < $related_pick_limit && ! empty( $bidirectional_ids ) && ! in_array( $id, $bidirectional_ids, true ) ) {
1411
					while ( $related_pick_limit <= count( $bidirectional_ids ) ) {
1412
						$remove_ids[] = (int) array_pop( $bidirectional_ids );
1413
					}
1414
				}
1415
1416
				// Remove this item from related items no longer related to.
1417
				$remove_ids = array_unique( array_filter( $remove_ids ) );
1418
1419
				if ( ! in_array( $id, $bidirectional_ids, true ) ) {
1420
					// Add to related items.
1421
					$bidirectional_ids[] = $id;
1422
				} elseif ( empty( $remove_ids ) ) {
1423
					// Nothing to change.
1424
					continue;
1425
				}
1426
1427
				self::$api->save_relationships( $related_id, $bidirectional_ids, $related_pod, $related_field );
1428
1429
				if ( ! empty( $remove_ids ) ) {
1430
					self::$api->delete_relationships( $remove_ids, $related_id, $pod, $options );
1431
				}
1432
			}
1433
1434
			if ( ! $no_conflict ) {
1435
				pods_no_conflict_off( $related_pod['type'] );
1436
			}
1437
		}
1438
1439
	}
1440
1441
	/**
1442
	 * Delete the value from the DB
1443
	 *
1444
	 * @param int    $id
1445
	 * @param string $name
1446
	 * @param array  $options
1447
	 * @param array  $pod
1448
	 *
1449
	 * @since 2.3
1450
	 */
1451
	public function delete( $id = null, $name = null, $options = null, $pod = null ) {
1452
1453
		if ( empty( self::$api ) ) {
1454
			self::$api = pods_api();
1455
		}
1456
1457
		$simple_tableless_objects = $this->simple_objects();
1458
1459
		// Bidirectional relationship requirement checks.
1460
		$related_object    = pods_v( self::$type . '_object', $options, '' ); // pod, post_type, taxonomy, etc..
1461
		$related_val       = pods_v( self::$type . '_val', $options, $related_object, true ); // pod name, post type name, taxonomy name, etc..
1462
		$related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1463
1464
		if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1465
			$related_pod = self::$api->load_pod( array( 'name' => $related_val, 'table_info' => false ), false );
1466
1467
			if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1468
				$related_field = false;
1469
1470
				// Ensure sister_id exists on related Pod.
1471 View Code Duplication
				foreach ( $related_pod['fields'] as $related_pod_field ) {
1472
					if ( 'pick' === $related_pod_field['type'] && (int) $related_sister_id === (int) $related_pod_field['id'] ) {
1473
						$related_field = $related_pod_field;
1474
1475
						break;
1476
					}
1477
				}
1478
1479
				if ( ! empty( $related_field ) ) {
1480
					$values = self::$api->lookup_related_items( $options['id'], $pod['id'], $id, $options, $pod );
1481
1482
					if ( ! empty( $values ) ) {
1483
						$no_conflict = pods_no_conflict_check( $related_pod['type'] );
1484
1485
						if ( ! $no_conflict ) {
1486
							pods_no_conflict_on( $related_pod['type'] );
1487
						}
1488
1489
						self::$api->delete_relationships( $values, $id, $related_pod, $related_field );
1490
1491
						if ( ! $no_conflict ) {
1492
							pods_no_conflict_off( $related_pod['type'] );
1493
						}
1494
					}
1495
				}
1496
			}
1497
		}
1498
1499
	}
1500
1501
	/**
1502
	 * {@inheritdoc}
1503
	 */
1504
	public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
1505
1506
		$value = $this->simple_value( $name, $value, $options, $pod, $id );
1507
1508
		return $this->display( $value, $name, $options, $pod, $id );
1509
1510
	}
1511
1512
	/**
1513
	 * Get the data from the field
1514
	 *
1515
	 * @param string       $name    The name of the field
1516
	 * @param string|array $value   The value of the field
1517
	 * @param array        $options Field options
1518
	 * @param array        $pod     Pod data
1519
	 * @param int          $id      Item ID
1520
	 * @param boolean      $in_form
1521
	 *
1522
	 * @return array Array of possible field data
1523
	 *
1524
	 * @since 2.0
1525
	 */
1526
	public function data( $name, $value = null, $options = null, $pod = null, $id = null, $in_form = true ) {
1527
1528 View Code Duplication
		if ( isset( $options['options'] ) ) {
1529
			$options = array_merge( $options, $options['options'] );
1530
1531
			unset( $options['options'] );
1532
		}
1533
1534
		$data = pods_v( 'data', $options, null, true );
1535
1536
		$object_params = array(
1537
			'name'    => $name, // The name of the field.
1538
			'value'   => $value, // The value of the field.
1539
			'options' => $options, // Field options.
1540
			'pod'     => $pod, // Pod data.
1541
			'id'      => $id, // Item ID.
1542
			'context' => 'data', // Data context.
1543
		);
1544
1545
		if ( null !== $data ) {
1546
			$data = (array) $data;
1547
		} else {
1548
			$data = $this->get_object_data( $object_params );
1549
		}
1550
1551
		if ( 'single' === pods_v( self::$type . '_format_type', $options, 'single' ) && 'dropdown' === pods_v( self::$type . '_format_single', $options, 'dropdown' ) ) {
1552
			$data = array( '' => pods_v( self::$type . '_select_text', $options, __( '-- Select One --', 'pods' ), true ) ) + $data;
1553
		}
1554
1555
		$data = apply_filters( 'pods_field_pick_data', $data, $name, $value, $options, $pod, $id );
1556
1557
		return $data;
1558
1559
	}
1560
1561
	/**
1562
	 * Convert a simple value to the correct value
1563
	 *
1564
	 * @param string       $name    The name of the field
1565
	 * @param string|array $value   The value of the field
1566
	 * @param array        $options Field options
1567
	 * @param array        $pod     Pod data
1568
	 * @param int          $id      Item ID
1569
	 * @param boolean      $raw     Whether to return the raw list of keys (true) or convert to key=>value (false)
1570
	 *
1571
	 * @return mixed Corrected value
1572
	 */
1573
	public function simple_value( $name, $value = null, $options = null, $pod = null, $id = null, $raw = false ) {
1574
1575
		if ( in_array( pods_v( self::$type . '_object', $options ), self::simple_objects(), true ) ) {
1576 View Code Duplication
			if ( isset( $options['options'] ) ) {
1577
				$options = array_merge( $options, $options['options'] );
1578
1579
				unset( $options['options'] );
1580
			}
1581
1582
			if ( ! is_array( $value ) && 0 < strlen( $value ) ) {
1583
				$simple = @json_decode( $value, true );
1584
1585
				if ( is_array( $simple ) ) {
1586
					$value = $simple;
1587
				}
1588
			}
1589
1590
			$data = pods_v( 'data', $options, null, true );
1591
1592
			$object_params = array(
1593
				'name'    => $name, // The name of the field.
1594
				'value'   => $value, // The value of the field.
1595
				'options' => $options, // Field options.
1596
				'pod'     => $pod, // Pod data.
1597
				'id'      => $id, // Item ID.
1598
				'context' => 'simple_value', // Data context.
1599
			);
1600
1601
			if ( null === $data ) {
1602
				$data = $this->get_object_data( $object_params );
1603
			}
1604
1605
			$data = (array) $data;
1606
1607
			$key = 0;
1608
1609
			if ( is_array( $value ) ) {
1610
				if ( ! empty( $data ) ) {
1611
					$val = array();
1612
1613
					foreach ( $value as $k => $v ) {
1614
						if ( isset( $data[ $v ] ) ) {
1615
							if ( false === $raw ) {
1616
								$k = $v;
1617
								$v = $data[ $v ];
1618
							}
1619
1620
							$val[ $k ] = $v;
1621
						}
1622
					}
1623
1624
					$value = $val;
1625
				}
1626
			} elseif ( isset( $data[ $value ] ) && false === $raw ) {
1627
				$key   = $value;
1628
				$value = $data[ $value ];
1629
			}
1630
1631
			$single_multi = pods_v( self::$type . '_format_type', $options, 'single' );
1632
1633
			if ( 'multi' === $single_multi ) {
1634
				$limit = (int) pods_v( self::$type . '_limit', $options, 0 );
1635
			} else {
1636
				$limit = 1;
1637
			}
1638
1639
			if ( is_array( $value ) && 0 < $limit ) {
1640
				if ( 1 === $limit ) {
1641
					$value = current( $value );
1642
				} else {
1643
					$value = array_slice( $value, 0, $limit, true );
1644
				}
1645
			} elseif ( ! is_array( $value ) && null !== $value && 0 < strlen( $value ) ) {
1646
				if ( 1 !== $limit || ( true === $raw && 'multi' === $single_multi ) ) {
1647
					$value = array(
1648
						$key => $value,
1649
					);
1650
				}
1651
			}
1652
		}
1653
1654
		return $value;
1655
1656
	}
1657
1658
	/**
1659
	 * Get the label from a pick value
1660
	 *
1661
	 * @param string       $name    The name of the field
1662
	 * @param string|array $value   The value of the field
1663
	 * @param array        $options Field options
1664
	 * @param array        $pod     Pod data
1665
	 * @param int          $id      Item ID
1666
	 *
1667
	 * @return string
1668
	 *
1669
	 * @since 2.2
1670
	 */
1671
	public function value_to_label( $name, $value = null, $options = null, $pod = null, $id = null ) {
1672
1673 View Code Duplication
		if ( isset( $options['options'] ) ) {
1674
			$options = array_merge( $options, $options['options'] );
1675
1676
			unset( $options['options'] );
1677
		}
1678
1679
		$data = pods_v( 'data', $options, null, true );
1680
1681
		$object_params = array(
1682
			'name'    => $name, // The name of the field.
1683
			'value'   => $value, // The value of the field.
1684
			'options' => $options, // Field options.
1685
			'pod'     => $pod, // Pod data.
1686
			'id'      => $id, // Item ID.
1687
			'context' => 'value_to_label', // Data context.
1688
		);
1689
1690
		if ( null !== $data ) {
1691
			$data = (array) $data;
1692
		} else {
1693
			$data = $this->get_object_data( $object_params );
1694
		}
1695
1696
		$labels = array();
1697
1698
		$check_value = $value;
1699
1700
		foreach ( $check_value as &$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...
1701
			$check_v = (string) $check_v;
1702
		}
1703
1704
		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...
1705
			if ( ! in_array( (string) $l, $labels, true ) && ( (string) $value === (string) $v || ( is_array( $value ) && in_array( (string) $v, $value, true ) ) ) ) {
1706
				$labels[] = (string) $l;
1707
			}
1708
		}
1709
1710
		$labels = apply_filters( 'pods_field_pick_value_to_label', $labels, $name, $value, $options, $pod, $id );
1711
1712
		$labels = pods_serial_comma( $labels );
1713
1714
		return $labels;
1715
1716
	}
1717
1718
	/**
1719
	 * Get available items from a relationship field
1720
	 *
1721
	 * @param array|string $field         Field array or field name
1722
	 * @param array        $options       [optional] Field options array overrides
1723
	 * @param array        $object_params [optional] Additional get_object_data options
1724
	 *
1725
	 * @return array An array of available items from a relationship field
1726
	 */
1727
	public function get_field_data( $field, $options = array(), $object_params = array() ) {
1728
1729
		// Handle field array overrides.
1730
		if ( is_array( $field ) ) {
1731
			$options = array_merge( $field, $options );
1732
		}
1733
1734
		// Get field name from array.
1735
		$field = pods_v( 'name', $options, $field, true );
1736
1737
		// Field name or options not set.
1738
		if ( empty( $field ) || empty( $options ) ) {
1739
			return array();
1740
		}
1741
1742
		// Options normalization.
1743
		$options = array_merge( $options, pods_v( 'options', $options, array(), true ) );
1744
1745
		// Setup object params.
1746
		$object_params = array_merge( array(
1747
			'name'    => $field, // The name of the field.
1748
			'options' => $options, // Field options.
1749
		), $object_params );
1750
1751
		// Get data override.
1752
		$data = pods_v( 'data', $options, null, true );
1753
1754
		if ( null !== $data ) {
1755
			// Return data override.
1756
			$data = (array) $data;
1757
		} else {
1758
			// Get object data.
1759
			$data = $this->get_object_data( $object_params );
1760
		}
1761
1762
		return $data;
1763
1764
	}
1765
1766
	/**
1767
	 * Get data from relationship objects
1768
	 *
1769
	 * @param array $object_params Object data parameters
1770
	 *
1771
	 * @return array|bool Object data
1772
	 */
1773
	public function get_object_data( $object_params = null ) {
1774
1775
		/**
1776
		 * @var $wpdb wpdb
1777
		 */
1778
		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...
1779
1780
		$object_params = array_merge( array(
1781
			// The name of the field.
1782
			'name'        => '',
1783
			// The value of the field.
1784
			'value'       => '',
1785
			// Field options.
1786
			'options'     => array(),
1787
			// Pod data.
1788
			'pod'         => '',
1789
			// Item ID.
1790
			'id'          => '',
1791
			// Data context.
1792
			'context'     => '',
1793
			// Data parameters.
1794
			'data_params' => array(
1795
				'query' => '', // Query being searched.
1796
			),
1797
			// Page number of results to get.
1798
			'page'        => 1,
1799
			// How many data items to limit to (autocomplete defaults to 30, set to -1 or 1+ to override).
1800
			'limit'       => 0,
1801
		), $object_params );
1802
1803
		$name        = $object_params['name'];
1804
		$value       = $object_params['value'];
1805
		$options     = $object_params['options'] = (array) $object_params['options'];
1806
		$pod         = $object_params['pod'];
1807
		$id          = $object_params['id'];
1808
		$context     = $object_params['context'];
1809
		$data_params = $object_params['data_params'] = (array) $object_params['data_params'];
1810
		$page        = min( 1, (int) $object_params['page'] );
1811
		$limit       = (int) $object_params['limit'];
1812
1813 View Code Duplication
		if ( isset( $options['options'] ) ) {
1814
			$options = array_merge( $options, $options['options'] );
1815
1816
			unset( $options['options'] );
1817
		}
1818
1819
		$data  = apply_filters( 'pods_field_pick_object_data', null, $name, $value, $options, $pod, $id, $object_params );
1820
		$items = array();
1821
1822
		if ( ! isset( $options[ self::$type . '_object' ] ) ) {
1823
			$data = pods_v( 'data', $options, array(), true );
1824
		}
1825
1826
		$simple = false;
1827
1828
		if ( null === $data ) {
1829
			$data = array();
1830
1831
			if ( 'custom-simple' === $options[ self::$type . '_object' ] ) {
1832
				$custom = pods_v( self::$type . '_custom', $options, '' );
1833
1834
				$custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $name, $value, $options, $pod, $id, $object_params );
1835
1836
				if ( ! empty( $custom ) ) {
1837
					if ( ! is_array( $custom ) ) {
1838
						$data = array();
1839
1840
						$custom = explode( "\n", trim( $custom ) );
1841
1842
						foreach ( $custom as $custom_value ) {
1843
							$custom_label = explode( '|', $custom_value );
1844
1845
							if ( empty( $custom_label ) ) {
1846
								continue;
1847
							}
1848
1849
							if ( 1 === count( $custom_label ) ) {
1850
								$custom_label = $custom_value;
1851
							} else {
1852
								$custom_value = $custom_label[0];
1853
								$custom_label = $custom_label[1];
1854
							}
1855
1856
							$custom_value = trim( (string) $custom_value );
1857
							$custom_label = trim( (string) $custom_label );
1858
1859
							$data[ $custom_value ] = $custom_label;
1860
						}
1861
					} else {
1862
						$data = $custom;
1863
					}
1864
1865
					$simple = true;
1866
				}
1867
			} elseif ( isset( self::$related_objects[ $options[ self::$type . '_object' ] ] ) && isset( self::$related_objects[ $options[ self::$type . '_object' ] ]['data'] ) && ! empty( self::$related_objects[ $options[ self::$type . '_object' ] ]['data'] ) ) {
1868
				$data = self::$related_objects[ $options[ self::$type . '_object' ] ]['data'];
1869
1870
				$simple = true;
1871
			} elseif ( isset( self::$related_objects[ $options[ self::$type . '_object' ] ] ) && isset( self::$related_objects[ $options[ self::$type . '_object' ] ]['data_callback'] ) && is_callable( self::$related_objects[ $options[ self::$type . '_object' ] ]['data_callback'] ) ) {
1872
				$data = call_user_func_array( self::$related_objects[ $options[ self::$type . '_object' ] ]['data_callback'], array(
1873
						$name,
1874
						$value,
1875
						$options,
1876
						$pod,
1877
						$id,
1878
					)
1879
				);
1880
1881 View Code Duplication
				if ( 'data' === $context ) {
1882
					self::$field_data = array(
1883
						'field'        => $name,
1884
						'id'           => $options['id'],
1885
						'autocomplete' => false,
1886
					);
1887
				}
1888
1889
				$simple = true;
1890
1891
				// Cache data from callback.
1892
				if ( ! empty( $data ) ) {
1893
					self::$related_objects[ $options[ self::$type . '_object' ] ]['data'] = $data;
1894
				}
1895
			} elseif ( 'simple_value' !== $context ) {
1896
				$pick_val = pods_v( self::$type . '_val', $options );
1897
1898
				if ( 'table' === pods_v( self::$type . '_object', $options ) ) {
1899
					$pick_val = pods_v( self::$type . '_table', $options, $pick_val, true );
1900
				}
1901
1902 View Code Duplication
				if ( '__current__' === $pick_val ) {
1903
					if ( is_object( $pod ) ) {
1904
						$pick_val = $pod->pod;
1905
					} elseif ( is_array( $pod ) ) {
1906
						$pick_val = $pod['name'];
1907
					} elseif ( 0 < strlen( $pod ) ) {
1908
						$pick_val = $pod;
1909
					}
1910
				}
1911
1912
				$options['table_info'] = pods_api()->get_table_info( pods_v( self::$type . '_object', $options ), $pick_val, null, null, $options );
1913
1914
				$search_data = pods_data();
1915
				$search_data->table( $options['table_info'] );
1916
1917
				if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) && isset( $options['table_info']['pod']['name'] ) ) {
1918
					$search_data->pod    = $options['table_info']['pod']['name'];
1919
					$search_data->fields = $options['table_info']['pod']['fields'];
1920
				}
1921
1922
				$params = array(
1923
					'select'     => "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`",
1924
					'table'      => $search_data->table,
1925
					'where'      => pods_v( self::$type . '_where', $options, (array) $options['table_info']['where_default'], true ),
1926
					'orderby'    => pods_v( self::$type . '_orderby', $options, null, true ),
1927
					'groupby'    => pods_v( self::$type . '_groupby', $options, null, true ),
1928
					// 'having' => pods_v( self::$type . '_having', $options, null, true ),
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% 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...
1929
					'pagination' => false,
1930
					'search'     => false
1931
				);
1932
1933
				if ( in_array( $options[ self::$type . '_object' ], array( 'site', 'network' ), true ) ) {
1934
					$params['select'] .= ', `t`.`path`';
1935
				}
1936
1937
				if ( ! empty( $params['where'] ) && (array) $options['table_info']['where_default'] !== $params['where'] ) {
1938
					$params['where'] = pods_evaluate_tags( $params['where'], true );
1939
				}
1940
1941
				if ( empty( $params['where'] ) || ( ! is_array( $params['where'] ) && strlen( trim( $params['where'] ) ) < 1 ) ) {
1942
					$params['where'] = array();
1943
				} elseif ( ! is_array( $params['where'] ) ) {
1944
					$params['where'] = (array) $params['where'];
1945
				}
1946
1947
				if ( 'value_to_label' === $context ) {
1948
					$params['where'][] = "`t`.`{$search_data->field_id}` = " . number_format( $value, 0, '', '' );
1949
				}
1950
1951
				/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
1952
				if ( ! empty( $params['orderby'] ) ) {
1953
					$params['orderby'] = pods_evaluate_tags( $params['orderby'], true );
1954
				}
1955
1956
				if ( ! empty( $params['groupby'] ) ) {
1957
					$params['groupby'] = pods_evaluate_tags( $params['groupby'], true );
1958
				}
1959
				*/
1960
1961
				$display = trim( pods_v( self::$type . '_display', $options ), ' {@}' );
1962
1963
				if ( 0 < strlen( $display ) ) {
1964
					if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) ) {
1965
						if ( isset( $options['table_info']['pod']['object_fields'] ) && isset( $options['table_info']['pod']['object_fields'][ $display ] ) ) {
1966
							$search_data->field_index = $display;
1967
1968
							$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
1969
						} elseif ( isset( $options['table_info']['pod']['fields'][ $display ] ) ) {
1970
							$search_data->field_index = $display;
1971
1972
							if ( 'table' === $options['table_info']['pod']['storage'] && ! in_array( $options['table_info']['pod']['type'], array(
1973
									'pod',
1974
									'table',
1975
								), true )
1976
							) {
1977
								$params['select'] = "`t`.`{$search_data->field_id}`, `d`.`{$search_data->field_index}`";
1978
							} elseif ( 'meta' === $options['table_info']['pod']['storage'] ) {
1979
								$params['select'] = "`t`.`{$search_data->field_id}`, `{$search_data->field_index}`.`meta_value` AS {$search_data->field_index}";
1980
							} else {
1981
								$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
1982
							}
1983
						}
1984
					} elseif ( isset( $options['table_info']['object_fields'] ) && isset( $options['table_info']['object_fields'][ $display ] ) ) {
1985
						$search_data->field_index = $display;
1986
1987
						$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
1988
					}
1989
				}
1990
1991
				$autocomplete = false;
1992
1993
				if ( 'single' === pods_v( self::$type . '_format_type', $options, 'single' ) && 'autocomplete' === pods_v( self::$type . '_format_single', $options, 'dropdown' ) ) {
1994
					$autocomplete = true;
1995
				} elseif ( 'multi' === pods_v( self::$type . '_format_type', $options, 'single' ) && 'autocomplete' === pods_v( self::$type . '_format_multi', $options, 'checkbox' ) ) {
1996
					$autocomplete = true;
1997
				}
1998
1999
				$hierarchy = false;
2000
2001
				if ( 'data' === $context && ! $autocomplete ) {
2002
					if ( 'single' === pods_v( self::$type . '_format_type', $options, 'single' ) && in_array( pods_v( self::$type . '_format_single', $options, 'dropdown' ), array(
2003
							'dropdown',
2004
							'radio',
2005
						), true )
2006
					) {
2007
						$hierarchy = true;
2008
					} elseif ( 'multi' === pods_v( self::$type . '_format_type', $options, 'single' ) && in_array( pods_v( self::$type . '_format_multi', $options, 'checkbox' ), array(
2009
							'multiselect',
2010
							'checkbox',
2011
						), true )
2012
					) {
2013
						$hierarchy = true;
2014
					}
2015
				}
2016
2017
				if ( $hierarchy && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
2018
					$params['select'] .= ', ' . $options['table_info']['field_parent_select'];
2019
				}
2020
2021
				if ( $autocomplete ) {
2022
					if ( 0 === $limit ) {
2023
						$limit = 30;
2024
					}
2025
2026
					$params['limit'] = apply_filters( 'pods_form_ui_field_pick_autocomplete_limit', $limit, $name, $value, $options, $pod, $id, $object_params );
2027
2028
					if ( is_array( $value ) && $params['limit'] < count( $value ) ) {
2029
						$params['limit'] = count( $value );
2030
					}
2031
2032
					$params['page'] = $page;
2033
2034
					if ( 'admin_ajax_relationship' === $context ) {
2035
						$lookup_where = array(
2036
							$search_data->field_index => "`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'",
2037
						);
2038
2039
						// @todo Hook into WPML for each table
2040
						if ( $wpdb->users === $search_data->table ) {
2041
							$lookup_where['display_name'] = "`t`.`display_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2042
							$lookup_where['user_login']   = "`t`.`user_login` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2043
							$lookup_where['user_email']   = "`t`.`user_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2044
						} elseif ( $wpdb->posts === $search_data->table ) {
2045
							$lookup_where['post_title']   = "`t`.`post_title` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2046
							$lookup_where['post_name']    = "`t`.`post_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2047
							$lookup_where['post_content'] = "`t`.`post_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2048
							$lookup_where['post_excerpt'] = "`t`.`post_excerpt` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2049
						} elseif ( $wpdb->terms === $search_data->table ) {
2050
							$lookup_where['name'] = "`t`.`name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2051
							$lookup_where['slug'] = "`t`.`slug` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2052
						} elseif ( $wpdb->comments === $search_data->table ) {
2053
							$lookup_where['comment_content']      = "`t`.`comment_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2054
							$lookup_where['comment_author']       = "`t`.`comment_author` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2055
							$lookup_where['comment_author_email'] = "`t`.`comment_author_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
2056
						}
2057
2058
						$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 );
2059
2060
						if ( ! empty( $lookup_where ) ) {
2061
							$params['where'][] = implode( ' OR ', $lookup_where );
2062
						}
2063
2064
						$orderby   = array();
2065
						$orderby[] = "(`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%' ) DESC";
2066
2067
						$pick_orderby = pods_v( self::$type . '_orderby', $options, null, true );
2068
2069
						if ( 0 < strlen( $pick_orderby ) ) {
2070
							$orderby[] = $pick_orderby;
2071
						}
2072
2073
						$orderby[] = "`t`.`{$search_data->field_index}`";
2074
						$orderby[] = "`t`.`{$search_data->field_id}`";
2075
2076
						$params['orderby'] = $orderby;
2077
					}
2078
				} elseif ( 0 < $limit ) {
2079
					$params['limit'] = $limit;
2080
					$params['page']  = $page;
2081
				}
2082
2083
				$extra = '';
2084
2085
				if ( $wpdb->posts === $search_data->table ) {
2086
					$extra = ', `t`.`post_type`';
2087
				} elseif ( $wpdb->terms === $search_data->table ) {
2088
					$extra = ', `tt`.`taxonomy`';
2089
				} elseif ( $wpdb->comments === $search_data->table ) {
2090
					$extra = ', `t`.`comment_type`';
2091
				}
2092
2093
				$params['select'] .= $extra;
2094
2095
				if ( 'user' === pods_v( self::$type . '_object', $options ) ) {
2096
					$roles = pods_v( self::$type . '_user_role', $options );
2097
2098
					if ( ! empty( $roles ) ) {
2099
						$where = array();
2100
2101
						foreach ( (array) $roles as $role ) {
2102
							if ( empty( $role ) || ( pods_clean_name( $role ) !== $role && sanitize_title( $role ) !== $role ) ) {
2103
								continue;
2104
							}
2105
2106
							$where[] = $wpdb->base_prefix . ( ( is_multisite() && ! is_main_site() ) ? get_current_blog_id() . '_' : '' ) . 'capabilities.meta_value LIKE "%\"' . pods_sanitize_like( $role ) . '\"%"';
2107
						}
2108
2109
						if ( ! empty( $where ) ) {
2110
							$params['where'][] = implode( ' OR ', $where );
2111
						}
2112
					}
2113
				}
2114
2115
				$results = $search_data->select( $params );
2116
2117
				if ( $autocomplete && $params['limit'] < $search_data->total_found() ) {
2118
					if ( ! empty( $value ) ) {
2119
						$ids = $value;
2120
2121
						if ( is_array( $ids ) && isset( $ids[0] ) && is_array( $ids[0] ) ) {
2122
							$ids = wp_list_pluck( $ids, $search_data->field_id );
2123
						}
2124
2125
						if ( is_array( $ids ) ) {
2126
							$ids = implode( ', ', $ids );
2127
						}
2128
2129
						if ( is_array( $params['where'] ) ) {
2130
							$params['where'] = implode( ' AND ', $params['where'] );
2131
						}
2132
						if ( ! empty( $params['where'] ) ) {
2133
							$params['where'] .= ' AND ';
2134
						}
2135
2136
						$params['where'] .= "`t`.`{$search_data->field_id}` IN ( {$ids} )";
2137
2138
						$results = $search_data->select( $params );
2139
					}
2140
				} else {
2141
					$autocomplete = false;
2142
				}
2143
2144 View Code Duplication
				if ( 'data' === $context ) {
2145
					self::$field_data = array(
2146
						'field'        => $name,
2147
						'id'           => $options['id'],
2148
						'autocomplete' => $autocomplete,
2149
					);
2150
				}
2151
2152
				if ( $hierarchy && ! $autocomplete && ! empty( $results ) && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
2153
					$select_args = array(
2154
						'id'     => $options['table_info']['field_id'],
2155
						'index'  => $options['table_info']['field_index'],
2156
						'parent' => $options['table_info']['field_parent'],
2157
					);
2158
2159
					$results = pods_hierarchical_select( $results, $select_args );
2160
				}
2161
2162
				$ids = array();
2163
2164
				if ( ! empty( $results ) ) {
2165
					$display_filter = pods_v( 'display_filter', pods_v( 'options', pods_v( $search_data->field_index, $search_data->pod_data['object_fields'] ) ) );
2166
2167
					foreach ( $results as $result ) {
2168
						$result = get_object_vars( $result );
2169
2170
						if ( ! isset( $result[ $search_data->field_id ] ) || ! isset( $result[ $search_data->field_index ] ) ) {
2171
							continue;
2172
						}
2173
2174
						$result[ $search_data->field_index ] = trim( $result[ $search_data->field_index ] );
2175
2176
						$object = $object_type = '';
2177
2178
						if ( $wpdb->posts === $search_data->table && isset( $result['post_type'] ) ) {
2179
							$object      = $result['post_type'];
2180
							$object_type = 'post_type';
2181
						} elseif ( $wpdb->terms === $search_data->table && isset( $result['taxonomy'] ) ) {
2182
							$object      = $result['taxonomy'];
2183
							$object_type = 'taxonomy';
2184
						}
2185
2186
						if ( 0 < strlen( $display_filter ) ) {
2187
							$display_filter_args = pods_v( 'display_filter_args', pods_v( 'options', pods_v( $search_data->field_index, $search_data->pod_data['object_fields'] ) ) );
2188
2189
							$filter_args = array(
2190
								$display_filter,
2191
								$result[ $search_data->field_index ],
2192
							);
2193
2194
							if ( ! empty( $display_filter_args ) ) {
2195
								foreach ( (array) $display_filter_args as $display_filter_arg ) {
2196
									if ( isset( $result[ $display_filter_arg ] ) ) {
2197
										$filter_args[] = $result[ $display_filter_arg ];
2198
									}
2199
								}
2200
							}
2201
2202
							$result[ $search_data->field_index ] = call_user_func_array( 'apply_filters', $filter_args );
2203
						}
2204
2205
						if ( in_array( $options[ self::$type . '_object' ], array( 'site', 'network' ), true ) ) {
2206
							$result[ $search_data->field_index ] = $result[ $search_data->field_index ] . $result['path'];
2207
						} elseif ( strlen( $result[ $search_data->field_index ] ) < 1 ) {
2208
							$result[ $search_data->field_index ] = '(No Title)';
2209
						}
2210
2211
						if ( 'admin_ajax_relationship' === $context ) {
2212
							$items[] = array(
2213
								'id'    => $result[ $search_data->field_id ],
2214
								'text'  => $result[ $search_data->field_index ],
2215
								'image' => '',
2216
							);
2217
						} else {
2218
							$data[ $result[ $search_data->field_id ] ] = $result[ $search_data->field_index ];
2219
						}
2220
2221
						$ids[] = $result[ $search_data->field_id ];
2222
					}
2223
				}
2224
			}
2225
2226
			if ( $simple && 'admin_ajax_relationship' === $context ) {
2227
				$found_data = array();
2228
2229
				foreach ( $data as $k => $v ) {
2230
					if ( false !== stripos( $v, $data_params['query'] ) || false !== stripos( $k, $data_params['query'] ) ) {
2231
						$found_data[ $k ] = $v;
2232
					}
2233
				}
2234
2235
				$data = $found_data;
2236
			}
2237
		}
2238
2239
		if ( 'admin_ajax_relationship' === $context ) {
2240
			if ( empty( $items ) && ! empty( $data ) ) {
2241
				foreach ( $data as $k => $v ) {
2242
					$items[] = array(
2243
						'id'    => $k,
2244
						'text'  => $v,
2245
						'image' => '',
2246
					);
2247
				}
2248
			}
2249
2250
			$data = $items;
2251
		}
2252
2253
		return $data;
2254
2255
	}
2256
2257
	/**
2258
	 * Handle autocomplete AJAX.
2259
	 *
2260
	 * @since 2.3
2261
	 */
2262
	public function admin_ajax_relationship() {
2263
2264
		pods_session_start();
2265
2266
		// Sanitize input.
2267
		$params = pods_unslash( (array) $_POST );
2268
2269 View Code Duplication
		foreach ( $params as $key => $value ) {
2270
			if ( 'action' === $key ) {
2271
				continue;
2272
			}
2273
2274
			unset( $params[ $key ] );
2275
2276
			$params[ str_replace( '_podsfix_', '', $key ) ] = $value;
2277
		}
2278
2279
		$params = (object) $params;
2280
2281
		$uid = @session_id();
2282
2283
		if ( is_user_logged_in() ) {
2284
			$uid = 'user_' . get_current_user_id();
2285
		}
2286
2287
		$nonce_check = 'pods_relationship_' . (int) $params->pod . '_' . $uid . '_' . $params->uri . '_' . (int) $params->field;
2288
2289 View Code Duplication
		if ( ! isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, $nonce_check ) ) {
2290
			pods_error( __( 'Unauthorized request', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
2291
		}
2292
2293
		if ( empty( self::$api ) ) {
2294
			self::$api = pods_api();
2295
		}
2296
2297
		$pod   = self::$api->load_pod( array( 'id' => (int) $params->pod ) );
2298
		$field = self::$api->load_field( array( 'id' => (int) $params->field, 'table_info' => true ) );
2299
		$id    = (int) $params->id;
2300
2301
		$limit = 15;
2302
2303
		if ( isset( $params->limit ) ) {
2304
			$limit = (int) $params->limit;
2305
		}
2306
2307
		$page = 1;
2308
2309
		if ( isset( $params->page ) ) {
2310
			$page = (int) $params->page;
2311
		}
2312
2313
		if ( ! isset( $params->query ) || strlen( trim( $params->query ) ) < 1 ) {
2314
			pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
2315
		} elseif ( empty( $pod ) || empty( $field ) || (int) $pod['id'] !== (int) $field['pod_id'] || ! isset( $pod['fields'][ $field['name'] ] ) ) {
2316
			pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
2317
		} elseif ( 'pick' !== $field['type'] || empty( $field['table_info'] ) ) {
2318
			pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
2319
		} elseif ( 'single' === pods_v( self::$type . '_format_type', $field ) && 'autocomplete' === pods_v( self::$type . '_format_single', $field ) ) {
2320
			pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
2321
		} elseif ( 'multi' === pods_v( self::$type . '_format_type', $field ) && 'autocomplete' === pods_v( self::$type . '_format_multi', $field ) ) {
2322
			pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
2323
		}
2324
2325
		$object_params = array(
2326
			'name'        => $field['name'], // The name of the field.
2327
			'value'       => null, // The value of the field.
2328
			'options'     => array_merge( $field, $field['options'] ), // Field options.
2329
			'pod'         => $pod, // Pod data.
2330
			'id'          => $id, // Item ID.
2331
			'context'     => 'admin_ajax_relationship', // Data context.
2332
			'data_params' => $params,
2333
			'page'        => $page,
2334
			'limit'       => $limit
2335
		);
2336
2337
		$pick_data = apply_filters( 'pods_field_pick_data_ajax', null, $field['name'], null, $field, $pod, $id );
2338
2339
		if ( null !== $pick_data ) {
2340
			$items = $pick_data;
2341
		} else {
2342
			$items = $this->get_object_data( $object_params );
2343
		}
2344
2345
		if ( ! empty( $items ) && isset( $items[0] ) && ! is_array( $items[0] ) ) {
2346
			$new_items = array();
2347
2348
			foreach ( $items as $id => $text ) {
2349
				$new_items[] = array(
2350
					'id'    => $id,
2351
					'text'  => $text,
2352
					'image' => '',
2353
				);
2354
			}
2355
2356
			$items = $new_items;
2357
		}
2358
2359
		$items = apply_filters( 'pods_field_pick_data_ajax_items', $items, $field['name'], null, $field, $pod, $id );
2360
2361
		$items = array(
2362
			'results' => $items,
2363
		);
2364
2365
		wp_send_json( $items );
2366
2367
		die(); // KBAI!
2368
2369
	}
2370
2371
	/**
2372
	 * Data callback for Post Stati
2373
	 *
2374
	 * @param string       $name    The name of the field
2375
	 * @param string|array $value   The value of the field
2376
	 * @param array        $options Field options
2377
	 * @param array        $pod     Pod data
2378
	 * @param int          $id      Item ID
2379
	 *
2380
	 * @return array
2381
	 *
2382
	 * @since 2.3
2383
	 */
2384
	public function data_post_stati( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2385
2386
		$data = array();
2387
2388
		$post_stati = get_post_stati( array(), 'objects' );
2389
2390
		foreach ( $post_stati as $post_status ) {
2391
			$data[ $post_status->name ] = $post_status->label;
2392
		}
2393
2394
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2395
2396
	}
2397
2398
	/**
2399
	 * Data callback for User Roles
2400
	 *
2401
	 * @param string       $name    The name of the field
2402
	 * @param string|array $value   The value of the field
2403
	 * @param array        $options Field options
2404
	 * @param array        $pod     Pod data
2405
	 * @param int          $id      Item ID
2406
	 *
2407
	 * @return array
2408
	 *
2409
	 * @since 2.3
2410
	 */
2411
	public function data_roles( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2412
2413
		$data = array();
2414
2415
		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...
2416
2417
		foreach ( $wp_roles->role_objects as $key => $role ) {
2418
			$data[ $key ] = $wp_roles->role_names[ $key ];
2419
		}
2420
2421
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2422
2423
	}
2424
2425
	/**
2426
	 * Data callback for User Capabilities
2427
	 *
2428
	 * @param string       $name    The name of the field
2429
	 * @param string|array $value   The value of the field
2430
	 * @param array        $options Field options
2431
	 * @param array        $pod     Pod data
2432
	 * @param int          $id      Item ID
2433
	 *
2434
	 * @return array
2435
	 *
2436
	 * @since 2.3
2437
	 */
2438
	public function data_capabilities( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2439
2440
		$data = array();
2441
2442
		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...
2443
2444
		$default_caps = array(
2445
			'activate_plugins',
2446
			'add_users',
2447
			'create_users',
2448
			'delete_others_pages',
2449
			'delete_others_posts',
2450
			'delete_pages',
2451
			'delete_plugins',
2452
			'delete_posts',
2453
			'delete_private_pages',
2454
			'delete_private_posts',
2455
			'delete_published_pages',
2456
			'delete_published_posts',
2457
			'delete_users',
2458
			'edit_dashboard',
2459
			'edit_files',
2460
			'edit_others_pages',
2461
			'edit_others_posts',
2462
			'edit_pages',
2463
			'edit_plugins',
2464
			'edit_posts',
2465
			'edit_private_pages',
2466
			'edit_private_posts',
2467
			'edit_published_pages',
2468
			'edit_published_posts',
2469
			'edit_theme_options',
2470
			'edit_themes',
2471
			'edit_users',
2472
			'import',
2473
			'install_plugins',
2474
			'install_themes',
2475
			'list_users',
2476
			'manage_categories',
2477
			'manage_links',
2478
			'manage_options',
2479
			'moderate_comments',
2480
			'promote_users',
2481
			'publish_pages',
2482
			'publish_posts',
2483
			'read',
2484
			'read_private_pages',
2485
			'read_private_posts',
2486
			'remove_users',
2487
			'switch_themes',
2488
			'unfiltered_html',
2489
			'unfiltered_upload',
2490
			'update_core',
2491
			'update_plugins',
2492
			'update_themes',
2493
			'upload_files',
2494
		);
2495
2496
		$role_caps = array();
2497
2498 View Code Duplication
		foreach ( $wp_roles->role_objects as $key => $role ) {
2499
			if ( is_array( $role->capabilities ) ) {
2500
				foreach ( $role->capabilities as $cap => $grant ) {
2501
					$role_caps[ $cap ] = $cap;
2502
				}
2503
			}
2504
		}
2505
2506
		$role_caps = array_unique( $role_caps );
2507
2508
		$capabilities = array_merge( $default_caps, $role_caps );
2509
2510
		// To support Members filters
2511
		$capabilities = apply_filters( 'members_get_capabilities', $capabilities );
2512
2513
		$capabilities = apply_filters( 'pods_roles_get_capabilities', $capabilities );
2514
2515
		sort( $capabilities );
2516
2517
		$capabilities = array_unique( $capabilities );
2518
2519
		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...
2520
2521
		foreach ( $capabilities as $capability ) {
2522
			$data[ $capability ] = $capability;
2523
		}
2524
2525
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2526
2527
	}
2528
2529
	/**
2530
	 * Data callback for Image Sizes
2531
	 *
2532
	 * @param string       $name    The name of the field
2533
	 * @param string|array $value   The value of the field
2534
	 * @param array        $options Field options
2535
	 * @param array        $pod     Pod data
2536
	 * @param int          $id      Item ID
2537
	 *
2538
	 * @return array
2539
	 *
2540
	 * @since 2.3
2541
	 */
2542 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...
2543
2544
		$data = array();
2545
2546
		$image_sizes = get_intermediate_image_sizes();
2547
2548
		foreach ( $image_sizes as $image_size ) {
2549
			$data[ $image_size ] = ucwords( str_replace( '-', ' ', $image_size ) );
2550
		}
2551
2552
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2553
2554
	}
2555
2556
	/**
2557
	 * Data callback for Countries
2558
	 *
2559
	 * @param string       $name    The name of the field
2560
	 * @param string|array $value   The value of the field
2561
	 * @param array        $options Field options
2562
	 * @param array        $pod     Pod data
2563
	 * @param int          $id      Item ID
2564
	 *
2565
	 * @return array
2566
	 *
2567
	 * @since 2.3
2568
	 */
2569
	public function data_countries( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2570
2571
		$data = array(
2572
			'AF' => __( 'Afghanistan' ),
2573
			'AL' => __( 'Albania' ),
2574
			'DZ' => __( 'Algeria' ),
2575
			'AS' => __( 'American Samoa' ),
2576
			'AD' => __( 'Andorra' ),
2577
			'AO' => __( 'Angola' ),
2578
			'AI' => __( 'Anguilla' ),
2579
			'AQ' => __( 'Antarctica' ),
2580
			'AG' => __( 'Antigua and Barbuda' ),
2581
			'AR' => __( 'Argentina' ),
2582
			'AM' => __( 'Armenia' ),
2583
			'AW' => __( 'Aruba' ),
2584
			'AU' => __( 'Australia' ),
2585
			'AT' => __( 'Austria' ),
2586
			'AZ' => __( 'Azerbaijan' ),
2587
			'BS' => __( 'Bahamas' ),
2588
			'BH' => __( 'Bahrain' ),
2589
			'BD' => __( 'Bangladesh' ),
2590
			'BB' => __( 'Barbados' ),
2591
			'BY' => __( 'Belarus' ),
2592
			'BE' => __( 'Belgium' ),
2593
			'BZ' => __( 'Belize' ),
2594
			'BJ' => __( 'Benin' ),
2595
			'BM' => __( 'Bermuda' ),
2596
			'BT' => __( 'Bhutan' ),
2597
			'BO' => __( 'Bolivia' ),
2598
			'BA' => __( 'Bosnia and Herzegovina' ),
2599
			'BW' => __( 'Botswana' ),
2600
			'BV' => __( 'Bouvet Island' ),
2601
			'BR' => __( 'Brazil' ),
2602
			'BQ' => __( 'British Antarctic Territory' ),
2603
			'IO' => __( 'British Indian Ocean Territory' ),
2604
			'VG' => __( 'British Virgin Islands' ),
2605
			'BN' => __( 'Brunei' ),
2606
			'BG' => __( 'Bulgaria' ),
2607
			'BF' => __( 'Burkina Faso' ),
2608
			'BI' => __( 'Burundi' ),
2609
			'KH' => __( 'Cambodia' ),
2610
			'CM' => __( 'Cameroon' ),
2611
			'CA' => __( 'Canada' ),
2612
			'CT' => __( 'Canton and Enderbury Islands' ),
2613
			'CV' => __( 'Cape Verde' ),
2614
			'KY' => __( 'Cayman Islands' ),
2615
			'CF' => __( 'Central African Republic' ),
2616
			'TD' => __( 'Chad' ),
2617
			'CL' => __( 'Chile' ),
2618
			'CN' => __( 'China' ),
2619
			'CX' => __( 'Christmas Island' ),
2620
			'CC' => __( 'Cocos [Keeling] Islands' ),
2621
			'CO' => __( 'Colombia' ),
2622
			'KM' => __( 'Comoros' ),
2623
			'CG' => __( 'Congo - Brazzaville' ),
2624
			'CD' => __( 'Congo - Kinshasa' ),
2625
			'CK' => __( 'Cook Islands' ),
2626
			'CR' => __( 'Costa Rica' ),
2627
			'HR' => __( 'Croatia' ),
2628
			'CU' => __( 'Cuba' ),
2629
			'CY' => __( 'Cyprus' ),
2630
			'CZ' => __( 'Czech Republic' ),
2631
			'CI' => __( 'Côte d’Ivoire' ),
2632
			'DK' => __( 'Denmark' ),
2633
			'DJ' => __( 'Djibouti' ),
2634
			'DM' => __( 'Dominica' ),
2635
			'DO' => __( 'Dominican Republic' ),
2636
			'NQ' => __( 'Dronning Maud Land' ),
2637
			'DD' => __( 'East Germany' ),
2638
			'EC' => __( 'Ecuador' ),
2639
			'EG' => __( 'Egypt' ),
2640
			'SV' => __( 'El Salvador' ),
2641
			'GQ' => __( 'Equatorial Guinea' ),
2642
			'ER' => __( 'Eritrea' ),
2643
			'EE' => __( 'Estonia' ),
2644
			'ET' => __( 'Ethiopia' ),
2645
			'FK' => __( 'Falkland Islands' ),
2646
			'FO' => __( 'Faroe Islands' ),
2647
			'FJ' => __( 'Fiji' ),
2648
			'FI' => __( 'Finland' ),
2649
			'FR' => __( 'France' ),
2650
			'GF' => __( 'French Guiana' ),
2651
			'PF' => __( 'French Polynesia' ),
2652
			'TF' => __( 'French Southern Territories' ),
2653
			'FQ' => __( 'French Southern and Antarctic Territories' ),
2654
			'GA' => __( 'Gabon' ),
2655
			'GM' => __( 'Gambia' ),
2656
			'GE' => __( 'Georgia' ),
2657
			'DE' => __( 'Germany' ),
2658
			'GH' => __( 'Ghana' ),
2659
			'GI' => __( 'Gibraltar' ),
2660
			'GR' => __( 'Greece' ),
2661
			'GL' => __( 'Greenland' ),
2662
			'GD' => __( 'Grenada' ),
2663
			'GP' => __( 'Guadeloupe' ),
2664
			'GU' => __( 'Guam' ),
2665
			'GT' => __( 'Guatemala' ),
2666
			'GG' => __( 'Guernsey' ),
2667
			'GN' => __( 'Guinea' ),
2668
			'GW' => __( 'Guinea-Bissau' ),
2669
			'GY' => __( 'Guyana' ),
2670
			'HT' => __( 'Haiti' ),
2671
			'HM' => __( 'Heard Island and McDonald Islands' ),
2672
			'HN' => __( 'Honduras' ),
2673
			'HK' => __( 'Hong Kong SAR China' ),
2674
			'HU' => __( 'Hungary' ),
2675
			'IS' => __( 'Iceland' ),
2676
			'IN' => __( 'India' ),
2677
			'ID' => __( 'Indonesia' ),
2678
			'IR' => __( 'Iran' ),
2679
			'IQ' => __( 'Iraq' ),
2680
			'IE' => __( 'Ireland' ),
2681
			'IM' => __( 'Isle of Man' ),
2682
			'IL' => __( 'Israel' ),
2683
			'IT' => __( 'Italy' ),
2684
			'JM' => __( 'Jamaica' ),
2685
			'JP' => __( 'Japan' ),
2686
			'JE' => __( 'Jersey' ),
2687
			'JT' => __( 'Johnston Island' ),
2688
			'JO' => __( 'Jordan' ),
2689
			'KZ' => __( 'Kazakhstan' ),
2690
			'KE' => __( 'Kenya' ),
2691
			'KI' => __( 'Kiribati' ),
2692
			'KW' => __( 'Kuwait' ),
2693
			'KG' => __( 'Kyrgyzstan' ),
2694
			'LA' => __( 'Laos' ),
2695
			'LV' => __( 'Latvia' ),
2696
			'LB' => __( 'Lebanon' ),
2697
			'LS' => __( 'Lesotho' ),
2698
			'LR' => __( 'Liberia' ),
2699
			'LY' => __( 'Libya' ),
2700
			'LI' => __( 'Liechtenstein' ),
2701
			'LT' => __( 'Lithuania' ),
2702
			'LU' => __( 'Luxembourg' ),
2703
			'MO' => __( 'Macau SAR China' ),
2704
			'MK' => __( 'Macedonia' ),
2705
			'MG' => __( 'Madagascar' ),
2706
			'MW' => __( 'Malawi' ),
2707
			'MY' => __( 'Malaysia' ),
2708
			'MV' => __( 'Maldives' ),
2709
			'ML' => __( 'Mali' ),
2710
			'MT' => __( 'Malta' ),
2711
			'MH' => __( 'Marshall Islands' ),
2712
			'MQ' => __( 'Martinique' ),
2713
			'MR' => __( 'Mauritania' ),
2714
			'MU' => __( 'Mauritius' ),
2715
			'YT' => __( 'Mayotte' ),
2716
			'FX' => __( 'Metropolitan France' ),
2717
			'MX' => __( 'Mexico' ),
2718
			'FM' => __( 'Micronesia' ),
2719
			'MI' => __( 'Midway Islands' ),
2720
			'MD' => __( 'Moldova' ),
2721
			'MC' => __( 'Monaco' ),
2722
			'MN' => __( 'Mongolia' ),
2723
			'ME' => __( 'Montenegro' ),
2724
			'MS' => __( 'Montserrat' ),
2725
			'MA' => __( 'Morocco' ),
2726
			'MZ' => __( 'Mozambique' ),
2727
			'MM' => __( 'Myanmar [Burma]' ),
2728
			'NA' => __( 'Namibia' ),
2729
			'NR' => __( 'Nauru' ),
2730
			'NP' => __( 'Nepal' ),
2731
			'NL' => __( 'Netherlands' ),
2732
			'AN' => __( 'Netherlands Antilles' ),
2733
			'NT' => __( 'Neutral Zone' ),
2734
			'NC' => __( 'New Caledonia' ),
2735
			'NZ' => __( 'New Zealand' ),
2736
			'NI' => __( 'Nicaragua' ),
2737
			'NE' => __( 'Niger' ),
2738
			'NG' => __( 'Nigeria' ),
2739
			'NU' => __( 'Niue' ),
2740
			'NF' => __( 'Norfolk Island' ),
2741
			'KP' => __( 'North Korea' ),
2742
			'VD' => __( 'North Vietnam' ),
2743
			'MP' => __( 'Northern Mariana Islands' ),
2744
			'NO' => __( 'Norway' ),
2745
			'OM' => __( 'Oman' ),
2746
			'PC' => __( 'Pacific Islands Trust Territory' ),
2747
			'PK' => __( 'Pakistan' ),
2748
			'PW' => __( 'Palau' ),
2749
			'PS' => __( 'Palestinian Territories' ),
2750
			'PA' => __( 'Panama' ),
2751
			'PZ' => __( 'Panama Canal Zone' ),
2752
			'PG' => __( 'Papua New Guinea' ),
2753
			'PY' => __( 'Paraguay' ),
2754
			'YD' => __( "People's Democratic Republic of Yemen" ),
2755
			'PE' => __( 'Peru' ),
2756
			'PH' => __( 'Philippines' ),
2757
			'PN' => __( 'Pitcairn Islands' ),
2758
			'PL' => __( 'Poland' ),
2759
			'PT' => __( 'Portugal' ),
2760
			'PR' => __( 'Puerto Rico' ),
2761
			'QA' => __( 'Qatar' ),
2762
			'RO' => __( 'Romania' ),
2763
			'RU' => __( 'Russia' ),
2764
			'RW' => __( 'Rwanda' ),
2765
			'RE' => __( 'Réunion' ),
2766
			'BL' => __( 'Saint Barthélemy' ),
2767
			'SH' => __( 'Saint Helena' ),
2768
			'KN' => __( 'Saint Kitts and Nevis' ),
2769
			'LC' => __( 'Saint Lucia' ),
2770
			'MF' => __( 'Saint Martin' ),
2771
			'PM' => __( 'Saint Pierre and Miquelon' ),
2772
			'VC' => __( 'Saint Vincent and the Grenadines' ),
2773
			'WS' => __( 'Samoa' ),
2774
			'SM' => __( 'San Marino' ),
2775
			'SA' => __( 'Saudi Arabia' ),
2776
			'SN' => __( 'Senegal' ),
2777
			'RS' => __( 'Serbia' ),
2778
			'CS' => __( 'Serbia and Montenegro' ),
2779
			'SC' => __( 'Seychelles' ),
2780
			'SL' => __( 'Sierra Leone' ),
2781
			'SG' => __( 'Singapore' ),
2782
			'SK' => __( 'Slovakia' ),
2783
			'SI' => __( 'Slovenia' ),
2784
			'SB' => __( 'Solomon Islands' ),
2785
			'SO' => __( 'Somalia' ),
2786
			'ZA' => __( 'South Africa' ),
2787
			'GS' => __( 'South Georgia and the South Sandwich Islands' ),
2788
			'KR' => __( 'South Korea' ),
2789
			'ES' => __( 'Spain' ),
2790
			'LK' => __( 'Sri Lanka' ),
2791
			'SD' => __( 'Sudan' ),
2792
			'SR' => __( 'Suriname' ),
2793
			'SJ' => __( 'Svalbard and Jan Mayen' ),
2794
			'SZ' => __( 'Swaziland' ),
2795
			'SE' => __( 'Sweden' ),
2796
			'CH' => __( 'Switzerland' ),
2797
			'SY' => __( 'Syria' ),
2798
			'ST' => __( 'São Tomé and Príncipe' ),
2799
			'TW' => __( 'Taiwan' ),
2800
			'TJ' => __( 'Tajikistan' ),
2801
			'TZ' => __( 'Tanzania' ),
2802
			'TH' => __( 'Thailand' ),
2803
			'TL' => __( 'Timor-Leste' ),
2804
			'TG' => __( 'Togo' ),
2805
			'TK' => __( 'Tokelau' ),
2806
			'TO' => __( 'Tonga' ),
2807
			'TT' => __( 'Trinidad and Tobago' ),
2808
			'TN' => __( 'Tunisia' ),
2809
			'TR' => __( 'Turkey' ),
2810
			'TM' => __( 'Turkmenistan' ),
2811
			'TC' => __( 'Turks and Caicos Islands' ),
2812
			'TV' => __( 'Tuvalu' ),
2813
			'UM' => __( 'U.S. Minor Outlying Islands' ),
2814
			'PU' => __( 'U.S. Miscellaneous Pacific Islands' ),
2815
			'VI' => __( 'U.S. Virgin Islands' ),
2816
			'UG' => __( 'Uganda' ),
2817
			'UA' => __( 'Ukraine' ),
2818
			'SU' => __( 'Union of Soviet Socialist Republics' ),
2819
			'AE' => __( 'United Arab Emirates' ),
2820
			'GB' => __( 'United Kingdom' ),
2821
			'US' => __( 'United States' ),
2822
			'ZZ' => __( 'Unknown or Invalid Region' ),
2823
			'UY' => __( 'Uruguay' ),
2824
			'UZ' => __( 'Uzbekistan' ),
2825
			'VU' => __( 'Vanuatu' ),
2826
			'VA' => __( 'Vatican City' ),
2827
			'VE' => __( 'Venezuela' ),
2828
			'VN' => __( 'Vietnam' ),
2829
			'WK' => __( 'Wake Island' ),
2830
			'WF' => __( 'Wallis and Futuna' ),
2831
			'EH' => __( 'Western Sahara' ),
2832
			'YE' => __( 'Yemen' ),
2833
			'ZM' => __( 'Zambia' ),
2834
			'ZW' => __( 'Zimbabwe' ),
2835
			'AX' => __( 'Åland Islands' ),
2836
		);
2837
2838
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2839
2840
	}
2841
2842
	/**
2843
	 * Data callback for US States
2844
	 *
2845
	 * @param string       $name    The name of the field
2846
	 * @param string|array $value   The value of the field
2847
	 * @param array        $options Field options
2848
	 * @param array        $pod     Pod data
2849
	 * @param int          $id      Item ID
2850
	 *
2851
	 * @return array
2852
	 *
2853
	 * @since 2.3
2854
	 */
2855
	public function data_us_states( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2856
2857
		$data = array(
2858
			'AL' => __( 'Alabama' ),
2859
			'AK' => __( 'Alaska' ),
2860
			'AZ' => __( 'Arizona' ),
2861
			'AR' => __( 'Arkansas' ),
2862
			'CA' => __( 'California' ),
2863
			'CO' => __( 'Colorado' ),
2864
			'CT' => __( 'Connecticut' ),
2865
			'DE' => __( 'Delaware' ),
2866
			'DC' => __( 'District Of Columbia' ),
2867
			'FL' => __( 'Florida' ),
2868
			'GA' => __( 'Georgia' ),
2869
			'HI' => __( 'Hawaii' ),
2870
			'ID' => __( 'Idaho' ),
2871
			'IL' => __( 'Illinois' ),
2872
			'IN' => __( 'Indiana' ),
2873
			'IA' => __( 'Iowa' ),
2874
			'KS' => __( 'Kansas' ),
2875
			'KY' => __( 'Kentucky' ),
2876
			'LA' => __( 'Louisiana' ),
2877
			'ME' => __( 'Maine' ),
2878
			'MD' => __( 'Maryland' ),
2879
			'MA' => __( 'Massachusetts' ),
2880
			'MI' => __( 'Michigan' ),
2881
			'MN' => __( 'Minnesota' ),
2882
			'MS' => __( 'Mississippi' ),
2883
			'MO' => __( 'Missouri' ),
2884
			'MT' => __( 'Montana' ),
2885
			'NE' => __( 'Nebraska' ),
2886
			'NV' => __( 'Nevada' ),
2887
			'NH' => __( 'New Hampshire' ),
2888
			'NJ' => __( 'New Jersey' ),
2889
			'NM' => __( 'New Mexico' ),
2890
			'NY' => __( 'New York' ),
2891
			'NC' => __( 'North Carolina' ),
2892
			'ND' => __( 'North Dakota' ),
2893
			'OH' => __( 'Ohio' ),
2894
			'OK' => __( 'Oklahoma' ),
2895
			'OR' => __( 'Oregon' ),
2896
			'PA' => __( 'Pennsylvania' ),
2897
			'RI' => __( 'Rhode Island' ),
2898
			'SC' => __( 'South Carolina' ),
2899
			'SD' => __( 'South Dakota' ),
2900
			'TN' => __( 'Tennessee' ),
2901
			'TX' => __( 'Texas' ),
2902
			'UT' => __( 'Utah' ),
2903
			'VT' => __( 'Vermont' ),
2904
			'VA' => __( 'Virginia' ),
2905
			'WA' => __( 'Washington' ),
2906
			'WV' => __( 'West Virginia' ),
2907
			'WI' => __( 'Wisconsin' ),
2908
			'WY' => __( 'Wyoming' ),
2909
		);
2910
2911
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2912
2913
	}
2914
2915
	/**
2916
	 * Data callback for US States
2917
	 *
2918
	 * @param string       $name    The name of the field
2919
	 * @param string|array $value   The value of the field
2920
	 * @param array        $options Field options
2921
	 * @param array        $pod     Pod data
2922
	 * @param int          $id      Item ID
2923
	 *
2924
	 * @return array
2925
	 *
2926
	 * @since 2.3
2927
	 */
2928
	public function data_days_of_week( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2929
2930
		/**
2931
		 * @var WP_Locale
2932
		 */
2933
		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...
2934
2935
		return $wp_locale->weekday;
2936
2937
	}
2938
2939
	/**
2940
	 * Data callback for US States
2941
	 *
2942
	 * @param string       $name    The name of the field
2943
	 * @param string|array $value   The value of the field
2944
	 * @param array        $options Field options
2945
	 * @param array        $pod     Pod data
2946
	 * @param int          $id      Item ID
2947
	 *
2948
	 * @return array
2949
	 *
2950
	 * @since 2.3
2951
	 */
2952
	public function data_months_of_year( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2953
2954
		/**
2955
		 * @var WP_Locale
2956
		 */
2957
		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...
2958
2959
		return $wp_locale->month;
2960
2961
	}
2962
2963
	/**
2964
	 * Add our modal input to the form so we can track whether we're in our modal during saving or not.
2965
	 */
2966
	public function admin_modal_input() {
2967
2968
		if ( ! pods_is_modal_window() ) {
2969
			return;
2970
		}
2971
2972
		echo '<input name="pods_modal" type="hidden" value="1" />';
2973
2974
	}
2975
2976
	/**
2977
	 * Bail to send new saved data back to our modal handler.
2978
	 *
2979
	 * @param int    $item_id
2980
	 * @param string $item_title
2981
	 * @param object $field_args
2982
	 */
2983
	public function admin_modal_bail( $item_id, $item_title, $field_args ) {
2984
2985
		$model_data = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $field_args );
2986
		?>
2987
			<script type="text/javascript">
2988
				window.parent.jQuery( window.parent ).trigger(
2989
					'dfv:modal:update',
2990
					<?php echo json_encode( $model_data, JSON_HEX_TAG ); ?>
0 ignored issues
show
Unused Code introduced by
The call to json_encode() has too many arguments starting with JSON_HEX_TAG.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
2991
				);
2992
			</script>
2993
		<?php
2994
2995
		die();
2996
2997
	}
2998
2999
	/**
3000
	 * Bail to send new saved data back to our modal handler.
3001
	 *
3002
	 * @param int    $item_id
3003
	 * @param string $item_title
3004
	 * @param object $field_args
3005
	 */
3006
	public function admin_modal_bail_JSON( $item_id, $item_title, $field_args ) {
3007
3008
		$model_data = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $field_args );
3009
		echo json_encode( $model_data, JSON_HEX_TAG );
0 ignored issues
show
Unused Code introduced by
The call to json_encode() has too many arguments starting with JSON_HEX_TAG.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
3010
3011
		die();
3012
	}
3013
3014
	/**
3015
	 * Bail on Post save redirect for Admin modal.
3016
	 *
3017
	 * @param string $location The destination URL.
3018
	 * @param int    $post_id  The post ID.
3019
	 *
3020
	 * @return string
3021
	 */
3022
	public function admin_modal_bail_post_redirect( $location, $post_id ) {
3023
3024
		if ( ! pods_is_modal_window() ) {
3025
			return $location;
3026
		}
3027
3028
		$post_title = get_the_title( $post_id );
3029
3030
		$field_args = (object) array(
3031
			'options' => array(
3032
				'pick_object' => 'post_type',
3033
				'pick_val'    => get_post_type( $post_id ),
3034
			),
3035
			'value'   => array(
3036
				$post_id => $post_title,
3037
			),
3038
		);
3039
3040
		$this->admin_modal_bail( $post_id, $post_title, $field_args );
3041
3042
		return $location;
3043
3044
	}
3045
3046
	/**
3047
	 * Hook into term updating process to bail on redirect.
3048
	 */
3049
	public function admin_modal_bail_term_action() {
3050
3051
		if ( ! pods_is_modal_window() ) {
3052
			return;
3053
		}
3054
3055
		add_action( 'created_term', array( $this, 'admin_modal_bail_term' ), 10, 3 );
3056
		add_action( 'edited_term', array( $this, 'admin_modal_bail_term' ), 10, 3 );
3057
3058
	}
3059
3060
	/**
3061
	 * Bail on Term save redirect for Admin modal.
3062
	 *
3063
	 * @param int    $term_id  Term ID.
3064
	 * @param int    $tt_id    Term taxonomy ID.
3065
	 * @param string $taxonomy Taxonomy slug.
3066
	 */
3067
	public function admin_modal_bail_term( $term_id, $tt_id, $taxonomy ) {
3068
3069
		if ( ! pods_is_modal_window() ) {
3070
			return;
3071
		}
3072
3073
		$term = get_term( $term_id );
3074
3075
		if ( ! $term || is_wp_error( $term ) ) {
3076
			return;
3077
		}
3078
3079
		$field_args = (object) array(
3080
			'options' => array(
3081
				'pick_object' => 'taxonomy',
3082
				'pick_val'    => $term->taxonomy,
3083
			),
3084
			'value'   => array(
3085
				$term->term_id => $term->name,
3086
			),
3087
		);
3088
3089
		$this->admin_modal_bail( $term->term_id, $term->name, $field_args );
3090
3091
	}
3092
3093
	/**
3094
	 * Hook into user updating process to bail on redirect.
3095
	 */
3096
	public function admin_modal_bail_user_action() {
3097
3098
		if ( ! pods_is_modal_window() ) {
3099
			return;
3100
		}
3101
3102
		add_filter( 'wp_redirect', array( $this, 'admin_modal_bail_user_redirect' ) );
3103
3104
	}
3105
3106
	/**
3107
	 * Bail on User save redirect for Admin modal.
3108
	 *
3109
	 * @param string $location The destination URL.
3110
	 *
3111
	 * @return string
3112
	 */
3113
	public function admin_modal_bail_user_redirect( $location ) {
3114
3115
		if ( ! pods_is_modal_window() ) {
3116
			return $location;
3117
		}
3118
3119
		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...
3120
3121
		$user = get_userdata( $user_id );
3122
3123
		if ( ! $user || is_wp_error( $user ) ) {
3124
			return $location;
3125
		}
3126
3127
		$field_args = (object) array(
3128
			'options' => array(
3129
				'pick_object' => 'user',
3130
				'pick_val'    => '',
3131
			),
3132
			'value'   => array(
3133
				$user->ID => $user->display_name,
3134
			),
3135
		);
3136
3137
		$this->admin_modal_bail( $user->ID, $user->display_name, $field_args );
3138
3139
		return $location;
3140
3141
	}
3142
3143
	/**
3144
	 * Bail on Pod item save for Admin modal.
3145
	 *
3146
	 * @param int       $id     Item ID.
3147
	 * @param array     $params save_pod_item parameters.
3148
	 * @param null|Pods $obj    Pod object (if set).
3149
	 */
3150
	public function admin_modal_bail_pod( $id, $params, $obj ) {
3151
3152
		if ( ! pods_is_modal_window() ) {
3153
			return;
3154
		}
3155
3156
		if ( ! $obj ) {
3157
			$obj = pods( $params['pod'] );
3158
		}
3159
3160
		if ( ! $obj || ! $obj->fetch( $id ) ) {
3161
			return;
3162
		}
3163
3164
		$item_id    = $obj->id();
3165
		$item_title = $obj->index();
3166
3167
		$field_args = (object) array(
3168
			'options' => array(
3169
				'pick_object' => $obj->pod_data['type'],
3170
				'pick_val'    => $obj->pod,
3171
			),
3172
			'value'   => array(
3173
				$obj->id() => $item_title,
3174
			),
3175
		);
3176
3177
		$this->admin_modal_bail_JSON( $item_id, $item_title, $field_args );
3178
3179
	}
3180
3181
}
3182