Completed
Pull Request — 2.x (#4068)
by Jory
04:54
created

PodsField_Pick::data_capabilities()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 90
Code Lines 68

Duplication

Lines 7
Ratio 7.78 %

Importance

Changes 0
Metric Value
cc 5
eloc 68
nc 8
nop 5
dl 7
loc 90
rs 8.2713
c 0
b 0
f 0

How to fix   Long Method   

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
	}
107
108
	/**
109
	 * {@inheritdoc}
110
	 */
111
	public function options() {
112
113
		$options = array(
114
			self::$type . '_format_type'    => array(
115
				'label'      => __( 'Selection Type', 'pods' ),
116
				'help'       => __( 'help', 'pods' ),
117
				'default'    => 'single',
118
				'type'       => 'pick',
119
				'data'       => array(
120
					'single' => __( 'Single Select', 'pods' ),
121
					'multi'  => __( 'Multiple Select', 'pods' ),
122
				),
123
				'dependency' => true,
124
			),
125
			self::$type . '_format_single'  => array(
126
				'label'      => __( 'Format', 'pods' ),
127
				'help'       => __( 'help', 'pods' ),
128
				'depends-on' => array( self::$type . '_format_type' => 'single' ),
129
				'default'    => 'dropdown',
130
				'type'       => 'pick',
131
				'data'       => apply_filters( 'pods_form_ui_field_pick_format_single_options', array(
132
						'dropdown'     => __( 'Drop Down', 'pods' ),
133
						'radio'        => __( 'Radio Buttons', 'pods' ),
134
						'autocomplete' => __( 'Autocomplete', 'pods' ),
135
						'list'         => __( 'List view', 'pods' ),
136
					)
137
				),
138
				'dependency' => true,
139
			),
140
			self::$type . '_format_multi'   => array(
141
				'label'      => __( 'Format', 'pods' ),
142
				'help'       => __( 'help', 'pods' ),
143
				'depends-on' => array( self::$type . '_format_type' => 'multi' ),
144
				'default'    => 'checkbox',
145
				'type'       => 'pick',
146
				'data'       => apply_filters( 'pods_form_ui_field_pick_format_multi_options', array(
147
						'checkbox'     => __( 'Checkboxes', 'pods' ),
148
						'multiselect'  => __( 'Multi Select', 'pods' ),
149
						'autocomplete' => __( 'Autocomplete', 'pods' ),
150
						'list'         => __( 'List view', 'pods' ),
151
					)
152
				),
153
				'dependency' => true,
154
			),
155
			self::$type . '_taggable'       => array(
156
				'label'       => __( 'Taggable', 'pods' ),
157
				'help'        => __( 'Allow new values to be inserted when using an Autocomplete field', 'pods' ),
158
				'excludes-on' => array(
159
					self::$type . '_format_single' => array( 'dropdown', 'radio', 'list' ),
160
					self::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'list' ),
161
					self::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
162
				),
163
				'type'        => 'boolean',
164
				'default'     => 0,
165
			),
166
			self::$type . '_show_icon'      => array(
167
				'label'       => __( 'Show Icons', 'pods' ),
168
				'excludes-on' => array(
169
					self::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
170
					self::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'autocomplete' ),
171
					self::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
172
				),
173
				'type'        => 'boolean',
174
				'default'     => 1,
175
			),
176
			self::$type . '_show_edit_link' => array(
177
				'label'       => __( 'Show Edit Links', 'pods' ),
178
				'excludes-on' => array(
179
					self::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
180
					self::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'autocomplete' ),
181
					self::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
182
				),
183
				'type'        => 'boolean',
184
				'default'     => 1,
185
			),
186
			self::$type . '_show_view_link' => array(
187
				'label'       => __( 'Show View Links', 'pods' ),
188
				'excludes-on' => array(
189
					self::$type . '_format_single' => array( 'dropdown', 'radio', 'autocomplete' ),
190
					self::$type . '_format_multi'  => array( 'checkbox', 'multiselect', 'autocomplete' ),
191
					self::$type . '_object'        => array_merge( array( 'site', 'network' ), self::simple_objects() ),
192
				),
193
				'type'        => 'boolean',
194
				'default'     => 1,
195
			),
196
			self::$type . '_select_text'    => array(
197
				'label'      => __( 'Default Select Text', 'pods' ),
198
				'help'       => __( 'This is the text use for the default "no selection" dropdown item, if empty, it will default to "-- Select One --"', 'pods' ),
199
				'depends-on' => array(
200
					self::$type . '_format_type'   => 'single',
201
					self::$type . '_format_single' => 'dropdown',
202
				),
203
				'default'    => '',
204
				'type'       => 'text',
205
			),
206
			self::$type . '_limit'          => array(
207
				'label'      => __( 'Selection Limit', 'pods' ),
208
				'help'       => __( 'help', 'pods' ),
209
				'depends-on' => array( self::$type . '_format_type' => 'multi' ),
210
				'default'    => 0,
211
				'type'       => 'number',
212
			),
213
			self::$type . '_table_id'       => array(
214
				'label'      => __( 'Table ID Column', 'pods' ),
215
				'help'       => __( 'You must provide the ID column name for the table, this will be used to keep track of the relationship', 'pods' ),
216
				'depends-on' => array( self::$type . '_object' => 'table' ),
217
				'required'   => 1,
218
				'default'    => '',
219
				'type'       => 'text',
220
			),
221
			self::$type . '_table_index'    => array(
222
				'label'      => __( 'Table Index Column', 'pods' ),
223
				'help'       => __( 'You must provide the index column name for the table, this may optionally also be the ID column name', 'pods' ),
224
				'depends-on' => array( self::$type . '_object' => 'table' ),
225
				'required'   => 1,
226
				'default'    => '',
227
				'type'       => 'text',
228
			),
229
			self::$type . '_display'        => array(
230
				'label'       => __( 'Display Field in Selection List', 'pods' ),
231
				'help'        => __( 'Provide the name of a field on the related object to reference, example: {@post_title}', 'pods' ),
232
				'excludes-on' => array(
233
					self::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
234
				),
235
				'default'     => '',
236
				'type'        => 'text',
237
			),
238
			self::$type . '_user_role'      => array(
239
				'label'            => __( 'Limit list to Role(s)', 'pods' ),
240
				'help'             => __( 'help', 'pods' ),
241
				'depends-on'       => array( self::$type . '_object' => 'user' ),
242
				'default'          => '',
243
				'type'             => 'pick',
244
				'pick_object'      => 'role',
245
				'pick_format_type' => 'multi',
246
			),
247
			/*
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...
248
            self::$type . '_user_site' => array(
249
                'label' => __( 'Limit list to Site(s)', 'pods' ),
250
                'help' => __( 'help', 'pods' ),
251
                'depends-on' => array( self::$type . '_object' => 'user' ),
252
                'default' => '',
253
                'type' => 'pick',
254
                'pick_object' => 'site',
255
                'pick_format_type' => 'multi',
256
            ),
257
			*/
258
			self::$type . '_where'          => array(
259
				'label'       => __( 'Customized <em>WHERE</em>', 'pods' ),
260
				'help'        => __( 'help', 'pods' ),
261
				'excludes-on' => array(
262
					self::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
263
				),
264
				'default'     => '',
265
				'type'        => 'text',
266
			),
267
			self::$type . '_orderby'        => array(
268
				'label'       => __( 'Customized <em>ORDER BY</em>', 'pods' ),
269
				'help'        => __( 'help', 'pods' ),
270
				'excludes-on' => array(
271
					self::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
272
				),
273
				'default'     => '',
274
				'type'        => 'text',
275
			),
276
			self::$type . '_groupby'        => array(
277
				'label'       => __( 'Customized <em>GROUP BY</em>', 'pods' ),
278
				'help'        => __( 'help', 'pods' ),
279
				'excludes-on' => array(
280
					self::$type . '_object' => array_merge( array( 'site', 'network' ), self::simple_objects() ),
281
				),
282
				'default'     => '',
283
				'type'        => 'text',
284
			),
285
			/*
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...
286
			self::$type . '_size' => array(
287
				'label' => __( 'Field Size', 'pods' ),
288
				'default' => 'medium',
289
				'type' => 'pick',
290
				'data' => array(
291
					'small' => __( 'Small', 'pods' ),
292
					'medium' => __( 'Medium', 'pods' ),
293
					'large' => __( 'Large', 'pods' )
294
				)
295
			),
296
			*/
297
		);
298
299
		$post_type_pick_objects = array();
300
301
		foreach ( get_post_types( '', 'names' ) as $post_type ) {
302
			$post_type_pick_objects[] = 'post-type_' . $post_type;
303
		}
304
305
		$options[ self::$type . '_post_status' ] = array(
306
			'name'             => 'post_status',
307
			'label'            => __( 'Post Status', 'pods' ),
308
			'help'             => __( 'help', 'pods' ),
309
			'type'             => 'pick',
310
			'pick_object'      => 'post-status',
311
			'pick_format_type' => 'multi',
312
			'default'          => 'publish',
313
			'depends-on'       => array(
314
				self::$type . '_object' => $post_type_pick_objects,
315
			),
316
		);
317
318
		/*
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...
319
		if ( ! is_multisite() ) {
320
			unset( $options[ self::$type . '_user_site' ] );
321
		}
322
		*/
323
324
		return $options;
325
326
	}
327
328
	/**
329
	 * Register a related object
330
	 *
331
	 * @param string $name    Object name
332
	 * @param string $label   Object label
333
	 * @param array  $options Object options
334
	 *
335
	 * @return array|boolean Object array or false if unsuccessful
336
	 * @since 2.3
337
	 */
338
	public function register_related_object( $name, $label, $options = null ) {
339
340
		if ( empty( $name ) || empty( $label ) ) {
341
			return false;
342
		}
343
344
		$related_object = array(
345
			'label'         => $label,
346
			'group'         => 'Custom Relationships',
347
			'simple'        => true,
348
			'bidirectional' => false,
349
			'data'          => array(),
350
			'data_callback' => null,
351
		);
352
353
		$related_object = array_merge( $related_object, $options );
354
355
		self::$custom_related_objects[ $name ] = $related_object;
356
357
		return true;
358
359
	}
360
361
	/**
362
	 * Setup related objects
363
	 *
364
	 * @param boolean $force Whether to force refresh of related objects
365
	 *
366
	 * @return bool True when data has been loaded
367
	 * @since 2.3
368
	 */
369
	public function setup_related_objects( $force = false ) {
370
371
		$new_data_loaded = false;
372
373
		if ( ! $force && empty( self::$related_objects ) ) {
374
			// Only load transient if we aren't forcing a refresh.
375
			self::$related_objects = pods_transient_get( 'pods_related_objects' );
376
377
			if ( false !== self::$related_objects ) {
378
				$new_data_loaded = true;
379
			}
380
		} elseif ( $force ) {
381
			// If we are rebuilding, make sure we start with a clean slate.
382
			self::$related_objects = array();
383
		}
384
385
		if ( empty( self::$related_objects ) ) {
386
			// Do a complete build of related_objects.
387
			$new_data_loaded = true;
388
389
			// Custom simple relationship lists.
390
			self::$related_objects['custom-simple'] = array(
391
				'label'  => __( 'Simple (custom defined list)', 'pods' ),
392
				'group'  => __( 'Custom', 'pods' ),
393
				'simple' => true,
394
			);
395
396
			// Pods options.
397
			$pod_options = array();
398
399
			// Include PodsMeta if not already included.
400
			pods_meta();
401
402
			// Advanced Content Types for relationships.
403
			$_pods = PodsMeta::$advanced_content_types;
404
405 View Code Duplication
			foreach ( $_pods as $pod ) {
406
				$pod_options[ $pod['name'] ] = $pod['label'] . ' (' . $pod['name'] . ')';
407
			}
408
409
			// Settings pods for relationships.
410
			$_pods = PodsMeta::$settings;
411
412 View Code Duplication
			foreach ( $_pods as $pod ) {
413
				$pod_options[ $pod['name'] ] = $pod['label'] . ' (' . $pod['name'] . ')';
414
			}
415
416
			asort( $pod_options );
417
418
			foreach ( $pod_options as $pod => $label ) {
419
				self::$related_objects[ 'pod-' . $pod ] = array(
420
					'label'         => $label,
421
					'group'         => __( 'Pods', 'pods' ),
422
					'bidirectional' => true,
423
				);
424
			}
425
426
			// Post Types for relationships.
427
			$post_types = get_post_types();
428
			asort( $post_types );
429
430
			$ignore = array( 'attachment', 'revision', 'nav_menu_item' );
431
432 View Code Duplication
			foreach ( $post_types as $post_type => $label ) {
433
				if ( in_array( $post_type, $ignore, true ) || empty( $post_type ) ) {
434
					unset( $post_types[ $post_type ] );
435
436
					continue;
437
				} elseif ( 0 === strpos( $post_type, '_pods_' ) && apply_filters( 'pods_pick_ignore_internal', true ) ) {
438
					unset( $post_types[ $post_type ] );
439
440
					continue;
441
				}
442
443
				$post_type = get_post_type_object( $post_type );
444
445
				self::$related_objects[ 'post_type-' . $post_type->name ] = array(
446
					'label'         => $post_type->label . ' (' . $post_type->name . ')',
447
					'group'         => __( 'Post Types', 'pods' ),
448
					'bidirectional' => true,
449
				);
450
			}
451
452
			// Taxonomies for relationships.
453
			$taxonomies = get_taxonomies();
454
			asort( $taxonomies );
455
456
			$ignore = array( 'nav_menu', 'post_format' );
457
458 View Code Duplication
			foreach ( $taxonomies as $taxonomy => $label ) {
459
				/**
460
				 * Prevent ability to extend core Pods content types.
461
				 *
462
				 * @param bool $ignore_internal Default is true, when set to false Pods internal content types can not be extended.
463
				 *
464
				 * @since 2.3.19
465
				 */
466
				$ignore_internal = apply_filters( 'pods_pick_ignore_internal', true );
467
468
				if ( in_array( $taxonomy, $ignore, true ) || empty( $taxonomy ) ) {
469
					unset( $taxonomies[ $taxonomy ] );
470
471
					continue;
472
				} elseif ( 0 === strpos( $taxonomy, '_pods_' ) && $ignore_internal ) {
473
					unset( $taxonomies[ $taxonomy ] );
474
475
					continue;
476
				}
477
478
				$taxonomy = get_taxonomy( $taxonomy );
479
480
				self::$related_objects[ 'taxonomy-' . $taxonomy->name ] = array(
481
					'label'         => $taxonomy->label . ' (' . $taxonomy->name . ')',
482
					'group'         => __( 'Taxonomies', 'pods' ),
483
					'bidirectional' => true,
484
				);
485
			}
486
487
			// Other WP Objects for relationships.
488
			self::$related_objects['user'] = array(
489
				'label'         => __( 'Users', 'pods' ),
490
				'group'         => __( 'Other WP Objects', 'pods' ),
491
				'bidirectional' => true,
492
			);
493
494
			self::$related_objects['role'] = array(
495
				'label'         => __( 'User Roles', 'pods' ),
496
				'group'         => __( 'Other WP Objects', 'pods' ),
497
				'simple'        => true,
498
				'data_callback' => array( $this, 'data_roles' ),
499
			);
500
501
			self::$related_objects['capability'] = array(
502
				'label'         => __( 'User Capabilities', 'pods' ),
503
				'group'         => __( 'Other WP Objects', 'pods' ),
504
				'simple'        => true,
505
				'data_callback' => array( $this, 'data_capabilities' ),
506
			);
507
508
			self::$related_objects['media'] = array(
509
				'label'         => __( 'Media', 'pods' ),
510
				'group'         => __( 'Other WP Objects', 'pods' ),
511
				'bidirectional' => true,
512
			);
513
514
			self::$related_objects['comment'] = array(
515
				'label'         => __( 'Comments', 'pods' ),
516
				'group'         => __( 'Other WP Objects', 'pods' ),
517
				'bidirectional' => true,
518
			);
519
520
			self::$related_objects['image-size'] = array(
521
				'label'         => __( 'Image Sizes', 'pods' ),
522
				'group'         => __( 'Other WP Objects', 'pods' ),
523
				'simple'        => true,
524
				'data_callback' => array( $this, 'data_image_sizes' ),
525
			);
526
527
			self::$related_objects['nav_menu'] = array(
528
				'label' => __( 'Navigation Menus', 'pods' ),
529
				'group' => __( 'Other WP Objects', 'pods' ),
530
			);
531
532
			self::$related_objects['post_format'] = array(
533
				'label' => __( 'Post Formats', 'pods' ),
534
				'group' => __( 'Other WP Objects', 'pods' ),
535
			);
536
537
			self::$related_objects['post-status'] = array(
538
				'label'         => __( 'Post Status', 'pods' ),
539
				'group'         => __( 'Other WP Objects', 'pods' ),
540
				'simple'        => true,
541
				'data_callback' => array( $this, 'data_post_stati' ),
542
			);
543
544
			do_action( 'pods_form_ui_field_pick_related_objects_other' );
545
546
			self::$related_objects['country'] = array(
547
				'label'         => __( 'Countries', 'pods' ),
548
				'group'         => __( 'Predefined Lists', 'pods' ),
549
				'simple'        => true,
550
				'data_callback' => array( $this, 'data_countries' ),
551
			);
552
553
			self::$related_objects['us_state'] = array(
554
				'label'         => __( 'US States', 'pods' ),
555
				'group'         => __( 'Predefined Lists', 'pods' ),
556
				'simple'        => true,
557
				'data_callback' => array( $this, 'data_us_states' ),
558
			);
559
560
			self::$related_objects['days_of_week'] = array(
561
				'label'         => __( 'Calendar - Days of Week', 'pods' ),
562
				'group'         => __( 'Predefined Lists', 'pods' ),
563
				'simple'        => true,
564
				'data_callback' => array( $this, 'data_days_of_week' ),
565
			);
566
567
			self::$related_objects['months_of_year'] = array(
568
				'label'         => __( 'Calendar - Months of Year', 'pods' ),
569
				'group'         => __( 'Predefined Lists', 'pods' ),
570
				'simple'        => true,
571
				'data_callback' => array( $this, 'data_months_of_year' ),
572
			);
573
574
			do_action( 'pods_form_ui_field_pick_related_objects_predefined' );
575
576
			if ( did_action( 'init' ) ) {
577
				pods_transient_set( 'pods_related_objects', self::$related_objects );
578
			}
579
		}
580
581
		/**
582
		 * Allow custom related objects to be defined
583
		 */
584
		do_action( 'pods_form_ui_field_pick_related_objects_custom' );
585
586
		foreach ( self::$custom_related_objects as $object => $related_object ) {
587
			if ( ! isset( self::$related_objects[ $object ] ) ) {
588
				$new_data_loaded = true;
589
590
				self::$related_objects[ $object ] = $related_object;
591
			}
592
		}
593
594
		return $new_data_loaded;
595
596
	}
597
598
	/**
599
	 * Return available related objects
600
	 *
601
	 * @param boolean $force Whether to force refresh of related objects
602
	 *
603
	 * @return array Field selection array
604
	 * @since 2.3
605
	 */
606
	public function related_objects( $force = false ) {
607
608
		if ( $this->setup_related_objects( $force ) || null === self::$names_related ) {
609
			$related_objects = array();
610
611
			foreach ( self::$related_objects as $related_object_name => $related_object ) {
612
				if ( ! isset( $related_objects[ $related_object['group'] ] ) ) {
613
					$related_objects[ $related_object['group'] ] = array();
614
				}
615
616
				$related_objects[ $related_object['group'] ][ $related_object_name ] = $related_object['label'];
617
			}
618
619
			self::$names_related = (array) apply_filters( 'pods_form_ui_field_pick_related_objects', $related_objects );
620
		}
621
622
		return self::$names_related;
623
624
	}
625
626
	/**
627
	 * Return available simple object names
628
	 *
629
	 * @return array Simple object names
630
	 * @since 2.3
631
	 */
632 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...
633
634
		if ( $this->setup_related_objects() || null === self::$names_simple ) {
635
			$simple_objects = array();
636
637
			foreach ( self::$related_objects as $object => $related_object ) {
638
				if ( ! isset( $related_object['simple'] ) || ! $related_object['simple'] ) {
639
					continue;
640
				}
641
642
				$simple_objects[] = $object;
643
			}
644
645
			self::$names_simple = (array) apply_filters( 'pods_form_ui_field_pick_simple_objects', $simple_objects );
646
		}
647
648
		return self::$names_simple;
649
650
	}
651
652
	/**
653
	 * Return available bidirectional object names
654
	 *
655
	 * @return array Bidirectional object names
656
	 * @since 2.3.4
657
	 */
658 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...
659
660
		if ( $this->setup_related_objects() || null === self::$names_bidirectional ) {
661
			$bidirectional_objects = array();
662
663
			foreach ( self::$related_objects as $object => $related_object ) {
664
				if ( ! isset( $related_object['bidirectional'] ) || ! $related_object['bidirectional'] ) {
665
					continue;
666
				}
667
668
				$bidirectional_objects[] = $object;
669
			}
670
671
			self::$names_bidirectional = (array) apply_filters( 'pods_form_ui_field_pick_bidirectional_objects', $bidirectional_objects );
672
		}
673
674
		return self::$names_bidirectional;
675
676
	}
677
678
	/**
679
	 * {@inheritdoc}
680
	 */
681
	public function schema( $options = null ) {
682
683
		$schema = false;
684
685
		$simple_tableless_objects = $this->simple_objects();
686
687
		if ( in_array( pods_v( self::$type . '_object', $options ), $simple_tableless_objects, true ) ) {
688
			$schema = 'LONGTEXT';
689
		}
690
691
		return $schema;
692
693
	}
694
695
	/**
696
	 * {@inheritdoc}
697
	 */
698
	public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
699
700
		$fields = null;
701
702
		if ( is_object( $pod ) && isset( $pod->fields ) ) {
703
			/**
704
			 * @var $pod Pods
705
			 */
706
			$fields = $pod->fields;
707
708
			if ( ! empty( $pod->pod_data['object_fields'] ) ) {
709
				$fields = array_merge( $fields, $pod->pod_data['object_fields'] );
710
			}
711 View Code Duplication
		} elseif ( is_array( $pod ) && isset( $pod['fields'] ) ) {
712
			$fields = $pod['fields'];
713
714
			if ( ! empty( $pod['object_fields'] ) ) {
715
				$fields = array_merge( $fields, $pod['object_fields'] );
716
			}
717
		}
718
719
		return pods_serial_comma( $value, array( 'field' => $name, 'fields' => $fields ) );
720
721
	}
722
723
	/**
724
	 * {@inheritdoc}
725
	 */
726
	public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
727
728
		$options = (array) $options;
729
730
		$type = pods_v( 'type', $options, static::$type );
731
732
		$args = compact( array_keys( get_defined_vars() ) );
733
		$args = (object) $args;
734
735
		wp_enqueue_style( 'pods-dfv-list' );
736
		wp_enqueue_script( 'pods-dfv' );
737
738
		wp_enqueue_style( 'pods-select2' );
739
		wp_enqueue_script( 'pods-select2' );
740
741
		$this->render_input_script( $args );
742
743
		return;
744
745
		// @todo Support custom integrations.
746
		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...
747
		do_action( 'pods_form_ui_field_pick_input', pods_v( self::$type . '_format_type', $options, 'single' ), $name, $value, $options, $pod, $id );
748
749
		// @todo Support custom integrations.
750
		do_action( 'pods_form_ui_field_pick_input', pods_v( self::$type . '_format_type', $options, 'single' ), $name, $value, $options, $pod, $id );
751
752
	}
753
754
	/**
755
	 * {@inheritdoc}
756
	 */
757
	public function build_dfv_field_options( $options, $args ) {
758
759
		$options['grouped'] = 1;
760
761
		if ( empty( $options['pick_object'] ) ) {
762
			$options['pick_object'] = '';
763
		}
764
765
		if ( empty( $options['pick_val'] ) ) {
766
			$options['pick_val'] = '';
767
		}
768
769
		$options['table_info'] = array();
770
771
		$custom = pods_v( $args->type . '_custom', $options, false );
772
773
		$custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $args->name, $args->value, $options, $args->pod, $args->id );
774
775
		$ajax = false;
776
777
		if ( ( 'custom-simple' !== pods_v( $args->type . '_object', $options ) || empty( $custom ) ) && '' !== pods_v( $args->type . '_object', $options, '', true ) ) {
778
			$ajax = true;
779
		}
780
781
		if ( ! empty( self::$field_data ) && self::$field_data['id'] === $options['id'] ) {
782
			$ajax = (boolean) self::$field_data['autocomplete'];
783
		}
784
785
		$ajax = apply_filters( 'pods_form_ui_field_pick_ajax', $ajax, $args->name, $args->value, $options, $args->pod, $args->id );
786
787
		if ( 0 === (int) pods_v( $args->type . '_ajax', $options, 1 ) ) {
788
			$ajax = false;
789
		}
790
791
		$options[ $args->type . '_ajax' ] = (int) $ajax;
792
793
		$format_type = pods_v( $args->type . '_format_type', $options, 'single', true );
794
795
		if ( 'single' === $format_type ) {
796
			$format_single = pods_v( $args->type . '_format_single', $options, 'dropdown', true );
797
798 View Code Duplication
			if ( 'dropdown' === $format_single ) {
799
				$options['view_name'] = 'select';
800
			} elseif ( 'radio' === $format_single ) {
801
				$options['view_name'] = 'radio';
802
			} elseif ( 'autocomplete' === $format_single ) {
803
				$options['view_name'] = 'select2';
804
			} elseif ( 'list' === $format_single ) {
805
				$options['view_name'] = 'list';
806
			} else {
807
				$options['view_name'] = $format_single;
808
			}
809
		} elseif ( 'multi' === $format_type ) {
810
			$format_multi = pods_v( $args->type . '_format_multi', $options, 'checkbox', true );
811
812
			if ( ! empty( $args->value ) && ! is_array( $args->value ) ) {
813
				$args->value = explode( ',', $args->value );
814
			}
815
816 View Code Duplication
			if ( 'checkbox' === $format_multi ) {
817
				$options['view_name'] = 'checkbox';
818
			} elseif ( 'multiselect' === $format_multi ) {
819
				$options['view_name'] = 'select';
820
			} elseif ( 'autocomplete' === $format_multi ) {
821
				$options['view_name'] = 'select2';
822
			} elseif ( 'list' === $format_multi ) {
823
				$options['view_name'] = 'list';
824
			} else {
825
				$options['view_name'] = $format_multi;
826
			}
827
		} else {
828
			$options['view_name'] = $format_type;
829
		}
830
831
		return $options;
832
833
	}
834
835
	/**
836
	 * {@inheritdoc}
837
	 */
838
	public function build_dfv_field_config( $args ) {
839
840
		$config = parent::build_dfv_field_config( $args );
841
842
		if ( ! isset( $config['optgroup'] ) ) {
843
			$config['optgroup'] = false;
844
		}
845
846
		$file_name  = '';
847
		$query_args = array();
848
849
		// Set the file name and args based on the content type of the relationship
850
		switch ( $args->options['pick_object'] ) {
851 View Code Duplication
			case 'post_type':
852
				if ( ! empty( $args->options['pick_val'] ) ) {
853
					$post_type_obj = get_post_type_object( $args->options['pick_val'] );
854
855
					if ( $post_type_obj && current_user_can( $post_type_obj->cap->create_posts ) ) {
856
						$file_name  = 'post-new.php';
857
						$query_args = array(
858
							'post_type' => $args->options['pick_val'],
859
						);
860
					}
861
				}
862
863
				break;
864
865 View Code Duplication
			case 'taxonomy':
866
				if ( ! empty( $args->options['pick_val'] ) ) {
867
					$taxonomy_obj = get_taxonomy( $args->options['pick_val'] );
868
869
					if ( $taxonomy_obj && current_user_can( $taxonomy_obj->cap->edit_terms ) ) {
870
						$file_name  = 'edit-tags.php';
871
						$query_args = array(
872
							'taxonomy' => $args->options['pick_val'],
873
						);
874
					}
875
				}
876
877
				break;
878
879
			case 'user':
880
				if ( current_user_can( 'create_users' ) ) {
881
					$file_name  = 'user-new.php';
882
				}
883
884
				break;
885
886
			case 'pod':
887
				if ( ! empty( $args->options['pick_val'] ) ) {
888
					if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
889
						$file_name  = 'admin.php';
890
						$query_args = array(
891
							'page'   => 'pods-manage-' . $args->options['pick_val'],
892
							'action' => 'add',
893
						);
894
895
					}
896
				}
897
898
				break;
899
		}
900
901
		$iframe_src = '';
902
903
		if ( ! empty( $file_name ) ) {
904
			// @todo: Replace string literal with defined constant
905
			$query_args['pods_modal'] = 1;
906
907
			// Add args we always need
908
			$iframe_src = add_query_arg( $query_args, admin_url( $file_name ) );
909
		}
910
911
		$config['iframe_src'] = $iframe_src;
912
913
		return $config;
914
915
	}
916
917
	/**
918
	 * {@inheritdoc}
919
	 */
920
	public function build_dfv_field_item_data( $args ) {
921
922
		$args->options['supports_thumbnails'] = null;
923
924
		$item_data = array();
925
926
		if ( ! empty( $args->options['data'] ) ) {
927
			$item_data = $this->build_dfv_field_item_data_recurse( $args->options['data'], $args );
928
		}
929
930
		return $item_data;
931
932
	}
933
934
	/**
935
	 * Loop through relationship data and expand item data with additional information for DFV.
936
	 *
937
	 * @param array     $data    Item data to expand.
938
	 * @param object    $args    {
939
	 *                           Field information arguments.
940
	 *
941
	 * @type string     $name    Field name
942
	 * @type string     $type    Field type
943
	 * @type array      $options Field options
944
	 * @type mixed      $value   Current value
945
	 * @type array      $pod     Pod information
946
	 * @type int|string $id      Current item ID
947
	 * }
948
	 *
949
	 * @return array
950
	 */
951
	public function build_dfv_field_item_data_recurse( $data, $args ) {
952
953
		$item_data = array();
954
955
		foreach ( $data as $item_id => $item_title ) {
956
			if ( is_array( $item_title ) ) {
957
				$args->options['optgroup'] = true;
958
959
				$item_data[] = array(
960
					'label'      => $item_id,
961
					'collection' => $this->build_dfv_field_item_data_recurse( $item_title, $args ),
962
				);
963
			} else {
964
				$item_data[] = $this->build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args );
965
			}
966
		}
967
968
		return $item_data;
969
970
	}
971
972
	/**
973
	 * Loop through relationship data and expand item data with additional information for DFV.
974
	 *
975
	 * @param int|string $item_id
976
	 * @param string     $item_title
977
	 * @param object     $args    {
978
	 *                            Field information arguments.
979
	 *
980
	 * @type string      $name    Field name
981
	 * @type string      $type    Field type
982
	 * @type array       $options Field options
983
	 * @type mixed       $value   Current value
984
	 * @type array       $pod     Pod information
985
	 * @type int|string  $id      Current item ID
986
	 * }
987
	 *
988
	 * @return array
989
	 */
990
	public function build_dfv_field_item_data_recurse_item( $item_id, $item_title, $args ) {
991
992
		$icon      = '';
993
		$edit_link = '';
994
		$link      = '';
995
996
		switch ( $args->options['pick_object'] ) {
997
			case 'post_type':
998
				$item_id = (int) $item_id;
999
1000
				if ( null === $args->options['supports_thumbnails'] && ! empty( $args->options['pick_val'] ) ) {
1001
					$args->options['supports_thumbnails'] = post_type_supports( $args->options['pick_val'], 'thumbnail' );
1002
				}
1003
1004
				if ( true === $args->options['supports_thumbnails'] ) {
1005
					$thumb = wp_get_attachment_image_src( $item_id, 'thumbnail', true );
1006
1007
					if ( ! empty( $thumb[0] ) ) {
1008
						$icon = $thumb[0];
1009
					}
1010
				}
1011
1012
				$edit_link = get_edit_post_link( $item_id, 'raw' );
1013
1014
				$link = get_permalink( $item_id );
1015
1016
				break;
1017
1018
			case 'taxonomy':
1019
				$item_id = (int) $item_id;
1020
1021
				if ( ! empty( $args->options['pick_val'] ) ) {
1022
					$edit_link = get_edit_term_link( $item_id, $args->options['pick_val'] );
1023
1024
					$link = get_term_link( $item_id, $args->options['pick_val'] );
1025
				}
1026
1027
				break;
1028
1029 View Code Duplication
			case 'user':
1030
				$item_id = (int) $item_id;
1031
1032
				$args->options['supports_thumbnails'] = true;
1033
1034
				$icon = get_avatar_url( $item_id, array( 'size' => 150 ) );
1035
1036
				$edit_link = get_edit_user_link( $item_id );
1037
1038
				$link = get_author_posts_url( $item_id );
1039
1040
				break;
1041
1042 View Code Duplication
			case 'comment':
1043
				$item_id = (int) $item_id;
1044
1045
				$args->options['supports_thumbnails'] = true;
1046
1047
				$icon = get_avatar_url( get_comment( $item_id ), array( 'size' => 150 ) );
1048
1049
				$edit_link = get_edit_comment_link( $item_id );
1050
1051
				$link = get_comment_link( $item_id );
1052
1053
				break;
1054
1055
			case 'pod':
1056
				$item_id = (int) $item_id;
1057
1058
				if ( ! empty( $args->options['pick_val'] ) ) {
1059
					if ( pods_is_admin( array( 'pods', 'pods_content', 'pods_edit_' . $args->options['pick_val'] ) ) ) {
1060
						$file_name  = 'admin.php';
1061
						$query_args = array(
1062
							'page'   => 'pods-manage-' . $args->options['pick_val'],
1063
							'action' => 'edit',
1064
							'id'     => $item_id,
1065
						);
1066
1067
						$edit_link = add_query_arg( $query_args, admin_url( $file_name ) );
1068
					}
1069
1070
					// @todo Add $link support
1071
					$link = '';
1072
				}
1073
1074
				break;
1075
		}
1076
1077
		$item = array(
1078
			'id'        => $item_id,
1079
			'icon'      => $icon,
1080
			'name'      => $item_title,
1081
			'edit_link' => $edit_link,
1082
			'link'      => $link,
1083
			'selected'  => ( isset( $args->value[ $item_id ] ) ),
1084
		);
1085
1086
		return $item;
1087
1088
	}
1089
1090
	/**
1091
	 * {@inheritdoc}
1092
	 */
1093
	public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1094
1095
		if ( empty( self::$api ) ) {
1096
			self::$api = pods_api();
1097
		}
1098
1099
		$simple_tableless_objects = $this->simple_objects();
1100
1101
		$related_pick_limit = 0;
1102
		$related_field      = $related_pod = $current_related_ids = false;
1103
1104
		// Bidirectional relationship requirement checks
1105
		$related_object = pods_v( self::$type . '_object', $options, '' ); // pod, post_type, taxonomy, etc..
1106
		$related_val    = pods_v( self::$type . '_val', $options, $related_object, null, true ); // pod name, post type name, taxonomy name, etc..
1107
		if ( empty( $related_val ) ) {
1108
			$related_val = $related_object;
1109
		}
1110
1111
		$related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1112
1113
		$options['id'] = (int) $options['id'];
1114
1115
		if ( ! isset( self::$related_data[ $options['id'] ] ) || empty( self::$related_data[ $options['id'] ] ) ) {
1116
			self::$related_data[ $options['id'] ] = array();
1117
		}
1118
1119
		if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1120
			$related_pod = self::$api->load_pod( array( 'name' => $related_val, 'table_info' => false ), false );
1121
1122
			if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1123
				$related_field = false;
1124
1125
				// Ensure sister_id exists on related Pod.
1126 View Code Duplication
				foreach ( $related_pod['fields'] as $related_pod_field ) {
1127
					if ( 'pick' === $related_pod_field['type'] && $related_sister_id === $related_pod_field['id'] ) {
1128
						$related_field = $related_pod_field;
1129
1130
						break;
1131
					}
1132
				}
1133
1134
				if ( ! empty( $related_field ) ) {
1135
					$current_ids = self::$api->lookup_related_items( $fields[ $name ]['id'], $pod['id'], $id, $fields[ $name ], $pod );
1136
1137
					self::$related_data[ $options['id'] ]['current_ids'] = $current_ids;
1138
1139
					$value_ids = $value;
1140
1141
					// Convert values from a comma-separated string into an array.
1142
					if ( ! is_array( $value_ids ) ) {
1143
						$value_ids = explode( ',', $value_ids );
1144
					}
1145
1146
					$value_ids = array_unique( array_filter( $value_ids ) );
1147
1148
					// Get ids to remove.
1149
					$remove_ids = array_diff( $current_ids, $value_ids );
1150
1151
					$related_required   = (boolean) pods_v( 'required', $related_field['options'], 0 );
1152
					$related_pick_limit = (int) pods_v( self::$type . '_limit', $related_field['options'], 0 );
1153
1154
					if ( 'single' === pods_v( self::$type . '_format_type', $related_field['options'] ) ) {
1155
						$related_pick_limit = 1;
1156
					}
1157
1158
					// Validate Required fields.
1159
					if ( $related_required && ! empty( $remove_ids ) ) {
1160
						foreach ( $remove_ids as $related_id ) {
1161
							$bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1162
1163
							self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] = $bidirectional_ids;
1164
1165
							if ( empty( $bidirectional_ids ) || ( in_array( (int) $id, $bidirectional_ids, true ) && 1 === count( $bidirectional_ids ) ) ) {
1166
								return sprintf( __( 'The %1$s field is required and cannot be removed by the %2$s field', 'pods' ), $related_field['label'], $options['label'] );
1167
							}
1168
						}
1169
					}
1170
				} else {
1171
					$related_pod = false;
1172
				}
1173
			} else {
1174
				$related_pod = false;
1175
			}
1176
		}
1177
1178
		if ( empty( self::$related_data[ $options['id'] ] ) ) {
1179
			unset( self::$related_data[ $options['id'] ] );
1180
		} else {
1181
			self::$related_data[ $options['id'] ]['related_pod']        = $related_pod;
1182
			self::$related_data[ $options['id'] ]['related_field']      = $related_field;
1183
			self::$related_data[ $options['id'] ]['related_pick_limit'] = $related_pick_limit;
1184
1185
			$pick_limit = (int) pods_v( self::$type . '_limit', $options['options'], 0 );
1186
1187
			if ( 'single' === pods_v( self::$type . '_format_type', $options['options'] ) ) {
1188
				$pick_limit = 1;
1189
			}
1190
1191
			$related_field['id'] = (int) $related_field['id'];
1192
1193
			if ( ! isset( self::$related_data[ $related_field['id'] ] ) || empty( self::$related_data[ $related_field['id'] ] ) ) {
1194
				self::$related_data[ $related_field['id'] ] = array(
1195
					'related_pod'        => $pod,
1196
					'related_field'      => $options,
1197
					'related_pick_limit' => $pick_limit,
1198
				);
1199
			}
1200
		}
1201
1202
		return true;
1203
1204
	}
1205
1206
	/**
1207
	 * {@inheritdoc}
1208
	 */
1209
	public function save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
1210
1211
		if ( empty( self::$api ) ) {
1212
			self::$api = pods_api();
1213
		}
1214
1215
		$options['id'] = (int) $options['id'];
1216
1217
		if ( ! isset( self::$related_data[ $options['id'] ] ) ) {
1218
			return;
1219
		}
1220
1221
		$related_pod        = self::$related_data[ $options['id'] ]['related_pod'];
1222
		$related_field      = self::$related_data[ $options['id'] ]['related_field'];
1223
		$related_pick_limit = self::$related_data[ $options['id'] ]['related_pick_limit'];
1224
1225
		// Bidirectional relationship updates.
1226
		if ( ! empty( $related_field ) ) {
1227
			// Don't use no conflict mode unless this isn't the current pod type.
1228
			$no_conflict = true;
1229
1230
			if ( $related_pod['type'] !== $pod['type'] ) {
1231
				$no_conflict = pods_no_conflict_check( $related_pod['type'] );
1232
			}
1233
1234
			if ( ! $no_conflict ) {
1235
				pods_no_conflict_on( $related_pod['type'] );
1236
			}
1237
1238
			$value = array_filter( $value );
1239
1240
			foreach ( $value as $related_id ) {
1241
				if ( isset( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) && ! empty( self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ] ) ) {
1242
					$bidirectional_ids = self::$related_data[ $options['id'] ][ 'related_ids_' . $related_id ];
1243
				} else {
1244
					$bidirectional_ids = self::$api->lookup_related_items( $related_field['id'], $related_pod['id'], $related_id, $related_field, $related_pod );
1245
				}
1246
1247
				$bidirectional_ids = array_filter( $bidirectional_ids );
1248
1249
				if ( empty( $bidirectional_ids ) ) {
1250
					$bidirectional_ids = array();
1251
				}
1252
1253
				$remove_ids = array();
1254
1255
				if ( 0 < $related_pick_limit && ! empty( $bidirectional_ids ) && ! in_array( $id, $bidirectional_ids, true ) ) {
1256
					while ( $related_pick_limit <= count( $bidirectional_ids ) ) {
1257
						$remove_ids[] = (int) array_pop( $bidirectional_ids );
1258
					}
1259
				}
1260
1261
				// Remove this item from related items no longer related to.
1262
				$remove_ids = array_unique( array_filter( $remove_ids ) );
1263
1264
				if ( ! in_array( $id, $bidirectional_ids, true ) ) {
1265
					// Add to related items.
1266
					$bidirectional_ids[] = $id;
1267
				} elseif ( empty( $remove_ids ) ) {
1268
					// Nothing to change.
1269
					continue;
1270
				}
1271
1272
				self::$api->save_relationships( $related_id, $bidirectional_ids, $related_pod, $related_field );
1273
1274
				if ( ! empty( $remove_ids ) ) {
1275
					self::$api->delete_relationships( $remove_ids, $related_id, $pod, $options );
1276
				}
1277
			}
1278
1279
			if ( ! $no_conflict ) {
1280
				pods_no_conflict_off( $related_pod['type'] );
1281
			}
1282
		}
1283
1284
	}
1285
1286
	/**
1287
	 * Delete the value from the DB
1288
	 *
1289
	 * @param int    $id
1290
	 * @param string $name
1291
	 * @param array  $options
1292
	 * @param array  $pod
1293
	 *
1294
	 * @since 2.3
1295
	 */
1296
	public function delete( $id = null, $name = null, $options = null, $pod = null ) {
1297
1298
		if ( empty( self::$api ) ) {
1299
			self::$api = pods_api();
1300
		}
1301
1302
		$simple_tableless_objects = $this->simple_objects();
1303
1304
		// Bidirectional relationship requirement checks.
1305
		$related_object    = pods_v( self::$type . '_object', $options, '' ); // pod, post_type, taxonomy, etc..
1306
		$related_val       = pods_v( self::$type . '_val', $options, $related_object, true ); // pod name, post type name, taxonomy name, etc..
1307
		$related_sister_id = (int) pods_v( 'sister_id', $options, 0 );
1308
1309
		if ( ! empty( $related_sister_id ) && ! in_array( $related_object, $simple_tableless_objects, true ) ) {
1310
			$related_pod = self::$api->load_pod( array( 'name' => $related_val, 'table_info' => false ), false );
1311
1312
			if ( false !== $related_pod && ( 'pod' === $related_object || $related_object === $related_pod['type'] ) ) {
1313
				$related_field = false;
1314
1315
				// Ensure sister_id exists on related Pod.
1316 View Code Duplication
				foreach ( $related_pod['fields'] as $related_pod_field ) {
1317
					if ( 'pick' === $related_pod_field['type'] && (int) $related_sister_id === (int) $related_pod_field['id'] ) {
1318
						$related_field = $related_pod_field;
1319
1320
						break;
1321
					}
1322
				}
1323
1324
				if ( ! empty( $related_field ) ) {
1325
					$values = self::$api->lookup_related_items( $options['id'], $pod['id'], $id, $options, $pod );
1326
1327
					if ( ! empty( $values ) ) {
1328
						$no_conflict = pods_no_conflict_check( $related_pod['type'] );
1329
1330
						if ( ! $no_conflict ) {
1331
							pods_no_conflict_on( $related_pod['type'] );
1332
						}
1333
1334
						self::$api->delete_relationships( $values, $id, $related_pod, $related_field );
1335
1336
						if ( ! $no_conflict ) {
1337
							pods_no_conflict_off( $related_pod['type'] );
1338
						}
1339
					}
1340
				}
1341
			}
1342
		}
1343
1344
	}
1345
1346
	/**
1347
	 * {@inheritdoc}
1348
	 */
1349
	public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
1350
1351
		$value = $this->simple_value( $name, $value, $options, $pod, $id );
1352
1353
		return $this->display( $value, $name, $options, $pod, $id );
1354
1355
	}
1356
1357
	/**
1358
	 * Get the data from the field
1359
	 *
1360
	 * @param string       $name    The name of the field
1361
	 * @param string|array $value   The value of the field
1362
	 * @param array        $options Field options
1363
	 * @param array        $pod     Pod data
1364
	 * @param int          $id      Item ID
1365
	 * @param boolean      $in_form
1366
	 *
1367
	 * @return array Array of possible field data
1368
	 *
1369
	 * @since 2.0
1370
	 */
1371
	public function data( $name, $value = null, $options = null, $pod = null, $id = null, $in_form = true ) {
1372
1373 View Code Duplication
		if ( isset( $options['options'] ) ) {
1374
			$options = array_merge( $options, $options['options'] );
1375
1376
			unset( $options['options'] );
1377
		}
1378
1379
		$data = pods_v( 'data', $options, null, true );
1380
1381
		$object_params = array(
1382
			'name'    => $name, // The name of the field.
1383
			'value'   => $value, // The value of the field.
1384
			'options' => $options, // Field options.
1385
			'pod'     => $pod, // Pod data.
1386
			'id'      => $id, // Item ID.
1387
			'context' => 'data', // Data context.
1388
		);
1389
1390
		if ( null !== $data ) {
1391
			$data = (array) $data;
1392
		} else {
1393
			$data = $this->get_object_data( $object_params );
1394
		}
1395
1396
		if ( 'single' === pods_v( self::$type . '_format_type', $options, 'single' ) && 'dropdown' === pods_v( self::$type . '_format_single', $options, 'dropdown' ) ) {
1397
			$data = array( '' => pods_v( self::$type . '_select_text', $options, __( '-- Select One --', 'pods' ), true ) ) + $data;
1398
		}
1399
1400
		$data = apply_filters( 'pods_field_pick_data', $data, $name, $value, $options, $pod, $id );
1401
1402
		return $data;
1403
1404
	}
1405
1406
	/**
1407
	 * Convert a simple value to the correct value
1408
	 *
1409
	 * @param string       $name    The name of the field
1410
	 * @param string|array $value   The value of the field
1411
	 * @param array        $options Field options
1412
	 * @param array        $pod     Pod data
1413
	 * @param int          $id      Item ID
1414
	 * @param boolean      $raw     Whether to return the raw list of keys (true) or convert to key=>value (false)
1415
	 *
1416
	 * @return mixed Corrected value
1417
	 */
1418
	public function simple_value( $name, $value = null, $options = null, $pod = null, $id = null, $raw = false ) {
1419
1420
		if ( in_array( pods_v( self::$type . '_object', $options ), self::simple_objects(), true ) ) {
1421 View Code Duplication
			if ( isset( $options['options'] ) ) {
1422
				$options = array_merge( $options, $options['options'] );
1423
1424
				unset( $options['options'] );
1425
			}
1426
1427
			if ( ! is_array( $value ) && 0 < strlen( $value ) ) {
1428
				$simple = @json_decode( $value, true );
1429
1430
				if ( is_array( $simple ) ) {
1431
					$value = $simple;
1432
				}
1433
			}
1434
1435
			$data = pods_v( 'data', $options, null, true );
1436
1437
			$object_params = array(
1438
				'name'    => $name, // The name of the field.
1439
				'value'   => $value, // The value of the field.
1440
				'options' => $options, // Field options.
1441
				'pod'     => $pod, // Pod data.
1442
				'id'      => $id, // Item ID.
1443
				'context' => 'simple_value', // Data context.
1444
			);
1445
1446
			if ( null === $data ) {
1447
				$data = $this->get_object_data( $object_params );
1448
			}
1449
1450
			$data = (array) $data;
1451
1452
			$key = 0;
1453
1454
			if ( is_array( $value ) ) {
1455
				if ( ! empty( $data ) ) {
1456
					$val = array();
1457
1458
					foreach ( $value as $k => $v ) {
1459
						if ( isset( $data[ $v ] ) ) {
1460
							if ( false === $raw ) {
1461
								$k = $v;
1462
								$v = $data[ $v ];
1463
							}
1464
1465
							$val[ $k ] = $v;
1466
						}
1467
					}
1468
1469
					$value = $val;
1470
				}
1471
			} elseif ( isset( $data[ $value ] ) && false === $raw ) {
1472
				$key   = $value;
1473
				$value = $data[ $value ];
1474
			}
1475
1476
			$single_multi = pods_v( self::$type . '_format_type', $options, 'single' );
1477
1478
			if ( 'multi' === $single_multi ) {
1479
				$limit = (int) pods_v( self::$type . '_limit', $options, 0 );
1480
			} else {
1481
				$limit = 1;
1482
			}
1483
1484
			if ( is_array( $value ) && 0 < $limit ) {
1485
				if ( 1 === $limit ) {
1486
					$value = current( $value );
1487
				} else {
1488
					$value = array_slice( $value, 0, $limit, true );
1489
				}
1490
			} elseif ( ! is_array( $value ) && null !== $value && 0 < strlen( $value ) ) {
1491
				if ( 1 !== $limit || ( true === $raw && 'multi' === $single_multi ) ) {
1492
					$value = array(
1493
						$key => $value,
1494
					);
1495
				}
1496
			}
1497
		}
1498
1499
		return $value;
1500
1501
	}
1502
1503
	/**
1504
	 * Get the label from a pick value
1505
	 *
1506
	 * @param string       $name    The name of the field
1507
	 * @param string|array $value   The value of the field
1508
	 * @param array        $options Field options
1509
	 * @param array        $pod     Pod data
1510
	 * @param int          $id      Item ID
1511
	 *
1512
	 * @return string
1513
	 *
1514
	 * @since 2.2
1515
	 */
1516
	public function value_to_label( $name, $value = null, $options = null, $pod = null, $id = null ) {
1517
1518 View Code Duplication
		if ( isset( $options['options'] ) ) {
1519
			$options = array_merge( $options, $options['options'] );
1520
1521
			unset( $options['options'] );
1522
		}
1523
1524
		$data = pods_v( 'data', $options, null, true );
1525
1526
		$object_params = array(
1527
			'name'    => $name, // The name of the field.
1528
			'value'   => $value, // The value of the field.
1529
			'options' => $options, // Field options.
1530
			'pod'     => $pod, // Pod data.
1531
			'id'      => $id, // Item ID.
1532
			'context' => 'value_to_label', // Data context.
1533
		);
1534
1535
		if ( null !== $data ) {
1536
			$data = (array) $data;
1537
		} else {
1538
			$data = $this->get_object_data( $object_params );
1539
		}
1540
1541
		$labels = array();
1542
1543
		$check_value = $value;
1544
1545
		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...
1546
			$check_v = (string) $check_v;
1547
		}
1548
1549
		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...
1550
			if ( ! in_array( (string) $l, $labels, true ) && ( (string) $value === (string) $v || ( is_array( $value ) && in_array( (string) $v, $value, true ) ) ) ) {
1551
				$labels[] = (string) $l;
1552
			}
1553
		}
1554
1555
		$labels = apply_filters( 'pods_field_pick_value_to_label', $labels, $name, $value, $options, $pod, $id );
1556
1557
		$labels = pods_serial_comma( $labels );
1558
1559
		return $labels;
1560
1561
	}
1562
1563
	/**
1564
	 * Get available items from a relationship field
1565
	 *
1566
	 * @param array|string $field         Field array or field name
1567
	 * @param array        $options       [optional] Field options array overrides
1568
	 * @param array        $object_params [optional] Additional get_object_data options
1569
	 *
1570
	 * @return array An array of available items from a relationship field
1571
	 */
1572
	public function get_field_data( $field, $options = array(), $object_params = array() ) {
1573
1574
		// Handle field array overrides.
1575
		if ( is_array( $field ) ) {
1576
			$options = array_merge( $field, $options );
1577
		}
1578
1579
		// Get field name from array.
1580
		$field = pods_v( 'name', $options, $field, true );
1581
1582
		// Field name or options not set.
1583
		if ( empty( $field ) || empty( $options ) ) {
1584
			return array();
1585
		}
1586
1587
		// Options normalization.
1588
		$options = array_merge( $options, pods_v( 'options', $options, array(), true ) );
1589
1590
		// Setup object params.
1591
		$object_params = array_merge( array(
1592
			'name'    => $field, // The name of the field.
1593
			'options' => $options, // Field options.
1594
		), $object_params );
1595
1596
		// Get data override.
1597
		$data = pods_v( 'data', $options, null, true );
1598
1599
		if ( null !== $data ) {
1600
			// Return data override.
1601
			$data = (array) $data;
1602
		} else {
1603
			// Get object data.
1604
			$data = $this->get_object_data( $object_params );
1605
		}
1606
1607
		return $data;
1608
1609
	}
1610
1611
	/**
1612
	 * Get data from relationship objects
1613
	 *
1614
	 * @param array $object_params Object data parameters
1615
	 *
1616
	 * @return array|bool Object data
1617
	 */
1618
	public function get_object_data( $object_params = null ) {
1619
1620
		/**
1621
		 * @var $wpdb wpdb
1622
		 */
1623
		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...
1624
1625
		$object_params = array_merge( array(
1626
			// The name of the field.
1627
			'name'        => '',
1628
			// The value of the field.
1629
			'value'       => '',
1630
			// Field options.
1631
			'options'     => array(),
1632
			// Pod data.
1633
			'pod'         => '',
1634
			// Item ID.
1635
			'id'          => '',
1636
			// Data context.
1637
			'context'     => '',
1638
			// Data parameters.
1639
			'data_params' => array(
1640
				'query' => '', // Query being searched.
1641
			),
1642
			// Page number of results to get.
1643
			'page'        => 1,
1644
			// How many data items to limit to (autocomplete defaults to 30, set to -1 or 1+ to override).
1645
			'limit'       => 0,
1646
		), $object_params );
1647
1648
		$name        = $object_params['name'];
1649
		$value       = $object_params['value'];
1650
		$options     = $object_params['options'] = (array) $object_params['options'];
1651
		$pod         = $object_params['pod'];
1652
		$id          = $object_params['id'];
1653
		$context     = $object_params['context'];
1654
		$data_params = $object_params['data_params'] = (array) $object_params['data_params'];
1655
		$page        = min( 1, (int) $object_params['page'] );
1656
		$limit       = (int) $object_params['limit'];
1657
1658 View Code Duplication
		if ( isset( $options['options'] ) ) {
1659
			$options = array_merge( $options, $options['options'] );
1660
1661
			unset( $options['options'] );
1662
		}
1663
1664
		$data  = apply_filters( 'pods_field_pick_object_data', null, $name, $value, $options, $pod, $id, $object_params );
1665
		$items = array();
1666
1667
		if ( ! isset( $options[ self::$type . '_object' ] ) ) {
1668
			$data = pods_v( 'data', $options, array(), true );
1669
		}
1670
1671
		$simple = false;
1672
1673
		if ( null === $data ) {
1674
			$data = array();
1675
1676
			if ( 'custom-simple' === $options[ self::$type . '_object' ] ) {
1677
				$custom = pods_v( self::$type . '_custom', $options, '' );
1678
1679
				$custom = apply_filters( 'pods_form_ui_field_pick_custom_values', $custom, $name, $value, $options, $pod, $id, $object_params );
1680
1681
				if ( ! empty( $custom ) ) {
1682
					if ( ! is_array( $custom ) ) {
1683
						$data = array();
1684
1685
						$custom = explode( "\n", trim( $custom ) );
1686
1687
						foreach ( $custom as $custom_value ) {
1688
							$custom_label = explode( '|', $custom_value );
1689
1690
							if ( empty( $custom_label ) ) {
1691
								continue;
1692
							}
1693
1694
							if ( 1 === count( $custom_label ) ) {
1695
								$custom_label = $custom_value;
1696
							} else {
1697
								$custom_value = $custom_label[0];
1698
								$custom_label = $custom_label[1];
1699
							}
1700
1701
							$custom_value = trim( (string) $custom_value );
1702
							$custom_label = trim( (string) $custom_label );
1703
1704
							$data[ $custom_value ] = $custom_label;
1705
						}
1706
					} else {
1707
						$data = $custom;
1708
					}
1709
1710
					$simple = true;
1711
				}
1712
			} 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'] ) ) {
1713
				$data = self::$related_objects[ $options[ self::$type . '_object' ] ]['data'];
1714
1715
				$simple = true;
1716
			} 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'] ) ) {
1717
				$data = call_user_func_array( self::$related_objects[ $options[ self::$type . '_object' ] ]['data_callback'], array(
1718
						$name,
1719
						$value,
1720
						$options,
1721
						$pod,
1722
						$id,
1723
					)
1724
				);
1725
1726 View Code Duplication
				if ( 'data' === $context ) {
1727
					self::$field_data = array(
1728
						'field'        => $name,
1729
						'id'           => $options['id'],
1730
						'autocomplete' => false,
1731
					);
1732
				}
1733
1734
				$simple = true;
1735
1736
				// Cache data from callback.
1737
				if ( ! empty( $data ) ) {
1738
					self::$related_objects[ $options[ self::$type . '_object' ] ]['data'] = $data;
1739
				}
1740
			} elseif ( 'simple_value' !== $context ) {
1741
				$pick_val = pods_v( self::$type . '_val', $options );
1742
1743
				if ( 'table' === pods_v( self::$type . '_object', $options ) ) {
1744
					$pick_val = pods_v( self::$type . '_table', $options, $pick_val, true );
1745
				}
1746
1747 View Code Duplication
				if ( '__current__' === $pick_val ) {
1748
					if ( is_object( $pod ) ) {
1749
						$pick_val = $pod->pod;
1750
					} elseif ( is_array( $pod ) ) {
1751
						$pick_val = $pod['name'];
1752
					} elseif ( 0 < strlen( $pod ) ) {
1753
						$pick_val = $pod;
1754
					}
1755
				}
1756
1757
				$options['table_info'] = pods_api()->get_table_info( pods_v( self::$type . '_object', $options ), $pick_val, null, null, $options );
1758
1759
				$search_data = pods_data();
1760
				$search_data->table( $options['table_info'] );
1761
1762
				if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) && isset( $options['table_info']['pod']['name'] ) ) {
1763
					$search_data->pod    = $options['table_info']['pod']['name'];
1764
					$search_data->fields = $options['table_info']['pod']['fields'];
1765
				}
1766
1767
				$params = array(
1768
					'select'     => "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`",
1769
					'table'      => $search_data->table,
1770
					'where'      => pods_v( self::$type . '_where', $options, (array) $options['table_info']['where_default'], true ),
1771
					'orderby'    => pods_v( self::$type . '_orderby', $options, null, true ),
1772
					'groupby'    => pods_v( self::$type . '_groupby', $options, null, true ),
1773
					// '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...
1774
					'pagination' => false,
1775
					'search'     => false
1776
				);
1777
1778
				if ( in_array( $options[ self::$type . '_object' ], array( 'site', 'network' ), true ) ) {
1779
					$params['select'] .= ', `t`.`path`';
1780
				}
1781
1782
				if ( ! empty( $params['where'] ) && (array) $options['table_info']['where_default'] !== $params['where'] ) {
1783
					$params['where'] = pods_evaluate_tags( $params['where'], true );
1784
				}
1785
1786
				if ( empty( $params['where'] ) || ( ! is_array( $params['where'] ) && strlen( trim( $params['where'] ) ) < 1 ) ) {
1787
					$params['where'] = array();
1788
				} elseif ( ! is_array( $params['where'] ) ) {
1789
					$params['where'] = (array) $params['where'];
1790
				}
1791
1792
				if ( 'value_to_label' === $context ) {
1793
					$params['where'][] = "`t`.`{$search_data->field_id}` = " . number_format( $value, 0, '', '' );
1794
				}
1795
1796
				/*
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...
1797
				if ( ! empty( $params['orderby'] ) ) {
1798
					$params['orderby'] = pods_evaluate_tags( $params['orderby'], true );
1799
				}
1800
1801
				if ( ! empty( $params['groupby'] ) ) {
1802
					$params['groupby'] = pods_evaluate_tags( $params['groupby'], true );
1803
				}
1804
				*/
1805
1806
				$display = trim( pods_v( self::$type . '_display', $options ), ' {@}' );
1807
1808
				if ( 0 < strlen( $display ) ) {
1809
					if ( isset( $options['table_info']['pod'] ) && ! empty( $options['table_info']['pod'] ) ) {
1810
						if ( isset( $options['table_info']['pod']['object_fields'] ) && isset( $options['table_info']['pod']['object_fields'][ $display ] ) ) {
1811
							$search_data->field_index = $display;
1812
1813
							$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
1814
						} elseif ( isset( $options['table_info']['pod']['fields'][ $display ] ) ) {
1815
							$search_data->field_index = $display;
1816
1817
							if ( 'table' === $options['table_info']['pod']['storage'] && ! in_array( $options['table_info']['pod']['type'], array(
1818
									'pod',
1819
									'table',
1820
								), true )
1821
							) {
1822
								$params['select'] = "`t`.`{$search_data->field_id}`, `d`.`{$search_data->field_index}`";
1823
							} elseif ( 'meta' === $options['table_info']['pod']['storage'] ) {
1824
								$params['select'] = "`t`.`{$search_data->field_id}`, `{$search_data->field_index}`.`meta_value` AS {$search_data->field_index}";
1825
							} else {
1826
								$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
1827
							}
1828
						}
1829
					} elseif ( isset( $options['table_info']['object_fields'] ) && isset( $options['table_info']['object_fields'][ $display ] ) ) {
1830
						$search_data->field_index = $display;
1831
1832
						$params['select'] = "`t`.`{$search_data->field_id}`, `t`.`{$search_data->field_index}`";
1833
					}
1834
				}
1835
1836
				$autocomplete = false;
1837
1838
				if ( 'single' === pods_v( self::$type . '_format_type', $options, 'single' ) && 'autocomplete' === pods_v( self::$type . '_format_single', $options, 'dropdown' ) ) {
1839
					$autocomplete = true;
1840
				} elseif ( 'multi' === pods_v( self::$type . '_format_type', $options, 'single' ) && 'autocomplete' === pods_v( self::$type . '_format_multi', $options, 'checkbox' ) ) {
1841
					$autocomplete = true;
1842
				}
1843
1844
				$hierarchy = false;
1845
1846
				if ( 'data' === $context && ! $autocomplete ) {
1847
					if ( 'single' === pods_v( self::$type . '_format_type', $options, 'single' ) && in_array( pods_v( self::$type . '_format_single', $options, 'dropdown' ), array(
1848
							'dropdown',
1849
							'radio',
1850
						), true )
1851
					) {
1852
						$hierarchy = true;
1853
					} elseif ( 'multi' === pods_v( self::$type . '_format_type', $options, 'single' ) && in_array( pods_v( self::$type . '_format_multi', $options, 'checkbox' ), array(
1854
							'multiselect',
1855
							'checkbox',
1856
						), true )
1857
					) {
1858
						$hierarchy = true;
1859
					}
1860
				}
1861
1862
				if ( $hierarchy && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
1863
					$params['select'] .= ', ' . $options['table_info']['field_parent_select'];
1864
				}
1865
1866
				if ( $autocomplete ) {
1867
					if ( 0 === $limit ) {
1868
						$limit = 30;
1869
					}
1870
1871
					$params['limit'] = apply_filters( 'pods_form_ui_field_pick_autocomplete_limit', $limit, $name, $value, $options, $pod, $id, $object_params );
1872
1873
					if ( is_array( $value ) && $params['limit'] < count( $value ) ) {
1874
						$params['limit'] = count( $value );
1875
					}
1876
1877
					$params['page'] = $page;
1878
1879
					if ( 'admin_ajax_relationship' === $context ) {
1880
						$lookup_where = array(
1881
							$search_data->field_index => "`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'",
1882
						);
1883
1884
						// @todo Hook into WPML for each table
1885
						if ( $wpdb->users === $search_data->table ) {
1886
							$lookup_where['display_name'] = "`t`.`display_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1887
							$lookup_where['user_login']   = "`t`.`user_login` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1888
							$lookup_where['user_email']   = "`t`.`user_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1889
						} elseif ( $wpdb->posts === $search_data->table ) {
1890
							$lookup_where['post_title']   = "`t`.`post_title` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1891
							$lookup_where['post_name']    = "`t`.`post_name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1892
							$lookup_where['post_content'] = "`t`.`post_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1893
							$lookup_where['post_excerpt'] = "`t`.`post_excerpt` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1894
						} elseif ( $wpdb->terms === $search_data->table ) {
1895
							$lookup_where['name'] = "`t`.`name` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1896
							$lookup_where['slug'] = "`t`.`slug` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1897
						} elseif ( $wpdb->comments === $search_data->table ) {
1898
							$lookup_where['comment_content']      = "`t`.`comment_content` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1899
							$lookup_where['comment_author']       = "`t`.`comment_author` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1900
							$lookup_where['comment_author_email'] = "`t`.`comment_author_email` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%'";
1901
						}
1902
1903
						$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 );
1904
1905
						if ( ! empty( $lookup_where ) ) {
1906
							$params['where'][] = implode( ' OR ', $lookup_where );
1907
						}
1908
1909
						$orderby   = array();
1910
						$orderby[] = "(`t`.`{$search_data->field_index}` LIKE '%" . pods_sanitize_like( $data_params['query'] ) . "%' ) DESC";
1911
1912
						$pick_orderby = pods_v( self::$type . '_orderby', $options, null, true );
1913
1914
						if ( 0 < strlen( $pick_orderby ) ) {
1915
							$orderby[] = $pick_orderby;
1916
						}
1917
1918
						$orderby[] = "`t`.`{$search_data->field_index}`";
1919
						$orderby[] = "`t`.`{$search_data->field_id}`";
1920
1921
						$params['orderby'] = $orderby;
1922
					}
1923
				} elseif ( 0 < $limit ) {
1924
					$params['limit'] = $limit;
1925
					$params['page']  = $page;
1926
				}
1927
1928
				$extra = '';
1929
1930
				if ( $wpdb->posts === $search_data->table ) {
1931
					$extra = ', `t`.`post_type`';
1932
				} elseif ( $wpdb->terms === $search_data->table ) {
1933
					$extra = ', `tt`.`taxonomy`';
1934
				} elseif ( $wpdb->comments === $search_data->table ) {
1935
					$extra = ', `t`.`comment_type`';
1936
				}
1937
1938
				$params['select'] .= $extra;
1939
1940
				if ( 'user' === pods_v( self::$type . '_object', $options ) ) {
1941
					$roles = pods_v( self::$type . '_user_role', $options );
1942
1943
					if ( ! empty( $roles ) ) {
1944
						$where = array();
1945
1946
						foreach ( (array) $roles as $role ) {
1947
							if ( empty( $role ) || ( pods_clean_name( $role ) !== $role && sanitize_title( $role ) !== $role ) ) {
1948
								continue;
1949
							}
1950
1951
							$where[] = $wpdb->base_prefix . ( ( is_multisite() && ! is_main_site() ) ? get_current_blog_id() . '_' : '' ) . 'capabilities.meta_value LIKE "%\"' . pods_sanitize_like( $role ) . '\"%"';
1952
						}
1953
1954
						if ( ! empty( $where ) ) {
1955
							$params['where'][] = implode( ' OR ', $where );
1956
						}
1957
					}
1958
				}
1959
1960
				$results = $search_data->select( $params );
1961
1962
				if ( $autocomplete && $params['limit'] < $search_data->total_found() ) {
1963
					if ( ! empty( $value ) ) {
1964
						$ids = $value;
1965
1966
						if ( is_array( $ids ) && isset( $ids[0] ) && is_array( $ids[0] ) ) {
1967
							$ids = wp_list_pluck( $ids, $search_data->field_id );
1968
						}
1969
1970
						if ( is_array( $ids ) ) {
1971
							$ids = implode( ', ', $ids );
1972
						}
1973
1974
						if ( is_array( $params['where'] ) ) {
1975
							$params['where'] = implode( ' AND ', $params['where'] );
1976
						}
1977
						if ( ! empty( $params['where'] ) ) {
1978
							$params['where'] .= ' AND ';
1979
						}
1980
1981
						$params['where'] .= "`t`.`{$search_data->field_id}` IN ( {$ids} )";
1982
1983
						$results = $search_data->select( $params );
1984
					}
1985
				} else {
1986
					$autocomplete = false;
1987
				}
1988
1989 View Code Duplication
				if ( 'data' === $context ) {
1990
					self::$field_data = array(
1991
						'field'        => $name,
1992
						'id'           => $options['id'],
1993
						'autocomplete' => $autocomplete,
1994
					);
1995
				}
1996
1997
				if ( $hierarchy && ! $autocomplete && ! empty( $results ) && $options['table_info']['object_hierarchical'] && ! empty( $options['table_info']['field_parent'] ) ) {
1998
					$select_args = array(
1999
						'id'     => $options['table_info']['field_id'],
2000
						'index'  => $options['table_info']['field_index'],
2001
						'parent' => $options['table_info']['field_parent'],
2002
					);
2003
2004
					$results = pods_hierarchical_select( $results, $select_args );
2005
				}
2006
2007
				$ids = array();
2008
2009
				if ( ! empty( $results ) ) {
2010
					$display_filter = pods_v( 'display_filter', pods_v( 'options', pods_v( $search_data->field_index, $search_data->pod_data['object_fields'] ) ) );
2011
2012
					foreach ( $results as $result ) {
2013
						$result = get_object_vars( $result );
2014
2015
						if ( ! isset( $result[ $search_data->field_id ] ) || ! isset( $result[ $search_data->field_index ] ) ) {
2016
							continue;
2017
						}
2018
2019
						$result[ $search_data->field_index ] = trim( $result[ $search_data->field_index ] );
2020
2021
						$object = $object_type = '';
2022
2023
						if ( $wpdb->posts === $search_data->table && isset( $result['post_type'] ) ) {
2024
							$object      = $result['post_type'];
2025
							$object_type = 'post_type';
2026
						} elseif ( $wpdb->terms === $search_data->table && isset( $result['taxonomy'] ) ) {
2027
							$object      = $result['taxonomy'];
2028
							$object_type = 'taxonomy';
2029
						}
2030
2031
						if ( 0 < strlen( $display_filter ) ) {
2032
							$display_filter_args = pods_v( 'display_filter_args', pods_v( 'options', pods_v( $search_data->field_index, $search_data->pod_data['object_fields'] ) ) );
2033
2034
							$filter_args = array(
2035
								$display_filter,
2036
								$result[ $search_data->field_index ],
2037
							);
2038
2039
							if ( ! empty( $display_filter_args ) ) {
2040
								foreach ( (array) $display_filter_args as $display_filter_arg ) {
2041
									if ( isset( $result[ $display_filter_arg ] ) ) {
2042
										$filter_args[] = $result[ $display_filter_arg ];
2043
									}
2044
								}
2045
							}
2046
2047
							$result[ $search_data->field_index ] = call_user_func_array( 'apply_filters', $filter_args );
2048
						}
2049
2050
						if ( in_array( $options[ self::$type . '_object' ], array( 'site', 'network' ), true ) ) {
2051
							$result[ $search_data->field_index ] = $result[ $search_data->field_index ] . $result['path'];
2052
						} elseif ( strlen( $result[ $search_data->field_index ] ) < 1 ) {
2053
							$result[ $search_data->field_index ] = '(No Title)';
2054
						}
2055
2056
						if ( 'admin_ajax_relationship' === $context ) {
2057
							$items[] = array(
2058
								'id'    => $result[ $search_data->field_id ],
2059
								'text'  => $result[ $search_data->field_index ],
2060
								'image' => '',
2061
							);
2062
						} else {
2063
							$data[ $result[ $search_data->field_id ] ] = $result[ $search_data->field_index ];
2064
						}
2065
2066
						$ids[] = $result[ $search_data->field_id ];
2067
					}
2068
				}
2069
			}
2070
2071
			if ( $simple && 'admin_ajax_relationship' === $context ) {
2072
				$found_data = array();
2073
2074
				foreach ( $data as $k => $v ) {
2075
					if ( false !== stripos( $v, $data_params['query'] ) || false !== stripos( $k, $data_params['query'] ) ) {
2076
						$found_data[ $k ] = $v;
2077
					}
2078
				}
2079
2080
				$data = $found_data;
2081
			}
2082
		}
2083
2084
		if ( 'admin_ajax_relationship' === $context ) {
2085
			if ( empty( $items ) && ! empty( $data ) ) {
2086
				foreach ( $data as $k => $v ) {
2087
					$items[] = array(
2088
						'id'    => $k,
2089
						'text'  => $v,
2090
						'image' => '',
2091
					);
2092
				}
2093
			}
2094
2095
			$data = $items;
2096
		}
2097
2098
		return $data;
2099
2100
	}
2101
2102
	/**
2103
	 * Handle autocomplete AJAX.
2104
	 *
2105
	 * @since 2.3
2106
	 */
2107
	public function admin_ajax_relationship() {
2108
2109
		pods_session_start();
2110
2111
		// Sanitize input.
2112
		$params = pods_unslash( (array) $_POST );
2113
2114 View Code Duplication
		foreach ( $params as $key => $value ) {
2115
			if ( 'action' === $key ) {
2116
				continue;
2117
			}
2118
2119
			unset( $params[ $key ] );
2120
2121
			$params[ str_replace( '_podsfix_', '', $key ) ] = $value;
2122
		}
2123
2124
		$params = (object) $params;
2125
2126
		$uid = @session_id();
2127
2128
		if ( is_user_logged_in() ) {
2129
			$uid = 'user_' . get_current_user_id();
2130
		}
2131
2132
		$nonce_check = 'pods_relationship_' . (int) $params->pod . '_' . $uid . '_' . $params->uri . '_' . (int) $params->field;
2133
2134 View Code Duplication
		if ( ! isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, $nonce_check ) ) {
2135
			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...
2136
		}
2137
2138
		if ( empty( self::$api ) ) {
2139
			self::$api = pods_api();
2140
		}
2141
2142
		$pod   = self::$api->load_pod( array( 'id' => (int) $params->pod ) );
2143
		$field = self::$api->load_field( array( 'id' => (int) $params->field, 'table_info' => true ) );
2144
		$id    = (int) $params->id;
2145
2146
		$limit = 15;
2147
2148
		if ( isset( $params->limit ) ) {
2149
			$limit = (int) $params->limit;
2150
		}
2151
2152
		$page = 1;
2153
2154
		if ( isset( $params->page ) ) {
2155
			$page = (int) $params->page;
2156
		}
2157
2158
		if ( ! isset( $params->query ) || strlen( trim( $params->query ) ) < 1 ) {
2159
			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...
2160
		} elseif ( empty( $pod ) || empty( $field ) || (int) $pod['id'] !== (int) $field['pod_id'] || ! isset( $pod['fields'][ $field['name'] ] ) ) {
2161
			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...
2162
		} elseif ( 'pick' !== $field['type'] || empty( $field['table_info'] ) ) {
2163
			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...
2164
		} elseif ( 'single' === pods_v( self::$type . '_format_type', $field ) && 'autocomplete' === pods_v( self::$type . '_format_single', $field ) ) {
2165
			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...
2166
		} elseif ( 'multi' === pods_v( self::$type . '_format_type', $field ) && 'autocomplete' === pods_v( self::$type . '_format_multi', $field ) ) {
2167
			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...
2168
		}
2169
2170
		$object_params = array(
2171
			'name'        => $field['name'], // The name of the field.
2172
			'value'       => null, // The value of the field.
2173
			'options'     => array_merge( $field, $field['options'] ), // Field options.
2174
			'pod'         => $pod, // Pod data.
2175
			'id'          => $id, // Item ID.
2176
			'context'     => 'admin_ajax_relationship', // Data context.
2177
			'data_params' => $params,
2178
			'page'        => $page,
2179
			'limit'       => $limit
2180
		);
2181
2182
		$pick_data = apply_filters( 'pods_field_pick_data_ajax', null, $field['name'], null, $field, $pod, $id );
2183
2184
		if ( null !== $pick_data ) {
2185
			$items = $pick_data;
2186
		} else {
2187
			$items = $this->get_object_data( $object_params );
2188
		}
2189
2190
		if ( ! empty( $items ) && isset( $items[0] ) && ! is_array( $items[0] ) ) {
2191
			$new_items = array();
2192
2193
			foreach ( $items as $id => $text ) {
2194
				$new_items[] = array(
2195
					'id'    => $id,
2196
					'text'  => $text,
2197
					'image' => '',
2198
				);
2199
			}
2200
2201
			$items = $new_items;
2202
		}
2203
2204
		$items = apply_filters( 'pods_field_pick_data_ajax_items', $items, $field['name'], null, $field, $pod, $id );
2205
2206
		$items = array(
2207
			'results' => $items,
2208
		);
2209
2210
		wp_send_json( $items );
2211
2212
		die(); // KBAI!
0 ignored issues
show
Coding Style Compatibility introduced by
The method admin_ajax_relationship() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
2213
2214
	}
2215
2216
	/**
2217
	 * Data callback for Post Stati
2218
	 *
2219
	 * @param string       $name    The name of the field
2220
	 * @param string|array $value   The value of the field
2221
	 * @param array        $options Field options
2222
	 * @param array        $pod     Pod data
2223
	 * @param int          $id      Item ID
2224
	 *
2225
	 * @return array
2226
	 *
2227
	 * @since 2.3
2228
	 */
2229
	public function data_post_stati( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2230
2231
		$data = array();
2232
2233
		$post_stati = get_post_stati( array(), 'objects' );
2234
2235
		foreach ( $post_stati as $post_status ) {
2236
			$data[ $post_status->name ] = $post_status->label;
2237
		}
2238
2239
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2240
2241
	}
2242
2243
	/**
2244
	 * Data callback for User Roles
2245
	 *
2246
	 * @param string       $name    The name of the field
2247
	 * @param string|array $value   The value of the field
2248
	 * @param array        $options Field options
2249
	 * @param array        $pod     Pod data
2250
	 * @param int          $id      Item ID
2251
	 *
2252
	 * @return array
2253
	 *
2254
	 * @since 2.3
2255
	 */
2256
	public function data_roles( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2257
2258
		$data = array();
2259
2260
		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...
2261
2262
		foreach ( $wp_roles->role_objects as $key => $role ) {
2263
			$data[ $key ] = $wp_roles->role_names[ $key ];
2264
		}
2265
2266
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2267
2268
	}
2269
2270
	/**
2271
	 * Data callback for User Capabilities
2272
	 *
2273
	 * @param string       $name    The name of the field
2274
	 * @param string|array $value   The value of the field
2275
	 * @param array        $options Field options
2276
	 * @param array        $pod     Pod data
2277
	 * @param int          $id      Item ID
2278
	 *
2279
	 * @return array
2280
	 *
2281
	 * @since 2.3
2282
	 */
2283
	public function data_capabilities( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2284
2285
		$data = array();
2286
2287
		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...
2288
2289
		$default_caps = array(
2290
			'activate_plugins',
2291
			'add_users',
2292
			'create_users',
2293
			'delete_others_pages',
2294
			'delete_others_posts',
2295
			'delete_pages',
2296
			'delete_plugins',
2297
			'delete_posts',
2298
			'delete_private_pages',
2299
			'delete_private_posts',
2300
			'delete_published_pages',
2301
			'delete_published_posts',
2302
			'delete_users',
2303
			'edit_dashboard',
2304
			'edit_files',
2305
			'edit_others_pages',
2306
			'edit_others_posts',
2307
			'edit_pages',
2308
			'edit_plugins',
2309
			'edit_posts',
2310
			'edit_private_pages',
2311
			'edit_private_posts',
2312
			'edit_published_pages',
2313
			'edit_published_posts',
2314
			'edit_theme_options',
2315
			'edit_themes',
2316
			'edit_users',
2317
			'import',
2318
			'install_plugins',
2319
			'install_themes',
2320
			'list_users',
2321
			'manage_categories',
2322
			'manage_links',
2323
			'manage_options',
2324
			'moderate_comments',
2325
			'promote_users',
2326
			'publish_pages',
2327
			'publish_posts',
2328
			'read',
2329
			'read_private_pages',
2330
			'read_private_posts',
2331
			'remove_users',
2332
			'switch_themes',
2333
			'unfiltered_html',
2334
			'unfiltered_upload',
2335
			'update_core',
2336
			'update_plugins',
2337
			'update_themes',
2338
			'upload_files',
2339
		);
2340
2341
		$role_caps = array();
2342
2343 View Code Duplication
		foreach ( $wp_roles->role_objects as $key => $role ) {
2344
			if ( is_array( $role->capabilities ) ) {
2345
				foreach ( $role->capabilities as $cap => $grant ) {
2346
					$role_caps[ $cap ] = $cap;
2347
				}
2348
			}
2349
		}
2350
2351
		$role_caps = array_unique( $role_caps );
2352
2353
		$capabilities = array_merge( $default_caps, $role_caps );
2354
2355
		// To support Members filters
2356
		$capabilities = apply_filters( 'members_get_capabilities', $capabilities );
2357
2358
		$capabilities = apply_filters( 'pods_roles_get_capabilities', $capabilities );
2359
2360
		sort( $capabilities );
2361
2362
		$capabilities = array_unique( $capabilities );
2363
2364
		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...
2365
2366
		foreach ( $capabilities as $capability ) {
2367
			$data[ $capability ] = $capability;
2368
		}
2369
2370
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2371
2372
	}
2373
2374
	/**
2375
	 * Data callback for Image Sizes
2376
	 *
2377
	 * @param string       $name    The name of the field
2378
	 * @param string|array $value   The value of the field
2379
	 * @param array        $options Field options
2380
	 * @param array        $pod     Pod data
2381
	 * @param int          $id      Item ID
2382
	 *
2383
	 * @return array
2384
	 *
2385
	 * @since 2.3
2386
	 */
2387 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...
2388
2389
		$data = array();
2390
2391
		$image_sizes = get_intermediate_image_sizes();
2392
2393
		foreach ( $image_sizes as $image_size ) {
2394
			$data[ $image_size ] = ucwords( str_replace( '-', ' ', $image_size ) );
2395
		}
2396
2397
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2398
2399
	}
2400
2401
	/**
2402
	 * Data callback for Countries
2403
	 *
2404
	 * @param string       $name    The name of the field
2405
	 * @param string|array $value   The value of the field
2406
	 * @param array        $options Field options
2407
	 * @param array        $pod     Pod data
2408
	 * @param int          $id      Item ID
2409
	 *
2410
	 * @return array
2411
	 *
2412
	 * @since 2.3
2413
	 */
2414
	public function data_countries( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2415
2416
		$data = array(
2417
			'AF' => __( 'Afghanistan' ),
2418
			'AL' => __( 'Albania' ),
2419
			'DZ' => __( 'Algeria' ),
2420
			'AS' => __( 'American Samoa' ),
2421
			'AD' => __( 'Andorra' ),
2422
			'AO' => __( 'Angola' ),
2423
			'AI' => __( 'Anguilla' ),
2424
			'AQ' => __( 'Antarctica' ),
2425
			'AG' => __( 'Antigua and Barbuda' ),
2426
			'AR' => __( 'Argentina' ),
2427
			'AM' => __( 'Armenia' ),
2428
			'AW' => __( 'Aruba' ),
2429
			'AU' => __( 'Australia' ),
2430
			'AT' => __( 'Austria' ),
2431
			'AZ' => __( 'Azerbaijan' ),
2432
			'BS' => __( 'Bahamas' ),
2433
			'BH' => __( 'Bahrain' ),
2434
			'BD' => __( 'Bangladesh' ),
2435
			'BB' => __( 'Barbados' ),
2436
			'BY' => __( 'Belarus' ),
2437
			'BE' => __( 'Belgium' ),
2438
			'BZ' => __( 'Belize' ),
2439
			'BJ' => __( 'Benin' ),
2440
			'BM' => __( 'Bermuda' ),
2441
			'BT' => __( 'Bhutan' ),
2442
			'BO' => __( 'Bolivia' ),
2443
			'BA' => __( 'Bosnia and Herzegovina' ),
2444
			'BW' => __( 'Botswana' ),
2445
			'BV' => __( 'Bouvet Island' ),
2446
			'BR' => __( 'Brazil' ),
2447
			'BQ' => __( 'British Antarctic Territory' ),
2448
			'IO' => __( 'British Indian Ocean Territory' ),
2449
			'VG' => __( 'British Virgin Islands' ),
2450
			'BN' => __( 'Brunei' ),
2451
			'BG' => __( 'Bulgaria' ),
2452
			'BF' => __( 'Burkina Faso' ),
2453
			'BI' => __( 'Burundi' ),
2454
			'KH' => __( 'Cambodia' ),
2455
			'CM' => __( 'Cameroon' ),
2456
			'CA' => __( 'Canada' ),
2457
			'CT' => __( 'Canton and Enderbury Islands' ),
2458
			'CV' => __( 'Cape Verde' ),
2459
			'KY' => __( 'Cayman Islands' ),
2460
			'CF' => __( 'Central African Republic' ),
2461
			'TD' => __( 'Chad' ),
2462
			'CL' => __( 'Chile' ),
2463
			'CN' => __( 'China' ),
2464
			'CX' => __( 'Christmas Island' ),
2465
			'CC' => __( 'Cocos [Keeling] Islands' ),
2466
			'CO' => __( 'Colombia' ),
2467
			'KM' => __( 'Comoros' ),
2468
			'CG' => __( 'Congo - Brazzaville' ),
2469
			'CD' => __( 'Congo - Kinshasa' ),
2470
			'CK' => __( 'Cook Islands' ),
2471
			'CR' => __( 'Costa Rica' ),
2472
			'HR' => __( 'Croatia' ),
2473
			'CU' => __( 'Cuba' ),
2474
			'CY' => __( 'Cyprus' ),
2475
			'CZ' => __( 'Czech Republic' ),
2476
			'CI' => __( 'Côte d’Ivoire' ),
2477
			'DK' => __( 'Denmark' ),
2478
			'DJ' => __( 'Djibouti' ),
2479
			'DM' => __( 'Dominica' ),
2480
			'DO' => __( 'Dominican Republic' ),
2481
			'NQ' => __( 'Dronning Maud Land' ),
2482
			'DD' => __( 'East Germany' ),
2483
			'EC' => __( 'Ecuador' ),
2484
			'EG' => __( 'Egypt' ),
2485
			'SV' => __( 'El Salvador' ),
2486
			'GQ' => __( 'Equatorial Guinea' ),
2487
			'ER' => __( 'Eritrea' ),
2488
			'EE' => __( 'Estonia' ),
2489
			'ET' => __( 'Ethiopia' ),
2490
			'FK' => __( 'Falkland Islands' ),
2491
			'FO' => __( 'Faroe Islands' ),
2492
			'FJ' => __( 'Fiji' ),
2493
			'FI' => __( 'Finland' ),
2494
			'FR' => __( 'France' ),
2495
			'GF' => __( 'French Guiana' ),
2496
			'PF' => __( 'French Polynesia' ),
2497
			'TF' => __( 'French Southern Territories' ),
2498
			'FQ' => __( 'French Southern and Antarctic Territories' ),
2499
			'GA' => __( 'Gabon' ),
2500
			'GM' => __( 'Gambia' ),
2501
			'GE' => __( 'Georgia' ),
2502
			'DE' => __( 'Germany' ),
2503
			'GH' => __( 'Ghana' ),
2504
			'GI' => __( 'Gibraltar' ),
2505
			'GR' => __( 'Greece' ),
2506
			'GL' => __( 'Greenland' ),
2507
			'GD' => __( 'Grenada' ),
2508
			'GP' => __( 'Guadeloupe' ),
2509
			'GU' => __( 'Guam' ),
2510
			'GT' => __( 'Guatemala' ),
2511
			'GG' => __( 'Guernsey' ),
2512
			'GN' => __( 'Guinea' ),
2513
			'GW' => __( 'Guinea-Bissau' ),
2514
			'GY' => __( 'Guyana' ),
2515
			'HT' => __( 'Haiti' ),
2516
			'HM' => __( 'Heard Island and McDonald Islands' ),
2517
			'HN' => __( 'Honduras' ),
2518
			'HK' => __( 'Hong Kong SAR China' ),
2519
			'HU' => __( 'Hungary' ),
2520
			'IS' => __( 'Iceland' ),
2521
			'IN' => __( 'India' ),
2522
			'ID' => __( 'Indonesia' ),
2523
			'IR' => __( 'Iran' ),
2524
			'IQ' => __( 'Iraq' ),
2525
			'IE' => __( 'Ireland' ),
2526
			'IM' => __( 'Isle of Man' ),
2527
			'IL' => __( 'Israel' ),
2528
			'IT' => __( 'Italy' ),
2529
			'JM' => __( 'Jamaica' ),
2530
			'JP' => __( 'Japan' ),
2531
			'JE' => __( 'Jersey' ),
2532
			'JT' => __( 'Johnston Island' ),
2533
			'JO' => __( 'Jordan' ),
2534
			'KZ' => __( 'Kazakhstan' ),
2535
			'KE' => __( 'Kenya' ),
2536
			'KI' => __( 'Kiribati' ),
2537
			'KW' => __( 'Kuwait' ),
2538
			'KG' => __( 'Kyrgyzstan' ),
2539
			'LA' => __( 'Laos' ),
2540
			'LV' => __( 'Latvia' ),
2541
			'LB' => __( 'Lebanon' ),
2542
			'LS' => __( 'Lesotho' ),
2543
			'LR' => __( 'Liberia' ),
2544
			'LY' => __( 'Libya' ),
2545
			'LI' => __( 'Liechtenstein' ),
2546
			'LT' => __( 'Lithuania' ),
2547
			'LU' => __( 'Luxembourg' ),
2548
			'MO' => __( 'Macau SAR China' ),
2549
			'MK' => __( 'Macedonia' ),
2550
			'MG' => __( 'Madagascar' ),
2551
			'MW' => __( 'Malawi' ),
2552
			'MY' => __( 'Malaysia' ),
2553
			'MV' => __( 'Maldives' ),
2554
			'ML' => __( 'Mali' ),
2555
			'MT' => __( 'Malta' ),
2556
			'MH' => __( 'Marshall Islands' ),
2557
			'MQ' => __( 'Martinique' ),
2558
			'MR' => __( 'Mauritania' ),
2559
			'MU' => __( 'Mauritius' ),
2560
			'YT' => __( 'Mayotte' ),
2561
			'FX' => __( 'Metropolitan France' ),
2562
			'MX' => __( 'Mexico' ),
2563
			'FM' => __( 'Micronesia' ),
2564
			'MI' => __( 'Midway Islands' ),
2565
			'MD' => __( 'Moldova' ),
2566
			'MC' => __( 'Monaco' ),
2567
			'MN' => __( 'Mongolia' ),
2568
			'ME' => __( 'Montenegro' ),
2569
			'MS' => __( 'Montserrat' ),
2570
			'MA' => __( 'Morocco' ),
2571
			'MZ' => __( 'Mozambique' ),
2572
			'MM' => __( 'Myanmar [Burma]' ),
2573
			'NA' => __( 'Namibia' ),
2574
			'NR' => __( 'Nauru' ),
2575
			'NP' => __( 'Nepal' ),
2576
			'NL' => __( 'Netherlands' ),
2577
			'AN' => __( 'Netherlands Antilles' ),
2578
			'NT' => __( 'Neutral Zone' ),
2579
			'NC' => __( 'New Caledonia' ),
2580
			'NZ' => __( 'New Zealand' ),
2581
			'NI' => __( 'Nicaragua' ),
2582
			'NE' => __( 'Niger' ),
2583
			'NG' => __( 'Nigeria' ),
2584
			'NU' => __( 'Niue' ),
2585
			'NF' => __( 'Norfolk Island' ),
2586
			'KP' => __( 'North Korea' ),
2587
			'VD' => __( 'North Vietnam' ),
2588
			'MP' => __( 'Northern Mariana Islands' ),
2589
			'NO' => __( 'Norway' ),
2590
			'OM' => __( 'Oman' ),
2591
			'PC' => __( 'Pacific Islands Trust Territory' ),
2592
			'PK' => __( 'Pakistan' ),
2593
			'PW' => __( 'Palau' ),
2594
			'PS' => __( 'Palestinian Territories' ),
2595
			'PA' => __( 'Panama' ),
2596
			'PZ' => __( 'Panama Canal Zone' ),
2597
			'PG' => __( 'Papua New Guinea' ),
2598
			'PY' => __( 'Paraguay' ),
2599
			'YD' => __( "People's Democratic Republic of Yemen" ),
2600
			'PE' => __( 'Peru' ),
2601
			'PH' => __( 'Philippines' ),
2602
			'PN' => __( 'Pitcairn Islands' ),
2603
			'PL' => __( 'Poland' ),
2604
			'PT' => __( 'Portugal' ),
2605
			'PR' => __( 'Puerto Rico' ),
2606
			'QA' => __( 'Qatar' ),
2607
			'RO' => __( 'Romania' ),
2608
			'RU' => __( 'Russia' ),
2609
			'RW' => __( 'Rwanda' ),
2610
			'RE' => __( 'Réunion' ),
2611
			'BL' => __( 'Saint Barthélemy' ),
2612
			'SH' => __( 'Saint Helena' ),
2613
			'KN' => __( 'Saint Kitts and Nevis' ),
2614
			'LC' => __( 'Saint Lucia' ),
2615
			'MF' => __( 'Saint Martin' ),
2616
			'PM' => __( 'Saint Pierre and Miquelon' ),
2617
			'VC' => __( 'Saint Vincent and the Grenadines' ),
2618
			'WS' => __( 'Samoa' ),
2619
			'SM' => __( 'San Marino' ),
2620
			'SA' => __( 'Saudi Arabia' ),
2621
			'SN' => __( 'Senegal' ),
2622
			'RS' => __( 'Serbia' ),
2623
			'CS' => __( 'Serbia and Montenegro' ),
2624
			'SC' => __( 'Seychelles' ),
2625
			'SL' => __( 'Sierra Leone' ),
2626
			'SG' => __( 'Singapore' ),
2627
			'SK' => __( 'Slovakia' ),
2628
			'SI' => __( 'Slovenia' ),
2629
			'SB' => __( 'Solomon Islands' ),
2630
			'SO' => __( 'Somalia' ),
2631
			'ZA' => __( 'South Africa' ),
2632
			'GS' => __( 'South Georgia and the South Sandwich Islands' ),
2633
			'KR' => __( 'South Korea' ),
2634
			'ES' => __( 'Spain' ),
2635
			'LK' => __( 'Sri Lanka' ),
2636
			'SD' => __( 'Sudan' ),
2637
			'SR' => __( 'Suriname' ),
2638
			'SJ' => __( 'Svalbard and Jan Mayen' ),
2639
			'SZ' => __( 'Swaziland' ),
2640
			'SE' => __( 'Sweden' ),
2641
			'CH' => __( 'Switzerland' ),
2642
			'SY' => __( 'Syria' ),
2643
			'ST' => __( 'São Tomé and Príncipe' ),
2644
			'TW' => __( 'Taiwan' ),
2645
			'TJ' => __( 'Tajikistan' ),
2646
			'TZ' => __( 'Tanzania' ),
2647
			'TH' => __( 'Thailand' ),
2648
			'TL' => __( 'Timor-Leste' ),
2649
			'TG' => __( 'Togo' ),
2650
			'TK' => __( 'Tokelau' ),
2651
			'TO' => __( 'Tonga' ),
2652
			'TT' => __( 'Trinidad and Tobago' ),
2653
			'TN' => __( 'Tunisia' ),
2654
			'TR' => __( 'Turkey' ),
2655
			'TM' => __( 'Turkmenistan' ),
2656
			'TC' => __( 'Turks and Caicos Islands' ),
2657
			'TV' => __( 'Tuvalu' ),
2658
			'UM' => __( 'U.S. Minor Outlying Islands' ),
2659
			'PU' => __( 'U.S. Miscellaneous Pacific Islands' ),
2660
			'VI' => __( 'U.S. Virgin Islands' ),
2661
			'UG' => __( 'Uganda' ),
2662
			'UA' => __( 'Ukraine' ),
2663
			'SU' => __( 'Union of Soviet Socialist Republics' ),
2664
			'AE' => __( 'United Arab Emirates' ),
2665
			'GB' => __( 'United Kingdom' ),
2666
			'US' => __( 'United States' ),
2667
			'ZZ' => __( 'Unknown or Invalid Region' ),
2668
			'UY' => __( 'Uruguay' ),
2669
			'UZ' => __( 'Uzbekistan' ),
2670
			'VU' => __( 'Vanuatu' ),
2671
			'VA' => __( 'Vatican City' ),
2672
			'VE' => __( 'Venezuela' ),
2673
			'VN' => __( 'Vietnam' ),
2674
			'WK' => __( 'Wake Island' ),
2675
			'WF' => __( 'Wallis and Futuna' ),
2676
			'EH' => __( 'Western Sahara' ),
2677
			'YE' => __( 'Yemen' ),
2678
			'ZM' => __( 'Zambia' ),
2679
			'ZW' => __( 'Zimbabwe' ),
2680
			'AX' => __( 'Åland Islands' ),
2681
		);
2682
2683
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2684
2685
	}
2686
2687
	/**
2688
	 * Data callback for US States
2689
	 *
2690
	 * @param string       $name    The name of the field
2691
	 * @param string|array $value   The value of the field
2692
	 * @param array        $options Field options
2693
	 * @param array        $pod     Pod data
2694
	 * @param int          $id      Item ID
2695
	 *
2696
	 * @return array
2697
	 *
2698
	 * @since 2.3
2699
	 */
2700
	public function data_us_states( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
2701
2702
		$data = array(
2703
			'AL' => __( 'Alabama' ),
2704
			'AK' => __( 'Alaska' ),
2705
			'AZ' => __( 'Arizona' ),
2706
			'AR' => __( 'Arkansas' ),
2707
			'CA' => __( 'California' ),
2708
			'CO' => __( 'Colorado' ),
2709
			'CT' => __( 'Connecticut' ),
2710
			'DE' => __( 'Delaware' ),
2711
			'DC' => __( 'District Of Columbia' ),
2712
			'FL' => __( 'Florida' ),
2713
			'GA' => __( 'Georgia' ),
2714
			'HI' => __( 'Hawaii' ),
2715
			'ID' => __( 'Idaho' ),
2716
			'IL' => __( 'Illinois' ),
2717
			'IN' => __( 'Indiana' ),
2718
			'IA' => __( 'Iowa' ),
2719
			'KS' => __( 'Kansas' ),
2720
			'KY' => __( 'Kentucky' ),
2721
			'LA' => __( 'Louisiana' ),
2722
			'ME' => __( 'Maine' ),
2723
			'MD' => __( 'Maryland' ),
2724
			'MA' => __( 'Massachusetts' ),
2725
			'MI' => __( 'Michigan' ),
2726
			'MN' => __( 'Minnesota' ),
2727
			'MS' => __( 'Mississippi' ),
2728
			'MO' => __( 'Missouri' ),
2729
			'MT' => __( 'Montana' ),
2730
			'NE' => __( 'Nebraska' ),
2731
			'NV' => __( 'Nevada' ),
2732
			'NH' => __( 'New Hampshire' ),
2733
			'NJ' => __( 'New Jersey' ),
2734
			'NM' => __( 'New Mexico' ),
2735
			'NY' => __( 'New York' ),
2736
			'NC' => __( 'North Carolina' ),
2737
			'ND' => __( 'North Dakota' ),
2738
			'OH' => __( 'Ohio' ),
2739
			'OK' => __( 'Oklahoma' ),
2740
			'OR' => __( 'Oregon' ),
2741
			'PA' => __( 'Pennsylvania' ),
2742
			'RI' => __( 'Rhode Island' ),
2743
			'SC' => __( 'South Carolina' ),
2744
			'SD' => __( 'South Dakota' ),
2745
			'TN' => __( 'Tennessee' ),
2746
			'TX' => __( 'Texas' ),
2747
			'UT' => __( 'Utah' ),
2748
			'VT' => __( 'Vermont' ),
2749
			'VA' => __( 'Virginia' ),
2750
			'WA' => __( 'Washington' ),
2751
			'WV' => __( 'West Virginia' ),
2752
			'WI' => __( 'Wisconsin' ),
2753
			'WY' => __( 'Wyoming' ),
2754
		);
2755
2756
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
2757
2758
	}
2759
2760
	/**
2761
	 * Data callback for US States
2762
	 *
2763
	 * @param string       $name    The name of the field
2764
	 * @param string|array $value   The value of the field
2765
	 * @param array        $options Field options
2766
	 * @param array        $pod     Pod data
2767
	 * @param int          $id      Item ID
2768
	 *
2769
	 * @return array
2770
	 *
2771
	 * @since 2.3
2772
	 */
2773
	public function data_days_of_week( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $pod is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2774
2775
		/**
2776
		 * @var WP_Locale
2777
		 */
2778
		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...
2779
2780
		return $wp_locale->weekday;
2781
2782
	}
2783
2784
	/**
2785
	 * Data callback for US States
2786
	 *
2787
	 * @param string       $name    The name of the field
2788
	 * @param string|array $value   The value of the field
2789
	 * @param array        $options Field options
2790
	 * @param array        $pod     Pod data
2791
	 * @param int          $id      Item ID
2792
	 *
2793
	 * @return array
2794
	 *
2795
	 * @since 2.3
2796
	 */
2797
	public function data_months_of_year( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $pod is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2798
2799
		/**
2800
		 * @var WP_Locale
2801
		 */
2802
		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...
2803
2804
		return $wp_locale->month;
2805
2806
	}
2807
2808
}
2809