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

Pods::prev_id()   F

Complexity

Conditions 23
Paths 400

Size

Total Lines 79
Code Lines 49

Duplication

Lines 32
Ratio 40.51 %

Importance

Changes 0
Metric Value
cc 23
eloc 49
nc 400
nop 2
dl 32
loc 79
rs 3.8635
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Pods class.
5
 *
6
 * @package Pods
7
 */
8
class Pods implements Iterator {
9
10
	/**
11
	 * Whether the Pods object is in a PHP Iterator call.
12
	 *
13
	 * @var bool
14
	 */
15
	private $iterator = false;
16
17
	/**
18
	 * PodsAPI object.
19
	 *
20
	 * @var PodsAPI
21
	 */
22
	public $api;
23
24
	/**
25
	 * PodsData object.
26
	 *
27
	 * @var PodsData
28
	 */
29
	public $data;
30
31
	/**
32
	 * PodsData object for additional calls.
33
	 *
34
	 * @var PodsData
35
	 */
36
	public $alt_data;
37
38
	/**
39
	 * Array of pod item arrays.
40
	 *
41
	 * @var array
42
	 */
43
	public $rows;
44
45
	/**
46
	 * Current pod item array.
47
	 *
48
	 * @var array
49
	 */
50
	public $row;
51
52
	/**
53
	 * Row number.
54
	 *
55
	 * @var int
56
	 */
57
	private $row_number;
58
59
	/**
60
	 * Override pod item array.
61
	 *
62
	 * @var array
63
	 */
64
	public $row_override = array();
65
66
	/**
67
	 * Whether to display errors on the screen.
68
	 *
69
	 * @var bool
70
	 */
71
	public $display_errors = true;
72
73
	/**
74
	 * Current pod information.
75
	 *
76
	 * @var array|bool|mixed|null|void
77
	 */
78
	public $pod_data;
79
80
	/**
81
	 * Last used Pods::find() parameters.
82
	 *
83
	 * @var array
84
	 */
85
	public $params = array();
86
87
	/**
88
	 * Current Pod name.
89
	 *
90
	 * @var string
91
	 */
92
	public $pod;
93
94
	/**
95
	 * Current Pod ID.
96
	 *
97
	 * @var int
98
	 */
99
	public $pod_id;
100
101
	/**
102
	 * Pod fields information.
103
	 *
104
	 * @var array
105
	 */
106
	public $fields;
107
108
	/**
109
	 * Last used filters() parameters.
110
	 *
111
	 * @var array
112
	 */
113
	public $filters = array();
114
115
	/**
116
	 * Detail page URL used for Advanced Content Types.
117
	 *
118
	 * @var string
119
	 */
120
	public $detail_page;
121
122
	/**
123
	 * Current Item ID.
124
	 *
125
	 * @var int
126
	 */
127
	public $id;
128
129
	/**
130
	 * Last used limit from find() lookup.
131
	 *
132
	 * @var int
133
	 */
134
	public $limit = 15;
135
136
	/**
137
	 * Last used offset from find() lookup.
138
	 *
139
	 * @var int
140
	 */
141
	public $offset = 0;
142
143
	/**
144
	 * Query variable used for pagination number.
145
	 *
146
	 * @var string
147
	 */
148
	public $page_var = 'pg';
149
150
	/**
151
	 * Last used page from find() lookup.
152
	 *
153
	 * @var int|mixed
154
	 */
155
	public $page = 1;
156
157
	/**
158
	 * Last used state of whether pagination was enabled from find() lookup.
159
	 *
160
	 * @var bool
161
	 */
162
	public $pagination = true;
163
164
	/**
165
	 * Last used state of whether search was enabled from find() lookup.
166
	 *
167
	 * @var bool
168
	 */
169
	public $search = true;
170
171
	/**
172
	 * Query variable used for search string.
173
	 *
174
	 * @var string
175
	 */
176
	public $search_var = 'search';
177
178
	/**
179
	 * Search mode (int | text | text_like).
180
	 *
181
	 * @var string
182
	 */
183
	public $search_mode = 'int';
184
185
	/**
186
	 * Total number of records returned from find() lookup.
187
	 *
188
	 * @var int
189
	 */
190
	public $total = 0;
191
192
	/**
193
	 * Total number of records found from find() lookup.
194
	 *
195
	 * @var int
196
	 */
197
	public $total_found = 0;
198
199
	/**
200
	 * Last used ui options for ui() call.
201
	 *
202
	 * @var array
203
	 */
204
	public $ui = array();
205
206
	/**
207
	 * Page template to use for SEO feature in Pods Pages.
208
	 *
209
	 * @var string
210
	 */
211
	public $page_template;
212
213
	/**
214
	 * Body classes to use for SEO feature in Pods Pages.
215
	 *
216
	 * @var array
217
	 */
218
	public $body_classes;
219
220
	/**
221
	 * Meta tags to use for SEO feature in Pods Pages.
222
	 *
223
	 * @var array
224
	 */
225
	public $meta = array();
226
227
	/**
228
	 * Meta properties to use for SEO feature in Pods Pages.
229
	 *
230
	 * @var array
231
	 */
232
	public $meta_properties = array();
233
234
	/**
235
	 * Meta custom HTML to use for SEO feature in Pods Pages.
236
	 *
237
	 * @var string
238
	 */
239
	public $meta_extra = '';
240
241
	/**
242
	 * Last SQL query used by a find() lookup.
243
	 *
244
	 * @var string
245
	 */
246
	public $sql;
247
248
	/**
249
	 * Pods_Deprecated object.
250
	 *
251
	 * @var Pods_Deprecated
252
	 */
253
	public $deprecated;
254
255
	/**
256
	 * Old Pod name variable.
257
	 *
258
	 * @var string
259
	 *
260
	 * @deprecated 2.0
261
	 */
262
	public $datatype;
263
264
	/**
265
	 * Old Pod ID variable.
266
	 *
267
	 * @var int
268
	 *
269
	 * @deprecated 2.0
270
	 */
271
	public $datatype_id;
272
273
	/**
274
	 * Constructor - Pods Framework core.
275
	 *
276
	 * @param string $pod The pod name.
277
	 * @param mixed  $id  (optional) The ID or slug, to load a single record; Provide array of $params to run 'find'.
278
	 *
279
	 * @license http://www.gnu.org/licenses/gpl-2.0.html
280
	 * @since   1.0.0
281
	 * @link    https://pods.io/docs/pods/
282
	 */
283
	public function __construct( $pod = null, $id = null ) {
284
285
		if ( null === $pod ) {
286
			$queried_object = get_queried_object();
287
288
			if ( $queried_object ) {
289
				$id_lookup = true;
290
291
				if ( isset( $queried_object->post_type ) ) {
292
					// Post Type Singular.
293
					$pod = $queried_object->post_type;
294
				} elseif ( isset( $queried_object->taxonomy ) ) {
295
					// Term Archive.
296
					$pod = $queried_object->taxonomy;
297
				} elseif ( isset( $queried_object->user_login ) ) {
298
					// Author Archive.
299
					$pod = 'user';
300
				} elseif ( isset( $queried_object->public, $queried_object->name ) ) {
301
					// Post Type Archive.
302
					$pod = $queried_object->name;
303
304
					$id_lookup = false;
305
				}
306
307
				if ( null === $id && $id_lookup ) {
308
					$id = get_queried_object_id();
309
				}
310
			}//end if
311
		}//end if
312
313
		$this->api                 = pods_api( $pod );
314
		$this->api->display_errors =& $this->display_errors;
315
316
		$this->data               = pods_data( $this->api, $id, false );
317
		PodsData::$display_errors =& $this->display_errors;
318
319
		// Set up page variable.
320
		if ( pods_strict( false ) ) {
321
			$this->page       = 1;
322
			$this->pagination = false;
323
			$this->search     = false;
324
		} else {
325
			// Get the page variable.
326
			$this->page = pods_v( $this->page_var, 'get' );
327
			$this->page = ( empty( $this->page ) ? 1 : max( pods_absint( $this->page ), 1 ) );
328
		}
329
330
		// Set default pagination handling to on/off.
331
		if ( defined( 'PODS_GLOBAL_POD_PAGINATION' ) ) {
332
			if ( ! PODS_GLOBAL_POD_PAGINATION ) {
333
				$this->page       = 1;
334
				$this->pagination = false;
335
			} else {
336
				$this->pagination = true;
337
			}
338
		}
339
340
		// Set default search to on/off.
341
		if ( defined( 'PODS_GLOBAL_POD_SEARCH' ) ) {
342
			if ( PODS_GLOBAL_POD_SEARCH ) {
343
				$this->search = true;
344
			} else {
345
				$this->search = false;
346
			}
347
		}
348
349
		// Set default search mode.
350
		$allowed_search_modes = array( 'int', 'text', 'text_like' );
351
352
		if ( defined( 'PODS_GLOBAL_POD_SEARCH_MODE' ) && in_array( PODS_GLOBAL_POD_SEARCH_MODE, $allowed_search_modes, true ) ) {
353
			$this->search_mode = PODS_GLOBAL_POD_SEARCH_MODE;
354
		}
355
356
		// Sync Settings.
357
		$this->data->page        =& $this->page;
358
		$this->data->limit       =& $this->limit;
359
		$this->data->pagination  =& $this->pagination;
360
		$this->data->search      =& $this->search;
361
		$this->data->search_mode =& $this->search_mode;
362
363
		// Sync Pod Data.
364
		$this->api->pod_data =& $this->data->pod_data;
365
		$this->pod_data      =& $this->api->pod_data;
366
		$this->api->pod_id   =& $this->data->pod_id;
0 ignored issues
show
Bug introduced by
The property pod_id does not seem to exist in PodsData.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
367
		$this->pod_id        =& $this->api->pod_id;
368
		$this->datatype_id   =& $this->pod_id;
0 ignored issues
show
Deprecated Code introduced by
The property Pods::$datatype_id has been deprecated with message: 2.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
369
		$this->api->pod      =& $this->data->pod;
370
		$this->pod           =& $this->api->pod;
371
		$this->datatype      =& $this->pod;
0 ignored issues
show
Deprecated Code introduced by
The property Pods::$datatype has been deprecated with message: 2.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
372
		$this->api->fields   =& $this->data->fields;
373
		$this->fields        =& $this->api->fields;
374
		$this->detail_page   =& $this->data->detail_page;
375
		$this->id            =& $this->data->id;
376
		$this->row           =& $this->data->row;
377
		$this->rows          =& $this->data->data;
378
		$this->row_number    =& $this->data->row_number;
379
		$this->sql           =& $this->data->sql;
380
381
		if ( is_array( $id ) || is_object( $id ) ) {
382
			$this->find( $id );
383
		}
384
	}
385
386
	/**
387
	 * Whether this Pod object is valid or not
388
	 *
389
	 * @return bool
390
	 *
391
	 * @since 2.0
392
	 */
393
	public function valid() {
394
395
		if ( empty( $this->pod_id ) ) {
396
			return false;
397
		}
398
399
		if ( $this->iterator ) {
400
			return isset( $this->rows[ $this->row_number ] );
401
		}
402
403
		return true;
404
	}
405
406
	/**
407
	 * Check if in Iterator mode
408
	 *
409
	 * @return bool
410
	 *
411
	 * @since 2.3.4
412
	 *
413
	 * @link  http://www.php.net/manual/en/class.iterator.php
414
	 */
415
	public function is_iterator() {
416
417
		return $this->iterator;
418
	}
419
420
	/**
421
	 * Turn off Iterator mode to off
422
	 *
423
	 * @return void
424
	 *
425
	 * @since 2.3.4
426
	 *
427
	 * @link  http://www.php.net/manual/en/class.iterator.php
428
	 */
429
	public function stop_iterator() {
430
431
		$this->iterator = false;
432
433
	}
434
435
	/**
436
	 * Rewind Iterator
437
	 *
438
	 * @since 2.3.4
439
	 *
440
	 * @link  http://www.php.net/manual/en/class.iterator.php
441
	 */
442
	public function rewind() {
443
444
		if ( ! $this->iterator ) {
445
			$this->iterator = true;
446
447
			$this->row_number = 0;
448
		}
449
	}
450
451
	/**
452
	 * Get current Iterator row
453
	 *
454
	 * @return mixed|boolean
455
	 *
456
	 * @since 2.3.4
457
	 *
458
	 * @link  http://www.php.net/manual/en/class.iterator.php
459
	 */
460
	public function current() {
461
462
		if ( $this->iterator && $this->fetch() ) {
463
			return $this;
464
		}
465
466
		return false;
467
	}
468
469
	/**
470
	 * Get current Iterator key
471
	 *
472
	 * @return int
473
	 *
474
	 * @since 2.3.4
475
	 *
476
	 * @link  http://www.php.net/manual/en/class.iterator.php
477
	 */
478
	public function key() {
479
480
		return $this->row_number;
481
	}
482
483
	/**
484
	 * Move onto the next Iterator row
485
	 *
486
	 * @return void
487
	 *
488
	 * @since 2.3.4
489
	 *
490
	 * @link  http://www.php.net/manual/en/class.iterator.php
491
	 */
492
	public function next() {
493
494
		$this->row_number ++;
495
	}
496
497
	/**
498
	 * Whether a Pod item exists or not when using fetch() or construct with an ID or slug
499
	 *
500
	 * @return bool
501
	 *
502
	 * @since 2.0
503
	 */
504
	public function exists() {
505
506
		if ( empty( $this->row ) ) {
507
			return false;
508
		}
509
510
		return true;
511
	}
512
513
	/**
514
	 * Return an array of all rows returned from a find() call.
515
	 *
516
	 * Most of the time, you will want to loop through data using fetch()
517
	 * instead of using this function.
518
	 *
519
	 * @return array|bool An array of all rows returned from a find() call, or false if no items returned
520
	 *
521
	 * @since 2.0
522
	 * @link  https://pods.io/docs/data/
523
	 */
524
	public function data() {
525
526
		do_action( 'pods_pods_data', $this );
527
528
		if ( empty( $this->rows ) ) {
529
			return false;
530
		}
531
532
		return (array) $this->rows;
533
	}
534
535
	/**
536
	 * Return a field input for a specific field
537
	 *
538
	 * @param string|array      $field      Field name or Field data array.
539
	 * @param string|array|null $input_name Input field name to use (overrides default name).
540
	 * @param mixed             $value      Current value to use.
541
	 *
542
	 * @return string Field Input HTML
543
	 *
544
	 * @since 2.3.10
545
	 */
546
	public function input( $field, $input_name = null, $value = '__null' ) {
547
548
		if ( is_array( $field ) ) {
549
			// Field data override.
550
			$field_data = $field;
551
552
			$field = pods_v( 'name', $field );
553
		} else {
554
			// Get field data from field name.
555
			$field_data = $this->fields( $field );
556
		}
557
558
		if ( ! empty( $field_data ) ) {
559
			$field_type = pods_v( 'type', $field_data );
560
561
			if ( empty( $input_name ) ) {
562
				$input_name = $field;
563
			}
564
565
			if ( '__null' === $value ) {
566
				$value = $this->field( array(
567
					'name'    => $field,
568
					'in_form' => true,
569
				) );
570
			}
571
572
			return PodsForm::field( $input_name, $value, $field_type, $field_data, $this, $this->id() );
573
		}
574
575
		return '';
576
577
	}
578
579
	/**
580
	 * Return field array from a Pod, a field's data, or a field option
581
	 *
582
	 * @param null $field  Field name.
583
	 * @param null $option Option name.
584
	 *
585
	 * @return bool|mixed
586
	 *
587
	 * @since 2.0
588
	 */
589
	public function fields( $field = null, $option = null ) {
590
591
		$field_data = null;
592
593
		if ( empty( $this->fields ) ) {
594
			// No fields found.
595
			$field_data = array();
596
		} elseif ( empty( $field ) ) {
597
			// Return all fields.
598
			$field_data = (array) $this->fields;
599
		} elseif ( ! isset( $this->fields[ $field ] ) && ! isset( $this->pod_data['object_fields'][ $field ] ) ) {
600
			// Field not found.
601
			$field_data = array();
602
		} elseif ( empty( $option ) ) {
603
			// Return all field data.
604
			if ( isset( $this->fields[ $field ] ) ) {
605
				$field_data = $this->fields[ $field ];
606
			} elseif ( isset( $this->pod_data['object_fields'] ) ) {
607
				$field_data = $this->pod_data['object_fields'][ $field ];
608
			}
609
		} else {
610
			$options = array();
611
612
			// Merge options.
613
			if ( isset( $this->fields[ $field ] ) ) {
614
				$options = array_merge( $this->fields[ $field ], $this->fields[ $field ]['options'] );
615
			} elseif ( isset( $this->pod_data['object_fields'] ) ) {
616
				$options = array_merge( $this->pod_data['object_fields'][ $field ], $this->pod_data['object_fields'][ $field ]['options'] );
617
			}
618
619
			if ( 'data' === $option && in_array( pods_v( 'type', $options ), PodsForm::tableless_field_types(), true ) ) {
620
				// Get a list of available items from a relationship field.
621
				$field_data = PodsForm::field_method( 'pick', 'get_field_data', $options );
622
			} elseif ( isset( $options[ $option ] ) ) {
623
				// Return option.
624
				$field_data = $options[ $option ];
625
			}
626
		}//end if
627
628
		/**
629
		 * Modify the field data before returning
630
		 *
631
		 * @since unknown
632
		 *
633
		 * @param array       $field_data The data for the field.
634
		 * @param string|null $field      The specific field that data is being return for, if set when method is called or null.
635
		 * @param string|null $option     Value of option param when method was called. Can be used to get a list of available items from a relationship field.
636
		 * @param Pods|object $this       The current Pods class instance.
637
		 */
638
		return apply_filters( 'pods_pods_fields', $field_data, $field, $option, $this );
639
640
	}
641
642
	/**
643
	 * Return row array for an item
644
	 *
645
	 * @return array|false
646
	 *
647
	 * @since 2.0
648
	 */
649
	public function row() {
650
651
		do_action( 'pods_pods_row', $this );
652
653
		if ( ! is_array( $this->row ) ) {
654
			return false;
655
		}
656
657
		return (array) $this->row;
658
	}
659
660
	/**
661
	 * Return the output for a field. If you want the raw value for use in PHP for custom manipulation,
662
	 * you will want to use field() instead. This function will automatically convert arrays into a
663
	 * list of text such as "Rick, John, and Gary"
664
	 *
665
	 * @param string|array|object  $name   The field name, or an associative array of parameters.
666
	 * @param boolean|array|object $single (optional) For tableless fields, to return an array or the first.
667
	 *
668
	 * @return string|null|false The output from the field, null if the field doesn't exist, false if no value returned
669
	 *                           for tableless fields
670
	 * @since 2.0
671
	 * @link  https://pods.io/docs/display/
672
	 */
673
	public function display( $name, $single = null ) {
674
675
		$defaults = array(
676
			'name'          => $name,
677
			'single'        => $single,
678
			'display'       => true,
679
			'serial_params' => null,
680
		);
681
682 View Code Duplication
		if ( is_array( $name ) || is_object( $name ) ) {
683
			$defaults['name'] = null;
684
685
			$params = (object) array_merge( $defaults, (array) $name );
686
		} elseif ( is_array( $single ) || is_object( $single ) ) {
687
			$defaults['single'] = null;
688
689
			$params = (object) array_merge( $defaults, (array) $single );
690
		} else {
691
			$params = $defaults;
692
		}
693
694
		$params = (object) $params;
695
696
		$value = $this->field( $params );
697
698
		if ( is_array( $value ) ) {
699
			$fields = $this->fields;
700
701
			if ( isset( $this->pod_data['object_fields'] ) ) {
702
				$fields = array_merge( $fields, $this->pod_data['object_fields'] );
703
			}
704
705
			$serial_params = array(
706
				'field'  => $params->name,
707
				'fields' => $fields,
708
			);
709
710
			if ( ! empty( $params->serial_params ) && is_array( $params->serial_params ) ) {
711
				$serial_params = array_merge( $serial_params, $params->serial_params );
712
			}
713
714
			$value = pods_serial_comma( $value, $serial_params );
715
		}
716
717
		return $value;
718
	}
719
720
	/**
721
	 * Return the raw output for a field If you want the raw value for use in PHP for custom manipulation,
722
	 * you will want to use field() instead. This function will automatically convert arrays into a
723
	 * list of text such as "Rick, John, and Gary"
724
	 *
725
	 * @param string|array|object  $name   The field name, or an associative array of parameters.
726
	 * @param boolean|array|object $single (optional) For tableless fields, to return an array or the first.
727
	 *
728
	 * @return string|null|false The output from the field, null if the field doesn't exist, false if no value returned
729
	 *                           for tableless fields
730
	 * @since 2.0
731
	 * @link  https://pods.io/docs/display/
732
	 */
733
	public function raw( $name, $single = null ) {
734
735
		$defaults = array(
736
			'name'   => $name,
737
			'single' => $single,
738
			'raw'    => true,
739
		);
740
741 View Code Duplication
		if ( is_array( $name ) || is_object( $name ) ) {
742
			$defaults['name'] = null;
743
744
			$params = (object) array_merge( $defaults, (array) $name );
745
		} elseif ( is_array( $single ) || is_object( $single ) ) {
746
			$defaults['single'] = null;
747
748
			$params = (object) array_merge( $defaults, (array) $single );
749
		} else {
750
			$params = (object) $defaults;
751
		}
752
753
		return $this->field( $params );
754
	}
755
756
	/**
757
	 * Return the value for a field.
758
	 *
759
	 * If you are getting a field for output in a theme, most of the time you will want to use display() instead.
760
	 *
761
	 * This function will return arrays for relationship and file fields.
762
	 *
763
	 * @param string|array|object  $name   The field name, or an associative array of parameters.
764
	 * @param boolean|array|object $single For tableless fields, to return the whole array or the just the first item,
765
	 *                                     or an associative array of parameters.
766
	 * @param boolean|array|object $raw    Whether to return the raw value, or to run through the field type's display
767
	 *                                     method, or an associative array of parameters.
768
	 *
769
	 * @return mixed|null Value returned depends on the field type, null if the field doesn't exist, false if no value
770
	 *                    returned for tableless fields.
771
	 * @since 2.0
772
	 * @link  https://pods.io/docs/field/
773
	 */
774
	public function field( $name, $single = null, $raw = false ) {
775
776
		$defaults = array(
777
			'name'        => $name,
778
			'orderby'     => null,
779
			'single'      => $single,
780
			'params'      => null,
781
			'in_form'     => false,
782
			'raw'         => $raw,
783
			'raw_display' => false,
784
			'display'     => false,
785
			'get_meta'    => false,
786
			'output'      => null,
787
			'deprecated'  => false,
788
			// extra data to send to field handlers.
789
			'args'        => array(),
790
		);
791
792
		$is_name_object   = is_object( $name );
793
		$is_single_object = is_object( $single );
794
		$is_raw_object    = is_object( $raw );
795
796
		if ( is_array( $name ) || $is_name_object ) {
797
			if ( $is_name_object ) {
798
				$name = get_object_vars( $name );
799
			}
800
801
			$defaults['name'] = null;
802
803
			$params = (object) array_merge( $defaults, (array) $name );
804
		} elseif ( is_array( $single ) || $is_single_object ) {
805
			if ( $is_single_object ) {
806
				$single = get_object_vars( $single );
807
			}
808
809
			$defaults['single'] = null;
810
811
			$params = (object) array_merge( $defaults, (array) $single );
812
		} elseif ( is_array( $raw ) || $is_raw_object ) {
813
			if ( $is_raw_object ) {
814
				$raw = get_object_vars( $raw );
815
			}
816
817
			$defaults['raw'] = false;
818
819
			$params = (object) array_merge( $defaults, (array) $raw );
820
		} else {
821
			$params = (object) $defaults;
822
		}//end if
823
824
		if ( $params->in_form ) {
825
			$params->output = 'ids';
826
		} elseif ( null === $params->output ) {
827
			/**
828
			 * Override the way related fields are output
829
			 *
830
			 * @param string       $output How to output related fields. Default is 'arrays'. Options: ids|names|objects|arrays|pods|find
831
			 * @param array|object $row    Current row being outputted.
832
			 * @param array        $params Params array passed to field().
833
			 * @param Pods         $this   Current Pods object.
834
			 */
835
			$params->output = apply_filters( 'pods_pods_field_related_output_type', 'arrays', $this->row, $params, $this );
836
		}
837
838
		if ( in_array( $params->output, array( 'id', 'name', 'object', 'array', 'pod' ), true ) ) {
839
			$params->output .= 's';
840
		}
841
842
		// Support old $orderby variable.
843
		if ( null !== $params->single && is_string( $params->single ) && empty( $params->orderby ) ) {
844
			if ( ! class_exists( 'Pod' ) || Pod::$deprecated_notice ) {
845
				pods_deprecated( 'Pods::field', '2.0', 'Use $params[ \'orderby\' ] instead' );
846
			}
847
848
			$params->orderby = $params->single;
849
			$params->single  = false;
850
		}
851
852
		if ( null !== $params->single ) {
853
			$params->single = (boolean) $params->single;
854
		}
855
856
		$params->name = trim( $params->name );
857
		if ( is_array( $params->name ) || '' === $params->name ) {
858
			return null;
859
		}
860
861
		$params->full_name = $params->name;
862
863
		$value = null;
864
865
		if ( isset( $this->row_override[ $params->name ] ) ) {
866
			$value = $this->row_override[ $params->name ];
867
		}
868
869
		if ( false === $this->row() ) {
870
			if ( false !== $this->data() ) {
871
				$this->fetch();
872
			} else {
873
				return $value;
874
			}
875
		}
876
877
		if ( $this->data->field_id === $params->name ) {
878 View Code Duplication
			if ( isset( $this->row[ $params->name ] ) ) {
879
				return $this->row[ $params->name ];
880
				// @codingStandardsIgnoreLine.
881
			} elseif ( null !== $value ) {
882
				return $value;
883
			}
884
885
			return 0;
886
		}
887
888
		$tableless_field_types    = PodsForm::tableless_field_types();
889
		$simple_tableless_objects = PodsForm::simple_tableless_objects();
890
891
		$params->traverse = array();
892
893
		if ( in_array( $params->name, array(
894
			'_link',
895
			'detail_url',
896
		), true ) || ( in_array( $params->name, array(
897
			'permalink',
898
			'the_permalink',
899
		), true ) && in_array( $this->pod_data['type'], array(
900
			'post_type',
901
			'taxonomy',
902
			'media',
903
			'user',
904
			'comment',
905
		), true ) ) ) {
906
			if ( 0 < strlen( $this->detail_page ) ) {
907
				$value = get_home_url() . '/' . $this->do_magic_tags( $this->detail_page );
908
			} elseif ( in_array( $this->pod_data['type'], array( 'post_type', 'media' ), true ) ) {
909
				$value = get_permalink( $this->id() );
910
			} elseif ( 'taxonomy' === $this->pod_data['type'] ) {
911
				$value = get_term_link( $this->id(), $this->pod_data['name'] );
912
			} elseif ( 'user' === $this->pod_data['type'] ) {
913
				$value = get_author_posts_url( $this->id() );
914
			} elseif ( 'comment' === $this->pod_data['type'] ) {
915
				$value = get_comment_link( $this->id() );
916
			}
917
		}
918
919
		$field_data      = false;
920
		$last_field_data = false;
921
		$field_type      = false;
922
923
		$first_field = explode( '.', $params->name );
924
		$first_field = $first_field[0];
925
926
		if ( isset( $this->fields[ $first_field ] ) ) {
927
			$field_data = $this->fields[ $first_field ];
928
			$field_type = 'field';
929
		} elseif ( ! empty( $this->pod_data['object_fields'] ) ) {
930
			if ( isset( $this->pod_data['object_fields'][ $first_field ] ) ) {
931
				$field_data = $this->pod_data['object_fields'][ $first_field ];
932
				$field_type = 'object_field';
933
			} else {
934
				$object_fields = (array) $this->pod_data['object_fields'];
935
936
				foreach ( $object_fields as $object_field => $object_field_opt ) {
937
					if ( in_array( $first_field, $object_field_opt['alias'], true ) ) {
938
						if ( $first_field === $params->name ) {
939
							$params->name = $object_field;
940
						}
941
942
						$first_field = $object_field;
943
						$field_data  = $object_field_opt;
944
						$field_type  = 'object_field';
945
946
						break;
947
					}
948
				}
949
			}
950
		}//end if
951
952
		// Simple fields have no other output options.
953
		if ( 'pick' === $field_data['type'] && in_array( $field_data['pick_object'], $simple_tableless_objects, true ) ) {
954
			$params->output = 'arrays';
955
		}
956
957
		if ( empty( $value ) && in_array( $field_data['type'], $tableless_field_types, true ) ) {
958
			$params->raw = true;
959
960
			$value = false;
961
962
			$row_key = sprintf( '_%s_%s', $params->output, $params->name );
963
964
			if ( 'arrays' !== $params->output && isset( $this->row[ $row_key ] ) ) {
965
				$value = $this->row[ '_' . $params->output . '_' . $params->name ];
966
			} elseif ( 'arrays' === $params->output && isset( $this->row[ $params->name ] ) ) {
967
				$value = $this->row[ $params->name ];
968
			}
969
970
			if ( false !== $value && ! is_array( $value ) && 'pick' === $field_data['type'] && in_array( $field_data['pick_object'], $simple_tableless_objects, true ) ) {
971
				$value = PodsForm::field_method( 'pick', 'simple_value', $params->name, $value, $field_data, $this->pod_data, $this->id(), true );
972
			}
973
		}
974
975
		if ( empty( $value ) && isset( $this->row[ $params->name ] ) && ( ! in_array( $field_data['type'], $tableless_field_types, true ) || 'arrays' === $params->output ) ) {
976
			if ( empty( $field_data ) || in_array( $field_data['type'], array(
977
				'boolean',
978
				'number',
979
				'currency',
980
			), true ) ) {
981
				$params->raw = true;
982
			}
983
984
			if ( null === $params->single ) {
985
				if ( isset( $this->fields[ $params->name ] ) && ! in_array( $this->fields[ $params->name ]['type'], $tableless_field_types, true ) ) {
986
					$params->single = true;
987
				} else {
988
					$params->single = false;
989
				}
990
			}
991
992
			$value = $this->row[ $params->name ];
993
		} elseif ( empty( $value ) ) {
994
			$object_field_found = false;
995
996
			if ( 'object_field' === $field_type ) {
997
				$object_field_found = true;
998
999
				if ( isset( $this->row[ $first_field ] ) ) {
1000
					$value = $this->row[ $first_field ];
1001
				} elseif ( in_array( $field_data['type'], $tableless_field_types, true ) ) {
1002
					$this->fields[ $first_field ] = $field_data;
1003
1004
					$object_field_found = false;
1005
				} else {
1006
					return null;
1007
				}
1008
			}
1009
1010
			if ( 'post_type' === $this->pod_data['type'] && ! isset( $this->fields[ $params->name ] ) ) {
1011
				if ( ! isset( $this->fields['post_thumbnail'] ) && ( 'post_thumbnail' === $params->name || 0 === strpos( $params->name, 'post_thumbnail.' ) ) ) {
1012
					$size = 'thumbnail';
1013
1014 View Code Duplication
					if ( 0 === strpos( $params->name, 'post_thumbnail.' ) ) {
1015
						$field_names = explode( '.', $params->name );
1016
1017
						if ( isset( $field_names[1] ) ) {
1018
							$size = $field_names[1];
1019
						}
1020
					}
1021
1022
					// Pods will auto-get the thumbnail ID if this isn't an attachment.
1023
					$value = pods_image( $this->id(), $size, 0, null, true );
1024
1025
					$object_field_found = true;
1026
				} elseif ( ! isset( $this->fields['post_thumbnail_url'] ) && ( 'post_thumbnail_url' === $params->name || 0 === strpos( $params->name, 'post_thumbnail_url.' ) ) ) {
1027
					$size = 'thumbnail';
1028
1029 View Code Duplication
					if ( 0 === strpos( $params->name, 'post_thumbnail_url.' ) ) {
1030
						$field_names = explode( '.', $params->name );
1031
1032
						if ( isset( $field_names[1] ) ) {
1033
							$size = $field_names[1];
1034
						}
1035
					}
1036
1037
					// Pods will auto-get the thumbnail ID if this isn't an attachment.
1038
					$value = pods_image_url( $this->id(), $size, 0, true );
1039
1040
					$object_field_found = true;
1041 View Code Duplication
				} elseif ( 0 === strpos( $params->name, 'image_attachment.' ) ) {
1042
					$size = 'thumbnail';
1043
1044
					$image_id = 0;
1045
1046
					$field_names = explode( '.', $params->name );
1047
1048
					if ( isset( $field_names[1] ) ) {
1049
						$image_id = $field_names[1];
1050
					}
1051
1052
					if ( isset( $field_names[2] ) ) {
1053
						$size = $field_names[2];
1054
					}
1055
1056
					if ( ! empty( $image_id ) ) {
1057
						$value = pods_image( $image_id, $size, 0, null, true );
1058
1059
						if ( ! empty( $value ) ) {
1060
							$object_field_found = true;
1061
						}
1062
					}
1063
				} elseif ( 0 === strpos( $params->name, 'image_attachment_url.' ) ) {
1064
					$size = 'thumbnail';
1065
1066
					$image_id = 0;
1067
1068
					$field_names = explode( '.', $params->name );
1069
1070
					if ( isset( $field_names[1] ) ) {
1071
						$image_id = $field_names[1];
1072
					}
1073
1074
					if ( isset( $field_names[2] ) ) {
1075
						$size = $field_names[2];
1076
					}
1077
1078
					if ( ! empty( $image_id ) ) {
1079
						$value = pods_image_url( $image_id, $size, 0, true );
1080
1081
						if ( ! empty( $value ) ) {
1082
							$object_field_found = true;
1083
						}
1084
					}
1085
				}//end if
1086
			} elseif ( 'user' === $this->pod_data['type'] && ! isset( $this->fields[ $params->name ] ) ) {
1087
				if ( ! isset( $this->fields['avatar'] ) && ( 'avatar' === $params->name || 0 === strpos( $params->name, 'avatar.' ) ) ) {
1088
					$size = null;
1089
1090 View Code Duplication
					if ( 0 === strpos( $params->name, 'avatar.' ) ) {
1091
						$field_names = explode( '.', $params->name );
1092
1093
						if ( isset( $field_names[1] ) ) {
1094
							$size = (int) $field_names[1];
1095
						}
1096
					}
1097
1098
					if ( 0 < $size ) {
1099
						$value = get_avatar( $this->id(), $size );
1100
					} else {
1101
						$value = get_avatar( $this->id() );
1102
					}
1103
1104
					$object_field_found = true;
1105
				}
1106 View Code Duplication
			} elseif ( 0 === strpos( $params->name, 'image_attachment.' ) ) {
1107
				$size = 'thumbnail';
1108
1109
				$image_id = 0;
1110
1111
				$field_names = explode( '.', $params->name );
1112
1113
				if ( isset( $field_names[1] ) ) {
1114
					$image_id = $field_names[1];
1115
				}
1116
1117
				if ( isset( $field_names[2] ) ) {
1118
					$size = $field_names[2];
1119
				}
1120
1121
				if ( ! empty( $image_id ) ) {
1122
					$value = pods_image( $image_id, $size, 0, null, true );
1123
1124
					if ( ! empty( $value ) ) {
1125
						$object_field_found = true;
1126
					}
1127
				}
1128
			} elseif ( 0 === strpos( $params->name, 'image_attachment_url.' ) ) {
1129
				$size = 'thumbnail';
1130
1131
				$image_id = 0;
1132
1133
				$field_names = explode( '.', $params->name );
1134
1135
				if ( isset( $field_names[1] ) ) {
1136
					$image_id = $field_names[1];
1137
				}
1138
1139
				if ( isset( $field_names[2] ) ) {
1140
					$size = $field_names[2];
1141
				}
1142
1143
				if ( ! empty( $image_id ) ) {
1144
					$value = pods_image_url( $image_id, $size, 0, true );
1145
1146
					if ( ! empty( $value ) ) {
1147
						$object_field_found = true;
1148
					}
1149
				}
1150
			}//end if
1151
1152
			if ( false === $object_field_found ) {
1153
				$params->traverse = array( $params->name );
1154
1155
				if ( false !== strpos( $params->name, '.' ) ) {
1156
					$params->traverse = explode( '.', $params->name );
1157
1158
					$params->name = $params->traverse[0];
1159
				}
1160
1161
				if ( isset( $this->fields[ $params->name ], $this->fields[ $params->name ]['type'] ) ) {
1162
					/**
1163
					 * Modify value returned by field() after its retrieved, but before its validated or formatted
1164
					 *
1165
					 * Filter name is set dynamically with name of field: "pods_pods_field_{field_name}"
1166
					 *
1167
					 * @since unknown
1168
					 *
1169
					 * @param array|string|null $value  Value retrieved.
1170
					 * @param array|object      $row    Current row being outputted.
1171
					 * @param array             $params Params array passed to field().
1172
					 * @param object|Pods       $this   Current Pods object.
1173
					 */
1174
					$v = apply_filters( 'pods_pods_field_' . $this->fields[ $params->name ]['type'], null, $this->fields[ $params->name ], $this->row, $params, $this );
1175
1176
					if ( null !== $v ) {
1177
						return $v;
1178
					}
1179
				}
1180
1181
				$simple = false;
1182
1183
				if ( isset( $this->fields[ $params->name ] ) ) {
1184
					if ( 'meta' === $this->pod_data['storage'] && ! in_array( $this->fields[ $params->name ]['type'], $tableless_field_types, true ) ) {
1185
						$simple = true;
1186
					}
1187
1188
					if ( in_array( $this->fields[ $params->name ]['type'], $tableless_field_types, true ) ) {
1189
						$params->raw = true;
1190
1191
						if ( 'pick' === $this->fields[ $params->name ]['type'] && in_array( $this->fields[ $params->name ]['pick_object'], $simple_tableless_objects, true ) ) {
1192
							$simple         = true;
1193
							$params->single = true;
1194
						}
1195
					} elseif ( in_array( $this->fields[ $params->name ]['type'], array(
1196
						'boolean',
1197
						'number',
1198
						'currency',
1199
					), true ) ) {
1200
						$params->raw = true;
1201
					}
1202
				}
1203
1204
				$is_field_set       = isset( $this->fields[ $params->name ] );
1205
				$is_tableless_field = in_array( $this->fields[ $params->name ]['type'], $tableless_field_types, true );
1206
1207
				if ( $simple || ! $is_field_set || ! $is_tableless_field ) {
1208
					if ( null === $params->single ) {
1209
						if ( $is_field_set && $is_tableless_field ) {
1210
							$params->single = true;
1211
						} else {
1212
							$params->single = false;
1213
						}
1214
					}
1215
1216
					$no_conflict = pods_no_conflict_check( $this->pod_data['type'] );
1217
1218
					if ( ! $no_conflict ) {
1219
						pods_no_conflict_on( $this->pod_data['type'] );
1220
					}
1221
1222
					if ( in_array( $this->pod_data['type'], array(
1223
						'post_type',
1224
						'media',
1225
						'taxonomy',
1226
						'user',
1227
						'comment',
1228
					), true ) ) {
1229
						$id = $this->id();
1230
1231
						$metadata_type = $this->pod_data['type'];
1232
1233
						if ( in_array( $this->pod_data['type'], array( 'post_type', 'media' ), true ) ) {
1234
							$metadata_type = 'post';
1235
1236
							// Support for WPML 'duplicated' translation handling.
1237 View Code Duplication
							if ( did_action( 'wpml_loaded' ) && apply_filters( 'wpml_is_translated_post_type', false, $this->pod_data['name'] ) ) {
1238
								$master_post_id = (int) apply_filters( 'wpml_master_post_from_duplicate', $id );
1239
1240
								if ( 0 < $master_post_id ) {
1241
									$id = $master_post_id;
1242
								}
1243
							}
1244
						} elseif ( 'taxonomy' === $this->pod_data['type'] ) {
1245
							$metadata_type = 'term';
1246
						}
1247
1248
						$value = get_metadata( $metadata_type, $id, $params->name, $params->single );
1249
1250
						$single_multi = 'single';
1251
1252
						if ( isset( $this->fields[ $params->name ] ) ) {
1253
							$single_multi = pods_v( $this->fields[ $params->name ]['type'] . '_format_type', $this->fields[ $params->name ]['options'], 'single' );
1254
						}
1255
1256
						if ( $simple && ! is_array( $value ) && 'single' !== $single_multi ) {
1257
							$value = get_metadata( $metadata_type, $id, $params->name );
1258
						}
1259
					} elseif ( 'settings' === $this->pod_data['type'] ) {
1260
						$value = get_option( $this->pod_data['name'] . '_' . $params->name, null );
1261
					}//end if
1262
1263
					// Handle Simple Relationships.
1264
					if ( $simple ) {
1265
						if ( null === $params->single ) {
1266
							$params->single = false;
1267
						}
1268
1269
						$value = PodsForm::field_method( 'pick', 'simple_value', $params->name, $value, $this->fields[ $params->name ], $this->pod_data, $this->id(), true );
1270
					}
1271
1272
					if ( ! $no_conflict ) {
1273
						pods_no_conflict_off( $this->pod_data['type'] );
1274
					}
1275
				} else {
1276
					// Dot-traversal.
1277
					$pod        = $this->pod;
1278
					$ids        = array( $this->id() );
1279
					$all_fields = array();
1280
1281
					$lookup = $params->traverse;
1282
1283
					// Get fields matching traversal names.
1284
					if ( ! empty( $lookup ) ) {
1285
						$fields = $this->api->load_fields( array(
1286
							'name'          => $lookup,
1287
							'type'          => $tableless_field_types,
1288
							'object_fields' => true,
1289
							// @todo support object fields too.
1290
						) );
1291
1292
						if ( ! empty( $fields ) ) {
1293
							foreach ( $fields as $field ) {
1294
								if ( ! empty( $field ) ) {
1295
									if ( ! isset( $all_fields[ $field['pod'] ] ) ) {
1296
										$all_fields[ $field['pod'] ] = array();
1297
									}
1298
1299
									$all_fields[ $field['pod'] ][ $field['name'] ] = $field;
1300
								}
1301
							}
1302
						}
1303
1304
						if ( ! empty( $this->pod_data['object_fields'] ) ) {
1305
							$object_fields = (array) $this->pod_data['object_fields'];
1306
1307
							foreach ( $object_fields as $object_field => $object_field_opt ) {
1308
								if ( in_array( $object_field_opt['type'], $tableless_field_types, true ) ) {
1309
									$all_fields[ $this->pod ][ $object_field ] = $object_field_opt;
1310
								}
1311
							}
1312
						}
1313
					}//end if
1314
1315
					$last_type     = '';
1316
					$last_object   = '';
1317
					$last_pick_val = '';
1318
1319
					$single_multi = pods_v( $this->fields[ $params->name ]['type'] . '_format_type', $this->fields[ $params->name ]['options'], 'single' );
1320
1321
					if ( 'multi' === $single_multi ) {
1322
						$limit = (int) pods_v( $this->fields[ $params->name ]['type'] . '_limit', $this->fields[ $params->name ]['options'], 0 );
1323
					} else {
1324
						$limit = 1;
1325
					}
1326
1327
					// Loop through each traversal level.
1328
					foreach ( $params->traverse as $key => $field ) {
1329
						$last_loop = false;
1330
1331
						if ( count( $params->traverse ) <= ( $key + 1 ) ) {
1332
							$last_loop = true;
1333
						}
1334
1335
						$field_exists = isset( $all_fields[ $pod ][ $field ] );
1336
1337
						$simple       = false;
1338
						$last_options = array();
1339
1340
						if ( $field_exists && 'pick' === $all_fields[ $pod ][ $field ]['type'] && in_array( $all_fields[ $pod ][ $field ]['pick_object'], $simple_tableless_objects, true ) ) {
1341
							$simple       = true;
1342
							$last_options = $all_fields[ $pod ][ $field ];
1343
						}
1344
1345
						// Tableless handler.
1346
						if ( $field_exists && ( ! $simple || ! in_array( $all_fields[ $pod ][ $field ]['type'], array(
1347
							'pick',
1348
							'taxonomy',
1349
							'comment',
1350
						), true ) ) ) {
1351
							$type        = $all_fields[ $pod ][ $field ]['type'];
1352
							$pick_object = $all_fields[ $pod ][ $field ]['pick_object'];
1353
							$pick_val    = $all_fields[ $pod ][ $field ]['pick_val'];
1354
1355
							if ( 'table' === $pick_object ) {
1356
								$pick_val = pods_v( 'pick_table', $all_fields[ $pod ][ $field ]['options'], $pick_val, true );
1357
							} elseif ( '__current__' === $pick_val ) {
1358
								$pick_val = $pod;
1359
							}
1360
1361
							$last_limit = 0;
1362
1363
							if ( in_array( $type, $tableless_field_types, true ) ) {
1364
								$single_multi = pods_v( "{$type}_format_type", $all_fields[ $pod ][ $field ]['options'], 'single' );
1365
1366
								if ( 'multi' === $single_multi ) {
1367
									$last_limit = (int) pods_v( "{$type}_limit", $all_fields[ $pod ][ $field ]['options'], 0 );
1368
								} else {
1369
									$last_limit = 1;
1370
								}
1371
							}
1372
1373
							$last_type     = $type;
1374
							$last_object   = $pick_object;
1375
							$last_pick_val = $pick_val;
1376
							$last_options  = $all_fields[ $pod ][ $field ];
1377
1378
							// Temporary hack until there's some better handling here.
1379
							$last_limit *= count( $ids );
1380
1381
							// Get related IDs.
1382
							if ( ! isset( $all_fields[ $pod ][ $field ]['pod_id'] ) ) {
1383
								$all_fields[ $pod ][ $field ]['pod_id'] = 0;
1384
							}
1385
1386
							if ( isset( $all_fields[ $pod ][ $field ]['id'] ) ) {
1387
								$ids = $this->api->lookup_related_items( $all_fields[ $pod ][ $field ]['id'], $all_fields[ $pod ][ $field ]['pod_id'], $ids, $all_fields[ $pod ][ $field ] );
1388
							}
1389
1390
							// No items found.
1391
							if ( empty( $ids ) ) {
1392
								return false;
1393
							} elseif ( 0 < $last_limit ) {
1394
								// @todo This should return array() if not $params->single.
1395
								$ids = array_slice( $ids, 0, $last_limit );
1396
							}
1397
1398
							// Get $pod if related to a Pod.
1399
							if ( ! empty( $pick_object ) && ( ! empty( $pick_val ) || in_array( $pick_object, array(
1400
								'user',
1401
								'media',
1402
								'comment',
1403
							), true ) ) ) {
1404
								if ( 'pod' === $pick_object ) {
1405
									$pod = $pick_val;
1406
								} else {
1407
									$check = $this->api->get_table_info( $pick_object, $pick_val );
1408
1409
									if ( ! empty( $check ) && ! empty( $check['pod'] ) ) {
1410
										$pod = $check['pod']['name'];
1411
									}
1412
								}
1413
							}
1414
						} else {
1415
							// Assume last iteration.
1416
							if ( 0 === $key ) {
1417
								// Invalid field.
1418
								return false;
1419
							}
1420
1421
							$last_loop = true;
1422
						}//end if
1423
1424
						if ( $last_loop ) {
1425
							$object_type = $last_object;
1426
							$object      = $last_pick_val;
1427
1428
							if ( in_array( $last_type, PodsForm::file_field_types(), true ) ) {
1429
								$object_type = 'media';
1430
								$object      = 'attachment';
1431
							}
1432
1433
							$data = array();
1434
1435
							$table = $this->api->get_table_info( $object_type, $object, null, null, $last_options );
1436
1437
							$join  = array();
1438
							$where = array();
1439
1440
							if ( ! empty( $table['join'] ) ) {
1441
								$join = (array) $table['join'];
1442
							}
1443
1444
							if ( ! empty( $ids ) || ! empty( $table['where'] ) ) {
1445
								foreach ( $ids as $id ) {
1446
									$where[ $id ] = '`t`.`' . $table['field_id'] . '` = ' . (int) $id;
1447
								}
1448
1449
								if ( ! empty( $where ) ) {
1450
									$where = array( implode( ' OR ', $where ) );
1451
								}
1452
1453
								if ( ! empty( $table['where'] ) ) {
1454
									// @codingStandardsIgnoreLine.
1455
									$where = array_merge( $where, array_values( (array) $table['where'] ) );
1456
								}
1457
							}
1458
1459
							/**
1460
							 * Related object.
1461
							 *
1462
							 * @var $related_obj Pods|false
1463
							 */
1464
							$related_obj = false;
1465
1466
							// Check if we can return the full object/array or if we need to traverse into it.
1467
							$is_field_output_full = false;
1468
1469
							if ( false !== $field_exists && ( in_array( $last_type, $tableless_field_types, true ) && ! $simple ) ) {
1470
								$is_field_output_full = true;
1471
							}
1472
1473
							if ( 'pod' === $object_type ) {
1474
								$related_obj = pods( $object, null, false );
1475
							} elseif ( ! empty( $table['pod'] ) ) {
1476
								$related_obj = pods( $table['pod']['name'], null, false );
1477
							}
1478
1479
							if ( $related_obj || ! empty( $table['table'] ) ) {
1480
								$sql = array(
1481
									'select'     => '*, `t`.`' . $table['field_id'] . '` AS `pod_item_id`',
1482
									'table'      => $table['table'],
1483
									'join'       => $join,
1484
									'where'      => $where,
1485
									'orderby'    => $params->orderby,
1486
									'pagination' => false,
1487
									'search'     => false,
1488
									'limit'      => - 1,
1489
									'expires'    => 180,
1490
									// @todo This could potentially cause issues if someone changes the data within this time and persistent storage is used.
1491
								);
1492
1493
								if ( ! empty( $table['where_default'] ) ) {
1494
									$sql['where_default'] = $table['where_default'];
1495
								}
1496
1497
								// Output types.
1498
								if ( in_array( $params->output, array( 'ids', 'objects', 'pods' ), true ) ) {
1499
									$sql['select'] = '`t`.`' . $table['field_id'] . '` AS `pod_item_id`';
1500 View Code Duplication
								} elseif ( 'names' === $params->output && ! empty( $table['field_index'] ) ) {
1501
									$sql['select'] = '`t`.`' . $table['field_index'] . '` AS `pod_item_index`, `t`.`' . $table['field_id'] . '` AS `pod_item_id`';
1502
								}
1503
1504
								if ( ! empty( $params->params ) && is_array( $params->params ) ) {
1505
									$where = $sql['where'];
1506
1507
									// @codingStandardsIgnoreLine.
1508
									$sql = array_merge( $sql, $params->params );
1509
1510
									if ( isset( $params->params['where'] ) ) {
1511
										// @codingStandardsIgnoreLine.
1512
										$sql['where'] = array_merge( (array) $where, (array) $params->params['where'] );
1513
									}
1514
								}
1515
1516
								$item_data = array();
1517
1518
								if ( ! $related_obj ) {
1519
									if ( ! is_object( $this->alt_data ) ) {
1520
										$this->alt_data = pods_data( null, 0, true, true );
1521
									}
1522
1523
									$item_data = $this->alt_data->select( $sql );
1524
								} else {
1525
									// Support 'find' output ordering.
1526
									if ( $ids && 'find' === $params->output && $is_field_output_full && empty( $sql['orderby'] ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $ids of type integer[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1527
										// Handle default orderby for ordering by the IDs.
1528
										$order_ids = implode( ', ', array_map( 'absint', $ids ) );
1529
1530
										$sql['orderby'] = 'FIELD( `t`.`' . $table['field_id'] . '`, ' . $order_ids . ' )';
1531
									}
1532
1533
									$related_obj->find( $sql );
1534
1535
									// Support 'find' output.
1536
									if ( 'find' === $params->output && $is_field_output_full ) {
1537
										$data = $related_obj;
1538
1539
										$is_field_output_full = true;
1540
									} else {
1541
										$item_data = $related_obj->data();
1542
									}
1543
								}//end if
1544
1545
								$items = array();
1546
1547
								if ( ! empty( $item_data ) ) {
1548
									foreach ( $item_data as $item ) {
1549
										if ( is_array( $item ) ) {
1550
											$item = (object) $item;
1551
										}
1552
1553
										if ( empty( $item->pod_item_id ) ) {
1554
											continue;
1555
										}
1556
1557
										// Bypass pass field.
1558
										if ( isset( $item->user_pass ) ) {
1559
											unset( $item->user_pass );
1560
										}
1561
1562
										// Get Item ID.
1563
										$item_id = $item->pod_item_id;
1564
1565
										// Output types.
1566
										if ( 'ids' === $params->output ) {
1567
											$item = (int) $item_id;
1568
										} elseif ( 'names' === $params->output && ! empty( $table['field_index'] ) ) {
1569
											$item = $item->pod_item_index;
1570
										} elseif ( 'objects' === $params->output ) {
1571
											if ( in_array( $object_type, array( 'post_type', 'media' ), true ) ) {
1572
												$item = get_post( $item_id );
1573
											} elseif ( 'taxonomy' === $object_type ) {
1574
												$item = get_term( $item_id, $object );
1575
											} elseif ( 'user' === $object_type ) {
1576
												$item = get_userdata( $item_id );
1577
1578
												if ( ! empty( $item ) ) {
1579
													// Get other vars.
1580
													$roles   = $item->roles;
1581
													$caps    = $item->caps;
1582
													$allcaps = $item->allcaps;
1583
1584
													$item = $item->data;
1585
1586
													// Set other vars.
1587
													$item->roles   = $roles;
1588
													$item->caps    = $caps;
1589
													$item->allcaps = $allcaps;
1590
1591
													unset( $item->user_pass );
1592
												}
1593
											} elseif ( 'comment' === $object_type ) {
1594
												$item = get_comment( $item_id );
1595
											} else {
1596
												$item = (object) $item;
1597
											}//end if
1598
										} elseif ( 'pods' === $params->output ) {
1599
											if ( in_array( $object_type, array( 'user', 'media' ), true ) ) {
1600
												$item = pods( $object_type, (int) $item_id );
1601
											} else {
1602
												$item = pods( $object, (int) $item_id );
1603
											}
1604
										} else {
1605
											// arrays.
1606
											$item = get_object_vars( (object) $item );
1607
										}//end if
1608
1609
										// Pass item data into $data.
1610
										$items[ $item_id ] = $item;
1611
									}//end foreach
1612
1613
									// Cleanup.
1614
									unset( $item_data );
1615
1616
									// Return all of the data in the order expected.
1617
									if ( empty( $params->orderby ) ) {
1618
										foreach ( $ids as $id ) {
1619
											if ( isset( $items[ $id ] ) ) {
1620
												$data[ $id ] = $items[ $id ];
1621
											}
1622
										}
1623
									} else {
1624
										// Use order set by orderby.
1625
										foreach ( $items as $id => $v ) {
1626
											// @codingStandardsIgnoreLine.
1627
											if ( in_array( $id, $ids ) ) {
1628
												$data[ $id ] = $v;
1629
											}
1630
										}
1631
									}
1632
								}//end if
1633
							}//end if
1634
1635
							if ( in_array( $last_type, $tableless_field_types, true ) || in_array( $last_type, array(
1636
								'boolean',
1637
								'number',
1638
								'currency',
1639
							), true ) ) {
1640
								$params->raw = true;
1641
							}
1642
1643
							if ( empty( $data ) ) {
1644
								$value = false;
1645
							} else {
1646
								$object_type = $table['type'];
1647
1648
								if ( in_array( $table['type'], array( 'post_type', 'attachment', 'media' ), true ) ) {
1649
									$object_type = 'post';
1650
								}
1651
1652
								$no_conflict = true;
1653
1654 View Code Duplication
								if ( in_array( $object_type, array(
1655
									'post',
1656
									'taxonomy',
1657
									'user',
1658
									'comment',
1659
									'settings',
1660
								), true ) ) {
1661
									$no_conflict = pods_no_conflict_check( $object_type );
1662
1663
									if ( ! $no_conflict ) {
1664
										pods_no_conflict_on( $object_type );
1665
									}
1666
								}
1667
1668
								if ( $is_field_output_full ) {
1669
									// Return entire array.
1670
									$value = $data;
1671
								} else {
1672
									// Return an array of single column values.
1673
									$value = array();
1674
1675
									foreach ( $data as $item_id => $item ) {
1676
										// $field is 123x123, needs to be _src.123x123
1677
										$full_field = implode( '.', array_splice( $params->traverse, $key ) );
1678
1679
										if ( is_array( $item ) && isset( $item[ $field ] ) ) {
1680 View Code Duplication
											if ( $table['field_id'] === $field ) {
1681
												$value[] = (int) $item[ $field ];
1682
											} else {
1683
												$value[] = $item[ $field ];
1684
											}
1685
										} elseif ( is_object( $item ) && isset( $item->{$field} ) ) {
1686 View Code Duplication
											if ( $table['field_id'] === $field ) {
1687
												$value[] = (int) $item->{$field};
1688
											} else {
1689
												$value[] = $item->{$field};
1690
											}
1691
										} elseif ( ( ( false !== strpos( $full_field, '_src' ) || 'guid' === $field ) && ( in_array( $table['type'], array(
1692
											'attachment',
1693
											'media',
1694
										), true ) || in_array( $last_type, PodsForm::file_field_types(), true ) ) ) || ( in_array( $field, array(
1695
											'_link',
1696
											'detail_url',
1697
										), true ) || in_array( $field, array(
1698
											'permalink',
1699
											'the_permalink',
1700
										), true ) && in_array( $last_type, PodsForm::file_field_types(), true ) ) ) {
1701
											// @todo Refactor the above condition statement.
1702
											$size = 'full';
1703
1704
											if ( false === strpos( 'image', get_post_mime_type( $item_id ) ) ) {
1705
												// No default sizes for non-images.
1706
												// When a size is defined this will be overwritten.
1707
												$size = null;
1708
											}
1709
1710
											if ( false !== strpos( $full_field, '_src.' ) && 5 < strlen( $full_field ) ) {
1711
												$size = substr( $full_field, 5 );
1712 View Code Duplication
											} elseif ( false !== strpos( $full_field, '_src_relative.' ) && 14 < strlen( $full_field ) ) {
1713
												$size = substr( $full_field, 14 );
1714
											} elseif ( false !== strpos( $full_field, '_src_schemeless.' ) && 16 < strlen( $full_field ) ) {
1715
												$size = substr( $full_field, 16 );
1716
											}
1717
1718
											if ( $size ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $size of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1719
												$value_url = pods_image_url( $item_id, $size );
1720
											} else {
1721
												$value_url = wp_get_attachment_url( $item_id );
1722
											}
1723
1724
											if ( ! empty( $value_url ) ) {
1725
												if ( false !== strpos( $full_field, '_src_relative' ) ) {
1726
													$value_url_parsed = wp_parse_url( $value_url );
1727
													$value_url        = $value_url_parsed['path'];
1728
												} elseif ( false !== strpos( $full_field, '_src_schemeless' ) ) {
1729
													$value_url = str_replace( array(
1730
														'http://',
1731
														'https://',
1732
													), '//', $value_url );
1733
												}
1734
											}
1735
1736
											if ( ! empty( $value_url ) ) {
1737
												$value[] = $value_url;
1738
											}
1739
1740
											$params->raw_display = true;
1741
										} elseif ( false !== strpos( $full_field, '_img' ) && ( in_array( $table['type'], array(
1742
											'attachment',
1743
											'media',
1744
										), true ) || in_array( $last_type, PodsForm::file_field_types(), true ) ) ) {
1745
											$size = 'full';
1746
1747 View Code Duplication
											if ( false !== strpos( $full_field, '_img.' ) && 5 < strlen( $full_field ) ) {
1748
												$size = substr( $full_field, 5 );
1749
											}
1750
1751
											$value[] = pods_image( $item_id, $size );
1752
1753
											$params->raw_display = true;
1754
										} elseif ( in_array( $field, array(
1755
											'_link',
1756
											'detail_url',
1757
										), true ) || in_array( $field, array( 'permalink', 'the_permalink' ), true ) ) {
1758
											if ( 'pod' === $object_type ) {
1759
												if ( is_object( $related_obj ) ) {
1760
													$related_obj->fetch( $item_id );
1761
1762
													$value[] = $related_obj->field( 'detail_url' );
1763
												} else {
1764
													$value[] = '';
1765
												}
1766
											} elseif ( 'post' === $object_type ) {
1767
												$value[] = get_permalink( $item_id );
1768
											} elseif ( 'taxonomy' === $object_type ) {
1769
												$value[] = get_term_link( $item_id, $object );
1770
											} elseif ( 'user' === $object_type ) {
1771
												$value[] = get_author_posts_url( $item_id );
1772
											} elseif ( 'comment' === $object_type ) {
1773
												$value[] = get_comment_link( $item_id );
1774
											} else {
1775
												$value[] = '';
1776
											}
1777
1778
											$params->raw_display = true;
1779
										} elseif ( in_array( $object_type, array(
1780
											'post',
1781
											'taxonomy',
1782
											'user',
1783
											'comment',
1784
										), true ) ) {
1785
											$metadata_object_id = $item_id;
1786
1787
											$metadata_type = $object_type;
1788
1789
											if ( 'post' === $object_type ) {
1790
												// Support for WPML 'duplicated' translation handling.
1791 View Code Duplication
												if ( did_action( 'wpml_loaded' ) && apply_filters( 'wpml_is_translated_post_type', false, $object ) ) {
1792
													$master_post_id = (int) apply_filters( 'wpml_master_post_from_duplicate', $metadata_object_id );
1793
1794
													if ( 0 < $master_post_id ) {
1795
														$metadata_object_id = $master_post_id;
1796
													}
1797
												}
1798
											} elseif ( 'taxonomy' === $object_type ) {
1799
												$metadata_type = 'term';
1800
											}
1801
1802
											$value[] = get_metadata( $metadata_type, $metadata_object_id, $field, true );
1803
										} elseif ( 'settings' === $object_type ) {
1804
											$value[] = get_option( $object . '_' . $field );
1805
										}//end if
1806
									}//end foreach
1807
								}//end if
1808
1809 View Code Duplication
								if ( ! $no_conflict && in_array( $object_type, array(
1810
									'post',
1811
									'taxonomy',
1812
									'user',
1813
									'comment',
1814
									'settings',
1815
								), true ) ) {
1816
									pods_no_conflict_off( $object_type );
1817
								}
1818
1819
								// Handle Simple Relationships.
1820
								if ( $simple ) {
1821
									if ( null === $params->single ) {
1822
										$params->single = false;
1823
									}
1824
1825
									$value = PodsForm::field_method( 'pick', 'simple_value', $field, $value, $last_options, $all_fields[ $pod ], 0, true );
1826
								} elseif ( false === $params->in_form && ! empty( $value ) && is_array( $value ) ) {
1827
									$value = array_values( $value );
1828
								}
1829
1830
								// Return a single column value.
1831
								if ( false === $params->in_form && 1 === $limit && ! empty( $value ) && is_array( $value ) && 1 === count( $value ) ) {
1832
									$value = current( $value );
1833
								}
1834
							}//end if
1835
1836
							if ( $last_options ) {
1837
								$last_field_data = $last_options;
1838
							}
1839
1840
							break;
1841
						}//end if
1842
					}//end foreach
1843
				}//end if
1844
			}//end if
1845
		}//end if
1846
1847
		if ( ! empty( $params->traverse ) && 1 < count( $params->traverse ) ) {
1848
			$field_names = implode( '.', $params->traverse );
1849
1850
			$this->row[ $field_names ] = $value;
1851
		} elseif ( 'arrays' !== $params->output && in_array( $field_data['type'], $tableless_field_types, true ) ) {
1852
			$this->row[ '_' . $params->output . '_' . $params->full_name ] = $value;
1853
		} elseif ( 'arrays' === $params->output || ! in_array( $field_data['type'], $tableless_field_types, true ) ) {
1854
			$this->row[ $params->full_name ] = $value;
1855
		}
1856
1857
		if ( $params->single && is_array( $value ) && 1 === count( $value ) ) {
1858
			$value = current( $value );
1859
		}
1860
1861
		if ( ! empty( $last_field_data ) ) {
1862
			$field_data = $last_field_data;
1863
		}
1864
1865
		// @todo Expand this into traversed fields too.
1866
		if ( ! empty( $field_data ) && ( $params->display || ! $params->raw ) && ! $params->in_form && ! $params->raw_display ) {
1867
			if ( $params->display || ( ( $params->get_meta || $params->deprecated ) && ! in_array( $field_data['type'], $tableless_field_types, true ) ) ) {
1868
				$field_data['options'] = pods_v( 'options', $field_data, array(), true );
1869
1870
				$post_temp   = false;
1871
				$old_post    = null;
1872
				$old_post_id = null;
1873
1874
				if ( empty( $GLOBALS['post'] ) && 'post_type' === pods_v( 'type', $this->pod_data ) && 0 < $this->id() ) {
1875
					global $post_ID, $post;
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...
1876
1877
					$post_temp = true;
1878
1879
					$old_post    = $post;
1880
					$old_post_id = $post_ID;
1881
1882
					// @codingStandardsIgnoreLine.
1883
					$post    = get_post( $this->id() );
1884
					// @codingStandardsIgnoreLine.
1885
					$post_ID = $this->id();
1886
				}
1887
1888
				$filter = pods_v( 'display_filter', $field_data['options'] );
1889
1890
				if ( 0 < strlen( $filter ) ) {
1891
					$args = array(
1892
						$filter,
1893
						$value,
1894
					);
1895
1896
					$filter_args = pods_v( 'display_filter_args', $field_data['options'] );
1897
1898
					if ( ! empty( $filter_args ) ) {
1899
						$args = array_merge( $args, compact( $filter_args ) );
1900
					}
1901
1902
					$value = call_user_func_array( 'apply_filters', $args );
1903
				} elseif ( 1 === (int) pods_v( 'display_process', $field_data['options'], 1 ) ) {
1904
					$value = PodsForm::display( $field_data['type'], $value, $params->name, array_merge( $field_data, $field_data['options'] ), $this->pod_data, $this->id() );
1905
				}
1906
1907
				if ( $post_temp ) {
1908
					// @codingStandardsIgnoreLine.
1909
					$post    = $old_post;
1910
					// @codingStandardsIgnoreLine.
1911
					$post_ID = $old_post_id;
1912
				}
1913
			} else {
1914
				$value = PodsForm::value( $field_data['type'], $value, $params->name, array_merge( $field_data, $field_data['options'] ), $this->pod_data, $this->id() );
1915
			}//end if
1916
		}//end if
1917
1918
		/**
1919
		 * Modify value returned by field() directly before output.
1920
		 *
1921
		 * Will not run if value was null
1922
		 *
1923
		 * @since unknown
1924
		 *
1925
		 * @param array|string|null $value  Value to be returned.
1926
		 * @param array|object      $row    Current row being outputted.
1927
		 * @param array             $params Params array passed to field().
1928
		 * @param object|Pods       $this   Current Pods object.
1929
		 */
1930
		$value = apply_filters( 'pods_pods_field', $value, $this->row, $params, $this );
1931
1932
		return $value;
1933
	}
1934
1935
	/**
1936
	 * Check if an item field has a specific value in it
1937
	 *
1938
	 * @param string $field Field name.
1939
	 * @param mixed  $value Value to check.
1940
	 * @param int    $id    (optional) ID of the pod item to check.
1941
	 *
1942
	 * @return bool Whether the value was found
1943
	 *
1944
	 * @since 2.3.3
1945
	 */
1946
	public function has( $field, $value, $id = null ) {
1947
1948
		$pod =& $this;
1949
1950 View Code Duplication
		if ( null === $id ) {
1951
			$id = $this->id();
1952
			// @codingStandardsIgnoreLine.
1953
		} elseif ( $id != $this->id() ) {
1954
			$pod = pods( $this->pod, $id );
1955
		}
1956
1957
		$this->do_hook( 'has', $field, $value, $id );
1958
1959
		if ( ! isset( $this->fields[ $field ] ) ) {
1960
			return false;
1961
		}
1962
1963
		// Tableless fields.
1964
		if ( in_array( $this->fields[ $field ]['type'], PodsForm::tableless_field_types(), true ) ) {
1965
			if ( ! is_array( $value ) ) {
1966
				$value = explode( ',', $value );
1967
			}
1968
1969 View Code Duplication
			if ( 'pick' === $this->fields[ $field ]['type'] && in_array( $this->fields[ $field ]['pick_object'], PodsForm::simple_tableless_objects(), true ) ) {
1970
				$current_value = $pod->raw( $field );
1971
1972
				if ( ! empty( $current_value ) ) {
1973
					$current_value = (array) $current_value;
1974
				}
1975
1976
				foreach ( $current_value as $v ) {
1977
					// @codingStandardsIgnoreLine.
1978
					if ( in_array( $v, $value ) ) {
1979
						return true;
1980
					}
1981
				}
1982
			} else {
1983
				$related_ids = $this->api->lookup_related_items( $this->fields[ $field ]['id'], $this->pod_data['id'], $id, $this->fields[ $field ], $this->pod_data );
1984
1985
				foreach ( $value as $k => $v ) {
1986
					if ( ! preg_match( '/[^\D]/', $v ) ) {
1987
						$value[ $k ] = (int) $v;
1988
					}
1989
1990
					// @todo Convert slugs into IDs.
1991
				}
1992
1993
				foreach ( $related_ids as $v ) {
1994
					// @codingStandardsIgnoreLine.
1995
					if ( in_array( $v, $value ) ) {
1996
						return true;
1997
					}
1998
				}
1999
			}//end if
2000 View Code Duplication
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::text_field_types(), true ) ) {
2001
			// Text fields.
2002
			$current_value = $pod->raw( $field );
2003
2004
			if ( 0 < strlen( $current_value ) ) {
2005
				return stripos( $current_value, $value );
2006
			}
2007
		} else {
2008
			// All other fields.
2009
			return $this->is( $field, $value, $id );
2010
		}//end if
2011
2012
		return false;
2013
	}
2014
2015
	/**
2016
	 * Check if an item field is a specific value
2017
	 *
2018
	 * @param string $field Field name.
2019
	 * @param mixed  $value Value to check.
2020
	 * @param int    $id    (optional) ID of the pod item to check.
2021
	 *
2022
	 * @return bool Whether the value was found
2023
	 *
2024
	 * @since 2.3.3
2025
	 */
2026
	public function is( $field, $value, $id = null ) {
2027
2028
		$pod =& $this;
2029
2030 View Code Duplication
		if ( null === $id ) {
2031
			$id = $this->id();
2032
			// @codingStandardsIgnoreLine.
2033
		} elseif ( $id != $this->id() ) {
2034
			$pod = pods( $this->pod, $id );
2035
		}
2036
2037
		$this->do_hook( 'is', $field, $value, $id );
2038
2039
		if ( ! isset( $this->fields[ $field ] ) ) {
2040
			return false;
2041
		}
2042
2043
		// Tableless fields.
2044
		if ( in_array( $this->fields[ $field ]['type'], PodsForm::tableless_field_types(), true ) ) {
2045
			if ( ! is_array( $value ) ) {
2046
				$value = explode( ',', $value );
2047
			}
2048
2049
			$current_value = array();
2050
2051 View Code Duplication
			if ( 'pick' === $this->fields[ $field ]['type'] && in_array( $this->fields[ $field ]['pick_object'], PodsForm::simple_tableless_objects(), true ) ) {
2052
				$current_value = $pod->raw( $field );
2053
2054
				if ( ! empty( $current_value ) ) {
2055
					$current_value = (array) $current_value;
2056
				}
2057
2058
				foreach ( $current_value as $v ) {
2059
					// @codingStandardsIgnoreLine.
2060
					if ( in_array( $v, $value ) ) {
2061
						return true;
2062
					}
2063
				}
2064
			} else {
2065
				$related_ids = $this->api->lookup_related_items( $this->fields[ $field ]['id'], $this->pod_data['id'], $id, $this->fields[ $field ], $this->pod_data );
2066
2067
				foreach ( $value as $k => $v ) {
2068
					if ( ! preg_match( '/[^\D]/', $v ) ) {
2069
						$value[ $k ] = (int) $v;
2070
					}
2071
2072
					// @todo Convert slugs into IDs.
2073
				}
2074
2075
				foreach ( $related_ids as $v ) {
2076
					// @codingStandardsIgnoreLine.
2077
					if ( in_array( $v, $value ) ) {
2078
						return true;
2079
					}
2080
				}
2081
			}//end if
2082
2083
			if ( ! empty( $current_value ) ) {
2084
				$current_value = array_filter( array_unique( $current_value ) );
2085
			} else {
2086
				$current_value = array();
2087
			}
2088
2089
			if ( ! empty( $value ) ) {
2090
				$value = array_filter( array_unique( $value ) );
2091
			} else {
2092
				$value = array();
2093
			}
2094
2095
			sort( $current_value );
2096
			sort( $value );
2097
2098
			if ( $value === $current_value ) {
2099
				return true;
2100
			}
2101
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::number_field_types(), true ) ) {
2102
			// Number fields.
2103
			$current_value = $pod->raw( $field );
2104
2105
			if ( (float) $current_value === (float) $value ) {
2106
				return true;
2107
			}
2108
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::date_field_types(), true ) ) {
2109
			// Date fields.
2110
			$current_value = $pod->raw( $field );
2111
2112
			if ( 0 < strlen( $current_value ) ) {
2113
				if ( strtotime( $current_value ) === strtotime( $value ) ) {
2114
					return true;
2115
				}
2116
			} elseif ( empty( $value ) ) {
2117
				return true;
2118
			}
2119
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::text_field_types(), true ) ) {
2120
			// Text fields.
2121
			$current_value = $pod->raw( $field );
2122
2123
			if ( (string) $current_value === (string) $value ) {
2124
				return true;
2125
			}
2126
		} else {
2127
			// All other fields.
2128
			$current_value = $pod->raw( $field );
2129
2130
			if ( $current_value === $value ) {
2131
				return true;
2132
			}
2133
		}//end if
2134
2135
		return false;
2136
	}
2137
2138
	/**
2139
	 * Return the item ID
2140
	 *
2141
	 * @return int
2142
	 * @since 2.0
2143
	 */
2144
	public function id() {
2145
2146
		if ( isset( $this->data->row, $this->data->row['id'] ) ) {
2147
			// If we already have data loaded return that ID.
2148
			return $this->data->row['id'];
2149
		}
2150
2151
		return $this->field( $this->data->field_id );
2152
	}
2153
2154
	/**
2155
	 * Return the previous item ID, loops at the last id to return the first
2156
	 *
2157
	 * @param int|null          $id              ID to start from.
2158
	 * @param array|object|null $params_override Override the find() parameters.
2159
	 *
2160
	 * @return int
2161
	 * @since 2.0
2162
	 */
2163
	public function prev_id( $id = null, $params_override = null ) {
2164
2165
		if ( null === $id ) {
2166
			$id = $this->id();
2167
		}
2168
2169
		$id = (int) $id;
2170
2171
		$params = array(
2172
			'select'  => "`t`.`{$this->data->field_id}`",
2173
			'where'   => "`t`.`{$this->data->field_id}` < {$id}",
2174
			'orderby' => "`t`.`{$this->data->field_id}` DESC",
2175
			'limit'   => 1,
2176
		);
2177
2178
		if ( ! empty( $params_override ) || ! empty( $this->params ) ) {
2179 View Code Duplication
			if ( ! empty( $params_override ) ) {
2180
				$params = $params_override;
2181
			} elseif ( ! empty( $this->params ) ) {
2182
				$params = $this->params;
2183
			}
2184
2185
			if ( is_object( $params ) ) {
2186
				$params = get_object_vars( $params );
2187
			}
2188
2189
			if ( 0 < $id ) {
2190 View Code Duplication
				if ( isset( $params['where'] ) && ! empty( $params['where'] ) ) {
2191
					$params['where']   = (array) $params['where'];
2192
					$params['where'][] = "`t`.`{$this->data->field_id}` < {$id}";
2193
				} else {
2194
					$params['where'] = "`t`.`{$this->data->field_id}` < {$id}";
2195
				}
2196
			} elseif ( isset( $params['offset'] ) && 0 < $params['offset'] ) {
2197
				$params['offset'] --;
2198
			} elseif ( 0 < $this->row_number && ! isset( $params['offset'] ) && ! empty( $this->params ) ) {
2199
				$params['offset'] = $this->row_number - 1;
2200
			} else {
2201
				return 0;
2202
			}
2203
2204 View Code Duplication
			if ( isset( $params['orderby'] ) && ! empty( $params['orderby'] ) ) {
2205
				if ( is_array( $params['orderby'] ) ) {
2206
					foreach ( $params['orderby'] as $orderby => $dir ) {
2207
						$dir = strtoupper( $dir );
2208
2209
						if ( ! in_array( $dir, array( 'ASC', 'DESC' ), true ) ) {
2210
							continue;
2211
						}
2212
2213
						if ( 'ASC' === $dir ) {
2214
							$params['orderby'][ $orderby ] = 'DESC';
2215
						} else {
2216
							$params['orderby'][ $orderby ] = 'ASC';
2217
						}
2218
					}
2219
2220
					$params['orderby'][ $this->data->field_id ] = 'DESC';
2221
				} elseif ( "`t`.`{$this->data->field_id}` DESC" !== $params['orderby'] ) {
2222
					$params['orderby'] .= ", `t`.`{$this->data->field_id}` DESC";
2223
				}
2224
			}//end if
2225
2226
			$params['select'] = "`t`.`{$this->data->field_id}`";
2227
			$params['limit']  = 1;
2228
		}//end if
2229
2230
		$pod = pods( $this->pod, $params );
2231
2232
		$new_id = 0;
2233
2234
		if ( $pod->fetch() ) {
2235
			$new_id = $pod->id();
2236
		}
2237
2238
		$new_id = $this->do_hook( 'prev_id', $new_id, $id, $pod, $params_override );
2239
2240
		return $new_id;
2241
	}
2242
2243
	/**
2244
	 * Return the next item ID, loops at the first id to return the last
2245
	 *
2246
	 * @param int|null          $id              ID to start from.
2247
	 * @param array|object|null $params_override Override the find() parameters.
2248
	 *
2249
	 * @return int
2250
	 * @since 2.0
2251
	 */
2252
	public function next_id( $id = null, $params_override = null ) {
2253
2254
		if ( null === $id ) {
2255
			$id = $this->id();
2256
		}
2257
2258
		$id = (int) $id;
2259
2260
		$params = array(
2261
			'select'  => "`t`.`{$this->data->field_id}`",
2262
			'where'   => "{$id} < `t`.`{$this->data->field_id}`",
2263
			'orderby' => "`t`.`{$this->data->field_id}` ASC",
2264
			'limit'   => 1,
2265
		);
2266
2267
		if ( ! empty( $params_override ) || ! empty( $this->params ) ) {
2268 View Code Duplication
			if ( ! empty( $params_override ) ) {
2269
				$params = $params_override;
2270
			} elseif ( ! empty( $this->params ) ) {
2271
				$params = $this->params;
2272
			}
2273
2274
			if ( is_object( $params ) ) {
2275
				$params = get_object_vars( $params );
2276
			}
2277
2278
			if ( 0 < $id ) {
2279 View Code Duplication
				if ( isset( $params['where'] ) && ! empty( $params['where'] ) ) {
2280
					$params['where']   = (array) $params['where'];
2281
					$params['where'][] = "{$id} < `t`.`{$this->data->field_id}`";
2282
				} else {
2283
					$params['where'] = "{$id} < `t`.`{$this->data->field_id}`";
2284
				}
2285
			} elseif ( ! isset( $params['offset'] ) ) {
2286
				if ( ! empty( $this->params ) && - 1 < $this->row_number ) {
2287
					$params['offset'] = $this->row_number + 1;
2288
				} else {
2289
					$params['offset'] = 1;
2290
				}
2291
			} else {
2292
				$params['offset'] ++;
2293
			}
2294
2295
			$params['select'] = "`t`.`{$this->data->field_id}`";
2296
			$params['limit']  = 1;
2297
		}//end if
2298
2299
		$pod = pods( $this->pod, $params );
2300
2301
		$new_id = 0;
2302
2303
		if ( $pod->fetch() ) {
2304
			$new_id = $pod->id();
2305
		}
2306
2307
		$new_id = $this->do_hook( 'next_id', $new_id, $id, $pod, $params_override );
2308
2309
		return $new_id;
2310
	}
2311
2312
	/**
2313
	 * Return the first item ID
2314
	 *
2315
	 * @param array|object|null $params_override Override the find() parameters.
2316
	 *
2317
	 * @return int
2318
	 * @since 2.3
2319
	 */
2320
	public function first_id( $params_override = null ) {
2321
2322
		$params = array(
2323
			'select'  => "`t`.`{$this->data->field_id}`",
2324
			'orderby' => "`t`.`{$this->data->field_id}` ASC",
2325
			'limit'   => 1,
2326
		);
2327
2328
		if ( ! empty( $params_override ) || ! empty( $this->params ) ) {
2329 View Code Duplication
			if ( ! empty( $params_override ) ) {
2330
				$params = $params_override;
2331
			} elseif ( ! empty( $this->params ) ) {
2332
				$params = $this->params;
2333
			}
2334
2335
			if ( is_object( $params ) ) {
2336
				$params = get_object_vars( $params );
2337
			}
2338
2339
			$params['select'] = "`t`.`{$this->data->field_id}`";
2340
			$params['offset'] = 0;
2341
			$params['limit']  = 1;
2342
		}
2343
2344
		$pod = pods( $this->pod, $params );
2345
2346
		$new_id = 0;
2347
2348
		if ( $pod->fetch() ) {
2349
			$new_id = $pod->id();
2350
		}
2351
2352
		$new_id = $this->do_hook( 'first_id', $new_id, $pod, $params_override );
2353
2354
		return $new_id;
2355
	}
2356
2357
	/**
2358
	 * Return the last item ID
2359
	 *
2360
	 * @param array|object|null $params_override Override the find() parameters.
2361
	 *
2362
	 * @return int
2363
	 * @since 2.3
2364
	 */
2365
	public function last_id( $params_override = null ) {
2366
2367
		$params = array(
2368
			'select'  => "`t`.`{$this->data->field_id}`",
2369
			'orderby' => "`t`.`{$this->data->field_id}` DESC",
2370
			'limit'   => 1,
2371
		);
2372
2373
		if ( ! empty( $params_override ) || ! empty( $this->params ) ) {
2374 View Code Duplication
			if ( ! empty( $params_override ) ) {
2375
				$params = $params_override;
2376
			} elseif ( ! empty( $this->params ) ) {
2377
				$params = $this->params;
2378
			}
2379
2380
			if ( is_object( $params ) ) {
2381
				$params = get_object_vars( $params );
2382
			}
2383
2384
			if ( isset( $params['total_found'] ) ) {
2385
				$params['offset'] = $params['total_found'] - 1;
2386
			} else {
2387
				$params['offset'] = $this->total_found() - 1;
2388
			}
2389
2390 View Code Duplication
			if ( isset( $params['orderby'] ) && ! empty( $params['orderby'] ) ) {
2391
				if ( is_array( $params['orderby'] ) ) {
2392
					foreach ( $params['orderby'] as $orderby => $dir ) {
2393
						$dir = strtoupper( $dir );
2394
2395
						if ( ! in_array( $dir, array( 'ASC', 'DESC' ), true ) ) {
2396
							continue;
2397
						}
2398
2399
						if ( 'ASC' === $dir ) {
2400
							$params['orderby'][ $orderby ] = 'DESC';
2401
						} else {
2402
							$params['orderby'][ $orderby ] = 'ASC';
2403
						}
2404
					}
2405
2406
					$params['orderby'][ $this->data->field_id ] = 'DESC';
2407
				} elseif ( "`t`.`{$this->data->field_id}` DESC" !== $params['orderby'] ) {
2408
					$params['orderby'] .= ", `t`.`{$this->data->field_id}` DESC";
2409
				}
2410
			}//end if
2411
2412
			$params['select'] = "`t`.`{$this->data->field_id}`";
2413
			$params['limit']  = 1;
2414
		}//end if
2415
2416
		$pod = pods( $this->pod, $params );
2417
2418
		$new_id = 0;
2419
2420
		if ( $pod->fetch() ) {
2421
			$new_id = $pod->id();
2422
		}
2423
2424
		$new_id = $this->do_hook( 'last_id', $new_id, $pod, $params_override );
2425
2426
		return $new_id;
2427
	}
2428
2429
	/**
2430
	 * Return the item name
2431
	 *
2432
	 * @return string
2433
	 * @since 2.0
2434
	 */
2435
	public function index() {
2436
2437
		return $this->field( $this->data->field_index );
2438
	}
2439
2440
	/**
2441
	 * Find items of a pod, much like WP_Query, but with advanced table handling.
2442
	 *
2443
	 * @param array|object $params An associative array of parameters.
2444
	 * @param int          $limit  (deprecated) Limit the number of items to find, -1 to return all items with no limit.
2445
	 * @param string       $where  (deprecated) SQL WHERE declaration to use.
2446
	 * @param string       $sql    (deprecated) For advanced use, a custom SQL query to run.
2447
	 *
2448
	 * @return \Pods The pod object
2449
	 * @since 2.0
2450
	 * @link  https://pods.io/docs/find/
2451
	 */
2452
	public function find( $params = null, $limit = 15, $where = null, $sql = null ) {
2453
2454
		$tableless_field_types    = PodsForm::tableless_field_types();
2455
		$simple_tableless_objects = PodsForm::simple_tableless_objects();
2456
2457
		$this->params = $params;
2458
2459
		$select = '`t`.*';
2460
2461
		if ( 'table' === $this->pod_data['storage'] && ! in_array( $this->pod_data['type'], array(
2462
			'pod',
2463
			'table',
2464
		), true ) ) {
2465
			$select .= ', `d`.*';
2466
		}
2467
2468
		if ( empty( $this->data->table ) ) {
2469
			return $this;
2470
		}
2471
2472
		$defaults = array(
2473
			// Optimization parameters.
2474
			'table'               => $this->data->table,
2475
			'select'              => $select,
2476
			'join'                => null,
2477
			// Main query parameters.
2478
			'where'               => $where,
2479
			'groupby'             => null,
2480
			'having'              => null,
2481
			'orderby'             => null,
2482
			// Pagination parameters.
2483
			'limit'               => (int) $limit,
2484
			'offset'              => null,
2485
			'page'                => (int) $this->page,
2486
			'page_var'            => $this->page_var,
2487
			'pagination'          => (boolean) $this->pagination,
2488
			// Search parameters.
2489
			'search'              => (boolean) $this->search,
2490
			'search_var'          => $this->search_var,
2491
			'search_query'        => null,
2492
			'search_mode'         => $this->search_mode,
2493
			'search_across'       => false,
2494
			'search_across_picks' => false,
2495
			'search_across_files' => false,
2496
			// Advanced parameters.
2497
			'filters'             => $this->filters,
2498
			'sql'                 => $sql,
2499
			// Caching parameters.
2500
			'expires'             => null,
2501
			'cache_mode'          => 'cache',
2502
		);
2503
2504
		if ( is_array( $params ) ) {
2505
			$params = (object) array_merge( $defaults, $params );
2506
		} elseif ( is_object( $params ) ) {
2507
			$params = (object) array_merge( $defaults, get_object_vars( $params ) );
2508
		} else {
2509
			$defaults['orderby'] = $params;
2510
2511
			$params = (object) $defaults;
2512
		}
2513
2514
		/**
2515
		 * Filter the Pods::find() parameters.
2516
		 *
2517
		 * @param object $params Parameters to make lookup with.
2518
		 */
2519
		$params = apply_filters( 'pods_pods_find', $params );
2520
2521
		$params->limit = (int) $params->limit;
2522
2523
		if ( 0 === $params->limit ) {
2524
			$params->limit = - 1;
2525
		}
2526
2527
		$this->limit      = (int) $params->limit;
2528
		$this->offset     = (int) $params->offset;
2529
		$this->page       = (int) $params->page;
2530
		$this->page_var   = $params->page_var;
2531
		$this->pagination = (boolean) $params->pagination;
2532
		$this->search     = (boolean) $params->search;
2533
		$this->search_var = $params->search_var;
2534
		$params->join     = (array) $params->join;
2535
2536
		if ( empty( $params->search_query ) ) {
2537
			$params->search_query = pods_v_sanitized( $this->search_var, 'get', '' );
2538
		}
2539
2540
		// Allow orderby array ( 'field' => 'asc|desc' ).
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
2541
		if ( ! empty( $params->orderby ) && is_array( $params->orderby ) ) {
2542
			foreach ( $params->orderby as $k => $orderby ) {
2543
				if ( ! is_numeric( $k ) ) {
2544
					$key = '';
2545
2546
					$order = 'ASC';
2547
2548
					if ( 'DESC' === strtoupper( $orderby ) ) {
2549
						$order = 'DESC';
2550
					}
2551
2552
					if ( isset( $this->fields[ $k ] ) && in_array( $this->fields[ $k ]['type'], $tableless_field_types, true ) ) {
2553
						if ( in_array( $this->fields[ $k ]['pick_object'], $simple_tableless_objects, true ) ) {
2554
							if ( 'table' === $this->pod_data['storage'] ) {
2555
								if ( ! in_array( $this->pod_data['type'], array( 'pod', 'table' ), true ) ) {
2556
									$key = "`d`.`{$k}`";
2557
								} else {
2558
									$key = "`t`.`{$k}`";
2559
								}
2560
							} else {
2561
								$key = "`{$k}`.`meta_value`";
2562
							}
2563
						} else {
2564
							$pick_val = $this->fields[ $k ]['pick_val'];
2565
2566
							if ( '__current__' === $pick_val ) {
2567
								$pick_val = $this->pod;
2568
							}
2569
2570
							$table = $this->api->get_table_info( $this->fields[ $k ]['pick_object'], $pick_val );
2571
2572
							if ( ! empty( $table ) ) {
2573
								$key = "`{$k}`.`" . $table['field_index'] . '`';
2574
							}
2575
						}//end if
2576
					}//end if
2577
2578
					if ( empty( $key ) ) {
2579 View Code Duplication
						if ( ! in_array( $this->pod_data['type'], array( 'pod', 'table' ), true ) ) {
2580
							if ( isset( $this->pod_data['object_fields'][ $k ] ) ) {
2581
								$key = "`t`.`{$k}`";
2582
							} elseif ( isset( $this->fields[ $k ] ) ) {
2583
								if ( 'table' === $this->pod_data['storage'] ) {
2584
									$key = "`d`.`{$k}`";
2585
								} else {
2586
									$key = "`{$k}`.`meta_value`";
2587
								}
2588
							} else {
2589
								$object_fields = (array) $this->pod_data['object_fields'];
2590
2591
								foreach ( $object_fields as $object_field => $object_field_opt ) {
2592
									if ( $object_field === $k || in_array( $k, $object_field_opt['alias'], true ) ) {
2593
										$key = "`t`.`{$object_field}`";
2594
									}
2595
								}
2596
							}
2597
						} elseif ( isset( $this->fields[ $k ] ) ) {
2598
							if ( 'table' === $this->pod_data['storage'] ) {
2599
								$key = "`t`.`{$k}`";
2600
							} else {
2601
								$key = "`{$k}`.`meta_value`";
2602
							}
2603
						}//end if
2604
2605
						if ( empty( $key ) ) {
2606
							$key = $k;
2607
2608
							if ( false === strpos( $key, ' ' ) && false === strpos( $key, '`' ) ) {
2609
								$key = '`' . str_replace( '.', '`.`', $key ) . '`';
2610
							}
2611
						}
2612
					}//end if
2613
2614
					$orderby = $key;
2615
2616
					if ( false === strpos( $orderby, ' ' ) ) {
2617
						$orderby .= ' ' . $order;
2618
					}
2619
2620
					$params->orderby[ $k ] = $orderby;
2621
				}//end if
2622
			}//end foreach
2623
		}//end if
2624
2625
		// Add prefix to $params->orderby if needed.
2626
		if ( ! empty( $params->orderby ) ) {
2627
			if ( ! is_array( $params->orderby ) ) {
2628
				$params->orderby = array( $params->orderby );
2629
			}
2630
2631
			foreach ( $params->orderby as $ok => $prefix_orderby ) {
2632
				if ( false === strpos( $prefix_orderby, ',' ) && false === strpos( $prefix_orderby, '(' ) && false === stripos( $prefix_orderby, ' AS ' ) && false === strpos( $prefix_orderby, '`' ) && false === strpos( $prefix_orderby, '.' ) ) {
2633
					if ( false !== stripos( $prefix_orderby, ' DESC' ) ) {
2634
						$k   = trim( str_ireplace( array( '`', ' DESC' ), '', $prefix_orderby ) );
2635
						$dir = 'DESC';
2636
					} else {
2637
						$k   = trim( str_ireplace( array( '`', ' ASC' ), '', $prefix_orderby ) );
2638
						$dir = 'ASC';
2639
					}
2640
2641
					$key = $k;
2642
2643 View Code Duplication
					if ( ! in_array( $this->pod_data['type'], array( 'pod', 'table' ), true ) ) {
2644
						if ( isset( $this->pod_data['object_fields'][ $k ] ) ) {
2645
							$key = "`t`.`{$k}`";
2646
						} elseif ( isset( $this->fields[ $k ] ) ) {
2647
							if ( 'table' === $this->pod_data['storage'] ) {
2648
								$key = "`d`.`{$k}`";
2649
							} else {
2650
								$key = "`{$k}`.`meta_value`";
2651
							}
2652
						} else {
2653
							$object_fields = (array) $this->pod_data['object_fields'];
2654
2655
							foreach ( $object_fields as $object_field => $object_field_opt ) {
2656
								if ( $object_field === $k || in_array( $k, $object_field_opt['alias'], true ) ) {
2657
									$key = "`t`.`{$object_field}`";
2658
								}
2659
							}
2660
						}
2661
					} elseif ( isset( $this->fields[ $k ] ) ) {
2662
						if ( 'table' === $this->pod_data['storage'] ) {
2663
							$key = "`t`.`{$k}`";
2664
						} else {
2665
							$key = "`{$k}`.`meta_value`";
2666
						}
2667
					}//end if
2668
2669
					$prefix_orderby = "{$key} {$dir}";
2670
2671
					$params->orderby[ $ok ] = $prefix_orderby;
2672
				}//end if
2673
			}//end foreach
2674
		}//end if
2675
2676
		$this->data->select( $params );
2677
2678
		return $this;
2679
	}
2680
2681
	/**
2682
	 * Fetch an item from a Pod. If $id is null, it will return the next item in the list after running find().
2683
	 * You can rewind the list back to the start by using reset().
2684
	 *
2685
	 * Providing an $id will fetch a specific item from a Pod, much like a call to pods(), and can handle either an id
2686
	 * or slug.
2687
	 *
2688
	 * @see   PodsData::fetch
2689
	 *
2690
	 * @param int  $id           ID or slug of the item to fetch.
2691
	 * @param bool $explicit_set Whether to set explicitly (use false when in loop).
2692
	 *
2693
	 * @return array An array of fields from the row
2694
	 *
2695
	 * @since 2.0
2696
	 * @link  https://pods.io/docs/fetch/
2697
	 */
2698
	public function fetch( $id = null, $explicit_set = true ) {
2699
2700
		/**
2701
		 * Runs directly before an item is fetched by fetch().
2702
		 *
2703
		 * @since unknown
2704
		 *
2705
		 * @param int|string|null $id   Item ID being fetched or null.
2706
		 * @param object|Pods     $this Current Pods object.
2707
		 */
2708
		do_action( 'pods_pods_fetch', $id, $this );
2709
2710
		if ( ! empty( $id ) ) {
2711
			$this->params = array();
2712
		}
2713
2714
		$this->data->fetch( $id, $explicit_set );
2715
2716
		return $this->row;
2717
	}
2718
2719
	/**
2720
	 * (Re)set the MySQL result pointer
2721
	 *
2722
	 * @see   PodsData::reset
2723
	 *
2724
	 * @param int $row ID of the row to reset to.
2725
	 *
2726
	 * @return \Pods The pod object
2727
	 *
2728
	 * @since 2.0
2729
	 * @link  https://pods.io/docs/reset/
2730
	 */
2731
	public function reset( $row = null ) {
2732
2733
		/**
2734
		 * Runs directly before the Pods object is reset by reset()
2735
		 *
2736
		 * @since unknown
2737
		 *
2738
		 * @param int|string|null The ID of the row being reset to or null if being reset to the beginning.
2739
		 * @param object|Pods $this Current Pods object.
2740
		 */
2741
		do_action( 'pods_pods_reset', $row, $this );
2742
2743
		$this->data->reset( $row );
2744
2745
		return $this;
2746
	}
2747
2748
	/**
2749
	 * Fetch the total row count returned by the last call to find(), based on the 'limit' parameter set.
2750
	 *
2751
	 * This is different than the total number of rows found in the database, which you can get with total_found().
2752
	 *
2753
	 * @see   PodsData::total
2754
	 *
2755
	 * @return int Number of rows returned by find(), based on the 'limit' parameter set
2756
	 * @since 2.0
2757
	 * @link  https://pods.io/docs/total/
2758
	 */
2759
	public function total() {
2760
2761
		do_action( 'pods_pods_total', $this );
2762
2763
		$this->data->total();
0 ignored issues
show
Unused Code introduced by
The call to the method PodsData::total() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
2764
2765
		$this->total =& $this->data->total;
2766
2767
		return $this->total;
2768
	}
2769
2770
	/**
2771
	 * Fetch the total amount of rows found by the last call to find(), regardless of the 'limit' parameter set.
2772
	 *
2773
	 * This is different than the total number of rows limited by the current call, which you can get with total().
2774
	 *
2775
	 * @see   PodsData::total_found
2776
	 *
2777
	 * @return int Number of rows returned by find(), regardless of the 'limit' parameter
2778
	 * @since 2.0
2779
	 * @link  https://pods.io/docs/total-found/
2780
	 */
2781
	public function total_found() {
2782
2783
		/**
2784
		 * Runs directly before the value of total_found() is determined and returned.
2785
		 *
2786
		 * @since unknown
2787
		 *
2788
		 * @param object|Pods $this Current Pods object.
2789
		 */
2790
		do_action( 'pods_pods_total_found', $this );
2791
2792
		$this->data->total_found();
2793
2794
		$this->total_found =& $this->data->total_found;
2795
2796
		return $this->total_found;
2797
	}
2798
2799
	/**
2800
	 * Fetch the total number of pages, based on total rows found and the last find() limit
2801
	 *
2802
	 * @param null|int $limit  Rows per page.
2803
	 * @param null|int $offset Offset of rows.
2804
	 * @param null|int $total  Total rows.
2805
	 *
2806
	 * @return int Number of pages
2807
	 * @since 2.3.10
2808
	 */
2809
	public function total_pages( $limit = null, $offset = null, $total = null ) {
2810
2811
		$this->do_hook( 'total_pages' );
2812
2813
		if ( null === $limit ) {
2814
			$limit = $this->limit;
2815
		}
2816
2817
		if ( null === $offset ) {
2818
			$offset = $this->offset;
2819
		}
2820
2821
		if ( null === $total ) {
2822
			$total = $this->total_found();
2823
		}
2824
2825
		return ceil( ( $total - $offset ) / $limit );
2826
2827
	}
2828
2829
	/**
2830
	 * Fetch the zebra switch
2831
	 *
2832
	 * @see   PodsData::zebra
2833
	 *
2834
	 * @return bool Zebra state
2835
	 * @since 1.12
2836
	 */
2837
	public function zebra() {
2838
2839
		$this->do_hook( 'zebra' );
2840
2841
		return $this->data->zebra();
2842
	}
2843
2844
	/**
2845
	 * Fetch the nth state
2846
	 *
2847
	 * @see   PodsData::nth
2848
	 *
2849
	 * @param int|string $nth The $nth to match on the PodsData::row_number.
2850
	 *
2851
	 * @return bool Whether $nth matches
2852
	 * @since 2.3
2853
	 */
2854
	public function nth( $nth = null ) {
2855
2856
		$this->do_hook( 'nth', $nth );
2857
2858
		return $this->data->nth( $nth );
2859
	}
2860
2861
	/**
2862
	 * Fetch the current position in the loop (starting at 1)
2863
	 *
2864
	 * @see   PodsData::position
2865
	 *
2866
	 * @return int Current row number (+1)
2867
	 * @since 2.3
2868
	 */
2869
	public function position() {
2870
2871
		$this->do_hook( 'position' );
2872
2873
		return $this->data->position();
2874
	}
2875
2876
	/**
2877
	 * Add an item to a Pod by giving an array of field data or set a specific field to
2878
	 * a specific value if you're just wanting to add a new item but only set one field.
2879
	 *
2880
	 * You may be looking for save() in most cases where you're setting a specific field.
2881
	 *
2882
	 * @see   PodsAPI::save_pod_item
2883
	 *
2884
	 * @param array|string $data  Either an associative array of field information or a field name.
2885
	 * @param mixed        $value (optional) Value of the field, if $data is a field name.
2886
	 *
2887
	 * @return int The item ID
2888
	 *
2889
	 * @since 2.0
2890
	 * @link  https://pods.io/docs/add/
2891
	 */
2892
	public function add( $data = null, $value = null ) {
2893
2894
		if ( null !== $value ) {
2895
			$data = array( $data => $value );
2896
		}
2897
2898
		$data = (array) $this->do_hook( 'add', $data );
2899
2900
		if ( empty( $data ) ) {
2901
			return 0;
2902
		}
2903
2904
		$params = array(
2905
			'pod'                 => $this->pod,
2906
			'data'                => $data,
2907
			'allow_custom_fields' => true,
2908
		);
2909
2910
		return $this->api->save_pod_item( $params );
2911
	}
2912
2913
	/**
2914
	 * Add an item to the values of a relationship field, add a value to a number field (field+1), add time to a date
2915
	 * field, or add text to a text field
2916
	 *
2917
	 * @see   PodsAPI::save_pod_item
2918
	 *
2919
	 * @param string $field Field name.
2920
	 * @param mixed  $value IDs to add, int|float to add to number field, string for dates (+1 day), or string for text.
2921
	 * @param int    $id    (optional) ID of the pod item to update.
2922
	 *
2923
	 * @return int The item ID
2924
	 *
2925
	 * @since 2.3
2926
	 */
2927
	public function add_to( $field, $value, $id = null ) {
2928
2929
		$pod =& $this;
2930
2931
		$fetch = false;
2932
2933 View Code Duplication
		if ( null === $id ) {
2934
			$fetch = true;
2935
2936
			$id = $pod->id();
2937
			// @codingStandardsIgnoreLine
2938
		} elseif ( $id != $this->id() ) {
2939
			$pod = pods( $this->pod, $id );
2940
		}
2941
2942
		$this->do_hook( 'add_to', $field, $value, $id );
2943
2944
		if ( ! isset( $this->fields[ $field ] ) ) {
2945
			return $id;
2946
		}
2947
2948
		// Tableless fields.
2949
		if ( in_array( $this->fields[ $field ]['type'], PodsForm::tableless_field_types(), true ) ) {
2950
			if ( ! is_array( $value ) ) {
2951
				$value = explode( ',', $value );
2952
			}
2953
2954
			if ( 'pick' === $this->fields[ $field ]['type'] && in_array( $this->fields[ $field ]['pick_object'], PodsForm::simple_tableless_objects(), true ) ) {
2955
				$current_value = $pod->raw( $field );
2956
2957
				if ( ! empty( $current_value ) || ( ! is_array( $current_value ) && 0 < strlen( $current_value ) ) ) {
2958
					$current_value = (array) $current_value;
2959
				} else {
2960
					$current_value = array();
2961
				}
2962
2963
				$value = array_merge( $current_value, $value );
2964
			} else {
2965
				$related_ids = $this->api->lookup_related_items( $this->fields[ $field ]['id'], $this->pod_data['id'], $id, $this->fields[ $field ], $this->pod_data );
2966
2967
				foreach ( $value as $k => $v ) {
2968
					if ( ! preg_match( '/[^\D]/', $v ) ) {
2969
						$value[ $k ] = (int) $v;
2970
					}
2971
				}
2972
2973
				$value = array_merge( $related_ids, $value );
2974
			}//end if
2975
2976
			if ( ! empty( $value ) ) {
2977
				$value = array_filter( array_unique( $value ) );
2978
			} else {
2979
				$value = array();
2980
			}
2981
2982
			if ( empty( $value ) ) {
2983
				return $id;
2984
			}
2985 View Code Duplication
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::number_field_types(), true ) ) {
2986
			// Number fields.
2987
			$current_value = (float) $pod->raw( $field );
2988
2989
			$value = ( $current_value + (float) $value );
2990
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::date_field_types(), true ) ) {
2991
			// Date fields.
2992
			$current_value = $pod->raw( $field );
2993
2994 View Code Duplication
			if ( 0 < strlen( $current_value ) ) {
2995
				$value = strtotime( $value, strtotime( $current_value ) );
2996
			} else {
2997
				$value = strtotime( $value );
2998
			}
2999 View Code Duplication
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::text_field_types(), true ) ) {
3000
			// Text fields.
3001
			$current_value = $pod->raw( $field );
3002
3003
			if ( 0 < strlen( $current_value ) ) {
3004
				$value = $current_value . $value;
3005
			}
3006
		}//end if
3007
3008
		// @todo handle object fields and taxonomies.
3009
		$params = array(
3010
			'pod'  => $this->pod,
3011
			'id'   => $id,
3012
			'data' => array(
3013
				$field => $value,
3014
			),
3015
		);
3016
3017
		$id = $this->api->save_pod_item( $params );
3018
3019 View Code Duplication
		if ( 0 < $id && $fetch ) {
3020
			// Clear local var cache of field values.
3021
			$pod->data->row = array();
3022
3023
			$pod->fetch( $id, false );
3024
		}
3025
3026
		return $id;
3027
	}
3028
3029
	/**
3030
	 * Remove an item from the values of a relationship field, remove a value from a number field (field-1), remove
3031
	 * time to a date field
3032
	 *
3033
	 * @see   PodsAPI::save_pod_item
3034
	 *
3035
	 * @param string $field Field name.
3036
	 * @param mixed  $value IDs to add, int|float to add to number field, string for dates (-1 day), or string for text.
3037
	 * @param int    $id    (optional) ID of the pod item to update.
3038
	 *
3039
	 * @return int The item ID
3040
	 *
3041
	 * @since 2.3.3
3042
	 */
3043
	public function remove_from( $field, $value = null, $id = null ) {
3044
3045
		$pod =& $this;
3046
3047
		$fetch = false;
3048
3049 View Code Duplication
		if ( null === $id ) {
3050
			$fetch = true;
3051
3052
			$id = $this->id();
3053
			// @codingStandardsIgnoreLine
3054
		} elseif ( $id != $this->id() ) {
3055
			$pod = pods( $this->pod, $id );
3056
		}
3057
3058
		$this->do_hook( 'remove_from', $field, $value, $id );
3059
3060
		if ( ! isset( $this->fields[ $field ] ) ) {
3061
			return $id;
3062
		}
3063
3064
		// Tableless fields.
3065
		if ( in_array( $this->fields[ $field ]['type'], PodsForm::tableless_field_types(), true ) ) {
3066
			if ( empty( $value ) ) {
3067
				$value = array();
3068
			}
3069
3070
			if ( ! empty( $value ) ) {
3071
				if ( ! is_array( $value ) ) {
3072
					$value = explode( ',', $value );
3073
				}
3074
3075
				if ( 'pick' === $this->fields[ $field ]['type'] && in_array( $this->fields[ $field ]['pick_object'], PodsForm::simple_tableless_objects(), true ) ) {
3076
					$current_value = $pod->raw( $field );
3077
3078
					if ( ! empty( $current_value ) ) {
3079
						$current_value = (array) $current_value;
3080
					}
3081
3082
					foreach ( $current_value as $k => $v ) {
3083
						// @codingStandardsIgnoreLine.
3084
						if ( in_array( $v, $value ) ) {
3085
							unset( $current_value[ $k ] );
3086
						}
3087
					}
3088
3089
					$value = $current_value;
3090
				} else {
3091
					$related_ids = $this->api->lookup_related_items( $this->fields[ $field ]['id'], $this->pod_data['id'], $id, $this->fields[ $field ], $this->pod_data );
3092
3093
					foreach ( $value as $k => $v ) {
3094
						if ( ! preg_match( '/[^\D]/', $v ) ) {
3095
							$value[ $k ] = (int) $v;
3096
						}
3097
3098
						// @todo Convert slugs into IDs.
3099
					}
3100
3101
					foreach ( $related_ids as $k => $v ) {
3102
						// @codingStandardsIgnoreLine.
3103
						if ( in_array( $v, $value ) ) {
3104
							unset( $related_ids[ $k ] );
3105
						}
3106
					}
3107
3108
					$value = $related_ids;
3109
				}//end if
3110
3111
				if ( ! empty( $value ) ) {
3112
					$value = array_filter( array_unique( $value ) );
3113
				} else {
3114
					$value = array();
3115
				}
3116
			}//end if
3117 View Code Duplication
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::number_field_types(), true ) ) {
3118
			// Number fields.
3119
			// Date fields don't support empty for removing.
3120
			if ( empty( $value ) ) {
3121
				return $id;
3122
			}
3123
3124
			$current_value = (float) $pod->raw( $field );
3125
3126
			$value = ( $current_value - (float) $value );
3127
		} elseif ( in_array( $this->fields[ $field ]['type'], PodsForm::date_field_types(), true ) ) {
3128
			// Date fields.
3129
			// Date fields don't support empty for removing.
3130
			if ( empty( $value ) ) {
3131
				return $id;
3132
			}
3133
3134
			$current_value = $pod->raw( $field );
3135
3136 View Code Duplication
			if ( 0 < strlen( $current_value ) ) {
3137
				$value = strtotime( $value, strtotime( $current_value ) );
3138
			} else {
3139
				$value = strtotime( $value );
3140
			}
3141
3142
			$value = date_i18n( 'Y-m-d h:i:s', $value );
3143
		}//end if
3144
3145
		// @todo handle object fields and taxonomies.
3146
		$params = array(
3147
			'pod'  => $this->pod,
3148
			'id'   => $id,
3149
			'data' => array(
3150
				$field => $value,
3151
			),
3152
		);
3153
3154
		$id = $this->api->save_pod_item( $params );
3155
3156 View Code Duplication
		if ( 0 < $id && $fetch ) {
3157
			// Clear local var cache of field values.
3158
			$pod->data->row = array();
3159
3160
			$pod->fetch( $id, false );
3161
		}
3162
3163
		return $id;
3164
3165
	}
3166
3167
	/**
3168
	 * Save an item by giving an array of field data or set a specific field to a specific value.
3169
	 *
3170
	 * Though this function has the capacity to add new items, best practice should direct you
3171
	 * to use add() for that instead.
3172
	 *
3173
	 * @see   PodsAPI::save_pod_item
3174
	 *
3175
	 * @param array|string $data   Either an associative array of field information or a field name.
3176
	 * @param mixed        $value  (optional) Value of the field, if $data is a field name.
3177
	 * @param int          $id     (optional) ID of the pod item to update.
3178
	 * @param array        $params (optional) Additional params to send to save_pod_item.
3179
	 *
3180
	 * @return int The item ID
3181
	 *
3182
	 * @since 2.0
3183
	 * @link  https://pods.io/docs/save/
3184
	 */
3185
	public function save( $data = null, $value = null, $id = null, $params = null ) {
3186
3187
		if ( null !== $value ) {
3188
			$data = array( $data => $value );
3189
		}
3190
3191
		$fetch = false;
3192
3193
		// @codingStandardsIgnoreLine
3194
		if ( null === $id || ( $this->row && $id == $this->id() ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->row of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
3195
			$fetch = true;
3196
3197
			if ( null === $id ) {
3198
				$id = $this->id();
3199
			}
3200
		}
3201
3202
		$data = (array) $this->do_hook( 'save', $data, $id );
3203
3204
		if ( empty( $data ) && empty( $params['is_new_item'] ) ) {
3205
			return $id;
3206
		}
3207
3208
		$default = array();
3209
3210
		if ( ! empty( $params ) && is_array( $params ) ) {
3211
			$default = $params;
3212
		}
3213
3214
		$params = array(
3215
			'pod'                 => $this->pod,
3216
			'id'                  => $id,
3217
			'data'                => $data,
3218
			'allow_custom_fields' => true,
3219
			'clear_slug_cache'    => false,
3220
		);
3221
3222
		if ( ! empty( $default ) ) {
3223
			$params = array_merge( $params, $default );
3224
		}
3225
3226
		$id = $this->api->save_pod_item( $params );
3227
3228 View Code Duplication
		if ( 0 < $id && $fetch ) {
3229
			// Clear local var cache of field values.
3230
			$this->data->row = array();
3231
3232
			$this->fetch( $id, false );
3233
		}
3234
3235
		if ( ! empty( $this->pod_data['field_slug'] ) ) {
3236
			if ( 0 < $id && $fetch ) {
3237
				$slug = $this->field( $this->pod_data['field_slug'] );
3238
			} else {
3239
				$slug = pods( $this->pod, $id )->field( $this->pod_data['field_slug'] );
3240
			}
3241
3242
			if ( 0 < strlen( $slug ) ) {
3243
				pods_cache_clear( $slug, 'pods_items_' . $this->pod );
3244
			}
3245
		}
3246
3247
		return $id;
3248
	}
3249
3250
	/**
3251
	 * Delete an item
3252
	 *
3253
	 * @see   PodsAPI::delete_pod_item
3254
	 *
3255
	 * @param int $id ID of the Pod item to delete.
3256
	 *
3257
	 * @return bool Whether the item was successfully deleted
3258
	 *
3259
	 * @since 2.0
3260
	 * @link  https://pods.io/docs/delete/
3261
	 */
3262 View Code Duplication
	public function delete( $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...
3263
3264
		if ( null === $id ) {
3265
			$id = $this->id();
3266
		}
3267
3268
		$id = (int) $this->do_hook( 'delete', $id );
3269
3270
		if ( empty( $id ) ) {
3271
			return false;
3272
		}
3273
3274
		$params = array(
3275
			'pod' => $this->pod,
3276
			'id'  => $id,
3277
		);
3278
3279
		return $this->api->delete_pod_item( $params );
3280
	}
3281
3282
	/**
3283
	 * Reset Pod
3284
	 *
3285
	 * @see   PodsAPI::reset_pod
3286
	 *
3287
	 * @return bool Whether the Pod was successfully reset
3288
	 *
3289
	 * @since 2.1.1
3290
	 */
3291
	public function reset_pod() {
3292
3293
		$params = array( 'id' => $this->pod_id );
3294
3295
		$this->data->id   = null;
3296
		$this->data->row  = array();
3297
		$this->data->data = array();
3298
3299
		$this->data->total       = 0;
3300
		$this->data->total_found = 0;
3301
3302
		return $this->api->reset_pod( $params );
3303
	}
3304
3305
	/**
3306
	 * Duplicate an item
3307
	 *
3308
	 * @see   PodsAPI::duplicate_pod_item
3309
	 *
3310
	 * @param int $id ID of the pod item to duplicate.
3311
	 *
3312
	 * @return int|bool ID of the new pod item
3313
	 *
3314
	 * @since 2.0
3315
	 * @link  https://pods.io/docs/duplicate/
3316
	 */
3317 View Code Duplication
	public function duplicate( $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...
3318
3319
		if ( null === $id ) {
3320
			$id = $this->id();
3321
		}
3322
3323
		$id = (int) $this->do_hook( 'duplicate', $id );
3324
3325
		if ( empty( $id ) ) {
3326
			return false;
3327
		}
3328
3329
		$params = array(
3330
			'pod' => $this->pod,
3331
			'id'  => $id,
3332
		);
3333
3334
		return $this->api->duplicate_pod_item( $params );
3335
	}
3336
3337
	/**
3338
	 * Import data / Save multiple rows of data at once
3339
	 *
3340
	 * @see   PodsAPI::import
3341
	 *
3342
	 * @param mixed  $import_data  PHP associative array or CSV input.
3343
	 * @param bool   $numeric_mode Use IDs instead of the name field when matching.
3344
	 * @param string $format       Format of import data, options are php or csv.
3345
	 *
3346
	 * @return array IDs of imported items
3347
	 *
3348
	 * @since 2.3
3349
	 */
3350
	public function import( $import_data, $numeric_mode = false, $format = null ) {
3351
3352
		return $this->api->import( $import_data, $numeric_mode, $format );
3353
	}
3354
3355
	/**
3356
	 * Export an item's data
3357
	 *
3358
	 * @see   PodsAPI::export_pod_item
3359
	 *
3360
	 * @param array       $fields (optional) Fields to export.
3361
	 * @param int         $id     (optional) ID of the pod item to export.
3362
	 * @param null|string $format (optional) The format of the export (php | json).
3363
	 *
3364
	 * @return array|bool Data array of the exported pod item
3365
	 *
3366
	 * @since 2.0
3367
	 * @link  https://pods.io/docs/export/
3368
	 */
3369
	public function export( $fields = null, $id = null, $format = null ) {
3370
3371
		$params = array(
3372
			'pod'     => $this->pod,
3373
			'id'      => $id,
3374
			'fields'  => null,
3375
			'depth'   => 2,
3376
			'flatten' => false,
3377
			'context' => null,
3378
			'format'  => $format,
3379
		);
3380
3381 View Code Duplication
		if ( is_array( $fields ) && ( isset( $fields['fields'] ) || isset( $fields['depth'] ) ) ) {
3382
			$params = array_merge( $params, $fields );
3383
		} else {
3384
			$params['fields'] = $fields;
3385
		}
3386
3387
		if ( isset( $params['fields'] ) && is_array( $params['fields'] ) && ! in_array( $this->pod_data['field_id'], $params['fields'], true ) ) {
3388
			$params['fields'] = array_merge( array( $this->pod_data['field_id'] ), $params['fields'] );
3389
		}
3390
3391
		if ( null === $params['id'] ) {
3392
			$params['id'] = $this->id();
3393
		}
3394
3395
		$params = (array) $this->do_hook( 'export', $params );
3396
3397
		if ( empty( $params['id'] ) ) {
3398
			return false;
3399
		}
3400
3401
		$data = $this->api->export_pod_item( $params );
3402
3403
		if ( ! empty( $params['format'] ) && 'json' === $params['format'] ) {
3404
			$data = wp_json_encode( (array) $data );
3405
		}
3406
3407
		return $data;
3408
	}
3409
3410
	/**
3411
	 * Export data from all items
3412
	 *
3413
	 * @see   PodsAPI::export
3414
	 *
3415
	 * @param array $params An associative array of parameters.
3416
	 *
3417
	 * @return array Data arrays of all exported pod items
3418
	 *
3419
	 * @since 2.3
3420
	 */
3421
	public function export_data( $params = null ) {
3422
3423
		$defaults = array(
3424
			'fields' => null,
3425
			'depth'  => 2,
3426
			'params' => null,
3427
		);
3428
3429
		if ( empty( $params ) ) {
3430
			$params = $defaults;
3431
		} else {
3432
			$params = array_merge( $defaults, (array) $params );
3433
		}
3434
3435
		return $this->api->export( $this, $params );
3436
	}
3437
3438
	/**
3439
	 * Display the pagination controls, types supported by default
3440
	 * are simple, paginate and advanced. The base and format parameters
3441
	 * are used only for the paginate view.
3442
	 *
3443
	 * @param array|object $params Associative array of parameters.
3444
	 *
3445
	 * @return string Pagination HTML
3446
	 * @since 2.0
3447
	 * @link  https://pods.io/docs/pagination/
3448
	 */
3449
	public function pagination( $params = null ) {
3450
3451
		if ( empty( $params ) ) {
3452
			$params = array();
3453
		} elseif ( ! is_array( $params ) ) {
3454
			$params = array( 'label' => $params );
3455
		}
3456
3457
		$this->page_var = pods_v( 'page_var', $params, $this->page_var );
3458
3459
		$url = pods_query_arg( null, null, $this->page_var );
3460
3461
		$append = '?';
3462
3463
		if ( false !== strpos( $url, '?' ) ) {
3464
			$append = '&';
3465
		}
3466
3467
		$defaults = array(
3468
			'type'        => 'advanced',
3469
			'label'       => __( 'Go to page:', 'pods' ),
3470
			'show_label'  => true,
3471
			'first_text'  => __( '&laquo; First', 'pods' ),
3472
			'prev_text'   => __( '&lsaquo; Previous', 'pods' ),
3473
			'next_text'   => __( 'Next &rsaquo;', 'pods' ),
3474
			'last_text'   => __( 'Last &raquo;', 'pods' ),
3475
			'prev_next'   => true,
3476
			'first_last'  => true,
3477
			'limit'       => (int) $this->limit,
3478
			'offset'      => (int) $this->offset,
3479
			'page'        => max( 1, (int) $this->page ),
3480
			'mid_size'    => 2,
3481
			'end_size'    => 1,
3482
			'total_found' => $this->total_found(),
3483
			'page_var'    => $this->page_var,
3484
			'base'        => "{$url}{$append}%_%",
3485
			'format'      => "{$this->page_var}=%#%",
3486
			'class'       => '',
3487
			'link_class'  => '',
3488
		);
3489
3490
		if ( is_object( $params ) ) {
3491
			$params = get_object_vars( $params );
3492
		}
3493
3494
		$params = (object) array_merge( $defaults, (array) $params );
3495
3496
		$params->total = $this->total_pages( $params->limit, $params->offset, $params->total_found );
3497
3498
		if ( $params->limit < 1 || $params->total_found < 1 || 1 === $params->total || $params->total_found <= $params->offset ) {
3499
			return $this->do_hook( 'pagination', $this->do_hook( 'pagination_' . $params->type, '', $params ), $params );
3500
		}
3501
3502
		$pagination = $params->type;
3503
3504
		if ( ! in_array( $params->type, array( 'simple', 'advanced', 'paginate', 'list' ), true ) ) {
3505
			$pagination = 'advanced';
3506
		}
3507
3508
		ob_start();
3509
3510
		pods_view( PODS_DIR . 'ui/front/pagination/' . $pagination . '.php', compact( array_keys( get_defined_vars() ) ) );
3511
3512
		$output = ob_get_clean();
3513
3514
		return $this->do_hook( 'pagination', $this->do_hook( 'pagination_' . $params->type, $output, $params ), $params );
3515
3516
	}
3517
3518
	/**
3519
	 * Return a filter form for searching a Pod
3520
	 *
3521
	 * @param array|string $params Comma-separated list of fields or array of parameters.
3522
	 *
3523
	 * @return string Filters HTML
3524
	 *
3525
	 * @since 2.0
3526
	 * @link  https://pods.io/docs/filters/
3527
	 */
3528
	public function filters( $params = null ) {
3529
3530
		$defaults = array(
3531
			'fields' => $params,
3532
			'label'  => '',
3533
			'action' => '',
3534
			'search' => '',
3535
		);
3536
3537
		if ( is_array( $params ) ) {
3538
			$params = array_merge( $defaults, $params );
3539
		} else {
3540
			$params = $defaults;
3541
		}
3542
3543
		$pod =& $this;
3544
3545
		/**
3546
		 * Filter the Pods::filters() parameters.
3547
		 *
3548
		 * @param array $params Parameters to filter with.
3549
		 * @param Pods  $pod    Pods object.
3550
		 */
3551
		$params = apply_filters( 'pods_filters_params', $params, $pod );
3552
3553
		$fields = $params['fields'];
3554
3555 View Code Duplication
		if ( null !== $fields && ! is_array( $fields ) && 0 < strlen( $fields ) ) {
3556
			$fields = explode( ',', $fields );
3557
		}
3558
3559
		$object_fields = (array) pods_v( 'object_fields', $this->pod_data, array(), true );
3560
3561
		// Force array.
3562
		if ( empty( $fields ) ) {
3563
			$fields = array();
3564
		} else {
3565
			// Temporary.
3566
			$filter_fields = $fields;
3567
3568
			$fields = array();
3569
3570
			foreach ( $filter_fields as $k => $field ) {
3571
				$name = $k;
3572
3573
				$defaults = array(
3574
					'name' => $name,
3575
				);
3576
3577
				if ( ! is_array( $field ) ) {
3578
					$name = $field;
3579
3580
					$field = array(
3581
						'name' => $name,
3582
					);
3583
				}
3584
3585
				// @codingStandardsIgnoreLine.
3586
				$field = array_merge( $defaults, $field );
3587
3588
				$field['name'] = trim( $field['name'] );
3589
3590
				if ( pods_v( 'hidden', $field, false, true ) ) {
3591
					$field['type'] = 'hidden';
3592
				}
3593
3594
				if ( isset( $object_fields[ $field['name'] ] ) ) {
3595
					// @codingStandardsIgnoreLine.
3596
					$fields[ $field['name'] ] = array_merge( $object_fields[ $field['name'] ], $field );
3597
				} elseif ( isset( $this->fields[ $field['name'] ] ) ) {
3598
					// @codingStandardsIgnoreLine.
3599
					$fields[ $field['name'] ] = array_merge( $this->fields[ $field['name'] ], $field );
3600
				}
3601
			}//end foreach
3602
3603
			// Cleanup.
3604
			unset( $filter_fields );
3605
		}//end if
3606
3607
		$this->filters = array_keys( $fields );
3608
3609
		$label = $params['label'];
3610
3611
		if ( '' === $label ) {
3612
			$label = __( 'Search', 'pods' );
3613
		}
3614
3615
		$action = $params['action'];
3616
3617
		$search = trim( $params['search'] );
3618
3619
		if ( '' === $search ) {
3620
			$search = pods_v_sanitized( $pod->search_var, 'get', '' );
3621
		}
3622
3623
		ob_start();
3624
3625
		pods_view( PODS_DIR . 'ui/front/filters.php', compact( array_keys( get_defined_vars() ) ) );
3626
3627
		$output = ob_get_clean();
3628
3629
		/**
3630
		 * Filter the HTML output of filters()
3631
		 *
3632
		 * @since unknown
3633
		 *
3634
		 * @param string      $output Filter output.
3635
		 * @param array       $params Params array passed to filters().
3636
		 * @param object|Pods $this   Current Pods object.
3637
		 */
3638
		return apply_filters( 'pods_pods_filters', $output, $params, $this );
3639
	}
3640
3641
	/**
3642
	 * Run a helper within a Pod Page or WP Template
3643
	 *
3644
	 * @see   Pods_Helpers::helper
3645
	 *
3646
	 * @param string|array $helper Helper name.
3647
	 * @param string       $value  Value to run the helper on.
3648
	 * @param string       $name   Field name.
3649
	 *
3650
	 * @return mixed Anything returned by the helper
3651
	 * @since 2.0
3652
	 */
3653
	public function helper( $helper, $value = null, $name = null ) {
3654
3655
		$params = array(
3656
			'helper'     => $helper,
3657
			'value'      => $value,
3658
			'name'       => $name,
3659
			'deprecated' => false,
3660
		);
3661
3662
		if ( class_exists( 'Pods_Templates' ) ) {
3663
			$params['deprecated'] = Pods_Templates::$deprecated;
3664
		}
3665
3666
		if ( is_array( $helper ) ) {
3667
			$params = array_merge( $params, $helper );
3668
		}
3669
3670
		if ( class_exists( 'Pods_Helpers' ) ) {
3671
			$value = Pods_Helpers::helper( $params, $this );
3672
		} elseif ( function_exists( $params['helper'] ) ) {
3673
			$disallowed = array(
3674
				'system',
3675
				'exec',
3676
				'popen',
3677
				'eval',
3678
				'preg_replace',
3679
				'create_function',
3680
				'include',
3681
				'include_once',
3682
				'require',
3683
				'require_once',
3684
			);
3685
3686
			$allowed = array();
3687
3688
			/**
3689
			 * Allows adjusting the disallowed callbacks as needed.
3690
			 *
3691
			 * @param array $disallowed List of callbacks not allowed.
3692
			 * @param array $params     Parameters used by Pods::helper() method.
3693
			 *
3694
			 * @since 2.7
3695
			 */
3696
			$disallowed = apply_filters( 'pods_helper_disallowed_callbacks', $disallowed, $params );
3697
3698
			/**
3699
			 * Allows adjusting the allowed allowed callbacks as needed.
3700
			 *
3701
			 * @param array $allowed List of callbacks explicitly allowed.
3702
			 * @param array $params  Parameters used by Pods::helper() method.
3703
			 *
3704
			 * @since 2.7
3705
			 */
3706
			$allowed = apply_filters( 'pods_helper_allowed_callbacks', $allowed, $params );
3707
3708
			// Clean up helper callback (if string).
3709
			if ( is_string( $params['helper'] ) ) {
3710
				$params['helper'] = strip_tags( str_replace( array( '`', chr( 96 ) ), "'", $params['helper'] ) );
3711
			}
3712
3713
			$is_allowed = false;
3714
3715
			if ( ! empty( $allowed ) ) {
3716
				if ( in_array( $params['helper'], $allowed, true ) ) {
3717
					$is_allowed = true;
3718
				}
3719
			} elseif ( ! in_array( $params['helper'], $disallowed, true ) ) {
3720
				$is_allowed = true;
3721
			}
3722
3723
			if ( $is_allowed ) {
3724
				$value = call_user_func( $params['helper'], $value );
3725
			}
3726
		} else {
3727
			$value = apply_filters( $params['helper'], $value );
3728
		}//end if
3729
3730
		return $value;
3731
	}
3732
3733
	/**
3734
	 * Display the page template
3735
	 *
3736
	 * @see   Pods_Templates::template
3737
	 *
3738
	 * @param string      $template_name The template name.
3739
	 * @param string|null $code          Custom template code to use instead.
3740
	 * @param bool        $deprecated    Whether to use deprecated functionality based on old function usage.
3741
	 *
3742
	 * @return mixed Template output
3743
	 *
3744
	 * @since 2.0
3745
	 * @link  https://pods.io/docs/template/
3746
	 */
3747
	public function template( $template_name, $code = null, $deprecated = false ) {
3748
3749
		$out = null;
3750
3751
		$obj =& $this;
3752
3753
		if ( ! empty( $code ) ) {
3754
			// backwards compatibility.
3755
			$code = str_replace( '$this->', '$obj->', $code );
3756
3757
			/**
3758
			 * Filter the template code before running it.
3759
			 *
3760
			 * @param string $code          Template code.
3761
			 * @param string $template_name Template name.
3762
			 * @param Pods  $pod            Pods object.
3763
			 */
3764
			$code = apply_filters( 'pods_templates_pre_template', $code, $template_name, $this );
3765
3766
			/**
3767
			 * Filter the template code before running it.
3768
			 *
3769
			 * @param string $code          Template code.
3770
			 * @param string $template_name Template name.
3771
			 * @param Pods  $pod            Pods object.
3772
			 */
3773
			$code = apply_filters( "pods_templates_pre_template_{$template_name}", $code, $template_name, $this );
3774
3775
			ob_start();
3776
3777
			if ( ! empty( $code ) ) {
3778
				// Only detail templates need $this->id.
3779
				if ( empty( $this->id ) ) {
3780
					while ( $this->fetch() ) {
3781
						// @codingStandardsIgnoreLine
3782
						echo $this->do_magic_tags( $code );
3783
					}
3784
				} else {
3785
					// @codingStandardsIgnoreLine
3786
					echo $this->do_magic_tags( $code );
3787
				}
3788
			}
3789
3790
			$out = ob_get_clean();
3791
3792
			/**
3793
			 * Filter the template output.
3794
			 *
3795
			 * @param string $out           Template output.
3796
			 * @param string $code          Template code.
3797
			 * @param string $template_name Template name.
3798
			 * @param Pods   $pod           Pods object.
3799
			 */
3800
			$out = apply_filters( 'pods_templates_post_template', $out, $code, $template_name, $this );
3801
3802
			/**
3803
			 * Filter the template output.
3804
			 *
3805
			 * @param string $out           Template output.
3806
			 * @param string $code          Template code.
3807
			 * @param string $template_name Template name.
3808
			 * @param Pods   $pod           Pods object.
3809
			 */
3810
			$out = apply_filters( "pods_templates_post_template_{$template_name}", $out, $code, $template_name, $this );
3811
		} elseif ( class_exists( 'Pods_Templates' ) ) {
3812
			$out = Pods_Templates::template( $template_name, $code, $this, $deprecated );
3813
		} elseif ( trim( preg_replace( '/[^a-zA-Z0-9_\-\/]/', '', $template_name ), ' /-' ) === $template_name ) {
3814
			ob_start();
3815
3816
			$default_templates = array(
3817
				'pods/' . $template_name,
3818
				'pods-' . $template_name,
3819
				$template_name,
3820
			);
3821
3822
			/**
3823
			 * Filter the default Pods Template files.
3824
			 *
3825
			 * @param array $default_templates Default Pods Template files.
3826
			 */
3827
			$default_templates = apply_filters( 'pods_template_default_templates', $default_templates );
3828
3829
			// Only detail templates need $this->id.
3830 View Code Duplication
			if ( empty( $this->id ) ) {
3831
				while ( $this->fetch() ) {
3832
					pods_template_part( $default_templates, compact( array_keys( get_defined_vars() ) ) );
3833
				}
3834
			} else {
3835
				pods_template_part( $default_templates, compact( array_keys( get_defined_vars() ) ) );
3836
			}
3837
3838
			$out = ob_get_clean();
3839
3840
			/**
3841
			 * Filter the template output.
3842
			 *
3843
			 * @param string $out           Template output.
3844
			 * @param string $code          Template code.
3845
			 * @param string $template_name Template name.
3846
			 * @param Pods   $pod           Pods object.
3847
			 */
3848
			$out = apply_filters( 'pods_templates_post_template', $out, $code, $template_name, $this );
3849
3850
			/**
3851
			 * Filter the template output.
3852
			 *
3853
			 * @param string $out           Template output.
3854
			 * @param string $code          Template code.
3855
			 * @param string $template_name Template name.
3856
			 * @param Pods   $pod           Pods object.
3857
			 */
3858
			$out = apply_filters( "pods_templates_post_template_{$template_name}", $out, $code, $template_name, $this );
3859
		}//end if
3860
3861
		return $out;
3862
	}
3863
3864
	/**
3865
	 * Embed a form to add / edit a pod item from within your theme. Provide an array of $fields to include
3866
	 * and override options where needed. For WP object based Pods, you can pass through the WP object
3867
	 * field names too, such as "post_title" or "post_content" for example.
3868
	 *
3869
	 * @param array  $params    (optional) Fields to show on the form, defaults to all fields.
3870
	 * @param string $label     (optional) Save button label, defaults to "Save Changes".
3871
	 * @param string $thank_you (optional) Thank you URL to send to upon success.
3872
	 *
3873
	 * @return bool|mixed
3874
	 * @since 2.0
3875
	 * @link  https://pods.io/docs/form/
3876
	 */
3877
	public function form( $params = null, $label = null, $thank_you = null ) {
3878
3879
		$defaults = array(
3880
			'fields'      => $params,
3881
			'label'       => $label,
3882
			'thank_you'   => $thank_you,
3883
			'fields_only' => false,
3884
		);
3885
3886
		if ( is_array( $params ) ) {
3887
			$params = array_merge( $defaults, $params );
3888
		} else {
3889
			$params = $defaults;
3890
		}
3891
3892
		$pod =& $this;
3893
3894
		$params = $this->do_hook( 'form_params', $params );
3895
3896
		$fields = $params['fields'];
3897
3898 View Code Duplication
		if ( null !== $fields && ! is_array( $fields ) && 0 < strlen( $fields ) ) {
3899
			$fields = explode( ',', $fields );
3900
		}
3901
3902
		$object_fields = (array) pods_v( 'object_fields', $this->pod_data, array(), true );
3903
3904
		if ( empty( $fields ) ) {
3905
			// Add core object fields if $fields is empty.
3906
			$fields = array_merge( $object_fields, $this->fields );
3907
		}
3908
3909
		// Temporary.
3910
		$form_fields = $fields;
3911
3912
		$fields = array();
3913
3914
		foreach ( $form_fields as $k => $field ) {
3915
			$name = $k;
3916
3917
			$defaults = array(
3918
				'name' => $name,
3919
			);
3920
3921
			if ( ! is_array( $field ) ) {
3922
				$name = $field;
3923
3924
				$field = array(
3925
					'name' => $name,
3926
				);
3927
			}
3928
3929
			// @codingStandardsIgnoreLine.
3930
			$field = array_merge( $defaults, $field );
3931
3932
			$field['name'] = trim( $field['name'] );
3933
3934
			$default_value = pods_v( 'default', $field );
3935
			$value         = pods_v( 'value', $field );
3936
3937
			if ( empty( $field['name'] ) ) {
3938
				$field['name'] = trim( $name );
3939
			}
3940
3941 View Code Duplication
			if ( isset( $object_fields[ $field['name'] ] ) ) {
3942
				// @codingStandardsIgnoreLine.
3943
				$field = array_merge( $object_fields[ $field['name'] ], $field );
3944
			} elseif ( isset( $this->fields[ $field['name'] ] ) ) {
3945
				// @codingStandardsIgnoreLine.
3946
				$field = array_merge( $this->fields[ $field['name'] ], $field );
3947
			}
3948
3949
			if ( pods_v( 'hidden', $field, false, true ) ) {
3950
				$field['type'] = 'hidden';
3951
			}
3952
3953
			$fields[ $field['name'] ] = $field;
3954
3955 View Code Duplication
			if ( empty( $this->id ) && null !== $default_value ) {
3956
				$this->row_override[ $field['name'] ] = $default_value;
3957
			} elseif ( ! empty( $this->id ) && null !== $value ) {
3958
				$this->row[ $field['name'] ] = $value;
3959
			}
3960
		}//end foreach
3961
3962
		// Cleanup.
3963
		unset( $form_fields );
3964
3965
		$fields = $this->do_hook( 'form_fields', $fields, $params );
3966
3967
		$label = $params['label'];
3968
3969
		if ( empty( $label ) ) {
3970
			$label = __( 'Save Changes', 'pods' );
3971
		}
3972
3973
		$thank_you   = $params['thank_you'];
3974
		$fields_only = $params['fields_only'];
3975
3976
		PodsForm::$form_counter ++;
3977
3978
		ob_start();
3979
3980
		if ( empty( $thank_you ) ) {
3981
			$success = 'success';
3982
3983
			if ( 1 < PodsForm::$form_counter ) {
3984
				$success .= PodsForm::$form_counter;
3985
			}
3986
3987
			$thank_you = pods_query_arg( array(
3988
				'success*' => null,
3989
				$success   => 1,
3990
			) );
3991
3992
			if ( 1 === (int) pods_v( $success, 'get', 0 ) ) {
3993
				$message = __( 'Form submitted successfully', 'pods' );
3994
3995
				/**
3996
				 * Change the text of the message that appears on successful form submission.
3997
				 *
3998
				 * @param string $message Success message.
3999
				 *
4000
				 * @since 2.7
4001
				 */
4002
				$message = apply_filters( 'pods_pod_form_success_message', $message );
4003
4004
				echo '<div id="message" class="pods-form-front-success">' . wp_kses_post( $message ) . '</div>';
4005
			}
4006
		}//end if
4007
4008
		pods_view( PODS_DIR . 'ui/front/form.php', compact( array_keys( get_defined_vars() ) ) );
4009
4010
		$output = ob_get_clean();
4011
4012
		if ( empty( $this->id ) ) {
4013
			$this->row_override = array();
4014
		}
4015
4016
		return $this->do_hook( 'form', $output, $fields, $label, $thank_you, $this, $this->id() );
4017
	}
4018
4019
	/**
4020
	 * Render a singular view for the Pod item content.
4021
	 *
4022
	 * @param array|string|null $fields (optional) Fields to show in the view, defaults to all fields.
4023
	 *
4024
	 * @return mixed
4025
	 * @since 2.3.10
4026
	 */
4027
	public function view( $fields = null ) {
4028
4029
		$pod =& $this;
4030
4031
		// Convert comma separated list of fields to an array.
4032 View Code Duplication
		if ( null !== $fields && ! is_array( $fields ) && 0 < strlen( $fields ) ) {
4033
			$fields = explode( ',', $fields );
4034
		}
4035
4036
		$object_fields = (array) pods_v( 'object_fields', $this->pod_data, array(), true );
4037
4038
		if ( empty( $fields ) ) {
4039
			// Add core object fields if $fields is empty.
4040
			$fields = array_merge( $object_fields, $this->fields );
4041
		}
4042
4043
		// Temporary.
4044
		$view_fields = $fields;
4045
4046
		$fields = array();
4047
4048
		foreach ( $view_fields as $name => $field ) {
0 ignored issues
show
Bug introduced by
The expression $view_fields of type array|string 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...
4049
			$defaults = array(
4050
				'name' => $name,
4051
			);
4052
4053
			if ( ! is_array( $field ) ) {
4054
				$name = $field;
4055
4056
				$field = array(
4057
					'name' => $name,
4058
				);
4059
			}
4060
4061
			// @codingStandardsIgnoreLine.
4062
			$field = array_merge( $defaults, $field );
4063
4064
			$field['name'] = trim( $field['name'] );
4065
4066
			if ( empty( $field['name'] ) ) {
4067
				$field['name'] = trim( $name );
4068
			}
4069
4070 View Code Duplication
			if ( isset( $object_fields[ $field['name'] ] ) ) {
4071
				// @codingStandardsIgnoreLine.
4072
				$field = array_merge( $field, $object_fields[ $field['name'] ] );
4073
			} elseif ( isset( $this->fields[ $field['name'] ] ) ) {
4074
				// @codingStandardsIgnoreLine.
4075
				$field = array_merge( $this->fields[ $field['name'] ], $field );
4076
			}
4077
4078 View Code Duplication
			if ( pods_v( 'hidden', $field, false, true ) || 'hidden' === $field['type'] ) {
4079
				continue;
4080
			} elseif ( ! PodsForm::permission( $field['type'], $field['name'], $field['options'], $fields, $pod, $pod->id() ) ) {
4081
				continue;
4082
			}
4083
4084
			$fields[ $field['name'] ] = $field;
4085
		}//end foreach
4086
4087
		// Cleanup.
4088
		unset( $view_fields );
4089
4090
		$output = pods_view( PODS_DIR . 'ui/front/view.php', compact( array_keys( get_defined_vars() ) ), false, 'cache', true );
4091
4092
		return $this->do_hook( 'view', $output, $fields, $this->id() );
4093
4094
	}
4095
4096
	/**
4097
	 * Replace magic tags with their values
4098
	 *
4099
	 * @param string $code The content to evaluate.
4100
	 *
4101
	 * @return string Code with Magic Tags evaluated
4102
	 *
4103
	 * @since 2.0
4104
	 */
4105
	public function do_magic_tags( $code ) {
4106
4107
		/**
4108
		 * Filters the Pods magic tags content before the default function.
4109
		 * Allows complete replacement of the Pods magic tag engine.
4110
		 *
4111
		 * @param null   $pre  Default is null which processes magic tags normally. Return any other value to override.
4112
		 * @param string $code The content to evaluate.
4113
		 * @param Pods   $pods The Pods Object.
4114
		 *
4115
		 * @since 2.7
4116
		 */
4117
		$pre = apply_filters( 'pods_pre_do_magic_tags', null, $code, $this );
4118
		if ( null !== $pre ) {
4119
			return $pre;
4120
		}
4121
4122
		return preg_replace_callback( '/({@(.*?)})/m', array( $this, 'process_magic_tags' ), $code );
4123
	}
4124
4125
	/**
4126
	 * Replace magic tags with their values
4127
	 *
4128
	 * @param string|array $tag The magic tag to process.
4129
	 *
4130
	 * @return string Code with Magic Tags evaluated
4131
	 *
4132
	 * @since 2.0.2
4133
	 */
4134
	private function process_magic_tags( $tag ) {
4135
4136
		if ( is_array( $tag ) ) {
4137
			if ( ! isset( $tag[2] ) && '' === trim( $tag[2] ) ) {
4138
				return '';
4139
			}
4140
4141
			$tag = $tag[2];
4142
		}
4143
4144
		$tag = trim( $tag, ' {@}' );
4145
		$tag = explode( ',', $tag );
4146
4147
		if ( empty( $tag ) || ! isset( $tag[0] ) || '' === trim( $tag[0] ) ) {
4148
			return '';
4149
		}
4150
4151
		foreach ( $tag as $k => $v ) {
4152
			$tag[ $k ] = trim( $v );
4153
		}
4154
4155
		$field_name = $tag[0];
4156
4157
		$helper_name = '';
4158
		$before      = '';
4159
		$after       = '';
4160
4161
		if ( isset( $tag[1] ) && ! empty( $tag[1] ) ) {
4162
			$value = $this->field( $field_name );
4163
4164
			$helper_name = $tag[1];
4165
4166
			$value = $this->helper( $helper_name, $value, $field_name );
4167
		} else {
4168
			$value = $this->display( $field_name );
4169
		}
4170
4171
		if ( isset( $tag[2] ) && ! empty( $tag[2] ) ) {
4172
			$before = $tag[2];
4173
		}
4174
4175
		if ( isset( $tag[3] ) && ! empty( $tag[3] ) ) {
4176
			$after = $tag[3];
4177
		}
4178
4179
		/**
4180
		 * Filter the magic tag output for a value.
4181
		 *
4182
		 * @param string $value      Magic tag output for value.
4183
		 * @param string $field_name Magic tag field name.
4184
		 * @param string $before     Before content.
4185
		 * @param string $after      After content.
4186
		 */
4187
		$value = apply_filters( 'pods_do_magic_tags', $value, $field_name, $helper_name, $before, $after );
4188
4189 View Code Duplication
		if ( is_array( $value ) ) {
4190
			$value = pods_serial_comma( $value, array(
4191
				'field'  => $field_name,
4192
				'fields' => $this->fields,
4193
			) );
4194
		}
4195
4196 View Code Duplication
		if ( null !== $value && false !== $value ) {
4197
			return $before . $value . $after;
4198
		}
4199
4200
		return '';
4201
	}
4202
4203
	/**
4204
	 *
4205
	 * Generate UI for Data Management
4206
	 *
4207
	 * @param mixed $options Array or String containing Pod or Options to be used.
4208
	 * @param bool  $amend   Whether to amend the default UI options or replace entirely.
4209
	 *
4210
	 * @return PodsUI|null UI object or null if custom UI used
4211
	 *
4212
	 * @since 2.3.10
4213
	 */
4214
	public function ui( $options = null, $amend = false ) {
4215
4216
		$num = '';
4217
4218
		if ( empty( $options ) ) {
4219
			$options = array();
4220
		} else {
4221
			$num = pods_v_sanitized( 'num', $options, '' );
4222
4223
			if ( empty( $num ) ) {
4224
				$num = '';
4225
			}
4226
		}
4227
4228
		$check_id = pods_v( 'id' . $num, 'get', null, true );
4229
4230
		// @codingStandardsIgnoreLine
4231
		if ( $this->id() != $check_id ) {
4232
			$this->fetch( $check_id );
4233
		}
4234
4235
		if ( ! empty( $options ) && ! $amend ) {
4236
			$this->ui = $options;
4237
4238
			return pods_ui( $this );
4239
		} elseif ( ! empty( $options ) || 'custom' !== pods_v( 'ui_style', $this->pod_data['options'], 'post_type', true ) ) {
4240
			$actions_enabled = pods_v( 'ui_actions_enabled', $this->pod_data['options'] );
4241
4242
			if ( ! empty( $actions_enabled ) ) {
4243
				$actions_enabled = (array) $actions_enabled;
4244
			} else {
4245
				$actions_enabled = array();
4246
			}
4247
4248
			$available_actions = array(
4249
				'add',
4250
				'edit',
4251
				'duplicate',
4252
				'delete',
4253
				'reorder',
4254
				'export',
4255
			);
4256
4257
			if ( ! empty( $actions_enabled ) ) {
4258
				$actions_disabled = array(
4259
					'view' => 'view',
4260
				);
4261
4262 View Code Duplication
				foreach ( $available_actions as $action ) {
4263
					if ( ! in_array( $action, $actions_enabled, true ) ) {
4264
						$actions_disabled[ $action ] = $action;
4265
					}
4266
				}
4267
			} else {
4268
				$actions_disabled = array(
4269
					'duplicate' => 'duplicate',
4270
					'view'      => 'view',
4271
					'export'    => 'export',
4272
				);
4273
4274
				if ( 1 === pods_v( 'ui_export', $this->pod_data['options'], 0 ) ) {
4275
					unset( $actions_disabled['export'] );
4276
				}
4277
			}//end if
4278
4279
			if ( empty( $options ) ) {
4280
				$author_restrict = false;
4281
4282
				if ( isset( $this->fields['author'] ) && 'pick' === $this->fields['author']['type'] && 'user' === $this->fields['author']['pick_object'] ) {
4283
					$author_restrict = 'author.ID';
4284
				}
4285
4286
				if ( ! pods_is_admin( array( 'pods', 'pods_content' ) ) ) {
4287
					if ( ! current_user_can( 'pods_add_' . $this->pod ) ) {
4288
						$actions_disabled['add'] = 'add';
4289
4290
						if ( 'add' === pods_v( 'action' . $num, 'get' ) ) {
4291
							$_GET[ 'action' . $num ] = 'manage';
4292
						}
4293
					}
4294
4295 View Code Duplication
					if ( ! $author_restrict && ! current_user_can( 'pods_edit_' . $this->pod ) && ! current_user_can( 'pods_edit_others_' . $this->pod ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $author_restrict of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
4296
						$actions_disabled['edit'] = 'edit';
4297
					}
4298
4299 View Code Duplication
					if ( ! $author_restrict && ! current_user_can( 'pods_delete_' . $this->pod ) && ! current_user_can( 'pods_delete_others_' . $this->pod ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $author_restrict of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
4300
						$actions_disabled['delete'] = 'delete';
4301
					}
4302
4303
					if ( ! current_user_can( 'pods_reorder_' . $this->pod ) ) {
4304
						$actions_disabled['reorder'] = 'reorder';
4305
					}
4306
4307
					if ( ! current_user_can( 'pods_export_' . $this->pod ) ) {
4308
						$actions_disabled['export'] = 'export';
4309
					}
4310
				}//end if
4311
			}//end if
4312
4313
			$_GET[ 'action' . $num ] = pods_v_sanitized( 'action' . $num, 'get', pods_v( 'action', $options, 'manage' ), true );
4314
4315
			$index = $this->pod_data['field_id'];
4316
			$label = __( 'ID', 'pods' );
4317
4318
			if ( isset( $this->pod_data['fields'][ $this->pod_data['field_index'] ] ) ) {
4319
				$index = $this->pod_data['field_index'];
4320
				$label = $this->pod_data['fields'][ $this->pod_data['field_index'] ];
4321
			}
4322
4323
			$manage = array(
4324
				$index => $label,
4325
			);
4326
4327
			if ( isset( $this->pod_data['fields']['modified'] ) ) {
4328
				$manage['modified'] = $this->pod_data['fields']['modified']['label'];
4329
			}
4330
4331
			$manage_fields = (array) pods_v( 'ui_fields_manage', $this->pod_data['options'] );
4332
4333
			if ( ! empty( $manage_fields ) ) {
4334
				$manage_new = array();
4335
4336
				foreach ( $manage_fields as $manage_field ) {
4337
					if ( isset( $this->pod_data['fields'][ $manage_field ] ) ) {
4338
						$manage_new[ $manage_field ] = $this->pod_data['fields'][ $manage_field ];
4339
					} elseif ( isset( $this->pod_data['object_fields'][ $manage_field ] ) ) {
4340
						$manage_new[ $manage_field ] = $this->pod_data['object_fields'][ $manage_field ];
4341
					} elseif ( $manage_field === $this->pod_data['field_id'] ) {
4342
						$field = array(
4343
							'name'  => $manage_field,
4344
							'label' => 'ID',
4345
							'type'  => 'number',
4346
							'width' => '8%',
4347
						);
4348
4349
						$manage_new[ $manage_field ] = PodsForm::field_setup( $field, null, $field['type'] );
4350
					}
4351
				}
4352
4353
				if ( ! empty( $manage_new ) ) {
4354
					$manage = $manage_new;
4355
				}
4356
			}//end if
4357
4358
			$manage = apply_filters( 'pods_admin_ui_fields_' . $this->pod, apply_filters( 'pods_admin_ui_fields', $manage, $this->pod, $this ), $this->pod, $this );
4359
4360
			$icon = pods_v( 'ui_icon', $this->pod_data['options'] );
4361
4362
			if ( ! empty( $icon ) ) {
4363
				$icon = pods_image_url( $icon, '32x32' );
4364
			}
4365
4366
			$filters = pods_v( 'ui_filters', $this->pod_data['options'] );
4367
4368
			if ( ! empty( $filters ) ) {
4369
				$filters_new = array();
4370
4371
				$filters = (array) $filters;
4372
4373
				foreach ( $filters as $filter_field ) {
4374
					if ( isset( $this->pod_data['fields'][ $filter_field ] ) ) {
4375
						$filters_new[ $filter_field ] = $this->pod_data['fields'][ $filter_field ];
4376
					} elseif ( isset( $this->pod_data['object_fields'][ $filter_field ] ) ) {
4377
						$filters_new[ $filter_field ] = $this->pod_data['object_fields'][ $filter_field ];
4378
					}
4379
				}
4380
4381
				$filters = $filters_new;
4382
			}
4383
4384
			$ui = array(
4385
				'fields'           => array(
4386
					'manage'    => $manage,
4387
					'add'       => $this->pod_data['fields'],
4388
					'edit'      => $this->pod_data['fields'],
4389
					'duplicate' => $this->pod_data['fields'],
4390
				),
4391
				'icon'             => $icon,
4392
				'actions_disabled' => $actions_disabled,
4393
				'actions_bulk'     => array(),
4394
			);
4395
4396
			if ( ! empty( $filters ) ) {
4397
				$ui['fields']['search'] = $filters;
4398
				$ui['filters']          = array_keys( $filters );
4399
				$ui['filters_enhanced'] = true;
4400
			}
4401
4402
			$reorder_field = pods_v( 'ui_reorder_field', $this->pod_data['options'] );
4403
4404
			if ( ! empty( $reorder_field ) && in_array( 'reorder', $actions_enabled, true ) && ! in_array( 'reorder', $actions_disabled, true ) && ( ( ! empty( $this->pod_data['object_fields'] ) && isset( $this->pod_data['object_fields'][ $reorder_field ] ) ) || isset( $this->pod_data['fields'][ $reorder_field ] ) ) ) {
4405
				$ui['reorder']     = array( 'on' => $reorder_field );
4406
				$ui['orderby']     = $reorder_field;
4407
				$ui['orderby_dir'] = 'ASC';
4408
			}
4409
4410
			if ( ! empty( $author_restrict ) ) {
4411
				$ui['restrict'] = array( 'author_restrict' => $author_restrict );
4412
			}
4413
4414 View Code Duplication
			if ( ! in_array( 'export', $ui['actions_disabled'], true ) ) {
4415
				$ui['actions_bulk']['export'] = array(
4416
					'label' => __( 'Export', 'pods' ),
4417
					// callback not needed, Pods has this built-in for export.
4418
				);
4419
			}
4420
4421 View Code Duplication
			if ( ! in_array( 'delete', $ui['actions_disabled'], true ) ) {
4422
				$ui['actions_bulk']['delete'] = array(
4423
					'label' => __( 'Delete', 'pods' ),
4424
					// callback not needed, Pods has this built-in for delete.
4425
				);
4426
			}
4427
4428
			$detail_url = pods_v( 'detail_url', $this->pod_data['options'] );
4429
4430
			if ( 0 < strlen( $detail_url ) ) {
4431
				$ui['actions_custom'] = array(
4432
					'view_url' => array(
4433
						'label' => 'View',
4434
						'link'  => get_site_url() . '/' . $detail_url,
4435
					),
4436
				);
4437
			}
4438
4439
			// @todo Customize the Add New / Manage links to point to their correct menu items.
4440
			$ui = apply_filters( 'pods_admin_ui_' . $this->pod, apply_filters( 'pods_admin_ui', $ui, $this->pod, $this ), $this->pod, $this );
4441
4442
			// Override UI options.
4443
			foreach ( $options as $option => $value ) {
4444
				$ui[ $option ] = $value;
4445
			}
4446
4447
			$this->ui = $ui;
4448
4449
			return pods_ui( $this );
4450
		}//end if
4451
4452
		do_action( 'pods_admin_ui_custom', $this );
4453
		do_action( 'pods_admin_ui_custom_' . $this->pod, $this );
4454
4455
		return null;
4456
	}
4457
4458
	/**
4459
	 * Handle filters / actions for the class
4460
	 *
4461
	 * @see   pods_do_hook
4462
	 *
4463
	 * @param string $name Hook name.
4464
	 *
4465
	 * @return mixed Value filtered
4466
	 *
4467
	 * @since 2.0
4468
	 */
4469 View Code Duplication
	private function do_hook( $name ) {
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...
4470
4471
		$args = func_get_args();
4472
4473
		if ( empty( $args ) ) {
4474
			return false;
4475
		}
4476
4477
		// Remove first argument.
4478
		array_shift( $args );
4479
4480
		return pods_do_hook( 'pods', $name, $args, $this );
4481
	}
4482
4483
	/**
4484
	 * Handle variables that have been deprecated and PodsData vars
4485
	 *
4486
	 * @param string $name Property name.
4487
	 *
4488
	 * @return mixed
4489
	 *
4490
	 * @since 2.0
4491
	 */
4492
	public function __get( $name ) {
4493
4494
		$name = (string) $name;
4495
4496
		// PodsData vars.
4497
		if ( isset( $this->data->{$name} ) && 0 === strpos( $name, 'field_' ) ) {
4498
			return $this->data->{$name};
4499
		}
4500
4501
		if ( ! $this->deprecated ) {
4502
			require_once PODS_DIR . 'deprecated/classes/Pods.php';
4503
4504
			$this->deprecated = new Pods_Deprecated( $this );
4505
		}
4506
4507
		$var = null;
4508
4509
		$pod_class_exists = class_exists( 'Pod' );
4510
4511
		if ( isset( $this->deprecated->{$name} ) ) {
4512
			if ( ! $pod_class_exists || Pod::$deprecated_notice ) {
4513
				pods_deprecated( "Pods->{$name}", '2.0' );
4514
			}
4515
4516
			$var = $this->deprecated->{$name};
4517
		} elseif ( ! $pod_class_exists || Pod::$deprecated_notice ) {
4518
			pods_deprecated( "Pods->{$name}", '2.0' );
4519
		}
4520
4521
		return $var;
4522
	}
4523
4524
	/**
4525
	 * Handle methods that have been deprecated and any aliasing.
4526
	 *
4527
	 * @param string $name Function name.
4528
	 * @param array  $args Arguments passed to function.
4529
	 *
4530
	 * @return mixed|null
4531
	 *
4532
	 * @since 2.0
4533
	 */
4534
	public function __call( $name, $args ) {
4535
4536
		$name = (string) $name;
4537
4538
		// select > find alias.
4539
		if ( 'select' === $name ) {
4540
			return call_user_func_array( array( $this, 'find' ), $args );
4541
		}
4542
4543
		if ( ! $this->deprecated ) {
4544
			require_once PODS_DIR . 'deprecated/classes/Pods.php';
4545
4546
			$this->deprecated = new Pods_Deprecated( $this );
4547
		}
4548
4549
		$pod_class_exists = class_exists( 'Pod' );
4550
4551 View Code Duplication
		if ( method_exists( $this->deprecated, $name ) ) {
4552
			return call_user_func_array( array( $this->deprecated, $name ), $args );
4553
			// @codingStandardsIgnoreLine
4554
		} elseif ( ! $pod_class_exists || Pod::$deprecated_notice ) {
4555
			pods_deprecated( "Pods::{$name}", '2.0' );
4556
		}
4557
4558
		return null;
4559
	}
4560
4561
	/**
4562
	 * Handle casting a Pods() object to string
4563
	 *
4564
	 * @return string Pod type and name in CURIE notation
4565
	 */
4566
	public function __toString() {
4567
4568
		$string = '';
4569
4570
		if ( ! empty( $this->pod_data ) ) {
4571
			$string = sprintf( '%s:%s', $this->pod_data['type'], $this->pod_data['name'] );
4572
		}
4573
4574
		return $string;
4575
4576
	}
4577
}
4578