Pods

The WordPress Core Pods class.

Defined (1)

The class is defined in the following location(s).

/classes/Pods.php  
  1. class Pods implements Iterator { 
  2.  
  3. /** 
  4. * @var bool 
  5. */ 
  6. private $iterator = false; 
  7.  
  8. /** 
  9. * @var PodsAPI 
  10. */ 
  11. public $api; 
  12.  
  13. /** 
  14. * @var PodsData 
  15. */ 
  16. public $data; 
  17.  
  18. /** 
  19. * @var PodsData 
  20. */ 
  21. public $alt_data; 
  22.  
  23. /** 
  24. * @var array Array of pod item arrays 
  25. */ 
  26. public $rows = array(); 
  27.  
  28. /** 
  29. * @var array Current pod item array 
  30. */ 
  31. public $row = array(); 
  32.  
  33. /** 
  34. * @var int 
  35. */ 
  36. private $row_number = -1; 
  37.  
  38. /** 
  39. * @var array Override pod item array 
  40. */ 
  41. public $row_override = array(); 
  42.  
  43. /** 
  44. * @var bool 
  45. */ 
  46. public $display_errors = true; 
  47.  
  48. /** 
  49. * @var array|bool|mixed|null|void 
  50. */ 
  51. public $pod_data; 
  52.  
  53. /** 
  54. * @var array 
  55. */ 
  56. public $params = array(); 
  57.  
  58. /** 
  59. * @var string 
  60. */ 
  61. public $pod = ''; 
  62.  
  63. /** 
  64. * @var int 
  65. */ 
  66. public $pod_id = 0; 
  67.  
  68. /** 
  69. * @var array 
  70. */ 
  71. public $fields = array(); 
  72.  
  73. /** 
  74. * @var array 
  75. */ 
  76. public $filters = array(); 
  77.  
  78. /** 
  79. * @var string 
  80. */ 
  81. public $detail_page; 
  82.  
  83. /** 
  84. * @var int 
  85. */ 
  86. public $id = 0; 
  87.  
  88. /** 
  89. * @var int 
  90. */ 
  91. public $limit = 15; 
  92.  
  93. /** 
  94. * @var int 
  95. */ 
  96. public $offset = 0; 
  97.  
  98. /** 
  99. * @var string 
  100. */ 
  101. public $page_var = 'pg'; 
  102.  
  103. /** 
  104. * @var int|mixed 
  105. */ 
  106. public $page = 1; 
  107.  
  108. /** 
  109. * @var bool 
  110. */ 
  111. public $pagination = true; 
  112.  
  113. /** 
  114. * @var bool 
  115. */ 
  116. public $search = true; 
  117.  
  118. /** 
  119. * @var string 
  120. */ 
  121. public $search_var = 'search'; 
  122.  
  123. /** 
  124. * @var string 
  125. */ 
  126. public $search_mode = 'int'; // int | text | text_like 
  127.  
  128. /** 
  129. * @var int 
  130. */ 
  131. public $total = 0; 
  132.  
  133. /** 
  134. * @var int 
  135. */ 
  136. public $total_found = 0; 
  137.  
  138. /** 
  139. * @var array 
  140. */ 
  141. public $ui = array(); 
  142.  
  143. /** 
  144. * @var mixed SEO related vars for Pod Pages 
  145. */ 
  146. public $page_template; 
  147. public $body_classes; 
  148. public $meta = array(); 
  149. public $meta_properties = array(); 
  150. public $meta_extra = ''; 
  151.  
  152. /** 
  153. * @var string Last SQL query used by a find() 
  154. */ 
  155. public $sql; 
  156.  
  157. /** 
  158. * @var 
  159. */ 
  160. public $deprecated; 
  161.  
  162. public $datatype; 
  163.  
  164. public $datatype_id; 
  165.  
  166. /** 
  167. * Constructor - Pods Framework core 
  168. * @param string $pod The pod name 
  169. * @param mixed $id (optional) The ID or slug, to load a single record; Provide array of $params to run 'find' 
  170. * @return \Pods 
  171. * @license http://www.gnu.org/licenses/gpl-2.0.html 
  172. * @since 1.0.0 
  173. * @link http://pods.io/docs/pods/ 
  174. */ 
  175. public function __construct ( $pod = null, $id = null ) { 
  176. if ( null === $pod ) { 
  177. $queried_object = get_queried_object(); 
  178.  
  179. if ( $queried_object ) { 
  180. $id_lookup = true; 
  181.  
  182. // Post Type Singular 
  183. if ( isset( $queried_object->post_type ) ) { 
  184. $pod = $queried_object->post_type; 
  185. // Term Archive 
  186. elseif ( isset( $queried_object->taxonomy ) ) { 
  187. $pod = $queried_object->taxonomy; 
  188. // Author Archive 
  189. elseif ( isset( $queried_object->user_login ) ) { 
  190. $pod = 'user'; 
  191. // Post Type Archive 
  192. elseif ( isset( $queried_object->public ) && isset( $queried_object->name ) ) { 
  193. $pod = $queried_object->name; 
  194.  
  195. $id_lookup = false; 
  196.  
  197. if ( null === $id && $id_lookup ) { 
  198. $id = get_queried_object_id(); 
  199.  
  200. $this->api = pods_api( $pod ); 
  201. $this->api->display_errors =& $this->display_errors; 
  202.  
  203. $this->data = pods_data( $this->api, $id, false ); 
  204. PodsData::$display_errors =& $this->display_errors; 
  205.  
  206. // Set up page variable 
  207. if ( pods_strict( false ) ) { 
  208. $this->page = 1; 
  209. $this->pagination = false; 
  210. $this->search = false; 
  211. else { 
  212. // Get the page variable 
  213. $this->page = pods_var( $this->page_var, 'get' ); 
  214. $this->page = ( empty( $this->page ) ? 1 : max( pods_absint( $this->page ), 1 ) ); 
  215.  
  216. // Set default pagination handling to on/off 
  217. if ( defined( 'PODS_GLOBAL_POD_PAGINATION' ) ) { 
  218. if ( !PODS_GLOBAL_POD_PAGINATION ) { 
  219. $this->page = 1; 
  220. $this->pagination = false; 
  221. else 
  222. $this->pagination = true; 
  223.  
  224. // Set default search to on/off 
  225. if ( defined( 'PODS_GLOBAL_POD_SEARCH' ) ) { 
  226. if ( PODS_GLOBAL_POD_SEARCH ) 
  227. $this->search = true; 
  228. else 
  229. $this->search = false; 
  230.  
  231. // Set default search mode 
  232. $allowed_search_modes = array( 'int', 'text', 'text_like' ); 
  233.  
  234. if ( defined( 'PODS_GLOBAL_POD_SEARCH_MODE' ) && in_array( PODS_GLOBAL_POD_SEARCH_MODE, $allowed_search_modes ) ) 
  235. $this->search_mode = PODS_GLOBAL_POD_SEARCH_MODE; 
  236.  
  237. // Sync Settings 
  238. $this->data->page =& $this->page; 
  239. $this->data->limit =& $this->limit; 
  240. $this->data->pagination =& $this->pagination; 
  241. $this->data->search =& $this->search; 
  242. $this->data->search_mode =& $this->search_mode; 
  243.  
  244. // Sync Pod Data 
  245. $this->api->pod_data =& $this->data->pod_data; 
  246. $this->pod_data =& $this->api->pod_data; 
  247. $this->api->pod_id =& $this->data->pod_id; 
  248. $this->pod_id =& $this->api->pod_id; 
  249. $this->datatype_id =& $this->pod_id; 
  250. $this->api->pod =& $this->data->pod; 
  251. $this->pod =& $this->api->pod; 
  252. $this->datatype =& $this->pod; 
  253. $this->api->fields =& $this->data->fields; 
  254. $this->fields =& $this->api->fields; 
  255. $this->detail_page =& $this->data->detail_page; 
  256. $this->id =& $this->data->id; 
  257. $this->row =& $this->data->row; 
  258. $this->rows =& $this->data->data; 
  259. $this->row_number =& $this->data->row_number; 
  260. $this->sql =& $this->data->sql; 
  261.  
  262. if ( is_array( $id ) || is_object( $id ) ) 
  263. $this->find( $id ); 
  264.  
  265. /** 
  266. * Whether this Pod object is valid or not 
  267. * @return bool 
  268. * @since 2.0 
  269. */ 
  270. public function valid () { 
  271. if ( empty( $this->pod_id ) ) 
  272. return false; 
  273.  
  274. if ( $this->iterator ) 
  275. return isset( $this->rows[ $this->row_number ] ); 
  276.  
  277. return true; 
  278.  
  279. /** 
  280. * Check if in Iterator mode 
  281. * @return bool 
  282. * @since 2.3.4 
  283. * @link http://www.php.net/manual/en/class.iterator.php 
  284. */ 
  285. public function is_iterator () { 
  286. return $this->iterator; 
  287.  
  288. /** 
  289. * Turn off Iterator mode to off 
  290. * @return void 
  291. * @since 2.3.4 
  292. * @link http://www.php.net/manual/en/class.iterator.php 
  293. */ 
  294. public function stop_iterator () { 
  295. $this->iterator = false; 
  296.  
  297. return; 
  298.  
  299. /** 
  300. * Rewind Iterator 
  301. * @return void|boolean 
  302. * @since 2.3.4 
  303. * @link http://www.php.net/manual/en/class.iterator.php 
  304. */ 
  305. public function rewind () { 
  306. if ( $this->iterator ) { 
  307. $this->row_number = 0; 
  308.  
  309. return; 
  310.  
  311. return false; 
  312.  
  313. /** 
  314. * Get current Iterator row 
  315. * @return mixed|boolean 
  316. * @since 2.3.4 
  317. * @link http://www.php.net/manual/en/class.iterator.php 
  318. */ 
  319. public function current () { 
  320. if ( $this->iterator && $this->fetch() ) 
  321. return $this; 
  322.  
  323. return false; 
  324.  
  325. /** 
  326. * Get current Iterator key 
  327. * @return int|boolean 
  328. * @since 2.3.4 
  329. * @link http://www.php.net/manual/en/class.iterator.php 
  330. */ 
  331. public function key () { 
  332. if ( $this->iterator ) 
  333. return $this->row_number; 
  334.  
  335. return false; 
  336.  
  337. /** 
  338. * Move onto the next Iterator row 
  339. * @return void|boolean 
  340. * @since 2.3.4 
  341. * @link http://www.php.net/manual/en/class.iterator.php 
  342. */ 
  343. public function next () { 
  344. if ( $this->iterator ) { 
  345. $this->row_number++; 
  346.  
  347. return; 
  348.  
  349. return false; 
  350.  
  351. /** 
  352. * Whether a Pod item exists or not when using fetch() or construct with an ID or slug 
  353. * @return bool 
  354. * @since 2.0 
  355. */ 
  356. public function exists () { 
  357. if ( empty( $this->row ) ) 
  358. return false; 
  359.  
  360. return true; 
  361.  
  362. /** 
  363. * Return an array of all rows returned from a find() call. 
  364. * Most of the time, you will want to loop through data using fetch() 
  365. * instead of using this function. 
  366. * @return array|bool An array of all rows returned from a find() call, or false if no items returned 
  367. * @since 2.0 
  368. * @link http://pods.io/docs/data/ 
  369. */ 
  370. public function data () { 
  371. do_action( 'pods_pods_data', $this ); 
  372.  
  373. if ( empty( $this->rows ) ) 
  374. return false; 
  375.  
  376. return (array) $this->rows; 
  377.  
  378. /** 
  379. * Return a field input for a specific field 
  380. * @param string|array $field Field name or Field data array 
  381. * @param string $field Input field name to use (overrides default name) 
  382. * @param mixed $value Current value to use 
  383. * @return string Field Input HTML 
  384. * @since 2.3.10 
  385. */ 
  386. public function input( $field, $input_name = null, $value = '__null' ) { 
  387.  
  388. // Field data override 
  389. if ( is_array( $field ) ) { 
  390. $field_data = $field; 
  391. $field = pods_var_raw( 'name', $field ); 
  392. // Get field data from field name 
  393. else { 
  394. $field_data = $this->fields( $field ); 
  395.  
  396. if ( !empty( $field_data ) ) { 
  397. $field_type = pods_var_raw( 'type', $field_data ); 
  398.  
  399. if ( empty( $input_name ) ) { 
  400. $input_name = $field; 
  401.  
  402. if ( '__null' == $value ) { 
  403. $value = $this->field( array( 'name' => $field, 'in_form' => true ) ); 
  404.  
  405. return PodsForm::field( $input_name, $value, $field_type, $field_data, $this, $this->id() ); 
  406.  
  407. return ''; 
  408.  
  409.  
  410. /** 
  411. * Return field array from a Pod, a field's data, or a field option 
  412. * @param null $field 
  413. * @param null $option 
  414. * @return bool|mixed 
  415. * @since 2.0 
  416. */ 
  417. public function fields ( $field = null, $option = null ) { 
  418.  
  419. $field_data = null; 
  420.  
  421. if ( empty( $this->fields ) ) { 
  422. // No fields found 
  423. $field_data = array(); 
  424. } elseif ( empty( $field ) ) { 
  425. // Return all fields 
  426. $field_data = (array) $this->fields; 
  427. } elseif ( ! isset( $this->fields[ $field ] ) && ! isset( $this->pod_data['object_fields'][ $field ] ) ) { 
  428. // Field not found 
  429. $field_data = array(); 
  430. } elseif ( empty( $option ) ) { 
  431. // Return all field data 
  432. if ( isset( $this->fields[ $field ] ) ) { 
  433. $field_data = $this->fields[ $field ]; 
  434. } elseif ( isset( $this->pod_data['object_fields'] ) ) { 
  435. $field_data = $this->pod_data['object_fields'][ $field ]; 
  436. } else { 
  437. // Merge options 
  438. if ( isset( $this->fields[ $field ] ) ) { 
  439. $options = array_merge( $this->fields[ $field ], $this->fields[ $field ]['options'] ); 
  440. } elseif ( isset( $this->pod_data['object_fields'] ) ) { 
  441. $options = array_merge( $this->pod_data['object_fields'][ $field ], $this->pod_data['object_fields'][ $field ]['options'] ); 
  442.  
  443. // Get a list of available items from a relationship field 
  444. if ( 'data' == $option && in_array( pods_var_raw( 'type', $options ), PodsForm::tableless_field_types() ) ) { 
  445. $field_data = PodsForm::field_method( 'pick', 'get_field_data', $options ); 
  446. } // Return option 
  447. elseif ( isset( $options[ $option ] ) ) { 
  448. $field_data = $options[ $option ]; 
  449.  
  450. /** 
  451. * Modify the field data before returning 
  452. * @since unknown 
  453. * @param array $field_data The data for the field. 
  454. * @param string|null $field The specific field that data is being return for, if set when method is called or null. 
  455. * @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. 
  456. * @param Pods|object $this The current Pods class instance. 
  457. */ 
  458. return apply_filters( 'pods_pods_fields', $field_data, $field, $option, $this ); 
  459.  
  460.  
  461. /** 
  462. * Return row array for an item 
  463. * @return array 
  464. * @since 2.0 
  465. */ 
  466. public function row () { 
  467. do_action( 'pods_pods_row', $this ); 
  468.  
  469. if ( !is_array( $this->row ) ) 
  470. return false; 
  471.  
  472. return (array) $this->row; 
  473.  
  474. /** 
  475. * Return the output for a field. If you want the raw value for use in PHP for custom manipulation,  
  476. * you will want to use field() instead. This function will automatically convert arrays into a 
  477. * list of text such as "Rick, John, and Gary" 
  478. * @param string|array $name The field name, or an associative array of parameters 
  479. * @param boolean $single (optional) For tableless fields, to return an array or the first 
  480. * @return string|null|false The output from the field, null if the field doesn't exist, false if no value returned for tableless fields 
  481. * @since 2.0 
  482. * @link http://pods.io/docs/display/ 
  483. */ 
  484. public function display ( $name, $single = null ) { 
  485. $defaults = array( 
  486. 'name' => $name,  
  487. 'single' => $single,  
  488. 'display' => true,  
  489. 'serial_params' => null 
  490. ); 
  491.  
  492. if ( is_array( $name ) || is_object( $name ) ) { 
  493. $defaults[ 'name' ] = null; 
  494. $params = (object) array_merge( $defaults, (array) $name ); 
  495. elseif ( is_array( $single ) || is_object( $single ) ) { 
  496. $defaults[ 'single' ] = null; 
  497. $params = (object) array_merge( $defaults, (array) $single ); 
  498. else 
  499. $params = $defaults; 
  500.  
  501. $params = (object) $params; 
  502.  
  503. $value = $this->field( $params ); 
  504.  
  505. if ( is_array( $value ) ) { 
  506. $fields = $this->fields; 
  507.  
  508. if ( isset( $this->pod_data[ 'object_fields' ] ) ) { 
  509. $fields = array_merge( $fields, $this->pod_data[ 'object_fields' ] ); 
  510.  
  511. $serial_params = array( 
  512. 'field' => $params->name,  
  513. 'fields' => $fields 
  514. ); 
  515.  
  516. if ( !empty( $params->serial_params ) && is_array( $params->serial_params ) ) 
  517. $serial_params = array_merge( $serial_params, $params->serial_params ); 
  518.  
  519. $value = pods_serial_comma( $value, $serial_params ); 
  520.  
  521. return $value; 
  522.  
  523. /** 
  524. * Return the raw output for a field If you want the raw value for use in PHP for custom manipulation,  
  525. * you will want to use field() instead. This function will automatically convert arrays into a 
  526. * list of text such as "Rick, John, and Gary" 
  527. * @param string|array $name The field name, or an associative array of parameters 
  528. * @param boolean $single (optional) For tableless fields, to return an array or the first 
  529. * @return string|null|false The output from the field, null if the field doesn't exist, false if no value returned for tableless fields 
  530. * @since 2.0 
  531. * @link http://pods.io/docs/display/ 
  532. */ 
  533. public function raw ( $name, $single = null ) { 
  534. $defaults = array( 
  535. 'name' => $name,  
  536. 'single' => $single,  
  537. 'raw' => true 
  538. ); 
  539.  
  540. if ( is_array( $name ) || is_object( $name ) ) { 
  541. $defaults[ 'name' ] = null; 
  542. $params = (object) array_merge( $defaults, (array) $name ); 
  543. elseif ( is_array( $single ) || is_object( $single ) ) { 
  544. $defaults[ 'single' ] = null; 
  545. $params = (object) array_merge( $defaults, (array) $single ); 
  546. else 
  547. $params = (object) $defaults; 
  548.  
  549. $value = $this->field( $params ); 
  550.  
  551. return $value; 
  552.  
  553. /** 
  554. * Return the value for a field. 
  555. * If you are getting a field for output in a theme, most of the time you will want to use display() instead. 
  556. * This function will return arrays for relationship and file fields. 
  557. * @param string|array $name The field name, or an associative array of parameters 
  558. * @param boolean $single (optional) For tableless fields, to return the whole array or the just the first item, or an associative array of parameters 
  559. * @param boolean $raw (optional) Whether to return the raw value, or to run through the field type's display method, or an associative array of parameters 
  560. * @return mixed|null Value returned depends on the field type, null if the field doesn't exist, false if no value returned for tableless fields 
  561. * @since 2.0 
  562. * @link http://pods.io/docs/field/ 
  563. */ 
  564. public function field ( $name, $single = null, $raw = false ) { 
  565.  
  566. $defaults = array( 
  567. 'name' => $name,  
  568. 'orderby' => null,  
  569. 'single' => $single,  
  570. 'params' => null,  
  571. 'in_form' => false,  
  572. 'raw' => $raw,  
  573. 'raw_display' => false,  
  574. 'display' => false,  
  575. 'get_meta' => false,  
  576. 'output' => null,  
  577. 'deprecated' => false,  
  578. 'args' => array() // extra data to send to field handlers 
  579. ); 
  580.  
  581. if ( is_array( $name ) || is_object( $name ) ) { 
  582. $defaults[ 'name' ] = null; 
  583. $params = (object) array_merge( $defaults, (array) $name ); 
  584. elseif ( is_array( $single ) || is_object( $single ) ) { 
  585. $defaults[ 'single' ] = null; 
  586. $params = (object) array_merge( $defaults, (array) $single ); 
  587. elseif ( is_array( $raw ) || is_object( $raw ) ) { 
  588. $defaults[ 'raw' ] = false; 
  589. $params = (object) array_merge( $defaults, (array) $raw ); 
  590. else 
  591. $params = (object) $defaults; 
  592.  
  593. if ( $params->in_form ) { 
  594. $params->output = 'ids'; 
  595. elseif ( null === $params->output ) { 
  596. /** 
  597. * Override the way realted fields are output 
  598. * @param string $output How to output related fields. Default is 'arrays'. Options: id|name|object|array|pod 
  599. * @param array|object $row Current row being outputted. 
  600. * @param array $params Params array passed to field(). 
  601. * @param object|Pods $this Current Pods object. 
  602. */ 
  603. $params->output = apply_filters( 'pods_pods_field_related_output_type', 'arrays', $this->row, $params, $this ); 
  604.  
  605. if ( in_array( $params->output, array( 'id', 'name', 'object', 'array', 'pod' ) ) ) 
  606. $params->output .= 's'; 
  607.  
  608. // Support old $orderby variable 
  609. if ( null !== $params->single && is_string( $params->single ) && empty( $params->orderby ) ) { 
  610. if ( ! class_exists( 'Pod' ) || Pod::$deprecated_notice ) { 
  611. pods_deprecated( 'Pods::field', '2.0', 'Use $params[ \'orderby\' ] instead' ); 
  612.  
  613. $params->orderby = $params->single; 
  614. $params->single = false; 
  615.  
  616. if ( null !== $params->single ) 
  617. $params->single = (boolean) $params->single; 
  618.  
  619. $params->name = trim( $params->name ); 
  620. if ( is_array( $params->name ) || strlen( $params->name ) < 1 ) 
  621. return null; 
  622.  
  623. $params->full_name = $params->name; 
  624.  
  625. $value = null; 
  626.  
  627. if ( isset( $this->row_override[ $params->name ] ) ) 
  628. $value = $this->row_override[ $params->name ]; 
  629.  
  630. if ( false === $this->row() ) { 
  631. if ( false !== $this->data() ) 
  632. $this->fetch(); 
  633. else 
  634. return $value; 
  635.  
  636. if ( $this->data->field_id == $params->name ) { 
  637. if ( isset( $this->row[ $params->name ] ) ) 
  638. return $this->row[ $params->name ]; 
  639. elseif ( null !== $value ) 
  640. return $value; 
  641.  
  642. return 0; 
  643.  
  644. $tableless_field_types = PodsForm::tableless_field_types(); 
  645. $simple_tableless_objects = PodsForm::simple_tableless_objects(); 
  646.  
  647. $params->traverse = array(); 
  648.  
  649. if ( in_array( $params->name, array( '_link', 'detail_url' ) ) || ( in_array( $params->name, array( 'permalink', 'the_permalink' ) ) && in_array( $this->pod_data[ 'type' ], array( 'post_type', 'taxonomy', 'media', 'user', 'comment' ) ) ) ) { 
  650. if ( 0 < strlen( $this->detail_page ) ) 
  651. $value = get_home_url() . '/' . $this->do_magic_tags( $this->detail_page ); 
  652. elseif ( in_array( $this->pod_data[ 'type' ], array( 'post_type', 'media' ) ) ) 
  653. $value = get_permalink( $this->id() ); 
  654. elseif ( 'taxonomy' == $this->pod_data[ 'type' ] ) 
  655. $value = get_term_link( $this->id(), $this->pod_data[ 'name' ] ); 
  656. elseif ( 'user' == $this->pod_data[ 'type' ] ) 
  657. $value = get_author_posts_url( $this->id() ); 
  658. elseif ( 'comment' == $this->pod_data[ 'type' ] ) 
  659. $value = get_comment_link( $this->id() ); 
  660.  
  661. $field_data = $last_field_data = false; 
  662. $field_type = false; 
  663.  
  664. $first_field = explode( '.', $params->name ); 
  665. $first_field = $first_field[ 0 ]; 
  666.  
  667. if ( isset( $this->fields[ $first_field ] ) ) { 
  668. $field_data = $this->fields[ $first_field ]; 
  669. $field_type = 'field'; 
  670. elseif ( !empty( $this->pod_data[ 'object_fields' ] ) ) { 
  671. if ( isset( $this->pod_data[ 'object_fields' ][ $first_field ] ) ) { 
  672. $field_data = $this->pod_data[ 'object_fields' ][ $first_field ]; 
  673. $field_type = 'object_field'; 
  674. else { 
  675. foreach ( $this->pod_data[ 'object_fields' ] as $object_field => $object_field_opt ) { 
  676. if ( in_array( $first_field, $object_field_opt[ 'alias' ] ) ) { 
  677. if ( $first_field == $params->name ) 
  678. $params->name = $object_field; 
  679.  
  680. $first_field = $object_field; 
  681. $field_data = $object_field_opt; 
  682. $field_type = 'object_field'; 
  683.  
  684. break; 
  685.  
  686. // Simple fields have no other output options 
  687. if ( 'pick' == $field_data[ 'type' ] && in_array( $field_data[ 'pick_object' ], $simple_tableless_objects ) ) { 
  688. $params->output = 'arrays'; 
  689.  
  690. if ( empty( $value ) && in_array( $field_data[ 'type' ], $tableless_field_types ) ) { 
  691. $params->raw = true; 
  692.  
  693. $value = false; 
  694.  
  695. if ( 'arrays' != $params->output && isset( $this->row[ '_' . $params->output . '_' . $params->name ] ) ) { 
  696. $value = $this->row[ '_' . $params->output . '_' . $params->name ]; 
  697. elseif ( 'arrays' == $params->output && isset( $this->row[ $params->name ] ) ) { 
  698. $value = $this->row[ $params->name ]; 
  699.  
  700. if ( false !== $value && !is_array( $value ) && 'pick' == $field_data[ 'type' ] && in_array( $field_data[ 'pick_object' ], $simple_tableless_objects ) ) 
  701. $value = PodsForm::field_method( 'pick', 'simple_value', $params->name, $value, $field_data, $this->pod_data, $this->id(), true ); 
  702.  
  703. if ( empty( $value ) && isset( $this->row[ $params->name ] ) && ( !in_array( $field_data[ 'type' ], $tableless_field_types ) || 'arrays' == $params->output ) ) { 
  704. if ( empty( $field_data ) || in_array( $field_data[ 'type' ], array( 'boolean', 'number', 'currency' ) ) ) 
  705. $params->raw = true; 
  706.  
  707. if ( null === $params->single ) { 
  708. if ( isset( $this->fields[ $params->name ] ) && !in_array( $this->fields[ $params->name ][ 'type' ], $tableless_field_types ) ) 
  709. $params->single = true; 
  710. else 
  711. $params->single = false; 
  712.  
  713. $value = $this->row[ $params->name ]; 
  714. elseif ( empty( $value ) ) { 
  715. $object_field_found = false; 
  716.  
  717. if ( 'object_field' == $field_type ) { 
  718. $object_field_found = true; 
  719.  
  720. if ( isset( $this->row[ $first_field ] ) ) 
  721. $value = $this->row[ $first_field ]; 
  722. elseif ( in_array( $field_data[ 'type' ], $tableless_field_types ) ) { 
  723. $this->fields[ $first_field ] = $field_data; 
  724.  
  725. $object_field_found = false; 
  726. else 
  727. return null; 
  728.  
  729. if ( 'post_type' == $this->pod_data[ 'type' ] && !isset( $this->fields[ $params->name ] ) ) { 
  730. if ( !isset( $this->fields[ 'post_thumbnail' ] ) && ( 'post_thumbnail' == $params->name || 0 === strpos( $params->name, 'post_thumbnail.' ) ) ) { 
  731. $size = 'thumbnail'; 
  732.  
  733. if ( 0 === strpos( $params->name, 'post_thumbnail.' ) ) { 
  734. $field_names = explode( '.', $params->name ); 
  735.  
  736. if ( isset( $field_names[ 1 ] ) ) 
  737. $size = $field_names[ 1 ]; 
  738.  
  739. // Pods will auto-get the thumbnail ID if this isn't an attachment 
  740. $value = pods_image( $this->id(), $size, 0, null, true ); 
  741.  
  742. $object_field_found = true; 
  743. elseif ( !isset( $this->fields[ 'post_thumbnail_url' ] ) && ( 'post_thumbnail_url' == $params->name || 0 === strpos( $params->name, 'post_thumbnail_url.' ) ) ) { 
  744. $size = 'thumbnail'; 
  745.  
  746. if ( 0 === strpos( $params->name, 'post_thumbnail_url.' ) ) { 
  747. $field_names = explode( '.', $params->name ); 
  748.  
  749. if ( isset( $field_names[ 1 ] ) ) 
  750. $size = $field_names[ 1 ]; 
  751.  
  752. // Pods will auto-get the thumbnail ID if this isn't an attachment 
  753. $value = pods_image_url( $this->id(), $size, 0, true ); 
  754.  
  755. $object_field_found = true; 
  756. elseif ( 0 === strpos( $params->name, 'image_attachment.' ) ) { 
  757. $size = 'thumbnail'; 
  758.  
  759. $image_id = 0; 
  760.  
  761. $field_names = explode( '.', $params->name ); 
  762.  
  763. if ( isset( $field_names[ 1 ] ) ) 
  764. $image_id = $field_names[ 1 ]; 
  765.  
  766. if ( isset( $field_names[ 2 ] ) ) 
  767. $size = $field_names[ 2 ]; 
  768.  
  769. if ( !empty( $image_id ) ) { 
  770. $value = pods_image( $image_id, $size, 0, null, true ); 
  771.  
  772. if ( !empty( $value ) ) 
  773. $object_field_found = true; 
  774. elseif ( 0 === strpos( $params->name, 'image_attachment_url.' ) ) { 
  775. $size = 'thumbnail'; 
  776.  
  777. $image_id = 0; 
  778.  
  779. $field_names = explode( '.', $params->name ); 
  780.  
  781. if ( isset( $field_names[ 1 ] ) ) 
  782. $image_id = $field_names[ 1 ]; 
  783.  
  784. if ( isset( $field_names[ 2 ] ) ) 
  785. $size = $field_names[ 2 ]; 
  786.  
  787. if ( !empty( $image_id ) ) { 
  788. $value = pods_image_url( $image_id, $size, 0, true ); 
  789.  
  790. if ( !empty( $value ) ) 
  791. $object_field_found = true; 
  792. elseif ( 'user' == $this->pod_data[ 'type' ] && !isset( $this->fields[ $params->name ] ) ) { 
  793. if ( !isset( $this->fields[ 'avatar' ] ) && ( 'avatar' == $params->name || 0 === strpos( $params->name, 'avatar.' ) ) ) { 
  794. $size = null; 
  795.  
  796. if ( 0 === strpos( $params->name, 'avatar.' ) ) { 
  797. $field_names = explode( '.', $params->name ); 
  798.  
  799. if ( isset( $field_names[ 1 ] ) ) 
  800. $size = (int) $field_names[ 1 ]; 
  801.  
  802. if ( !empty( $size ) ) 
  803. $value = get_avatar( $this->id(), $size ); 
  804. else 
  805. $value = get_avatar( $this->id() ); 
  806.  
  807. $object_field_found = true; 
  808. elseif ( 0 === strpos( $params->name, 'image_attachment.' ) ) { 
  809. $size = 'thumbnail'; 
  810.  
  811. $image_id = 0; 
  812.  
  813. $field_names = explode( '.', $params->name ); 
  814.  
  815. if ( isset( $field_names[ 1 ] ) ) 
  816. $image_id = $field_names[ 1 ]; 
  817.  
  818. if ( isset( $field_names[ 2 ] ) ) 
  819. $size = $field_names[ 2 ]; 
  820.  
  821. if ( !empty( $image_id ) ) { 
  822. $value = pods_image( $image_id, $size, 0, null, true ); 
  823.  
  824. if ( !empty( $value ) ) 
  825. $object_field_found = true; 
  826. elseif ( 0 === strpos( $params->name, 'image_attachment_url.' ) ) { 
  827. $size = 'thumbnail'; 
  828.  
  829. $image_id = 0; 
  830.  
  831. $field_names = explode( '.', $params->name ); 
  832.  
  833. if ( isset( $field_names[ 1 ] ) ) 
  834. $image_id = $field_names[ 1 ]; 
  835.  
  836. if ( isset( $field_names[ 2 ] ) ) 
  837. $size = $field_names[ 2 ]; 
  838.  
  839. if ( !empty( $image_id ) ) { 
  840. $value = pods_image_url( $image_id, $size, 0, true ); 
  841.  
  842. if ( !empty( $value ) ) 
  843. $object_field_found = true; 
  844.  
  845. if ( false === $object_field_found ) { 
  846. $params->traverse = array( $params->name ); 
  847.  
  848. if ( false !== strpos( $params->name, '.' ) ) { 
  849. $params->traverse = explode( '.', $params->name ); 
  850.  
  851. $params->name = $params->traverse[ 0 ]; 
  852.  
  853. if ( isset( $this->fields[ $params->name ] ) && isset( $this->fields[ $params->name ][ 'type' ] ) ) { 
  854. /** 
  855. * Modify value returned by field() after its retrieved, but before its validated or formatted 
  856. * Filter name is set dynamically with name of field: "pods_pods_field_{field_name}" 
  857. * @since unknown 
  858. * @param array|string|null $value Value retrieved. 
  859. * @param array|object $row Current row being outputted. 
  860. * @param array $params Params array passed to field(). 
  861. * @param object|Pods $this Current Pods object. 
  862. */ 
  863. $v = apply_filters( 'pods_pods_field_' . $this->fields[ $params->name ][ 'type' ], null, $this->fields[ $params->name ], $this->row, $params, $this ); 
  864.  
  865. if ( null !== $v ) 
  866. return $v; 
  867.  
  868. $simple = false; 
  869. $simple_data = array(); 
  870.  
  871. if ( isset( $this->fields[ $params->name ] ) ) { 
  872. if ( 'meta' == $this->pod_data[ 'storage' ] ) { 
  873. if ( !in_array( $this->fields[ $params->name ][ 'type' ], $tableless_field_types ) ) 
  874. $simple = true; 
  875.  
  876. if ( in_array( $this->fields[ $params->name ][ 'type' ], $tableless_field_types ) ) { 
  877. $params->raw = true; 
  878.  
  879. if ( 'pick' == $this->fields[ $params->name ][ 'type' ] && in_array( $this->fields[ $params->name ][ 'pick_object' ], $simple_tableless_objects ) ) { 
  880. $simple = true; 
  881. $params->single = true; 
  882. elseif ( in_array( $this->fields[ $params->name ][ 'type' ], array( 'boolean', 'number', 'currency' ) ) ) 
  883. $params->raw = true; 
  884.  
  885. if ( !isset( $this->fields[ $params->name ] ) || !in_array( $this->fields[ $params->name ][ 'type' ], $tableless_field_types ) || $simple ) { 
  886. if ( null === $params->single ) { 
  887. if ( isset( $this->fields[ $params->name ] ) && !in_array( $this->fields[ $params->name ][ 'type' ], $tableless_field_types ) ) 
  888. $params->single = true; 
  889. else 
  890. $params->single = false; 
  891.  
  892. $no_conflict = pods_no_conflict_check( $this->pod_data[ 'type' ] ); 
  893.  
  894. if ( !$no_conflict ) 
  895. pods_no_conflict_on( $this->pod_data[ 'type' ] ); 
  896.  
  897. if ( in_array( $this->pod_data[ 'type' ], array( 'post_type', 'media', 'taxonomy', 'user', 'comment' ) ) ) { 
  898. $id = $this->id(); 
  899.  
  900. $metadata_type = $this->pod_data['type']; 
  901.  
  902. if ( in_array( $this->pod_data[ 'type' ], array( 'post_type', 'media' ) ) ) { 
  903. $metadata_type = 'post'; 
  904.  
  905. // Support for WPML 'duplicated' translation handling 
  906. if ( did_action( 'wpml_loaded' ) 
  907. && apply_filters( 'wpml_is_translated_post_type', false, $this->pod_data[ 'name' ] ) ) { 
  908. $master_post_id = (int) apply_filters( 'wpml_master_post_from_duplicate', $id ); 
  909.  
  910. if ( 0 < $master_post_id ) 
  911. $id = $master_post_id; 
  912. } elseif ( 'taxonomy' == $this->pod_data[ 'type' ] ) { 
  913. $metadata_type = 'term'; 
  914.  
  915. $value = get_metadata( $metadata_type, $id, $params->name, $params->single ); 
  916.  
  917. $single_multi = 'single'; 
  918.  
  919. if ( isset( $this->fields[ $params->name ] ) ) { 
  920. $single_multi = pods_v( $this->fields[ $params->name ][ 'type' ] . '_format_type', $this->fields[ $params->name ][ 'options' ], 'single' ); 
  921.  
  922. if ( $simple && !is_array( $value ) && 'single' != $single_multi ) { 
  923. $value = get_metadata( $metadata_type, $id, $params->name ); 
  924. elseif ( 'settings' == $this->pod_data[ 'type' ] ) 
  925. $value = get_option( $this->pod_data[ 'name' ] . '_' . $params->name, null ); 
  926.  
  927. // Handle Simple Relationships 
  928. if ( $simple ) { 
  929. if ( null === $params->single ) 
  930. $params->single = false; 
  931.  
  932.  
  933. $value = PodsForm::field_method( 'pick', 'simple_value', $params->name, $value, $this->fields[ $params->name ], $this->pod_data, $this->id(), true ); 
  934.  
  935. if ( !$no_conflict ) 
  936. pods_no_conflict_off( $this->pod_data[ 'type' ] ); 
  937. else { 
  938. // Dot-traversal 
  939. $pod = $this->pod; 
  940. $ids = array( $this->id() ); 
  941. $all_fields = array(); 
  942.  
  943. $lookup = $params->traverse; 
  944.  
  945. // Get fields matching traversal names 
  946. if ( !empty( $lookup ) ) { 
  947. $fields = $this->api->load_fields( array( 
  948. 'name' => $lookup,  
  949. 'type' => $tableless_field_types,  
  950. 'object_fields' => true // @todo support object fields too 
  951. ) ); 
  952.  
  953. if ( !empty( $fields ) ) { 
  954. foreach ( $fields as $field ) { 
  955. if ( !empty( $field ) ) { 
  956. if ( !isset( $all_fields[ $field[ 'pod' ] ] ) ) 
  957. $all_fields[ $field[ 'pod' ] ] = array(); 
  958.  
  959. $all_fields[ $field[ 'pod' ] ][ $field[ 'name' ] ] = $field; 
  960.  
  961. if ( !empty( $this->pod_data[ 'object_fields' ] ) ) { 
  962. foreach ( $this->pod_data[ 'object_fields' ] as $object_field => $object_field_opt ) { 
  963. if ( in_array( $object_field_opt[ 'type' ], $tableless_field_types ) ) { 
  964. $all_fields[ $this->pod ][ $object_field ] = $object_field_opt; 
  965.  
  966. $last_type = $last_object = $last_pick_val = ''; 
  967. $last_options = array(); 
  968.  
  969. $single_multi = pods_v( $this->fields[ $params->name ][ 'type' ] . '_format_type', $this->fields[ $params->name ][ 'options' ], 'single' ); 
  970.  
  971. if ( 'multi' == $single_multi ) 
  972. $limit = (int) pods_v( $this->fields[ $params->name ][ 'type' ] . '_limit', $this->fields[ $params->name ][ 'options' ], 0 ); 
  973. else 
  974. $limit = 1; 
  975.  
  976. $last_limit = 0; 
  977.  
  978. // Loop through each traversal level 
  979. foreach ( $params->traverse as $key => $field ) { 
  980. $last_loop = false; 
  981.  
  982. if ( count( $params->traverse ) <= ( $key + 1 ) ) 
  983. $last_loop = true; 
  984.  
  985. $field_exists = isset( $all_fields[ $pod ][ $field ] ); 
  986.  
  987. $simple = false; 
  988. $last_options = array(); 
  989.  
  990. if ( $field_exists && 'pick' == $all_fields[ $pod ][ $field ][ 'type' ] && in_array( $all_fields[ $pod ][ $field ][ 'pick_object' ], $simple_tableless_objects ) ) { 
  991. $simple = true; 
  992. $last_options = $all_fields[ $pod ][ $field ]; 
  993.  
  994. // Tableless handler 
  995. if ( $field_exists && ( !in_array( $all_fields[ $pod ][ $field ][ 'type' ], array( 'pick', 'taxonomy' ) ) || !$simple ) ) { 
  996. $type = $all_fields[ $pod ][ $field ][ 'type' ]; 
  997. $pick_object = $all_fields[ $pod ][ $field ][ 'pick_object' ]; 
  998. $pick_val = $all_fields[ $pod ][ $field ][ 'pick_val' ]; 
  999.  
  1000. if ( 'table' == $pick_object ) { 
  1001. $pick_val = pods_v( 'pick_table', $all_fields[ $pod ][ $field ][ 'options' ], $pick_val, true ); 
  1002. elseif ( '__current__' == $pick_val ) { 
  1003. $pick_val = $pod; 
  1004.  
  1005. $last_limit = 0; 
  1006.  
  1007. if ( in_array( $type, $tableless_field_types ) ) { 
  1008. $single_multi = pods_v( "{$type}_format_type", $all_fields[ $pod ][ $field ][ 'options' ], 'single' ); 
  1009.  
  1010. if ( 'multi' == $single_multi ) { 
  1011. $last_limit = (int) pods_v( "{$type}_limit", $all_fields[ $pod ][ $field ][ 'options' ], 0 ); 
  1012. else { 
  1013. $last_limit = 1; 
  1014.  
  1015. $last_type = $type; 
  1016. $last_object = $pick_object; 
  1017. $last_pick_val = $pick_val; 
  1018. $last_options = $all_fields[ $pod ][ $field ]; 
  1019.  
  1020. // Temporary hack until there's some better handling here 
  1021. $last_limit = $last_limit * count( $ids ); 
  1022.  
  1023. // Get related IDs 
  1024. if ( !isset( $all_fields[ $pod ][ $field ][ 'pod_id' ] ) ) { 
  1025. $all_fields[ $pod ][ $field ][ 'pod_id' ] = 0; 
  1026.  
  1027. if ( isset( $all_fields[ $pod ][ $field ][ 'id' ] ) ) { 
  1028. $ids = $this->api->lookup_related_items( 
  1029. $all_fields[ $pod ][ $field ][ 'id' ],  
  1030. $all_fields[ $pod ][ $field ][ 'pod_id' ],  
  1031. $ids,  
  1032. $all_fields[ $pod ][ $field ] 
  1033. ); 
  1034.  
  1035. // No items found 
  1036. if ( empty( $ids ) ) { 
  1037. return false; 
  1038. } // @todo This should return array() if not $params->single 
  1039. elseif ( 0 < $last_limit ) { 
  1040. $ids = array_slice( $ids, 0, $last_limit ); 
  1041.  
  1042. // Get $pod if related to a Pod 
  1043. if ( !empty( $pick_object ) && ( !empty( $pick_val ) || in_array( $pick_object, array( 'user', 'media', 'comment' ) ) ) ) { 
  1044. if ( 'pod' == $pick_object ) { 
  1045. $pod = $pick_val; 
  1046. else { 
  1047. $check = $this->api->get_table_info( $pick_object, $pick_val ); 
  1048.  
  1049. if ( !empty( $check ) && !empty( $check[ 'pod' ] ) ) { 
  1050. $pod = $check[ 'pod' ][ 'name' ]; 
  1051. // Assume last iteration 
  1052. else { 
  1053. // Invalid field 
  1054. if ( 0 == $key ) { 
  1055. return false; 
  1056.  
  1057. $last_loop = true; 
  1058.  
  1059. if ( $last_loop ) { 
  1060. $object_type = $last_object; 
  1061. $object = $last_pick_val; 
  1062.  
  1063. if ( in_array( $last_type, PodsForm::file_field_types() ) ) { 
  1064. $object_type = 'media'; 
  1065. $object = 'attachment'; 
  1066.  
  1067. $data = array(); 
  1068.  
  1069. $table = $this->api->get_table_info( $object_type, $object, null, null, $last_options ); 
  1070.  
  1071. $join = $where = array(); 
  1072.  
  1073. if ( !empty( $table[ 'join' ] ) ) 
  1074. $join = (array) $table[ 'join' ]; 
  1075.  
  1076. if ( !empty( $table[ 'where' ] ) || !empty( $ids ) ) { 
  1077. foreach ( $ids as $id ) { 
  1078. $where[ $id ] = '`t`.`' . $table[ 'field_id' ] . '` = ' . (int) $id; 
  1079.  
  1080. if ( !empty( $where ) ) { 
  1081. $where = array( implode( ' OR ', $where ) ); 
  1082.  
  1083. if ( !empty( $table[ 'where' ] ) ) { 
  1084. $where = array_merge( $where, array_values( (array) $table[ 'where' ] ) ); 
  1085.  
  1086. /** 
  1087. * @var $related_obj Pods 
  1088. */ 
  1089. $related_obj = false; 
  1090.  
  1091. if ( 'pod' == $object_type ) 
  1092. $related_obj = pods( $object, null, false ); 
  1093. elseif ( !empty( $table[ 'pod' ] ) ) 
  1094. $related_obj = pods( $table[ 'pod' ][ 'name' ], null, false ); 
  1095.  
  1096. if ( !empty( $table[ 'table' ] ) || !empty( $related_obj ) ) { 
  1097. $sql = array( 
  1098. 'select' => '*, `t`.`' . $table[ 'field_id' ] . '` AS `pod_item_id`',  
  1099. 'table' => $table[ 'table' ],  
  1100. 'join' => $join,  
  1101. 'where' => $where,  
  1102. 'orderby' => $params->orderby,  
  1103. 'pagination' => false,  
  1104. 'search' => false,  
  1105. 'limit' => -1,  
  1106. 'expires' => 180 // @todo This could potentially cause issues if someone changes the data within this time and persistent storage is used 
  1107. ); 
  1108.  
  1109. // Output types 
  1110. if ( in_array( $params->output, array( 'ids', 'objects', 'pods' ) ) ) 
  1111. $sql[ 'select' ] = '`t`.`' . $table[ 'field_id' ] . '` AS `pod_item_id`'; 
  1112. elseif ( 'names' == $params->output && !empty( $table[ 'field_index' ] ) ) 
  1113. $sql[ 'select' ] = '`t`.`' . $table[ 'field_index' ] . '` AS `pod_item_index`, `t`.`' . $table[ 'field_id' ] . '` AS `pod_item_id`'; 
  1114.  
  1115. if ( !empty( $params->params ) && is_array( $params->params ) ) { 
  1116. $where = $sql[ 'where' ]; 
  1117.  
  1118. $sql = array_merge( $sql, $params->params ); 
  1119.  
  1120. if ( isset( $params->params[ 'where' ] ) ) 
  1121. $sql[ 'where' ] = array_merge( (array) $where, (array) $params->params['where' ] ); 
  1122.  
  1123. if ( empty( $related_obj ) ) { 
  1124. if ( !is_object( $this->alt_data ) ) 
  1125. $this->alt_data = pods_data( null, 0, true, true ); 
  1126.  
  1127. $item_data = $this->alt_data->select( $sql ); 
  1128. else 
  1129. $item_data = $related_obj->find( $sql )->data(); 
  1130.  
  1131. $items = array(); 
  1132.  
  1133. if ( !empty( $item_data ) ) { 
  1134. foreach ( $item_data as $item ) { 
  1135. if ( is_array( $item ) ) 
  1136. $item = (object) $item; 
  1137.  
  1138. if ( empty( $item->pod_item_id ) ) 
  1139. continue; 
  1140.  
  1141. // Bypass pass field 
  1142. if ( isset( $item->user_pass ) ) 
  1143. unset( $item->user_pass ); 
  1144.  
  1145. // Get Item ID 
  1146. $item_id = $item->pod_item_id; 
  1147.  
  1148. // Output types 
  1149. if ( 'ids' == $params->output ) 
  1150. $item = (int) $item_id; 
  1151. elseif ( 'names' == $params->output && !empty( $table[ 'field_index' ] ) ) 
  1152. $item = $item->pod_item_index; 
  1153. elseif ( 'objects' == $params->output ) { 
  1154. if ( in_array( $object_type, array( 'post_type', 'media' ) ) ) 
  1155. $item = get_post( $item_id ); 
  1156. elseif ( 'taxonomy' == $object_type ) 
  1157. $item = get_term( $item_id, $object ); 
  1158. elseif ( 'user' == $object_type ) { 
  1159. $item = get_userdata( $item_id ); 
  1160.  
  1161. if ( !empty( $item ) ) { 
  1162. // Get other vars 
  1163. $roles = $item->roles; 
  1164. $caps = $item->caps; 
  1165. $allcaps = $item->allcaps; 
  1166.  
  1167. $item = $item->data; 
  1168.  
  1169. // Set other vars 
  1170. $item->roles = $roles; 
  1171. $item->caps = $caps; 
  1172. $item->allcaps = $allcaps; 
  1173.  
  1174. unset( $item->user_pass ); 
  1175. elseif ( 'comment' == $object_type ) 
  1176. $item = get_comment( $item_id ); 
  1177. else 
  1178. $item = (object) $item; 
  1179. } elseif ( 'pods' == $params->output ) { 
  1180. if ( in_array( $object_type, array( 'user', 'media' ) ) ) { 
  1181. $item = pods( $object_type, (int) $item_id ); 
  1182. } else { 
  1183. $item = pods( $object, (int) $item_id ); 
  1184. else // arrays 
  1185. $item = get_object_vars( (object) $item ); 
  1186.  
  1187. // Pass item data into $data 
  1188. $items[ $item_id ] = $item; 
  1189.  
  1190. // Cleanup 
  1191. unset( $item_data ); 
  1192.  
  1193. // Return all of the data in the order expected 
  1194. if ( empty( $params->orderby ) ) { 
  1195. foreach ( $ids as $id ) { 
  1196. if ( isset( $items[ $id ] ) ) { 
  1197. $data[ $id ] = $items[ $id ]; 
  1198. } else { 
  1199. // Use order set by orderby 
  1200. foreach ( $items as $id => $v ) { 
  1201. if ( in_array( $id, $ids ) ) { 
  1202. $data[ $id ] = $v; 
  1203.  
  1204. if ( in_array( $last_type, $tableless_field_types ) || in_array( $last_type, array( 'boolean', 'number', 'currency' ) ) ) 
  1205. $params->raw = true; 
  1206.  
  1207. if ( empty( $data ) ) 
  1208. $value = false; 
  1209. else { 
  1210. $object_type = $table[ 'type' ]; 
  1211.  
  1212. if ( in_array( $table[ 'type' ], array( 'post_type', 'attachment', 'media' ) ) ) 
  1213. $object_type = 'post'; 
  1214.  
  1215. $no_conflict = true; 
  1216.  
  1217. if ( in_array( $object_type, array( 'post', 'taxonomy', 'user', 'comment', 'settings' ) ) ) { 
  1218. $no_conflict = pods_no_conflict_check( $object_type ); 
  1219.  
  1220. if ( !$no_conflict ) 
  1221. pods_no_conflict_on( $object_type ); 
  1222.  
  1223. // Return entire array 
  1224. if ( false !== $field_exists && ( in_array( $last_type, $tableless_field_types ) && !$simple ) ) 
  1225. $value = $data; 
  1226. // Return an array of single column values 
  1227. else { 
  1228. $value = array(); 
  1229.  
  1230. foreach ( $data as $item_id => $item ) { 
  1231. // $field is 123x123, needs to be _src.123x123 
  1232. $full_field = implode( '.', array_splice( $params->traverse, $key ) ); 
  1233.  
  1234. if ( is_array( $item ) && isset( $item[ $field ] ) ) { 
  1235. if ( $table[ 'field_id' ] == $field ) 
  1236. $value[] = (int) $item[ $field ]; 
  1237. else 
  1238. $value[] = $item[ $field ]; 
  1239. elseif ( is_object( $item ) && isset( $item->{$field} ) ) { 
  1240. if ( $table[ 'field_id' ] == $field ) 
  1241. $value[] = (int) $item->{$field}; 
  1242. else 
  1243. $value[] = $item->{$field}; 
  1244. elseif ( ( ( false !== strpos( $full_field, '_src' ) || 'guid' == $field ) && ( in_array( $table[ 'type' ], array( 'attachment', 'media' ) ) || in_array( $last_type, PodsForm::file_field_types() ) ) ) || ( in_array( $field, array( '_link', 'detail_url' ) ) || in_array( $field, array( 'permalink', 'the_permalink' ) ) && in_array( $last_type, PodsForm::file_field_types() ) ) ) { 
  1245. $size = 'full'; 
  1246.  
  1247. if ( false !== strpos( $full_field, '_src.' ) && 5 < strlen( $full_field ) ) 
  1248. $size = substr( $full_field, 5 ); 
  1249. elseif ( false !== strpos( $full_field, '_src_relative.' ) && 14 < strlen( $full_field ) ) 
  1250. $size = substr( $full_field, 14 ); 
  1251. elseif ( false !== strpos( $full_field, '_src_schemeless.' ) && 16 < strlen( $full_field ) ) 
  1252. $size = substr( $full_field, 16 ); 
  1253.  
  1254. $value_url = pods_image_url( $item_id, $size ); 
  1255.  
  1256. if ( false !== strpos( $full_field, '_src_relative' ) && !empty( $value_url ) ) { 
  1257. $value_url_parsed = parse_url( $value_url ); 
  1258. $value_url = $value_url_parsed[ 'path' ]; 
  1259. elseif ( false !== strpos( $full_field, '_src_schemeless' ) && !empty( $value_url ) ) 
  1260. $value_url = str_replace( array( 'http://', 'https://' ), '//', $value_url ); 
  1261.  
  1262. if ( !empty( $value_url ) ) 
  1263. $value[] = $value_url; 
  1264.  
  1265. $params->raw_display = true; 
  1266. elseif ( false !== strpos( $full_field, '_img' ) && ( in_array( $table[ 'type' ], array( 'attachment', 'media' ) ) || in_array( $last_type, PodsForm::file_field_types() ) ) ) { 
  1267. $size = 'full'; 
  1268.  
  1269. if ( false !== strpos( $full_field, '_img.' ) && 5 < strlen( $full_field ) ) 
  1270. $size = substr( $full_field, 5 ); 
  1271.  
  1272. $value[] = pods_image( $item_id, $size ); 
  1273.  
  1274. $params->raw_display = true; 
  1275. elseif ( in_array( $field, array( '_link', 'detail_url' ) ) || in_array( $field, array( 'permalink', 'the_permalink' ) ) ) { 
  1276. if ( 'pod' == $object_type ) { 
  1277. if ( is_object( $related_obj ) ) { 
  1278. $related_obj->fetch( $item_id ); 
  1279.  
  1280. $value[] = $related_obj->field( 'detail_url' ); 
  1281. else 
  1282. $value[] = ''; 
  1283. elseif ( 'post' == $object_type ) 
  1284. $value[] = get_permalink( $item_id ); 
  1285. elseif ( 'taxonomy' == $object_type ) 
  1286. $value[] = get_term_link( $item_id, $object ); 
  1287. elseif ( 'user' == $object_type ) 
  1288. $value[] = get_author_posts_url( $item_id ); 
  1289. elseif ( 'comment' == $object_type ) 
  1290. $value[] = get_comment_link( $item_id ); 
  1291. else 
  1292. $value[] = ''; 
  1293.  
  1294. $params->raw_display = true; 
  1295. elseif ( in_array( $object_type, array( 'post', 'taxonomy', 'user', 'comment' ) ) ) { 
  1296. $metadata_object_id = $item_id; 
  1297.  
  1298. $metadata_type = $object_type; 
  1299.  
  1300. if ( 'post' == $object_type ) { 
  1301. // Support for WPML 'duplicated' translation handling 
  1302. if ( did_action( 'wpml_loaded' ) 
  1303. && apply_filters( 'wpml_is_translated_post_type', false, $object ) ) { 
  1304. $master_post_id = (int) apply_filters( 'wpml_master_post_from_duplicate', $metadata_object_id ); 
  1305.  
  1306. if ( 0 < $master_post_id ) 
  1307. $metadata_object_id = $master_post_id; 
  1308. } elseif ( 'taxonomy' == $object_type ) { 
  1309. $metadata_type = 'term'; 
  1310.  
  1311. $value[] = get_metadata( $metadata_type, $metadata_object_id, $field, true ); 
  1312. elseif ( 'settings' == $object_type ) 
  1313. $value[] = get_option( $object . '_' . $field ); 
  1314.  
  1315. if ( in_array( $object_type, array( 'post', 'taxonomy', 'user', 'comment', 'settings' ) ) && !$no_conflict ) 
  1316. pods_no_conflict_off( $object_type ); 
  1317.  
  1318. // Handle Simple Relationships 
  1319. if ( $simple ) { 
  1320. if ( null === $params->single ) 
  1321. $params->single = false; 
  1322.  
  1323. $value = PodsForm::field_method( 'pick', 'simple_value', $field, $value, $last_options, $all_fields[ $pod ], 0, true ); 
  1324. elseif ( false === $params->in_form && !empty( $value ) ) 
  1325. $value = array_values( $value ); 
  1326.  
  1327. // Return a single column value 
  1328. if ( false === $params->in_form && 1 == $limit && !empty( $value ) && is_array( $value ) && 1 == count( $value ) ) 
  1329. $value = current( $value ); 
  1330.  
  1331. if ( $last_options ) { 
  1332. $last_field_data = $last_options; 
  1333.  
  1334. break; 
  1335.  
  1336. if ( !empty( $params->traverse ) && 1 < count( $params->traverse ) ) { 
  1337. $field_names = implode( '.', $params->traverse ); 
  1338.  
  1339. $this->row[ $field_names ] = $value; 
  1340. elseif ( 'arrays' != $params->output && in_array( $field_data[ 'type' ], $tableless_field_types ) ) { 
  1341. $this->row[ '_' . $params->output . '_' . $params->full_name ] = $value; 
  1342. elseif ( 'arrays' == $params->output || !in_array( $field_data[ 'type' ], $tableless_field_types ) ) { 
  1343. $this->row[ $params->full_name ] = $value; 
  1344.  
  1345. if ( $params->single && is_array( $value ) && 1 == count( $value ) ) 
  1346. $value = current( $value ); 
  1347.  
  1348. if ( ! empty( $last_field_data ) ) { 
  1349. $field_data = $last_field_data; 
  1350.  
  1351. // @todo Expand this into traversed fields too 
  1352. if ( !empty( $field_data ) && ( $params->display || !$params->raw ) && !$params->in_form && !$params->raw_display ) { 
  1353. if ( $params->display || ( ( $params->get_meta || $params->deprecated ) && !in_array( $field_data[ 'type' ], $tableless_field_types ) ) ) { 
  1354. $field_data[ 'options' ] = pods_var_raw( 'options', $field_data, array(), null, true ); 
  1355.  
  1356. $post_temp = false; 
  1357.  
  1358. if ( 'post_type' == pods_v( 'type', $this->pod_data ) && 0 < $this->id() && ( !isset( $GLOBALS[ 'post' ] ) || empty( $GLOBALS[ 'post' ] ) ) ) { 
  1359. global $post_ID, $post; 
  1360.  
  1361. $post_temp = true; 
  1362.  
  1363. $old_post = $GLOBALS[ 'post' ]; 
  1364. $old_ID = $GLOBALS[ 'post_ID' ]; 
  1365.  
  1366. $post = get_post( $this->id() ); 
  1367. $post_ID = $this->id(); 
  1368.  
  1369. $filter = pods_var_raw( 'display_filter', $field_data[ 'options' ] ); 
  1370.  
  1371. if ( 0 < strlen( $filter ) ) { 
  1372. $args = array( 
  1373. $filter,  
  1374. $value 
  1375. ); 
  1376.  
  1377. $filter_args = pods_var_raw( 'display_filter_args', $field_data[ 'options' ] ); 
  1378.  
  1379. if ( !empty( $filter_args ) ) 
  1380. $args = array_merge( $args, compact( $filter_args ) ); 
  1381.  
  1382. $value = call_user_func_array( 'apply_filters', $args ); 
  1383. elseif ( 1 == pods_v( 'display_process', $field_data[ 'options' ], 1 ) ) { 
  1384. $value = PodsForm::display( 
  1385. $field_data[ 'type' ],  
  1386. $value,  
  1387. $params->name,  
  1388. array_merge( $field_data, $field_data[ 'options' ] ),  
  1389. $this->pod_data,  
  1390. $this->id() 
  1391. ); 
  1392.  
  1393. if ( $post_temp ) { 
  1394. $post = $old_post; 
  1395. $post_ID = $old_ID; 
  1396. else { 
  1397. $value = PodsForm::value( 
  1398. $field_data[ 'type' ],  
  1399. $value,  
  1400. $params->name,  
  1401. array_merge( $field_data, $field_data[ 'options' ] ),  
  1402. $this->pod_data,  
  1403. $this->id() 
  1404. ); 
  1405.  
  1406. /** 
  1407. * Modify value returned by field() directly before output. 
  1408. * Will not run if value was null 
  1409. * @since unknown 
  1410. * @param array|string|null $value Value to be returned. 
  1411. * @param array|object $row Current row being outputted. 
  1412. * @param array $params Params array passed to field(). 
  1413. * @param object|Pods $this Current Pods object. 
  1414. */ 
  1415. $value = apply_filters( 'pods_pods_field', $value, $this->row, $params, $this ); 
  1416.  
  1417. return $value; 
  1418.  
  1419. /** 
  1420. * Check if an item field has a specific value in it 
  1421. * @param string $field Field name 
  1422. * @param mixed $value Value to check 
  1423. * @param int $id (optional) ID of the pod item to check 
  1424. * @return bool Whether the value was found 
  1425. * @since 2.3.3 
  1426. */ 
  1427. public function has ( $field, $value, $id = null ) { 
  1428. $pod =& $this; 
  1429.  
  1430. if ( null === $id ) 
  1431. $id = $this->id(); 
  1432. elseif ( $id != $this->id() ) 
  1433. $pod = pods( $this->pod, $id ); 
  1434.  
  1435. $this->do_hook( 'has', $field, $value, $id ); 
  1436.  
  1437. if ( !isset( $this->fields[ $field ] ) ) 
  1438. return false; 
  1439.  
  1440. // Tableless fields 
  1441. if ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::tableless_field_types() ) ) { 
  1442. if ( !is_array( $value ) ) 
  1443. $value = explode( ', ', $value ); 
  1444.  
  1445. if ( 'pick' == $this->fields[ $field ][ 'type' ] && in_array( $this->fields[ $field ][ 'pick_object' ], PodsForm::simple_tableless_objects() ) ) { 
  1446. $current_value = $pod->raw( $field ); 
  1447.  
  1448. if ( !empty( $current_value ) ) 
  1449. $current_value = (array) $current_value; 
  1450.  
  1451. foreach ( $current_value as $v ) { 
  1452. if ( in_array( $v, $value ) ) 
  1453. return true; 
  1454. else { 
  1455. $related_ids = $this->api->lookup_related_items( $this->fields[ $field ][ 'id' ], $this->pod_data[ 'id' ], $id, $this->fields[ $field ], $this->pod_data ); 
  1456.  
  1457. foreach ( $value as $k => $v ) { 
  1458. if ( !preg_match( '/[^0-9]/', $v ) ) 
  1459. $value[ $k ] = (int) $v; 
  1460. // @todo Convert slugs into IDs 
  1461. else { 
  1462.  
  1463.  
  1464. foreach ( $related_ids as $v ) { 
  1465. if ( in_array( $v, $value ) ) 
  1466. return true; 
  1467. // Text fields 
  1468. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::text_field_types() ) ) { 
  1469. $current_value = $pod->raw( $field ); 
  1470.  
  1471. if ( 0 < strlen( $current_value ) ) 
  1472. return stripos( $current_value, $value ); 
  1473. // All other fields 
  1474. else 
  1475. return $this->is( $field, $value, $id ); 
  1476.  
  1477. return false; 
  1478.  
  1479. /** 
  1480. * Check if an item field is a specific value 
  1481. * @param string $field Field name 
  1482. * @param mixed $value Value to check 
  1483. * @param int $id (optional) ID of the pod item to check 
  1484. * @return bool Whether the value was found 
  1485. * @since 2.3.3 
  1486. */ 
  1487. public function is ( $field, $value, $id = null ) { 
  1488. $pod =& $this; 
  1489.  
  1490. if ( null === $id ) 
  1491. $id = $this->id(); 
  1492. elseif ( $id != $this->id() ) 
  1493. $pod = pods( $this->pod, $id ); 
  1494.  
  1495. $this->do_hook( 'is', $field, $value, $id ); 
  1496.  
  1497. if ( !isset( $this->fields[ $field ] ) ) 
  1498. return false; 
  1499.  
  1500. // Tableless fields 
  1501. if ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::tableless_field_types() ) ) { 
  1502. if ( !is_array( $value ) ) 
  1503. $value = explode( ', ', $value ); 
  1504.  
  1505. $current_value = array(); 
  1506.  
  1507. if ( 'pick' == $this->fields[ $field ][ 'type' ] && in_array( $this->fields[ $field ][ 'pick_object' ], PodsForm::simple_tableless_objects() ) ) { 
  1508. $current_value = $pod->raw( $field ); 
  1509.  
  1510. if ( !empty( $current_value ) ) 
  1511. $current_value = (array) $current_value; 
  1512.  
  1513. foreach ( $current_value as $v ) { 
  1514. if ( in_array( $v, $value ) ) 
  1515. return true; 
  1516. else { 
  1517. $related_ids = $this->api->lookup_related_items( $this->fields[ $field ][ 'id' ], $this->pod_data[ 'id' ], $id, $this->fields[ $field ], $this->pod_data ); 
  1518.  
  1519. foreach ( $value as $k => $v ) { 
  1520. if ( !preg_match( '/[^0-9]/', $v ) ) 
  1521. $value[ $k ] = (int) $v; 
  1522. // @todo Convert slugs into IDs 
  1523. else { 
  1524.  
  1525.  
  1526. foreach ( $related_ids as $v ) { 
  1527. if ( in_array( $v, $value ) ) 
  1528. return true; 
  1529.  
  1530. if ( !empty( $current_value ) ) 
  1531. $current_value = array_filter( array_unique( $current_value ) ); 
  1532. else 
  1533. $current_value = array(); 
  1534.  
  1535. if ( !empty( $value ) ) 
  1536. $value = array_filter( array_unique( $value ) ); 
  1537. else 
  1538. $value = array(); 
  1539.  
  1540. sort( $current_value ); 
  1541. sort( $value ); 
  1542.  
  1543. if ( $value === $current_value ) 
  1544. return true; 
  1545. // Number fields 
  1546. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::number_field_types() ) ) { 
  1547. $current_value = $pod->raw( $field ); 
  1548.  
  1549. if ( (float) $current_value === (float) $value ) 
  1550. return true; 
  1551. // Date fields 
  1552. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::date_field_types() ) ) { 
  1553. $current_value = $pod->raw( $field ); 
  1554.  
  1555. if ( 0 < strlen( $current_value ) ) { 
  1556. if ( strtotime( $current_value ) == strtotime( $value ) ) 
  1557. return true; 
  1558. elseif ( empty( $value ) ) 
  1559. return true; 
  1560. // Text fields 
  1561. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::text_field_types() ) ) { 
  1562. $current_value = $pod->raw( $field ); 
  1563.  
  1564. if ( (string) $current_value === (string) $value ) 
  1565. return true; 
  1566. // All other fields 
  1567. else { 
  1568. $current_value = $pod->raw( $field ); 
  1569.  
  1570. if ( $current_value === $value ) 
  1571. return true; 
  1572.  
  1573. return false; 
  1574.  
  1575. /** 
  1576. * Return the item ID 
  1577. * @return int 
  1578. * @since 2.0 
  1579. */ 
  1580. public function id () { 
  1581. if ( isset( $this->data->row ) && isset( $this->data->row[ 'id' ] ) ) { 
  1582. // If we already have data loaded return that ID 
  1583. return $this->data->row[ 'id' ]; 
  1584. return $this->field( $this->data->field_id ); 
  1585.  
  1586. /** 
  1587. * Return the previous item ID, loops at the last id to return the first 
  1588. * @param int $id 
  1589. * @param array $params_override 
  1590. * @return int 
  1591. * @since 2.0 
  1592. */ 
  1593. public function prev_id ( $id = null, $params_override = null ) { 
  1594. if ( null === $id ) 
  1595. $id = $this->id(); 
  1596.  
  1597. $id = (int) $id; 
  1598.  
  1599. $params = array( 
  1600. 'select' => "`t`.`{$this->data->field_id}`",  
  1601. 'where' => "`t`.`{$this->data->field_id}` < {$id}",  
  1602. 'orderby' => "`t`.`{$this->data->field_id}` DESC",  
  1603. 'limit' => 1 
  1604. ); 
  1605.  
  1606. if ( !empty( $params_override ) || !empty( $this->params ) ) { 
  1607. if ( !empty( $params_override ) ) 
  1608. $params = $params_override; 
  1609. elseif ( !empty( $this->params ) ) 
  1610. $params = $this->params; 
  1611.  
  1612. if ( is_object( $params ) ) { 
  1613. $params = get_object_vars( $params ); 
  1614.  
  1615. if ( 0 < $id ) { 
  1616. if ( isset( $params[ 'where' ] ) && !empty( $params[ 'where' ] ) ) { 
  1617. $params[ 'where' ] = (array) $params[ 'where' ]; 
  1618. $params[ 'where' ][] = "`t`.`{$this->data->field_id}` < {$id}"; 
  1619. else { 
  1620. $params[ 'where' ] = "`t`.`{$this->data->field_id}` < {$id}"; 
  1621. elseif ( isset( $params[ 'offset' ] ) && 0 < $params[ 'offset' ] ) 
  1622. $params[ 'offset' ] -= 1; 
  1623. elseif ( !isset( $params[ 'offset' ] ) && !empty( $this->params ) && 0 < $this->row_number ) 
  1624. $params[ 'offset' ] = $this->row_number - 1; 
  1625. else 
  1626. return 0; 
  1627.  
  1628. if ( isset( $params[ 'orderby' ] ) && !empty( $params[ 'orderby' ] ) ) { 
  1629. if ( is_array( $params[ 'orderby' ] ) ) { 
  1630. foreach ( $params[ 'orderby' ] as $orderby => $dir ) { 
  1631. $dir = strtoupper( $dir ); 
  1632.  
  1633. if ( !in_array( $dir, array( 'ASC', 'DESC' ) ) ) { 
  1634. continue; 
  1635.  
  1636. if ( 'ASC' == $dir ) { 
  1637. $params[ 'orderby' ][ $orderby ] = 'DESC'; 
  1638. else { 
  1639. $params[ 'orderby' ][ $orderby ] = 'ASC'; 
  1640.  
  1641. $params[ 'orderby' ][ $this->data->field_id ] = 'DESC'; 
  1642. elseif ( "`t`.`{$this->data->field_id}` DESC" != $params[ 'orderby' ] ) { 
  1643. $params[ 'orderby' ] .= ", `t`.`{$this->data->field_id}` DESC"; 
  1644.  
  1645. $params[ 'select' ] = "`t`.`{$this->data->field_id}`"; 
  1646. $params[ 'limit' ] = 1; 
  1647.  
  1648. $pod = pods( $this->pod, $params ); 
  1649.  
  1650. $new_id = 0; 
  1651.  
  1652. if ( $pod->fetch() ) 
  1653. $new_id = $pod->id(); 
  1654.  
  1655. $new_id = $this->do_hook( 'prev_id', $new_id, $id, $pod, $params_override ); 
  1656.  
  1657. return $new_id; 
  1658.  
  1659. /** 
  1660. * Return the next item ID, loops at the first id to return the last 
  1661. * @param int $id 
  1662. * @param array $find_params 
  1663. * @return int 
  1664. * @since 2.0 
  1665. */ 
  1666. public function next_id ( $id = null, $params_override = null ) { 
  1667. if ( null === $id ) 
  1668. $id = $this->id(); 
  1669.  
  1670. $id = (int) $id; 
  1671.  
  1672. $params = array( 
  1673. 'select' => "`t`.`{$this->data->field_id}`",  
  1674. 'where' => "{$id} < `t`.`{$this->data->field_id}`",  
  1675. 'orderby' => "`t`.`{$this->data->field_id}` ASC",  
  1676. 'limit' => 1 
  1677. ); 
  1678.  
  1679. if ( !empty( $params_override ) || !empty( $this->params ) ) { 
  1680. if ( !empty( $params_override ) ) 
  1681. $params = $params_override; 
  1682. elseif ( !empty( $this->params ) ) 
  1683. $params = $this->params; 
  1684.  
  1685. if ( is_object( $params ) ) { 
  1686. $params = get_object_vars( $params ); 
  1687.  
  1688. if ( 0 < $id ) { 
  1689. if ( isset( $params[ 'where' ] ) && !empty( $params[ 'where' ] ) ) { 
  1690. $params[ 'where' ] = (array) $params[ 'where' ]; 
  1691. $params[ 'where' ][] = "{$id} < `t`.`{$this->data->field_id}`"; 
  1692. else { 
  1693. $params[ 'where' ] = "{$id} < `t`.`{$this->data->field_id}`"; 
  1694. elseif ( !isset( $params[ 'offset' ] ) ) { 
  1695. if ( !empty( $this->params ) && -1 < $this->row_number ) 
  1696. $params[ 'offset' ] = $this->row_number + 1; 
  1697. else 
  1698. $params[ 'offset' ] = 1; 
  1699. else 
  1700. $params[ 'offset' ] += 1; 
  1701.  
  1702. $params[ 'select' ] = "`t`.`{$this->data->field_id}`"; 
  1703. $params[ 'limit' ] = 1; 
  1704.  
  1705. $pod = pods( $this->pod, $params ); 
  1706.  
  1707. $new_id = 0; 
  1708.  
  1709. if ( $pod->fetch() ) 
  1710. $new_id = $pod->id(); 
  1711.  
  1712. $new_id = $this->do_hook( 'next_id', $new_id, $id, $pod, $params_override ); 
  1713.  
  1714. return $new_id; 
  1715.  
  1716. /** 
  1717. * Return the first item ID 
  1718. * @param array $params_override 
  1719. * @return int 
  1720. * @since 2.3 
  1721. */ 
  1722. public function first_id ( $params_override = null ) { 
  1723. $params = array( 
  1724. 'select' => "`t`.`{$this->data->field_id}`",  
  1725. 'orderby' => "`t`.`{$this->data->field_id}` ASC",  
  1726. 'limit' => 1 
  1727. ); 
  1728.  
  1729. if ( !empty( $params_override ) || !empty( $this->params ) ) { 
  1730. if ( !empty( $params_override ) ) 
  1731. $params = $params_override; 
  1732. elseif ( !empty( $this->params ) ) 
  1733. $params = $this->params; 
  1734.  
  1735. if ( is_object( $params ) ) { 
  1736. $params = get_object_vars( $params ); 
  1737.  
  1738. $params[ 'select' ] = "`t`.`{$this->data->field_id}`"; 
  1739. $params[ 'offset' ] = 0; 
  1740. $params[ 'limit' ] = 1; 
  1741.  
  1742. $pod = pods( $this->pod, $params ); 
  1743.  
  1744. $new_id = 0; 
  1745.  
  1746. if ( $pod->fetch() ) 
  1747. $new_id = $pod->id(); 
  1748.  
  1749. $new_id = $this->do_hook( 'first_id', $new_id, $pod, $params_override ); 
  1750.  
  1751. return $new_id; 
  1752.  
  1753. /** 
  1754. * Return the last item ID 
  1755. * @param array $params_override 
  1756. * @return int 
  1757. * @since 2.3 
  1758. */ 
  1759. public function last_id ( $params_override = null ) { 
  1760. $params = array( 
  1761. 'select' => "`t`.`{$this->data->field_id}`",  
  1762. 'orderby' => "`t`.`{$this->data->field_id}` DESC",  
  1763. 'limit' => 1 
  1764. ); 
  1765.  
  1766. if ( !empty( $params_override ) || !empty( $this->params ) ) { 
  1767. if ( !empty( $params_override ) ) 
  1768. $params = $params_override; 
  1769. elseif ( !empty( $this->params ) ) 
  1770. $params = $this->params; 
  1771.  
  1772. if ( is_object( $params ) ) { 
  1773. $params = get_object_vars( $params ); 
  1774.  
  1775. if ( isset( $params[ 'total_found' ] ) ) 
  1776. $params[ 'offset' ] = $params[ 'total_found' ] - 1; 
  1777. else 
  1778. $params[ 'offset' ] = $this->total_found() - 1; 
  1779.  
  1780. if ( isset( $params[ 'orderby' ] ) && !empty( $params[ 'orderby' ] ) ) { 
  1781. if ( is_array( $params[ 'orderby' ] ) ) { 
  1782. foreach ( $params[ 'orderby' ] as $orderby => $dir ) { 
  1783. $dir = strtoupper( $dir ); 
  1784.  
  1785. if ( !in_array( $dir, array( 'ASC', 'DESC' ) ) ) { 
  1786. continue; 
  1787.  
  1788. if ( 'ASC' == $dir ) { 
  1789. $params[ 'orderby' ][ $orderby ] = 'DESC'; 
  1790. else { 
  1791. $params[ 'orderby' ][ $orderby ] = 'ASC'; 
  1792.  
  1793. $params[ 'orderby' ][ $this->data->field_id ] = 'DESC'; 
  1794. elseif ( "`t`.`{$this->data->field_id}` DESC" != $params[ 'orderby' ] ) { 
  1795. $params[ 'orderby' ] .= ", `t`.`{$this->data->field_id}` DESC"; 
  1796.  
  1797. $params[ 'select' ] = "`t`.`{$this->data->field_id}`"; 
  1798. $params[ 'limit' ] = 1; 
  1799.  
  1800. $pod = pods( $this->pod, $params ); 
  1801.  
  1802. $new_id = 0; 
  1803.  
  1804. if ( $pod->fetch() ) 
  1805. $new_id = $pod->id(); 
  1806.  
  1807. $new_id = $this->do_hook( 'last_id', $new_id, $pod, $params_override ); 
  1808. return $new_id; 
  1809.  
  1810. /** 
  1811. * Return the item name 
  1812. * @return string 
  1813. * @since 2.0 
  1814. */ 
  1815. public function index () { 
  1816. return $this->field( $this->data->field_index ); 
  1817.  
  1818. /** 
  1819. * Find items of a pod, much like WP_Query, but with advanced table handling. 
  1820. * @param array $params An associative array of parameters 
  1821. * @param int $limit (optional) (deprecated) Limit the number of items to find, use -1 to return all items with no limit 
  1822. * @param string $where (optional) (deprecated) SQL WHERE declaration to use 
  1823. * @param string $sql (optional) (deprecated) For advanced use, a custom SQL query to run 
  1824. * @return \Pods The pod object 
  1825. * @since 2.0 
  1826. * @link http://pods.io/docs/find/ 
  1827. */ 
  1828. public function find ( $params = null, $limit = 15, $where = null, $sql = null ) { 
  1829.  
  1830. $tableless_field_types = PodsForm::tableless_field_types(); 
  1831. $simple_tableless_objects = PodsForm::simple_tableless_objects(); 
  1832.  
  1833.  
  1834. $this->params = $params; 
  1835.  
  1836. $select = '`t`.*'; 
  1837.  
  1838. if ( !in_array( $this->pod_data[ 'type' ], array( 'pod', 'table' ) ) && 'table' == $this->pod_data[ 'storage' ] ) 
  1839. $select .= ', `d`.*'; 
  1840.  
  1841. if ( empty( $this->data->table ) ) 
  1842. return $this; 
  1843.  
  1844. $defaults = array( 
  1845. 'table' => $this->data->table,  
  1846. 'select' => $select,  
  1847. 'join' => null,  
  1848.  
  1849. 'where' => $where,  
  1850. 'groupby' => null,  
  1851. 'having' => null,  
  1852. 'orderby' => null,  
  1853.  
  1854. 'limit' => (int) $limit,  
  1855. 'offset' => null,  
  1856. 'page' => (int) $this->page,  
  1857. 'page_var' => $this->page_var,  
  1858. 'pagination' => (boolean) $this->pagination,  
  1859.  
  1860. 'search' => (boolean) $this->search,  
  1861. 'search_var' => $this->search_var,  
  1862. 'search_query' => null,  
  1863. 'search_mode' => $this->search_mode,  
  1864. 'search_across' => false,  
  1865. 'search_across_picks' => false,  
  1866. 'search_across_files' => false,  
  1867.  
  1868. 'filters' => $this->filters,  
  1869. 'sql' => $sql,  
  1870.  
  1871. 'expires' => null,  
  1872. 'cache_mode' => 'cache' 
  1873. ); 
  1874.  
  1875. if ( is_array( $params ) ) 
  1876. $params = (object) array_merge( $defaults, $params ); 
  1877. if ( is_object( $params ) ) 
  1878. $params = (object) array_merge( $defaults, get_object_vars( $params ) ); 
  1879. else { 
  1880. $defaults[ 'orderby' ] = $params; 
  1881. $params = (object) $defaults; 
  1882.  
  1883. $params = apply_filters( 'pods_pods_find', $params ); 
  1884.  
  1885. $params->limit = (int) $params->limit; 
  1886.  
  1887. if ( 0 == $params->limit ) 
  1888. $params->limit = -1; 
  1889.  
  1890. $this->limit = (int) $params->limit; 
  1891. $this->offset = (int) $params->offset; 
  1892. $this->page = (int) $params->page; 
  1893. $this->page_var = $params->page_var; 
  1894. $this->pagination = (boolean) $params->pagination; 
  1895. $this->search = (boolean) $params->search; 
  1896. $this->search_var = $params->search_var; 
  1897. $params->join = (array) $params->join; 
  1898.  
  1899. if ( empty( $params->search_query ) ) 
  1900. $params->search_query = pods_var( $this->search_var, 'get', '' ); 
  1901.  
  1902. // Allow orderby array ( 'field' => 'asc|desc' ) 
  1903. if ( !empty( $params->orderby ) && is_array( $params->orderby ) ) { 
  1904. foreach ( $params->orderby as $k => &$orderby ) { 
  1905. if ( !is_numeric( $k ) ) { 
  1906. $key = ''; 
  1907.  
  1908. $order = 'ASC'; 
  1909.  
  1910. if ( 'DESC' == strtoupper( $orderby ) ) 
  1911. $order = 'DESC'; 
  1912.  
  1913. if ( isset( $this->fields[ $k ] ) && in_array( $this->fields[ $k ][ 'type' ], $tableless_field_types ) ) { 
  1914. if ( in_array( $this->fields[ $k ][ 'pick_object' ], $simple_tableless_objects ) ) { 
  1915. if ( 'table' == $this->pod_data[ 'storage' ] ) { 
  1916. if ( !in_array( $this->pod_data[ 'type' ], array( 'pod', 'table' ) ) ) 
  1917. $key = "`d`.`{$k}`"; 
  1918. else 
  1919. $key = "`t`.`{$k}`"; 
  1920. else 
  1921. $key = "`{$k}`.`meta_value`"; 
  1922. else { 
  1923. $pick_val = $this->fields[ $k ][ 'pick_val' ]; 
  1924.  
  1925. if ( '__current__' == $pick_val ) 
  1926. $pick_val = $this->pod; 
  1927.  
  1928. $table = $this->api->get_table_info( $this->fields[ $k ][ 'pick_object' ], $pick_val ); 
  1929.  
  1930. if ( !empty( $table ) ) 
  1931. $key = "`{$k}`.`" . $table[ 'field_index' ] . '`'; 
  1932.  
  1933. if ( empty( $key ) ) { 
  1934. if ( !in_array( $this->pod_data[ 'type' ], array( 'pod', 'table' ) ) ) { 
  1935. if ( isset( $this->pod_data[ 'object_fields' ][ $k ] ) ) 
  1936. $key = "`t`.`{$k}`"; 
  1937. elseif ( isset( $this->fields[ $k ] ) ) { 
  1938. if ( 'table' == $this->pod_data[ 'storage' ] ) 
  1939. $key = "`d`.`{$k}`"; 
  1940. else 
  1941. $key = "`{$k}`.`meta_value`"; 
  1942. else { 
  1943. foreach ( $this->pod_data[ 'object_fields' ] as $object_field => $object_field_opt ) { 
  1944. if ( $object_field == $k || in_array( $k, $object_field_opt[ 'alias' ] ) ) 
  1945. $key = "`t`.`{$object_field}`"; 
  1946. elseif ( isset( $this->fields[ $k ] ) ) { 
  1947. if ( 'table' == $this->pod_data[ 'storage' ] ) 
  1948. $key = "`t`.`{$k}`"; 
  1949. else 
  1950. $key = "`{$k}`.`meta_value`"; 
  1951.  
  1952. if ( empty( $key ) ) { 
  1953. $key = $k; 
  1954.  
  1955. if ( false === strpos( $key, ' ' ) && false === strpos( $key, '`' ) ) 
  1956. $key = '`' . str_replace( '.', '`.`', $key ) . '`'; 
  1957.  
  1958. $orderby = $key; 
  1959.  
  1960. if ( false === strpos( $orderby, ' ' ) ) 
  1961. $orderby .= ' ' . $order; 
  1962.  
  1963. // Add prefix to $params->orderby if needed 
  1964. if ( !empty( $params->orderby ) ) { 
  1965. if ( !is_array( $params->orderby ) ) 
  1966. $params->orderby = array( $params->orderby ); 
  1967.  
  1968. foreach ( $params->orderby as &$prefix_orderby ) { 
  1969. if ( false === strpos( $prefix_orderby, ', ' ) && false === strpos( $prefix_orderby, '(' ) && false === stripos( $prefix_orderby, ' AS ' ) && false === strpos( $prefix_orderby, '`' ) && false === strpos( $prefix_orderby, '.' ) ) { 
  1970. if ( false !== stripos( $prefix_orderby, ' DESC' ) ) { 
  1971. $k = trim( str_ireplace( array( '`', ' DESC' ), '', $prefix_orderby ) ); 
  1972. $dir = 'DESC'; 
  1973. else { 
  1974. $k = trim( str_ireplace( array( '`', ' ASC' ), '', $prefix_orderby ) ); 
  1975. $dir = 'ASC'; 
  1976.  
  1977. $key = $k; 
  1978.  
  1979. if ( !in_array( $this->pod_data[ 'type' ], array( 'pod', 'table' ) ) ) { 
  1980. if ( isset( $this->pod_data[ 'object_fields' ][ $k ] ) ) 
  1981. $key = "`t`.`{$k}`"; 
  1982. elseif ( isset( $this->fields[ $k ] ) ) { 
  1983. if ( 'table' == $this->pod_data[ 'storage' ] ) 
  1984. $key = "`d`.`{$k}`"; 
  1985. else 
  1986. $key = "`{$k}`.`meta_value`"; 
  1987. else { 
  1988. foreach ( $this->pod_data[ 'object_fields' ] as $object_field => $object_field_opt ) { 
  1989. if ( $object_field == $k || in_array( $k, $object_field_opt[ 'alias' ] ) ) 
  1990. $key = "`t`.`{$object_field}`"; 
  1991. elseif ( isset( $this->fields[ $k ] ) ) { 
  1992. if ( 'table' == $this->pod_data[ 'storage' ] ) 
  1993. $key = "`t`.`{$k}`"; 
  1994. else 
  1995. $key = "`{$k}`.`meta_value`"; 
  1996.  
  1997. $prefix_orderby = "{$key} {$dir}"; 
  1998.  
  1999. $this->data->select( $params ); 
  2000.  
  2001. return $this; 
  2002.  
  2003. /** 
  2004. * Fetch an item from a Pod. If $id is null, it will return the next item in the list after running find(). 
  2005. * You can rewind the list back to the start by using reset(). 
  2006. * Providing an $id will fetch a specific item from a Pod, much like a call to pods(), and can handle either an id or slug. 
  2007. * @see PodsData::fetch 
  2008. * @param int $id ID or slug of the item to fetch 
  2009. * @param bool $explicit_set Whether to set explicitly (use false when in loop) 
  2010. * @return array An array of fields from the row 
  2011. * @since 2.0 
  2012. * @link http://pods.io/docs/fetch/ 
  2013. */ 
  2014. public function fetch ( $id = null, $explicit_set = true ) { 
  2015. /** 
  2016. * Runs directly before an item is fetched by fetch() 
  2017. * @since unknown 
  2018. * @param int|string|null $id Item ID being fetched or null. 
  2019. * @param object|Pods $this Current Pods object. 
  2020. */ 
  2021. do_action( 'pods_pods_fetch', $id, $this ); 
  2022.  
  2023. if ( !empty( $id ) ) 
  2024. $this->params = array(); 
  2025.  
  2026. $this->data->fetch( $id, $explicit_set ); 
  2027.  
  2028. return $this->row; 
  2029.  
  2030. /** 
  2031. * (Re)set the MySQL result pointer 
  2032. * @see PodsData::reset 
  2033. * @param int $row ID of the row to reset to 
  2034. * @return \Pods The pod object 
  2035. * @since 2.0 
  2036. * @link http://pods.io/docs/reset/ 
  2037. */ 
  2038. public function reset ( $row = null ) { 
  2039. /** 
  2040. * Runs directly before the Pods object is reset by reset() 
  2041. * @since unknown 
  2042. * @param int|string|null The ID of the row being reset to or null if being reset to the beginningg. 
  2043. * @param object|Pods $this Current Pods object. 
  2044. */ 
  2045. do_action( 'pods_pods_reset', $row, $this ); 
  2046.  
  2047. $this->data->reset( $row ); 
  2048.  
  2049. return $this; 
  2050.  
  2051. /** 
  2052. * Fetch the total row count returned by the last call to find(), based on the 'limit' parameter set. 
  2053. * This is different than the total number of rows found in the database, which you can get with total_found(). 
  2054. * @see PodsData::total 
  2055. * @return int Number of rows returned by find(), based on the 'limit' parameter set 
  2056. * @since 2.0 
  2057. * @link http://pods.io/docs/total/ 
  2058. */ 
  2059. public function total () { 
  2060. do_action( 'pods_pods_total', $this ); 
  2061.  
  2062. $this->data->total(); 
  2063.  
  2064. $this->total =& $this->data->total; 
  2065.  
  2066. return $this->total; 
  2067.  
  2068. /** 
  2069. * Fetch the total amount of rows found by the last call to find(), regardless of the 'limit' parameter set. 
  2070. * This is different than the total number of rows limited by the current call, which you can get with total(). 
  2071. * @see PodsData::total_found 
  2072. * @return int Number of rows returned by find(), regardless of the 'limit' parameter 
  2073. * @since 2.0 
  2074. * @link http://pods.io/docs/total-found/ 
  2075. */ 
  2076. public function total_found () { 
  2077. /** 
  2078. * Runs directly before the value of total_found() is determined and returned. 
  2079. * @since unknown 
  2080. * @param object|Pods $this Current Pods object. 
  2081. */ 
  2082. do_action( 'pods_pods_total_found', $this ); 
  2083.  
  2084. $this->data->total_found(); 
  2085.  
  2086. $this->total_found =& $this->data->total_found; 
  2087.  
  2088. return $this->total_found; 
  2089.  
  2090. /** 
  2091. * Fetch the total number of pages, based on total rows found and the last find() limit 
  2092. * @param null|int $limit Rows per page 
  2093. * @param null|int $offset Offset of rows 
  2094. * @param null|int $total Total rows 
  2095. * @return int Number of pages 
  2096. * @since 2.3.10 
  2097. */ 
  2098. public function total_pages( $limit = null, $offset = null, $total = null ) { 
  2099.  
  2100. $this->do_hook( 'total_pages' ); 
  2101.  
  2102. if ( null === $limit ) { 
  2103. $limit = $this->limit; 
  2104.  
  2105. if ( null === $offset ) { 
  2106. $offset = $this->offset; 
  2107.  
  2108. if ( null === $total ) { 
  2109. $total = $this->total_found(); 
  2110.  
  2111. $total_pages = ceil( ( $total - $offset ) / $limit ); 
  2112.  
  2113. return $total_pages; 
  2114.  
  2115.  
  2116. /** 
  2117. * Fetch the zebra switch 
  2118. * @see PodsData::zebra 
  2119. * @return bool Zebra state 
  2120. * @since 1.12 
  2121. */ 
  2122. public function zebra () { 
  2123. $this->do_hook( 'zebra' ); 
  2124.  
  2125. return $this->data->zebra(); 
  2126.  
  2127. /** 
  2128. * Fetch the nth state 
  2129. * @see PodsData::nth 
  2130. * @param int|string $nth The $nth to match on the PodsData::row_number 
  2131. * @return bool Whether $nth matches 
  2132. * @since 2.3 
  2133. */ 
  2134. public function nth ( $nth = null ) { 
  2135. $this->do_hook( 'nth', $nth ); 
  2136.  
  2137. return $this->data->nth( $nth ); 
  2138.  
  2139. /** 
  2140. * Fetch the current position in the loop (starting at 1) 
  2141. * @see PodsData::position 
  2142. * @return int Current row number (+1) 
  2143. * @since 2.3 
  2144. */ 
  2145. public function position () { 
  2146. $this->do_hook( 'position' ); 
  2147.  
  2148. return $this->data->position(); 
  2149.  
  2150. /** 
  2151. * Add an item to a Pod by giving an array of field data or set a specific field to 
  2152. * a specific value if you're just wanting to add a new item but only set one field. 
  2153. * You may be looking for save() in most cases where you're setting a specific field. 
  2154. * @see PodsAPI::save_pod_item 
  2155. * @param array|string $data Either an associative array of field information or a field name 
  2156. * @param mixed $value (optional) Value of the field, if $data is a field name 
  2157. * @return int The item ID 
  2158. * @since 2.0 
  2159. * @link http://pods.io/docs/add/ 
  2160. */ 
  2161. public function add ( $data = null, $value = null ) { 
  2162. if ( null !== $value ) 
  2163. $data = array( $data => $value ); 
  2164.  
  2165. $data = (array) $this->do_hook( 'add', $data ); 
  2166.  
  2167. if ( empty( $data ) ) 
  2168. return 0; 
  2169.  
  2170. $params = array( 
  2171. 'pod' => $this->pod,  
  2172. 'data' => $data,  
  2173. 'allow_custom_fields' => true 
  2174. ); 
  2175.  
  2176. return $this->api->save_pod_item( $params ); 
  2177.  
  2178. /** 
  2179. * Add an item to the values of a relationship field, add a value to a number field (field+1), add time to a date field, or add text to a text field 
  2180. * @see PodsAPI::save_pod_item 
  2181. * @param string $field Field name 
  2182. * @param mixed $value ID(s) to add, int|float to add to number field, string for dates (+1 week), or string for text 
  2183. * @param int $id (optional) ID of the pod item to update 
  2184. * @return int The item ID 
  2185. * @since 2.3 
  2186. */ 
  2187. public function add_to ( $field, $value, $id = null ) { 
  2188. $pod =& $this; 
  2189.  
  2190. $fetch = false; 
  2191.  
  2192. if ( null === $id ) { 
  2193. $fetch = true; 
  2194.  
  2195. $id = $pod->id(); 
  2196. elseif ( $id != $this->id() ) { 
  2197. $pod = pods( $this->pod, $id ); 
  2198.  
  2199. $this->do_hook( 'add_to', $field, $value, $id ); 
  2200.  
  2201. if ( !isset( $this->fields[ $field ] ) ) 
  2202. return $id; 
  2203.  
  2204. // Tableless fields 
  2205. if ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::tableless_field_types() ) ) { 
  2206. if ( !is_array( $value ) ) 
  2207. $value = explode( ', ', $value ); 
  2208.  
  2209. if ( 'pick' == $this->fields[ $field ][ 'type' ] && in_array( $this->fields[ $field ][ 'pick_object' ], PodsForm::simple_tableless_objects() ) ) { 
  2210. $current_value = $pod->raw( $field ); 
  2211.  
  2212. if ( !empty( $current_value ) || ( !is_array( $current_value ) && 0 < strlen( $current_value ) ) ) 
  2213. $current_value = (array) $current_value; 
  2214. else 
  2215. $current_value = array(); 
  2216.  
  2217. $value = array_merge( $current_value, $value ); 
  2218. else { 
  2219. $related_ids = $this->api->lookup_related_items( $this->fields[ $field ][ 'id' ], $this->pod_data[ 'id' ], $id, $this->fields[ $field ], $this->pod_data ); 
  2220.  
  2221. foreach ( $value as $k => $v ) { 
  2222. if ( !preg_match( '/[^0-9]/', $v ) ) 
  2223. $value[ $k ] = (int) $v; 
  2224.  
  2225. $value = array_merge( $related_ids, $value ); 
  2226.  
  2227. if ( !empty( $value ) ) 
  2228. $value = array_filter( array_unique( $value ) ); 
  2229. else 
  2230. $value = array(); 
  2231.  
  2232. if ( empty( $value ) ) 
  2233. return $id; 
  2234. // Number fields 
  2235. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::number_field_types() ) ) { 
  2236. $current_value = (float) $pod->raw( $field ); 
  2237.  
  2238. $value = ( $current_value + (float) $value ); 
  2239. // Date fields 
  2240. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::date_field_types() ) ) { 
  2241. $current_value = $pod->raw( $field ); 
  2242.  
  2243. if ( 0 < strlen( $current_value ) ) 
  2244. $value = strtotime( $value, strtotime( $current_value ) ); 
  2245. else 
  2246. $value = strtotime( $value ); 
  2247. // Text fields 
  2248. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::text_field_types() ) ) { 
  2249. $current_value = $pod->raw( $field ); 
  2250.  
  2251. if ( 0 < strlen( $current_value ) ) 
  2252. $value = $current_value . $value; 
  2253.  
  2254. // @todo handle object fields and taxonomies 
  2255.  
  2256. $params = array( 
  2257. 'pod' => $this->pod,  
  2258. 'id' => $id,  
  2259. 'data' => array( 
  2260. $field => $value 
  2261. ); 
  2262.  
  2263. $id = $this->api->save_pod_item( $params ); 
  2264.  
  2265. if ( 0 < $id && $fetch ) { 
  2266. // Clear local var cache of field values 
  2267. $pod->data->row = array(); 
  2268.  
  2269. $pod->fetch( $id, false ); 
  2270.  
  2271. return $id; 
  2272.  
  2273. /** 
  2274. * Remove an item from the values of a relationship field, remove a value from a number field (field-1), remove time to a date field 
  2275. * @see PodsAPI::save_pod_item 
  2276. * @param string $field Field name 
  2277. * @param mixed $value ID(s) to add, int|float to add to number field, string for dates (-1 week), or string for text 
  2278. * @param int $id (optional) ID of the pod item to update 
  2279. * @return int The item ID 
  2280. * @since 2.3.3 
  2281. */ 
  2282. public function remove_from( $field, $value = null, $id = null ) { 
  2283. $pod =& $this; 
  2284.  
  2285. $fetch = false; 
  2286.  
  2287. if ( null === $id ) { 
  2288. $fetch = true; 
  2289.  
  2290. $id = $this->id(); 
  2291. elseif ( $id != $this->id() ) { 
  2292. $pod = pods( $this->pod, $id ); 
  2293.  
  2294. $this->do_hook( 'remove_from', $field, $value, $id ); 
  2295.  
  2296. if ( !isset( $this->fields[ $field ] ) ) { 
  2297. return $id; 
  2298.  
  2299. // Tableless fields 
  2300. if ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::tableless_field_types() ) ) { 
  2301. if ( empty( $value ) ) { 
  2302. $value = array(); 
  2303.  
  2304. if ( !empty( $value ) ) { 
  2305. if ( !is_array( $value ) ) { 
  2306. $value = explode( ', ', $value ); 
  2307.  
  2308. if ( 'pick' == $this->fields[ $field ][ 'type' ] && in_array( $this->fields[ $field ][ 'pick_object' ], PodsForm::simple_tableless_objects() ) ) { 
  2309. $current_value = $pod->raw( $field ); 
  2310.  
  2311. if ( !empty( $current_value ) ) { 
  2312. $current_value = (array) $current_value; 
  2313.  
  2314. foreach ( $current_value as $k => $v ) { 
  2315. if ( in_array( $v, $value ) ) { 
  2316. unset( $current_value[ $k ] ); 
  2317.  
  2318. $value = $current_value; 
  2319. else { 
  2320. $related_ids = $this->api->lookup_related_items( $this->fields[ $field ][ 'id' ], $this->pod_data[ 'id' ], $id, $this->fields[ $field ], $this->pod_data ); 
  2321.  
  2322. foreach ( $value as $k => $v ) { 
  2323. if ( !preg_match( '/[^0-9]/', $v ) ) { 
  2324. $value[ $k ] = (int) $v; 
  2325. // @todo Convert slugs into IDs 
  2326. else { 
  2327.  
  2328.  
  2329. foreach ( $related_ids as $k => $v ) { 
  2330. if ( in_array( $v, $value ) ) { 
  2331. unset( $related_ids[ $k ] ); 
  2332.  
  2333. $value = $related_ids; 
  2334.  
  2335. if ( !empty( $value ) ) { 
  2336. $value = array_filter( array_unique( $value ) ); 
  2337. else { 
  2338. $value = array(); 
  2339. // Number fields 
  2340. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::number_field_types() ) ) { 
  2341. // Date fields don't support empty for removing 
  2342. if ( empty( $value ) ) { 
  2343. return $id; 
  2344.  
  2345. $current_value = (float) $pod->raw( $field ); 
  2346.  
  2347. $value = ( $current_value - (float) $value ); 
  2348. // Date fields 
  2349. elseif ( in_array( $this->fields[ $field ][ 'type' ], PodsForm::date_field_types() ) ) { 
  2350. // Date fields don't support empty for removing 
  2351. if ( empty( $value ) ) { 
  2352. return $id; 
  2353.  
  2354. $current_value = $pod->raw( $field ); 
  2355.  
  2356. if ( 0 < strlen( $current_value ) ) { 
  2357. $value = strtotime( $value, strtotime( $current_value ) ); 
  2358. else { 
  2359. $value = strtotime( $value ); 
  2360.  
  2361. $value = date_i18n( 'Y-m-d h:i:s', $value ); 
  2362.  
  2363. // @todo handle object fields and taxonomies 
  2364.  
  2365. $params = array( 
  2366. 'pod' => $this->pod,  
  2367. 'id' => $id,  
  2368. 'data' => array( 
  2369. $field => $value 
  2370. ); 
  2371.  
  2372. $id = $this->api->save_pod_item( $params ); 
  2373.  
  2374. if ( 0 < $id && $fetch ) { 
  2375. // Clear local var cache of field values 
  2376. $pod->data->row = array(); 
  2377.  
  2378. $pod->fetch( $id, false ); 
  2379.  
  2380. return $id; 
  2381.  
  2382.  
  2383. /** 
  2384. * Save an item by giving an array of field data or set a specific field to a specific value. 
  2385. * Though this function has the capacity to add new items, best practice should direct you 
  2386. * to use add() for that instead. 
  2387. * @see PodsAPI::save_pod_item 
  2388. * @param array|string $data Either an associative array of field information or a field name 
  2389. * @param mixed $value (optional) Value of the field, if $data is a field name 
  2390. * @param int $id (optional) ID of the pod item to update 
  2391. * @param array $params (optional) Additional params to send to save_pod_item 
  2392. * @return int The item ID 
  2393. * @since 2.0 
  2394. * @link http://pods.io/docs/save/ 
  2395. */ 
  2396. public function save ( $data = null, $value = null, $id = null, $params = null ) { 
  2397. if ( null !== $value ) 
  2398. $data = array( $data => $value ); 
  2399.  
  2400. $fetch = false; 
  2401.  
  2402. if ( null === $id || ( $this->row && $id == $this->id() ) ) { 
  2403. $fetch = true; 
  2404.  
  2405. if ( null === $id ) { 
  2406. $id = $this->id(); 
  2407.  
  2408. $data = (array) $this->do_hook( 'save', $data, $id ); 
  2409.  
  2410. if ( empty( $data ) && empty( $params['is_new_item'] ) ) 
  2411. return $id; 
  2412.  
  2413. $default = array(); 
  2414.  
  2415. if ( !empty( $params ) && is_array( $params ) ) 
  2416. $default = $params; 
  2417.  
  2418. $params = array( 
  2419. 'pod' => $this->pod,  
  2420. 'id' => $id,  
  2421. 'data' => $data,  
  2422. 'allow_custom_fields' => true,  
  2423. 'clear_slug_cache' => false 
  2424. ); 
  2425.  
  2426. if ( !empty( $default ) ) 
  2427. $params = array_merge( $params, $default ); 
  2428.  
  2429. $id = $this->api->save_pod_item( $params ); 
  2430.  
  2431. if ( 0 < $id && $fetch ) { 
  2432. // Clear local var cache of field values 
  2433. $this->data->row = array(); 
  2434.  
  2435. $this->fetch( $id, false ); 
  2436.  
  2437. if ( !empty( $this->pod_data[ 'field_slug' ] ) ) { 
  2438. if ( 0 < $id && $fetch ) { 
  2439. $slug = $this->field( $this->pod_data[ 'field_slug' ] ); 
  2440. else { 
  2441. $slug = pods( $this->pod, $id )->field( $this->pod_data[ 'field_slug' ] ); 
  2442.  
  2443. if ( 0 < strlen( $slug ) ) { 
  2444. pods_cache_clear( $slug, 'pods_items_' . $this->pod ); 
  2445.  
  2446. return $id; 
  2447.  
  2448. /** 
  2449. * Delete an item 
  2450. * @see PodsAPI::delete_pod_item 
  2451. * @param int $id ID of the Pod item to delete 
  2452. * @return bool Whether the item was successfully deleted 
  2453. * @since 2.0 
  2454. * @link http://pods.io/docs/delete/ 
  2455. */ 
  2456. public function delete ( $id = null ) { 
  2457. if ( null === $id ) 
  2458. $id = $this->id(); 
  2459.  
  2460. $id = (int) $this->do_hook( 'delete', $id ); 
  2461.  
  2462. if ( empty( $id ) ) 
  2463. return false; 
  2464.  
  2465. $params = array( 
  2466. 'pod' => $this->pod,  
  2467. 'id' => $id 
  2468. ); 
  2469.  
  2470. return $this->api->delete_pod_item( $params ); 
  2471.  
  2472. /** 
  2473. * Reset Pod 
  2474. * @see PodsAPI::reset_pod 
  2475. * @return bool Whether the Pod was successfully reset 
  2476. * @since 2.1.1 
  2477. */ 
  2478. public function reset_pod () { 
  2479. $params = array( 'id' => $this->pod_id ); 
  2480.  
  2481. $this->data->id = null; 
  2482. $this->data->row = array(); 
  2483. $this->data->data = array(); 
  2484.  
  2485. $this->data->total = 0; 
  2486. $this->data->total_found = 0; 
  2487.  
  2488. return $this->api->reset_pod( $params ); 
  2489.  
  2490. /** 
  2491. * Duplicate an item 
  2492. * @see PodsAPI::duplicate_pod_item 
  2493. * @param int $id ID of the pod item to duplicate 
  2494. * @return int|bool ID of the new pod item 
  2495. * @since 2.0 
  2496. * @link http://pods.io/docs/duplicate/ 
  2497. */ 
  2498. public function duplicate ( $id = null ) { 
  2499. if ( null === $id ) 
  2500. $id = $this->id(); 
  2501.  
  2502. $id = (int) $this->do_hook( 'duplicate', $id ); 
  2503.  
  2504. if ( empty( $id ) ) 
  2505. return false; 
  2506.  
  2507. $params = array( 
  2508. 'pod' => $this->pod,  
  2509. 'id' => $id 
  2510. ); 
  2511.  
  2512. return $this->api->duplicate_pod_item( $params ); 
  2513.  
  2514. /** 
  2515. * Import data / Save multiple rows of data at once 
  2516. * @see PodsAPI::import 
  2517. * @param mixed $import_data PHP associative array or CSV input 
  2518. * @param bool $numeric_mode Use IDs instead of the name field when matching 
  2519. * @param string $format Format of import data, options are php or csv 
  2520. * @return array IDs of imported items 
  2521. * @since 2.3 
  2522. */ 
  2523. public function import ( $import_data, $numeric_mode = false, $format = null ) { 
  2524. return $this->api->import( $import_data, $numeric_mode, $format ); 
  2525.  
  2526. /** 
  2527. * Export an item's data 
  2528. * @see PodsAPI::export_pod_item 
  2529. * @param array $fields (optional) Fields to export 
  2530. * @param int $id (optional) ID of the pod item to export 
  2531. * @return array|bool Data array of the exported pod item 
  2532. * @since 2.0 
  2533. * @link http://pods.io/docs/export/ 
  2534. */ 
  2535. public function export ( $fields = null, $id = null, $format = null ) { 
  2536. $params = array( 
  2537. 'pod' => $this->pod,  
  2538. 'id' => $id,  
  2539. 'fields' => null,  
  2540. 'depth' => 2,  
  2541. 'flatten' => false 
  2542. ); 
  2543.  
  2544. if ( is_array( $fields ) && ( isset( $fields[ 'fields' ] ) || isset( $fields[ 'depth' ] ) ) ) 
  2545. $params = array_merge( $params, $fields ); 
  2546. else 
  2547. $params[ 'fields' ] = $fields; 
  2548.  
  2549. if ( isset( $params[ 'fields' ] ) && is_array( $params[ 'fields' ] ) && !in_array( $this->pod_data[ 'field_id' ], $params[ 'fields' ] ) ) 
  2550. $params[ 'fields' ] = array_merge( array( $this->pod_data[ 'field_id' ] ), $params[ 'fields' ] ); 
  2551.  
  2552. if ( null === $params[ 'id' ] ) 
  2553. $params[ 'id' ] = $this->id(); 
  2554.  
  2555. $params = (array) $this->do_hook( 'export', $params ); 
  2556.  
  2557. if ( empty( $params[ 'id' ] ) ) 
  2558. return false; 
  2559.  
  2560. $data = $this->api->export_pod_item( $params ); 
  2561.  
  2562. if ( !empty( $format ) ) { 
  2563. if ( 'json' == $format ) 
  2564. $data = json_encode( (array) $data ); 
  2565. // @todo more formats 
  2566.  
  2567. return $data; 
  2568.  
  2569. /** 
  2570. * Export data from all items 
  2571. * @see PodsAPI::export 
  2572. * @param array $params An associative array of parameters 
  2573. * @return array Data arrays of all exported pod items 
  2574. * @since 2.3 
  2575. */ 
  2576. public function export_data ( $params = null ) { 
  2577. $defaults = array( 
  2578. 'fields' => null,  
  2579. 'depth' => 2,  
  2580. 'params' => null 
  2581. ); 
  2582.  
  2583. if ( empty( $params ) ) 
  2584. $params = $defaults; 
  2585. else 
  2586. $params = array_merge( $defaults, (array) $params ); 
  2587.  
  2588. return $this->api->export( $this, $params ); 
  2589.  
  2590. /** 
  2591. * Display the pagination controls, types supported by default 
  2592. * are simple, paginate and advanced. The base and format parameters 
  2593. * are used only for the paginate view. 
  2594. * @var array $params Associative array of parameters 
  2595. * @return string Pagination HTML 
  2596. * @since 2.0 
  2597. * @link http://pods.io/docs/pagination/ 
  2598. */ 
  2599. public function pagination( $params = null ) { 
  2600.  
  2601. if ( empty( $params ) ) { 
  2602. $params = array(); 
  2603. elseif ( !is_array( $params ) ) { 
  2604. $params = array( 'label' => $params ); 
  2605.  
  2606. $this->page_var = pods_var_raw( 'page_var', $params, $this->page_var ); 
  2607.  
  2608. $url = pods_query_arg( null, null, $this->page_var ); 
  2609.  
  2610. $append = '?'; 
  2611.  
  2612. if ( false !== strpos( $url, '?' ) ) { 
  2613. $append = '&'; 
  2614.  
  2615. $defaults = array( 
  2616. 'type' => 'advanced',  
  2617. 'label' => __( 'Go to page:', 'pods' ),  
  2618. 'show_label' => true,  
  2619. 'first_text' => __( '« First', 'pods' ),  
  2620. 'prev_text' => __( '‹ Previous', 'pods' ),  
  2621. 'next_text' => __( 'Next ›', 'pods' ),  
  2622. 'last_text' => __( 'Last »', 'pods' ),  
  2623. 'prev_next' => true,  
  2624. 'first_last' => true,  
  2625. 'limit' => (int) $this->limit,  
  2626. 'offset' => (int) $this->offset,  
  2627. 'page' => max( 1, (int) $this->page ),  
  2628. 'mid_size' => 2,  
  2629. 'end_size' => 1,  
  2630. 'total_found' => $this->total_found(),  
  2631. 'page_var' => $this->page_var,  
  2632. 'base' => "{$url}{$append}%_%",  
  2633. 'format' => "{$this->page_var}=%#%",  
  2634. 'class' => '',  
  2635. 'link_class' => '' 
  2636. ); 
  2637.  
  2638. $params = (object) array_merge( $defaults, $params ); 
  2639.  
  2640. $params->total = $this->total_pages( $params->limit, $params->offset, $params->total_found ); 
  2641.  
  2642. if ( $params->limit < 1 || $params->total_found < 1 || 1 == $params->total || $params->total_found <= $params->offset ) { 
  2643. return $this->do_hook( 'pagination', $this->do_hook( 'pagination_' . $params->type, '', $params ), $params ); 
  2644.  
  2645. $pagination = $params->type; 
  2646.  
  2647. if ( !in_array( $params->type, array( 'simple', 'advanced', 'paginate', 'list' ) ) ) { 
  2648. $pagination = 'advanced'; 
  2649.  
  2650. ob_start(); 
  2651.  
  2652. pods_view( PODS_DIR . 'ui/front/pagination/' . $pagination . '.php', compact( array_keys( get_defined_vars() ) ) ); 
  2653.  
  2654. $output = ob_get_clean(); 
  2655.  
  2656. return $this->do_hook( 'pagination', $this->do_hook( 'pagination_' . $params->type, $output, $params ), $params ); 
  2657.  
  2658.  
  2659. /** 
  2660. * Return a filter form for searching a Pod 
  2661. * @var array|string $params Comma-separated list of fields or array of parameters 
  2662. * @return string Filters HTML 
  2663. * @since 2.0 
  2664. * @link http://pods.io/docs/filters/ 
  2665. */ 
  2666. public function filters ( $params = null ) { 
  2667. $defaults = array( 
  2668. 'fields' => $params,  
  2669. 'label' => '',  
  2670. 'action' => '',  
  2671. 'search' => '' 
  2672. ); 
  2673.  
  2674. if ( is_array( $params ) ) 
  2675. $params = array_merge( $defaults, $params ); 
  2676. else 
  2677. $params = $defaults; 
  2678.  
  2679. $pod =& $this; 
  2680.  
  2681. $params = apply_filters( 'pods_filters_params', $params, $pod ); 
  2682.  
  2683. $fields = $params[ 'fields' ]; 
  2684.  
  2685. if ( null !== $fields && !is_array( $fields ) && 0 < strlen( $fields ) ) 
  2686. $fields = explode( ', ', $fields ); 
  2687.  
  2688. $object_fields = (array) pods_var_raw( 'object_fields', $this->pod_data, array(), null, true ); 
  2689.  
  2690. // Force array 
  2691. if ( empty( $fields ) ) 
  2692. $fields = array(); 
  2693. else { 
  2694. $filter_fields = $fields; // Temporary 
  2695.  
  2696. $fields = array(); 
  2697.  
  2698. foreach ( $filter_fields as $k => $field ) { 
  2699. $name = $k; 
  2700.  
  2701. $defaults = array( 
  2702. 'name' => $name 
  2703. ); 
  2704.  
  2705. if ( !is_array( $field ) ) { 
  2706. $name = $field; 
  2707.  
  2708. $field = array( 
  2709. 'name' => $name 
  2710. ); 
  2711.  
  2712. $field = array_merge( $defaults, $field ); 
  2713.  
  2714. $field[ 'name' ] = trim( $field[ 'name' ] ); 
  2715.  
  2716. if ( pods_var_raw( 'hidden', $field, false, null, true ) ) 
  2717. $field[ 'type' ] = 'hidden'; 
  2718.  
  2719. if ( isset( $object_fields[ $field[ 'name' ] ] ) ) 
  2720. $fields[ $field[ 'name' ] ] = array_merge( $object_fields[ $field[ 'name' ] ], $field ); 
  2721. elseif ( isset( $this->fields[ $field[ 'name' ] ] ) ) 
  2722. $fields[ $field[ 'name' ] ] = array_merge( $this->fields[ $field[ 'name' ] ], $field ); 
  2723.  
  2724. unset( $filter_fields ); // Cleanup 
  2725.  
  2726. $this->filters = array_keys( $fields ); 
  2727.  
  2728. $label = $params[ 'label' ]; 
  2729.  
  2730. if ( strlen( $label ) < 1 ) 
  2731. $label = __( 'Search', 'pods' ); 
  2732.  
  2733. $action = $params[ 'action' ]; 
  2734.  
  2735. $search = trim( $params[ 'search' ] ); 
  2736.  
  2737. if ( strlen( $search ) < 1 ) 
  2738. $search = pods_var_raw( $pod->search_var, 'get', '' ); 
  2739.  
  2740. ob_start(); 
  2741.  
  2742. pods_view( PODS_DIR . 'ui/front/filters.php', compact( array_keys( get_defined_vars() ) ) ); 
  2743.  
  2744. $output = ob_get_clean(); 
  2745.  
  2746. /** 
  2747. * Filter the HTML output of filters() 
  2748. * @since unknown 
  2749. * @param string $output 
  2750. * @param array $params Params array passed to filters(). 
  2751. * @param object|Pods $this Current Pods object. 
  2752. */ 
  2753. return apply_filters( 'pods_pods_filters', $output, $params, $this ); 
  2754.  
  2755. /** 
  2756. * Run a helper within a Pod Page or WP Template 
  2757. * @see Pods_Helpers::helper 
  2758. * @param string $helper Helper name 
  2759. * @param string $value Value to run the helper on 
  2760. * @param string $name Field name 
  2761. * @return mixed Anything returned by the helper 
  2762. * @since 2.0 
  2763. */ 
  2764. public function helper ( $helper, $value = null, $name = null ) { 
  2765. $params = array( 
  2766. 'helper' => $helper,  
  2767. 'value' => $value,  
  2768. 'name' => $name,  
  2769. 'deprecated' => false 
  2770. ); 
  2771.  
  2772. if ( class_exists( 'Pods_Templates' ) ) 
  2773. $params[ 'deprecated' ] = Pods_Templates::$deprecated; 
  2774.  
  2775. if ( is_array( $helper ) ) 
  2776. $params = array_merge( $params, $helper ); 
  2777.  
  2778. if ( class_exists( 'Pods_Helpers' ) ) 
  2779. $value = Pods_Helpers::helper( $params, $this ); 
  2780. elseif ( function_exists( $params[ 'helper' ] ) ) 
  2781. $value = call_user_func( $params[ 'helper' ], $value ); 
  2782. else 
  2783. $value = apply_filters( $params[ 'helper' ], $value ); 
  2784.  
  2785. return $value; 
  2786.  
  2787. /** 
  2788. * Display the page template 
  2789. * @see Pods_Templates::template 
  2790. * @param string $template The template name 
  2791. * @param string $code Custom template code to use instead 
  2792. * @param bool $deprecated Whether to use deprecated functionality based on old function usage 
  2793. * @return mixed Template output 
  2794. * @since 2.0 
  2795. * @link http://pods.io/docs/template/ 
  2796. */ 
  2797. public function template ( $template_name, $code = null, $deprecated = false ) { 
  2798. $out = null; 
  2799.  
  2800. $obj =& $this; 
  2801.  
  2802. if ( !empty( $code ) ) { 
  2803. $code = str_replace( '$this->', '$obj->', $code ); // backwards compatibility 
  2804.  
  2805. $code = apply_filters( 'pods_templates_pre_template', $code, $template_name, $this ); 
  2806. $code = apply_filters( "pods_templates_pre_template_{$template_name}", $code, $template_name, $this ); 
  2807.  
  2808. ob_start(); 
  2809.  
  2810. if ( !empty( $code ) ) { 
  2811. // Only detail templates need $this->id 
  2812. if ( empty( $this->id ) ) { 
  2813. while ( $this->fetch() ) { 
  2814. echo $this->do_magic_tags( $code ); 
  2815. else 
  2816. echo $this->do_magic_tags( $code ); 
  2817.  
  2818. $out = ob_get_clean(); 
  2819.  
  2820. $out = apply_filters( 'pods_templates_post_template', $out, $code, $template_name, $this ); 
  2821. $out = apply_filters( "pods_templates_post_template_{$template_name}", $out, $code, $template_name, $this ); 
  2822. elseif ( class_exists( 'Pods_Templates' ) ) 
  2823. $out = Pods_Templates::template( $template_name, $code, $this, $deprecated ); 
  2824. elseif ( $template_name == trim( preg_replace( '/[^a-zA-Z0-9_\-\/]/', '', $template_name ), ' /-' ) ) { 
  2825. ob_start(); 
  2826.  
  2827. $default_templates = array( 
  2828. 'pods/' . $template_name,  
  2829. 'pods-' . $template_name,  
  2830. $template_name 
  2831. ); 
  2832.  
  2833. $default_templates = apply_filters( 'pods_template_default_templates', $default_templates ); 
  2834.  
  2835. // Only detail templates need $this->id 
  2836. if ( empty( $this->id ) ) { 
  2837. while ( $this->fetch() ) { 
  2838. pods_template_part( $default_templates, compact( array_keys( get_defined_vars() ) ) ); 
  2839. else 
  2840. pods_template_part( $default_templates, compact( array_keys( get_defined_vars() ) ) ); 
  2841.  
  2842. $out = ob_get_clean(); 
  2843.  
  2844. $out = apply_filters( 'pods_templates_post_template', $out, $code, $template_name, $this ); 
  2845. $out = apply_filters( "pods_templates_post_template_{$template_name}", $out, $code, $template_name, $this ); 
  2846.  
  2847. return $out; 
  2848.  
  2849. /** 
  2850. * Embed a form to add / edit a pod item from within your theme. Provide an array of $fields to include 
  2851. * and override options where needed. For WP object based Pods, you can pass through the WP object 
  2852. * field names too, such as "post_title" or "post_content" for example. 
  2853. * @param array $params (optional) Fields to show on the form, defaults to all fields 
  2854. * @param string $label (optional) Save button label, defaults to "Save Changes" 
  2855. * @param string $thank_you (optional) Thank you URL to send to upon success 
  2856. * @return bool|mixed 
  2857. * @since 2.0 
  2858. * @link http://pods.io/docs/form/ 
  2859. */ 
  2860. public function form ( $params = null, $label = null, $thank_you = null ) { 
  2861. $defaults = array( 
  2862. 'fields' => $params,  
  2863. 'label' => $label,  
  2864. 'thank_you' => $thank_you,  
  2865. 'fields_only' => false 
  2866. ); 
  2867.  
  2868. if ( is_array( $params ) ) 
  2869. $params = array_merge( $defaults, $params ); 
  2870. else 
  2871. $params = $defaults; 
  2872.  
  2873. $pod =& $this; 
  2874.  
  2875. $params = $this->do_hook( 'form_params', $params ); 
  2876.  
  2877. $fields = $params[ 'fields' ]; 
  2878.  
  2879. if ( null !== $fields && !is_array( $fields ) && 0 < strlen( $fields ) ) 
  2880. $fields = explode( ', ', $fields ); 
  2881.  
  2882. $object_fields = (array) pods_var_raw( 'object_fields', $this->pod_data, array(), null, true ); 
  2883.  
  2884. if ( empty( $fields ) ) { 
  2885. // Add core object fields if $fields is empty 
  2886. $fields = array_merge( $object_fields, $this->fields ); 
  2887.  
  2888. $form_fields = $fields; // Temporary 
  2889.  
  2890. $fields = array(); 
  2891.  
  2892. foreach ( $form_fields as $k => $field ) { 
  2893. $name = $k; 
  2894.  
  2895. $defaults = array( 
  2896. 'name' => $name 
  2897. ); 
  2898.  
  2899. if ( !is_array( $field ) ) { 
  2900. $name = $field; 
  2901.  
  2902. $field = array( 
  2903. 'name' => $name 
  2904. ); 
  2905.  
  2906. $field = array_merge( $defaults, $field ); 
  2907.  
  2908. $field[ 'name' ] = trim( $field[ 'name' ] ); 
  2909.  
  2910. $default_value = pods_var_raw( 'default', $field ); 
  2911. $value = pods_var_raw( 'value', $field ); 
  2912.  
  2913. if ( empty( $field[ 'name' ] ) ) 
  2914. $field[ 'name' ] = trim( $name ); 
  2915.  
  2916. if ( isset( $object_fields[ $field[ 'name' ] ] ) ) { 
  2917. $field = array_merge( $object_fields[ $field[ 'name' ] ], $field ); 
  2918. elseif ( isset( $this->fields[ $field[ 'name' ] ] ) ) { 
  2919. $field = array_merge( $this->fields[ $field[ 'name' ] ], $field ); 
  2920.  
  2921. if ( pods_var_raw( 'hidden', $field, false, null, true ) ) 
  2922. $field[ 'type' ] = 'hidden'; 
  2923.  
  2924. $fields[ $field[ 'name' ] ] = $field; 
  2925.  
  2926. if ( empty( $this->id ) && null !== $default_value ) { 
  2927. $this->row_override[ $field[ 'name' ] ] = $default_value; 
  2928. elseif ( !empty( $this->id ) && null !== $value ) { 
  2929. $this->row[ $field[ 'name' ] ] = $value; 
  2930.  
  2931. unset( $form_fields ); // Cleanup 
  2932.  
  2933. $fields = $this->do_hook( 'form_fields', $fields, $params ); 
  2934.  
  2935. $label = $params[ 'label' ]; 
  2936.  
  2937. if ( empty( $label ) ) 
  2938. $label = __( 'Save Changes', 'pods' ); 
  2939.  
  2940. $thank_you = $params[ 'thank_you' ]; 
  2941. $fields_only = $params[ 'fields_only' ]; 
  2942.  
  2943. PodsForm::$form_counter++; 
  2944.  
  2945. ob_start(); 
  2946.  
  2947. if ( empty( $thank_you ) ) { 
  2948. $success = 'success'; 
  2949.  
  2950. if ( 1 < PodsForm::$form_counter ) 
  2951. $success .= PodsForm::$form_counter; 
  2952.  
  2953. $thank_you = pods_query_arg( array( 'success*' => null, $success => 1 ) ); 
  2954.  
  2955. if ( 1 == pods_v( $success, 'get', 0 ) ) { 
  2956. $message = __( 'Form submitted successfully', 'pods' ); 
  2957. /** 
  2958. * Change the text of the message that appears on succesful form submission. 
  2959. * @param string $message 
  2960. * @returns string the message 
  2961. * @since 3.0.0 
  2962. */ 
  2963. $message = apply_filters( 'pods_pod_form_success_message', $message ); 
  2964.  
  2965. echo '<div id="message" class="pods-form-front-success">' . $message . '</div>'; 
  2966.  
  2967. pods_view( PODS_DIR . 'ui/front/form.php', compact( array_keys( get_defined_vars() ) ) ); 
  2968.  
  2969. $output = ob_get_clean(); 
  2970.  
  2971. if ( empty( $this->id ) ) 
  2972. $this->row_override = array(); 
  2973.  
  2974. return $this->do_hook( 'form', $output, $fields, $label, $thank_you, $this, $this->id() ); 
  2975.  
  2976. /** 
  2977. * @param array $fields (optional) Fields to show in the view, defaults to all fields 
  2978. * @return mixed 
  2979. * @since 2.3.10 
  2980. */ 
  2981. public function view( $fields = null ) { 
  2982.  
  2983. $pod =& $this; 
  2984.  
  2985. // Convert comma separated list of fields to an array 
  2986. if ( null !== $fields && !is_array( $fields ) && 0 < strlen( $fields ) ) { 
  2987. $fields = explode( ', ', $fields ); 
  2988.  
  2989. $object_fields = (array) pods_v( 'object_fields', $this->pod_data, array(), true ); 
  2990.  
  2991. if ( empty( $fields ) ) { 
  2992. // Add core object fields if $fields is empty 
  2993. $fields = array_merge( $object_fields, $this->fields ); 
  2994.  
  2995. $view_fields = $fields; // Temporary 
  2996.  
  2997. $fields = array(); 
  2998.  
  2999. foreach ( $view_fields as $name => $field ) { 
  3000.  
  3001. $defaults = array( 
  3002. 'name' => $name 
  3003. ); 
  3004.  
  3005. if ( !is_array( $field ) ) { 
  3006. $name = $field; 
  3007.  
  3008. $field = array( 
  3009. 'name' => $name 
  3010. ); 
  3011.  
  3012. $field = array_merge( $defaults, $field ); 
  3013.  
  3014. $field[ 'name' ] = trim( $field[ 'name' ] ); 
  3015.  
  3016. if ( empty( $field[ 'name' ] ) ) { 
  3017. $field[ 'name' ] = trim( $name ); 
  3018.  
  3019. if ( isset( $object_fields[ $field[ 'name' ] ] ) ) 
  3020. $field = array_merge( $field, $object_fields[ $field[ 'name' ] ] ); 
  3021. elseif ( isset( $this->fields[ $field[ 'name' ] ] ) ) 
  3022. $field = array_merge( $this->fields[ $field[ 'name' ] ], $field ); 
  3023.  
  3024. if ( pods_v( 'hidden', $field, false, null, true ) || 'hidden' == $field[ 'type' ] ) { 
  3025. continue; 
  3026. elseif ( !PodsForm::permission( $field[ 'type' ], $field[ 'name' ], $field[ 'options' ], $fields, $pod, $pod->id() ) ) { 
  3027. continue; 
  3028.  
  3029. $fields[ $field[ 'name' ] ] = $field; 
  3030.  
  3031. unset( $view_fields ); // Cleanup 
  3032.  
  3033. $output = pods_view( PODS_DIR . 'ui/front/view.php', compact( array_keys( get_defined_vars() ) ), false, 'cache', true ); 
  3034.  
  3035. return $this->do_hook( 'view', $output, $fields, $this->id() ); 
  3036.  
  3037.  
  3038. /** 
  3039. * Replace magic tags with their values 
  3040. * @param string $code The content to evaluate 
  3041. * @param object $obj The Pods object 
  3042. * @return string Code with Magic Tags evaluated 
  3043. * @since 2.0 
  3044. */ 
  3045. public function do_magic_tags ( $code ) { 
  3046. return preg_replace_callback( '/({@(.*?)})/m', array( $this, 'process_magic_tags' ), $code ); 
  3047.  
  3048. /** 
  3049. * Replace magic tags with their values 
  3050. * @param string $tag The magic tag to process 
  3051. * @param object $obj The Pods object 
  3052. * @return string Code with Magic Tags evaluated 
  3053. * @since 2.0.2 
  3054. */ 
  3055. private function process_magic_tags ( $tag ) { 
  3056.  
  3057. if ( is_array( $tag ) ) { 
  3058. if ( !isset( $tag[ 2 ] ) && strlen( trim( $tag[ 2 ] ) ) < 1 ) 
  3059. return ''; 
  3060.  
  3061. $tag = $tag[ 2 ]; 
  3062.  
  3063. $tag = trim( $tag, ' {@}' ); 
  3064. $tag = explode( ', ', $tag ); 
  3065.  
  3066. if ( empty( $tag ) || !isset( $tag[ 0 ] ) || strlen( trim( $tag[ 0 ] ) ) < 1 ) 
  3067. return ''; 
  3068.  
  3069. foreach ( $tag as $k => $v ) { 
  3070. $tag[ $k ] = trim( $v ); 
  3071.  
  3072. $field_name = $tag[ 0 ]; 
  3073.  
  3074. $helper_name = $before = $after = ''; 
  3075.  
  3076. if ( isset( $tag[ 1 ] ) && !empty( $tag[ 1 ] ) ) { 
  3077. $value = $this->field( $field_name ); 
  3078.  
  3079. $helper_name = $tag[ 1 ]; 
  3080.  
  3081. $value = $this->helper( $helper_name, $value, $field_name ); 
  3082. else 
  3083. $value = $this->display( $field_name ); 
  3084.  
  3085. if ( isset( $tag[ 2 ] ) && !empty( $tag[ 2 ] ) ) 
  3086. $before = $tag[ 2 ]; 
  3087.  
  3088. if ( isset( $tag[ 3 ] ) && !empty( $tag[ 3 ] ) ) 
  3089. $after = $tag[ 3 ]; 
  3090.  
  3091. $value = apply_filters( 'pods_do_magic_tags', $value, $field_name, $helper_name, $before, $after ); 
  3092.  
  3093. if ( is_array( $value ) ) 
  3094. $value = pods_serial_comma( $value, array( 'field' => $field_name, 'fields' => $this->fields ) ); 
  3095.  
  3096. if ( null !== $value && false !== $value ) 
  3097. return $before . $value . $after; 
  3098.  
  3099. return ''; 
  3100.  
  3101. /** 
  3102. * Generate UI for Data Management 
  3103. * @param mixed $options Array or String containing Pod or Options to be used 
  3104. * @param bool $amend Whether to amend the default UI options or replace entirely 
  3105. * @return PodsUI|void UI object or void if custom UI used 
  3106. * @since 2.3.10 
  3107. */ 
  3108. public function ui ( $options = null, $amend = false ) { 
  3109. $num = ''; 
  3110.  
  3111. if ( empty( $options ) ) 
  3112. $options = array(); 
  3113. else { 
  3114. $num = pods_var( 'num', $options, '' ); 
  3115.  
  3116. if ( empty( $num ) ) { 
  3117. $num = ''; 
  3118.  
  3119. if ( $this->id() != pods_var( 'id' . $num, 'get', null, null, true ) ) 
  3120. $this->fetch( pods_var( 'id' . $num, 'get', null, null, true ) ); 
  3121.  
  3122. if ( !empty( $options ) && !$amend ) { 
  3123. $this->ui = $options; 
  3124.  
  3125. return pods_ui( $this ); 
  3126. elseif ( !empty( $options ) || 'custom' != pods_var( 'ui_style', $this->pod_data[ 'options' ], 'post_type', null, true ) ) { 
  3127. $actions_enabled = pods_var_raw( 'ui_actions_enabled', $this->pod_data[ 'options' ] ); 
  3128.  
  3129. if ( !empty( $actions_enabled ) ) 
  3130. $actions_enabled = (array) $actions_enabled; 
  3131. else 
  3132. $actions_enabled = array(); 
  3133.  
  3134. $available_actions = array( 
  3135. 'add',  
  3136. 'edit',  
  3137. 'duplicate',  
  3138. 'delete',  
  3139. 'reorder',  
  3140. 'export' 
  3141. ); 
  3142.  
  3143. if ( !empty( $actions_enabled ) ) { 
  3144. $actions_disabled = array( 
  3145. 'view' => 'view' 
  3146. ); 
  3147.  
  3148. foreach ( $available_actions as $action ) { 
  3149. if ( !in_array( $action, $actions_enabled ) ) 
  3150. $actions_disabled[ $action ] = $action; 
  3151. else { 
  3152. $actions_disabled = array( 
  3153. 'duplicate' => 'duplicate',  
  3154. 'view' => 'view',  
  3155. 'export' => 'export' 
  3156. ); 
  3157.  
  3158. if ( 1 == pods_var( 'ui_export', $this->pod_data[ 'options' ], 0 ) ) 
  3159. unset( $actions_disabled[ 'export' ] ); 
  3160.  
  3161. if ( empty( $options ) ) { 
  3162. $author_restrict = false; 
  3163.  
  3164. if ( isset( $this->fields[ 'author' ] ) && 'pick' == $this->fields[ 'author' ][ 'type' ] && 'user' == $this->fields[ 'author' ][ 'pick_object' ] ) 
  3165. $author_restrict = 'author.ID'; 
  3166.  
  3167. if ( !pods_is_admin( array( 'pods', 'pods_content' ) ) ) { 
  3168. if ( !current_user_can( 'pods_add_' . $this->pod ) ) { 
  3169. $actions_disabled[ 'add' ] = 'add'; 
  3170.  
  3171. if ( 'add' == pods_var( 'action' . $num, 'get' ) ) 
  3172. $_GET[ 'action' . $num ] = 'manage'; 
  3173.  
  3174. if ( !$author_restrict && !current_user_can( 'pods_edit_' . $this->pod ) && !current_user_can( 'pods_edit_others_' . $this->pod ) ) 
  3175. $actions_disabled[ 'edit' ] = 'edit'; 
  3176.  
  3177. if ( !$author_restrict && !current_user_can( 'pods_delete_' . $this->pod ) && !current_user_can( 'pods_delete_others_' . $this->pod ) ) 
  3178. $actions_disabled[ 'delete' ] = 'delete'; 
  3179.  
  3180. if ( !current_user_can( 'pods_reorder_' . $this->pod ) ) 
  3181. $actions_disabled[ 'reorder' ] = 'reorder'; 
  3182.  
  3183. if ( !current_user_can( 'pods_export_' . $this->pod ) ) 
  3184. $actions_disabled[ 'export' ] = 'export'; 
  3185.  
  3186. $_GET[ 'action' . $num ] = pods_var( 'action' . $num, 'get', pods_var( 'action', $options, 'manage' ) ); 
  3187.  
  3188. $index = $this->pod_data[ 'field_id' ]; 
  3189. $label = __( 'ID', 'pods' ); 
  3190.  
  3191. if ( isset( $this->pod_data[ 'fields' ][ $this->pod_data[ 'field_index' ] ] ) ) { 
  3192. $index = $this->pod_data[ 'field_index' ]; 
  3193. $label = $this->pod_data[ 'fields' ][ $this->pod_data[ 'field_index' ] ]; 
  3194.  
  3195. $manage = array( 
  3196. $index => $label 
  3197. ); 
  3198.  
  3199. if ( isset( $this->pod_data[ 'fields' ][ 'modified' ] ) ) 
  3200. $manage[ 'modified' ] = $this->pod_data[ 'fields' ][ 'modified' ][ 'label' ]; 
  3201.  
  3202. $manage_fields = pods_var_raw( 'ui_fields_manage', $this->pod_data[ 'options' ] ); 
  3203.  
  3204. if ( !empty( $manage_fields ) ) { 
  3205. $manage_new = array(); 
  3206.  
  3207. foreach ( $manage_fields as $manage_field ) { 
  3208. if ( isset( $this->pod_data[ 'fields' ][ $manage_field ] ) ) 
  3209. $manage_new[ $manage_field ] = $this->pod_data[ 'fields' ][ $manage_field ]; 
  3210. elseif ( isset( $this->pod_data[ 'object_fields' ][ $manage_field ] ) ) 
  3211. $manage_new[ $manage_field ] = $this->pod_data[ 'object_fields' ][ $manage_field ]; 
  3212. elseif ( $manage_field == $this->pod_data[ 'field_id' ] ) { 
  3213. $field = array( 
  3214. 'name' => $manage_field,  
  3215. 'label' => 'ID',  
  3216. 'type' => 'number',  
  3217. 'width' => '8%' 
  3218. ); 
  3219.  
  3220. $manage_new[ $manage_field ] = PodsForm::field_setup( $field, null, $field[ 'type' ] ); 
  3221.  
  3222. if ( !empty( $manage_new ) ) 
  3223. $manage = $manage_new; 
  3224.  
  3225. $manage = apply_filters( 'pods_admin_ui_fields_' . $this->pod, apply_filters( 'pods_admin_ui_fields', $manage, $this->pod, $this ), $this->pod, $this ); 
  3226.  
  3227. $icon = pods_var_raw( 'ui_icon', $this->pod_data[ 'options' ] ); 
  3228.  
  3229. if ( !empty( $icon ) ) 
  3230. $icon = pods_image_url( $icon, '32x32' ); 
  3231.  
  3232. $filters = pods_var_raw( 'ui_filters', $this->pod_data[ 'options' ] ); 
  3233.  
  3234. if ( !empty( $filters ) ) { 
  3235. $filters_new = array(); 
  3236.  
  3237. $filters = (array) $filters; 
  3238.  
  3239. foreach ( $filters as $filter_field ) { 
  3240. if ( isset( $this->pod_data[ 'fields' ][ $filter_field ] ) ) 
  3241. $filters_new[ $filter_field ] = $this->pod_data[ 'fields' ][ $filter_field ]; 
  3242. elseif ( isset( $this->pod_data[ 'object_fields' ][ $filter_field ] ) ) 
  3243. $filters_new[ $filter_field ] = $this->pod_data[ 'object_fields' ][ $filter_field ]; 
  3244.  
  3245. $filters = $filters_new; 
  3246.  
  3247. $ui = array( 
  3248. 'fields' => array( 
  3249. 'manage' => $manage,  
  3250. 'add' => $this->pod_data[ 'fields' ],  
  3251. 'edit' => $this->pod_data[ 'fields' ],  
  3252. 'duplicate' => $this->pod_data[ 'fields' ] 
  3253. ),  
  3254. 'icon' => $icon,  
  3255. 'actions_disabled' => $actions_disabled 
  3256. ); 
  3257.  
  3258. if ( !empty( $filters ) ) { 
  3259. $ui[ 'fields' ][ 'search' ] = $filters; 
  3260. $ui[ 'filters' ] = array_keys( $filters ); 
  3261. $ui[ 'filters_enhanced' ] = true; 
  3262.  
  3263. $reorder_field = pods_var_raw( 'ui_reorder_field', $this->pod_data[ 'options' ] ); 
  3264.  
  3265. if ( in_array( 'reorder', $actions_enabled ) && !in_array( 'reorder', $actions_disabled ) && !empty( $reorder_field ) && ( ( !empty( $this->pod_data[ 'object_fields' ] ) && isset( $this->pod_data[ 'object_fields' ][ $reorder_field ] ) ) || isset( $this->pod_data[ 'fields' ][ $reorder_field ] ) ) ) { 
  3266. $ui[ 'reorder' ] = array( 'on' => $reorder_field ); 
  3267. $ui[ 'orderby' ] = $reorder_field; 
  3268. $ui[ 'orderby_dir' ] = 'ASC'; 
  3269.  
  3270. if ( !empty( $author_restrict ) ) 
  3271. $ui[ 'restrict' ] = array( 'author_restrict' => $author_restrict ); 
  3272.  
  3273. if ( !in_array( 'delete', $ui[ 'actions_disabled' ] ) ) { 
  3274. $ui[ 'actions_bulk' ] = array( 
  3275. 'delete' => array( 
  3276. 'label' => __( 'Delete', 'pods' ) 
  3277. // callback not needed, Pods has this built-in for delete 
  3278. ); 
  3279.  
  3280. $detail_url = pods_var( 'detail_url', $this->pod_data[ 'options' ] ); 
  3281.  
  3282. if ( 0 < strlen( $detail_url ) ) { 
  3283. $ui[ 'actions_custom' ] = array( 
  3284. 'view_url' => array( 
  3285. 'label' => 'View',  
  3286. 'link' => get_site_url() . '/' . $detail_url 
  3287. ); 
  3288.  
  3289. // @todo Customize the Add New / Manage links to point to their correct menu items 
  3290.  
  3291. $ui = apply_filters( 'pods_admin_ui_' . $this->pod, apply_filters( 'pods_admin_ui', $ui, $this->pod, $this ), $this->pod, $this ); 
  3292.  
  3293. // Override UI options 
  3294. foreach ( $options as $option => $value ) { 
  3295. $ui[ $option ] = $value; 
  3296.  
  3297. $this->ui = $ui; 
  3298.  
  3299. return pods_ui( $this ); 
  3300.  
  3301. do_action( 'pods_admin_ui_custom', $this ); 
  3302. do_action( 'pods_admin_ui_custom_' . $this->pod, $this ); 
  3303.  
  3304. /** 
  3305. * Handle filters / actions for the class 
  3306. * @see pods_do_hook 
  3307. * @return mixed Value filtered 
  3308. * @since 2.0 
  3309. */ 
  3310. private function do_hook () { 
  3311. $args = func_get_args(); 
  3312.  
  3313. if ( empty( $args ) ) 
  3314. return false; 
  3315.  
  3316. $name = array_shift( $args ); 
  3317.  
  3318. return pods_do_hook( 'pods', $name, $args, $this ); 
  3319.  
  3320. /** 
  3321. * Handle variables that have been deprecated and PodsData vars 
  3322. * @var $name 
  3323. * @return mixed 
  3324. * @since 2.0 
  3325. */ 
  3326. public function __get ( $name ) { 
  3327. $name = (string) $name; 
  3328.  
  3329. // PodsData vars 
  3330. if ( 0 === strpos( $name, 'field_' ) && isset( $this->data->{$name} ) ) { 
  3331. return $this->data->{$name}; 
  3332.  
  3333. if ( !isset( $this->deprecated ) ) { 
  3334. require_once( PODS_DIR . 'deprecated/classes/Pods.php' ); 
  3335. $this->deprecated = new Pods_Deprecated( $this ); 
  3336.  
  3337. $var = null; 
  3338.  
  3339. if ( isset( $this->deprecated->{$name} ) ) { 
  3340. if ( ! class_exists( 'Pod' ) || Pod::$deprecated_notice ) { 
  3341. pods_deprecated( "Pods->{$name}", '2.0' ); 
  3342.  
  3343. $var = $this->deprecated->{$name}; 
  3344. elseif ( ! class_exists( 'Pod' ) || Pod::$deprecated_notice ) { 
  3345. pods_deprecated( "Pods->{$name}", '2.0' ); 
  3346.  
  3347. return $var; 
  3348.  
  3349. /** 
  3350. * Handle methods that have been deprecated and any aliasing 
  3351. * @var $name 
  3352. * @var $args 
  3353. * @return mixed 
  3354. * @since 2.0 
  3355. */ 
  3356. public function __call ( $name, $args ) { 
  3357. $name = (string) $name; 
  3358.  
  3359. // select > find alias 
  3360. if ( 'select' == $name ) { 
  3361. return call_user_func_array( array( $this, 'find' ), $args ); 
  3362.  
  3363. if ( !isset( $this->deprecated ) ) { 
  3364. require_once( PODS_DIR . 'deprecated/classes/Pods.php' ); 
  3365. $this->deprecated = new Pods_Deprecated( $this ); 
  3366.  
  3367. if ( method_exists( $this->deprecated, $name ) ) { 
  3368. return call_user_func_array( array( $this->deprecated, $name ), $args ); 
  3369. elseif ( ! class_exists( 'Pod' ) || Pod::$deprecated_notice ) { 
  3370. pods_deprecated( "Pods::{$name}", '2.0' );