PodsData

The WordPress Core PodsData class.

Defined (1)

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

/classes/PodsData.php  
  1. class PodsData { 
  2.  
  3. /** 
  4. * @var PodsData 
  5. */ 
  6. static $instance = null; 
  7.  
  8. /** 
  9. * @var string 
  10. */ 
  11. static protected $prefix = 'pods_'; 
  12.  
  13. /** 
  14. * @var array 
  15. */ 
  16. static protected $field_types = array(); 
  17.  
  18. /** 
  19. * @var bool 
  20. */ 
  21. public static $display_errors = true; 
  22.  
  23. /** 
  24. * @var PodsAPI 
  25. */ 
  26. public $api = null; 
  27.  
  28. /** 
  29. * @var null 
  30. */ 
  31. public $select = null; 
  32.  
  33. /** 
  34. * @var null 
  35. */ 
  36. public $table = null; 
  37.  
  38. /** 
  39. * @var null 
  40. */ 
  41. public $pod = null; 
  42.  
  43. /** 
  44. * @var array|bool|mixed|null|void 
  45. */ 
  46. public $pod_data = null; 
  47.  
  48. /** 
  49. * @var int 
  50. */ 
  51. public $id = 0; 
  52.  
  53. /** 
  54. * @var string 
  55. */ 
  56. public $field_id = 'id'; 
  57.  
  58. /** 
  59. * @var string 
  60. */ 
  61. public $field_index = 'name'; 
  62.  
  63. /** 
  64. * @var string 
  65. */ 
  66. public $field_slug = ''; 
  67.  
  68. /** 
  69. * @var string 
  70. */ 
  71. public $join = ''; 
  72.  
  73. /** 
  74. * @var array 
  75. */ 
  76. public $where = array(); 
  77.  
  78. /** 
  79. * @var array 
  80. */ 
  81. public $where_default = array(); 
  82.  
  83. /** 
  84. * @var string 
  85. */ 
  86. public $orderby = ''; 
  87.  
  88. /** 
  89. * @var array 
  90. */ 
  91. public $fields = array(); 
  92.  
  93. /** 
  94. * @var array 
  95. */ 
  96. public $aliases = array(); 
  97.  
  98. /** 
  99. * @var 
  100. */ 
  101. public $detail_page; 
  102.  
  103. // data 
  104. /** 
  105. * @var int 
  106. */ 
  107. public $row_number = -1; 
  108.  
  109. /** 
  110. * @var 
  111. */ 
  112. public $data; 
  113.  
  114. /** 
  115. * @var 
  116. */ 
  117. public $row; 
  118.  
  119. /** 
  120. * @var 
  121. */ 
  122. public $insert_id; 
  123.  
  124. /** 
  125. * @var 
  126. */ 
  127. public $total; 
  128.  
  129. /** 
  130. * @var 
  131. */ 
  132. public $total_found; 
  133.  
  134. /** 
  135. * @var bool 
  136. */ 
  137. public $total_found_calculated; 
  138.  
  139. // pagination 
  140. /** 
  141. * @var string 
  142. */ 
  143. public $page_var = 'pg'; 
  144.  
  145. /** 
  146. * @var int 
  147. */ 
  148. public $page = 1; 
  149.  
  150. /** 
  151. * @var int 
  152. */ 
  153. public $limit = 15; 
  154.  
  155. /** 
  156. * @var bool 
  157. */ 
  158. public $pagination = true; 
  159.  
  160. // search 
  161. /** 
  162. * @var bool 
  163. */ 
  164. public $search = true; 
  165.  
  166. /** 
  167. * @var string 
  168. */ 
  169. public $search_var = 'search'; 
  170.  
  171. /** 
  172. * @var string 
  173. */ 
  174. public $search_mode = 'int'; // int | text | text_like 
  175. /** 
  176. * @var string 
  177. */ 
  178. public $search_query = ''; 
  179.  
  180. /** 
  181. * @var array 
  182. */ 
  183. public $search_fields = array(); 
  184.  
  185. /** 
  186. * @var string 
  187. */ 
  188. public $search_where = array(); 
  189.  
  190. /** 
  191. * @var array 
  192. */ 
  193. public $filters = array(); 
  194.  
  195. /** 
  196. * Holds Traversal information about Pods 
  197. * @var array 
  198. */ 
  199. public $traversal = array(); 
  200.  
  201. /** 
  202. * Holds custom Traversals to be included 
  203. * @var array 
  204. */ 
  205. public $traverse = array(); 
  206.  
  207. /** 
  208. * Last select() query SQL 
  209. * @var string 
  210. */ 
  211. public $sql = false; 
  212.  
  213. /** 
  214. * Last total sql 
  215. * @var string 
  216. */ 
  217. public $total_sql = false; 
  218.  
  219. /** 
  220. * Singleton handling for a basic pods_data() request 
  221. * @param string $pod Pod name 
  222. * @param integer $id Pod Item ID 
  223. * @param bool $strict If true throws an error if a pod is not found. 
  224. * @return \PodsData 
  225. * @since 2.3.5 
  226. */ 
  227. public static function init ( $pod = null, $id = 0, $strict = true ) { 
  228. if ( ( true !== $pod && null !== $pod ) || 0 != $id ) 
  229. return new PodsData( $pod, $id, $strict ); 
  230. elseif ( !is_object( self::$instance ) ) 
  231. self::$instance = new PodsData(); 
  232. else { 
  233. $vars = get_class_vars( __CLASS__ ); 
  234.  
  235. foreach ( $vars as $var => $default ) { 
  236. if ( 'api' == $var ) 
  237. continue; 
  238.  
  239. self::$instance->{$var} = $default; 
  240.  
  241. return self::$instance; 
  242.  
  243. /** 
  244. * Data Abstraction Class for Pods 
  245. * @param string $pod Pod name 
  246. * @param integer $id Pod Item ID 
  247. * @param bool $strict If true throws an error if a pod is not found. 
  248. * @return \PodsData 
  249. * @license http://www.gnu.org/licenses/gpl-2.0.html 
  250. * @since 2.0 
  251. */ 
  252. public function __construct ( $pod = null, $id = 0, $strict = true ) { 
  253. global $wpdb; 
  254.  
  255. if ( is_object( $pod ) && 'PodsAPI' == get_class( $pod ) ) { 
  256. $this->api = $pod; 
  257. $pod = $this->api->pod; 
  258. else 
  259. $this->api = pods_api( $pod ); 
  260.  
  261. $this->api->display_errors =& self::$display_errors; 
  262.  
  263. if ( !empty( $pod ) ) { 
  264. $this->pod_data =& $this->api->pod_data; 
  265.  
  266. if ( false === $this->pod_data ) { 
  267. if ( true === $strict ) 
  268. return pods_error( 'Pod not found', $this ); 
  269. else 
  270. return $this; 
  271.  
  272. $this->pod_id = $this->pod_data[ 'id' ]; 
  273. $this->pod = $this->pod_data[ 'name' ]; 
  274. $this->fields = $this->pod_data[ 'fields' ]; 
  275.  
  276. if ( isset( $this->pod_data[ 'options' ][ 'detail_url' ] ) ) 
  277. $this->detail_page = $this->pod_data[ 'options' ][ 'detail_url' ]; 
  278.  
  279. if ( isset( $this->pod_data[ 'select' ] ) ) 
  280. $this->select = $this->pod_data[ 'select' ]; 
  281.  
  282. if ( isset( $this->pod_data[ 'table' ] ) ) 
  283. $this->table = $this->pod_data[ 'table' ]; 
  284.  
  285. if ( isset( $this->pod_data[ 'join' ] ) ) 
  286. $this->join = $this->pod_data[ 'join' ]; 
  287.  
  288. if ( isset( $this->pod_data[ 'field_id' ] ) ) 
  289. $this->field_id = $this->pod_data[ 'field_id' ]; 
  290.  
  291. if ( isset( $this->pod_data[ 'field_index' ] ) ) 
  292. $this->field_index = $this->pod_data[ 'field_index' ]; 
  293.  
  294. if ( isset( $this->pod_data[ 'field_slug' ] ) ) 
  295. $this->field_slug = $this->pod_data[ 'field_slug' ]; 
  296.  
  297. if ( isset( $this->pod_data[ 'where' ] ) ) 
  298. $this->where = $this->pod_data[ 'where' ]; 
  299.  
  300. if ( isset( $this->pod_data[ 'where_default' ] ) ) 
  301. $this->where_default = $this->pod_data[ 'where_default' ]; 
  302.  
  303. if ( isset( $this->pod_data[ 'orderby' ] ) ) 
  304. $this->orderby = $this->pod_data[ 'orderby' ]; 
  305.  
  306. if ( 'settings' == $this->pod_data[ 'type' ] ) { 
  307. $this->id = $this->pod_data[ 'id' ]; 
  308.  
  309. $this->fetch( $this->id ); 
  310. elseif ( null !== $id && !is_array( $id ) && !is_object( $id ) ) { 
  311. $this->id = $id; 
  312.  
  313. $this->fetch( $this->id ); 
  314.  
  315. /** 
  316. * Handle tables like they are Pods (for traversal in select/build) 
  317. * @param array|string $table 
  318. * @param string $object 
  319. */ 
  320. public function table ( $table, $object = '' ) { 
  321. global $wpdb; 
  322.  
  323. if ( !is_array( $table ) ) { 
  324. $object_type = ''; 
  325.  
  326. if ( $wpdb->users == $table ) 
  327. $object_type = 'user'; 
  328. elseif ( $wpdb->posts == $table ) 
  329. $object_type = 'post_type'; 
  330. elseif ( $wpdb->terms == $table ) 
  331. $object_type = 'taxonomy'; 
  332. elseif ( $wpdb->options == $table ) 
  333. $object_type = 'settings'; 
  334.  
  335. if ( !empty( $object_type ) ) 
  336. $table = $this->api->get_table_info( $object_type, $object ); 
  337.  
  338. if ( !empty( $table ) && is_array( $table ) ) { 
  339. $table[ 'id' ] = pods_var( 'id', $table[ 'pod' ], 0, null, true ); 
  340. $table[ 'name' ] = pods_var( 'name', $table[ 'pod' ], $table[ 'object_type' ], null, true ); 
  341. $table[ 'type' ] = pods_var_raw( 'type', $table[ 'pod' ], $table[ 'object_type' ], null, true ); 
  342.  
  343. $default_storage = 'meta'; 
  344.  
  345. if ( 'taxonomy' == $table[ 'type' ] && ! function_exists( 'get_term_meta' ) ) { 
  346. $default_storage = 'none'; 
  347.  
  348. $table[ 'storage' ] = pods_var_raw( 'storage', $table[ 'pod' ], $default_storage, null, true ); 
  349. $table[ 'fields' ] = pods_var_raw( 'fields', $table[ 'pod' ], array() ); 
  350. $table[ 'object_fields' ] = pods_var_raw( 'object_fields', $table[ 'pod' ], $this->api->get_wp_object_fields( $table[ 'object_type' ] ), null, true ); 
  351.  
  352. $this->pod_data = $table; 
  353. $this->pod_id = $this->pod_data[ 'id' ]; 
  354. $this->pod = $this->pod_data[ 'name' ]; 
  355. $this->fields = $this->pod_data[ 'fields' ]; 
  356.  
  357. if ( isset( $this->pod_data[ 'select' ] ) ) 
  358. $this->select = $this->pod_data[ 'select' ]; 
  359.  
  360. if ( isset( $this->pod_data[ 'table' ] ) ) 
  361. $this->table = $this->pod_data[ 'table' ]; 
  362.  
  363. if ( isset( $this->pod_data[ 'join' ] ) ) 
  364. $this->join = $this->pod_data[ 'join' ]; 
  365.  
  366. if ( isset( $this->pod_data[ 'field_id' ] ) ) 
  367. $this->field_id = $this->pod_data[ 'field_id' ]; 
  368.  
  369. if ( isset( $this->pod_data[ 'field_index' ] ) ) 
  370. $this->field_index = $this->pod_data[ 'field_index' ]; 
  371.  
  372. if ( isset( $this->pod_data[ 'field_slug' ] ) ) 
  373. $this->field_slug = $this->pod_data[ 'field_slug' ]; 
  374.  
  375. if ( isset( $this->pod_data[ 'where' ] ) ) 
  376. $this->where = $this->pod_data[ 'where' ]; 
  377.  
  378. if ( isset( $this->pod_data[ 'where_default' ] ) ) 
  379. $this->where_default = $this->pod_data[ 'where_default' ]; 
  380.  
  381. if ( isset( $this->pod_data[ 'orderby' ] ) ) 
  382. $this->orderby = $this->pod_data[ 'orderby' ]; 
  383.  
  384. /** 
  385. * Insert an item, eventually mapping to WPDB::insert 
  386. * @param string $table Table name 
  387. * @param array $data Data to insert (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 
  388. * @param array $format (optional) An array of formats to be mapped to each of the value in $data. 
  389. * @return int|bool The ID of the item 
  390. * @uses wpdb::insert 
  391. * @since 2.0 
  392. */ 
  393. public function insert ( $table, $data, $format = null ) { 
  394. /** 
  395. * @var $wpdb wpdb 
  396. */ 
  397. global $wpdb; 
  398.  
  399. if ( strlen( $table ) < 1 || empty( $data ) || !is_array( $data ) ) 
  400. return false; 
  401.  
  402. if ( empty( $format ) ) { 
  403. $format = array(); 
  404.  
  405. foreach ( $data as $field ) { 
  406. if ( isset( self::$field_types[ $field ] ) ) 
  407. $format[] = self::$field_types[ $field ]; 
  408. elseif ( isset( $wpdb->field_types[ $field ] ) ) 
  409. $format[] = $wpdb->field_types[ $field ]; 
  410. else 
  411. break; 
  412.  
  413. list( $table, $data, $format ) = $this->do_hook( 'insert', array( $table, $data, $format ) ); 
  414.  
  415. $result = $wpdb->insert( $table, $data, $format ); 
  416. $this->insert_id = $wpdb->insert_id; 
  417.  
  418. if ( false !== $result ) 
  419. return $this->insert_id; 
  420.  
  421. return false; 
  422.  
  423. /** 
  424. * @static 
  425. * Insert into a table, if unique key exists just update values. 
  426. * Data must be a key value pair array, keys act as table rows. 
  427. * Returns the prepared query from wpdb or false for errors 
  428. * @param string $table Name of the table to update 
  429. * @param array $data column => value pairs 
  430. * @param array $formats For $wpdb->prepare, uses sprintf formatting 
  431. * @return mixed Sanitized query string 
  432. * @uses wpdb::prepare 
  433. * @since 2.0 
  434. */ 
  435. public static function insert_on_duplicate ( $table, $data, $formats = array() ) { 
  436. /** 
  437. * @var $wpdb wpdb 
  438. */ 
  439. global $wpdb; 
  440.  
  441. $columns = array_keys( $data ); 
  442.  
  443. $update = array(); 
  444. $values = array(); 
  445.  
  446. foreach ( $columns as $column ) { 
  447. $update[] = "`{$column}` = VALUES( `{$column}` )"; 
  448. $values[] = "%s"; 
  449.  
  450. if ( empty( $formats ) ) 
  451. $formats = $values; 
  452.  
  453. $columns_data = implode( '`, `', $columns ); 
  454. $formats = implode( ", ", $formats ); 
  455. $update = implode( ', ', $update ); 
  456.  
  457. $sql = "INSERT INTO `{$table}` ( `{$columns_data}` ) VALUES ( {$formats} ) ON DUPLICATE KEY UPDATE {$update}"; 
  458.  
  459. return $wpdb->prepare( $sql, $data ); 
  460.  
  461. /** 
  462. * Update an item, eventually mapping to WPDB::update 
  463. * @param string $table Table name 
  464. * @param array $data Data to update (in column => value pairs). Both $data columns and $data values should be "raw" (neither should be SQL escaped). 
  465. * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw". 
  466. * @param array $format (optional) An array of formats to be mapped to each of the values in $data. 
  467. * @param array $where_format (optional) An array of formats to be mapped to each of the values in $where. 
  468. * @return bool 
  469. * @since 2.0 
  470. */ 
  471. public function update ( $table, $data, $where, $format = null, $where_format = null ) { 
  472. /** 
  473. * @var $wpdb wpdb 
  474. */ 
  475. global $wpdb; 
  476.  
  477. if ( strlen( $table ) < 1 || empty( $data ) || !is_array( $data ) ) 
  478. return false; 
  479.  
  480. if ( empty( $format ) ) { 
  481. $format = array(); 
  482.  
  483. foreach ( $data as $field ) { 
  484. if ( isset( self::$field_types[ $field ] ) ) 
  485. $form = self::$field_types[ $field ]; 
  486. elseif ( isset( $wpdb->field_types[ $field ] ) ) 
  487. $form = $wpdb->field_types[ $field ]; 
  488. else 
  489. $form = '%s'; 
  490.  
  491. $format[] = $form; 
  492.  
  493. if ( empty( $where_format ) ) { 
  494. $where_format = array(); 
  495.  
  496. foreach ( (array) array_keys( $where ) as $field ) { 
  497. if ( isset( self::$field_types[ $field ] ) ) 
  498. $form = self::$field_types[ $field ]; 
  499. elseif ( isset( $wpdb->field_types[ $field ] ) ) 
  500. $form = $wpdb->field_types[ $field ]; 
  501. else 
  502. $form = '%s'; 
  503.  
  504. $where_format[] = $form; 
  505.  
  506. list( $table, $data, $where, $format, $where_format ) = $this->do_hook( 'update', array( 
  507. $table,  
  508. $data,  
  509. $where,  
  510. $format,  
  511. $where_format 
  512. ) ); 
  513.  
  514. $result = $wpdb->update( $table, $data, $where, $format, $where_format ); 
  515.  
  516. if ( false !== $result ) 
  517. return true; 
  518.  
  519. return false; 
  520.  
  521. /** 
  522. * Delete an item 
  523. * @param string $table Table name 
  524. * @param array $where A named array of WHERE clauses (in column => value pairs). Multiple clauses will be joined with ANDs. Both $where columns and $where values should be "raw". 
  525. * @param array $where_format (optional) An array of formats to be mapped to each of the values in $where. 
  526. * @return array|bool|mixed|null|void 
  527. * @uses PodsData::query 
  528. * @uses PodsData::prepare 
  529. * @since 2.0 
  530. */ 
  531. public function delete ( $table, $where, $where_format = null ) { 
  532. /** 
  533. * @var $wpdb wpdb 
  534. */ 
  535. global $wpdb; 
  536.  
  537. if ( strlen( $table ) < 1 || empty( $where ) || !is_array( $where ) ) 
  538. return false; 
  539.  
  540. $wheres = array(); 
  541. $where_formats = $where_format = (array) $where_format; 
  542.  
  543. foreach ( (array) array_keys( $where ) as $field ) { 
  544. if ( !empty( $where_format ) ) 
  545. $form = ( $form = array_shift( $where_formats ) ) ? $form : $where_format[ 0 ]; 
  546. elseif ( isset( self::$field_types[ $field ] ) ) 
  547. $form = self::$field_types[ $field ]; 
  548. elseif ( isset( $wpdb->field_types[ $field ] ) ) 
  549. $form = $wpdb->field_types[ $field ]; 
  550. else 
  551. $form = '%s'; 
  552.  
  553. $wheres[] = "`{$field}` = {$form}"; 
  554.  
  555. $sql = "DELETE FROM `$table` WHERE " . implode( ' AND ', $wheres ); 
  556.  
  557. list( $sql, $where ) = $this->do_hook( 'delete', array( 
  558. $sql,  
  559. array_values( $where ) 
  560. ), $table, $where, $where_format, $wheres ); 
  561.  
  562. return $this->query( self::prepare( $sql, $where ) ); 
  563.  
  564. /** 
  565. * Select items, eventually building dynamic query 
  566. * @param array $params 
  567. * @return array|bool|mixed 
  568. * @since 2.0 
  569. */ 
  570. public function select ( $params ) { 
  571. global $wpdb; 
  572.  
  573. $cache_key = $results = false; 
  574.  
  575. $params = apply_filters( 'pods_data_pre_select_params', $params ); 
  576.  
  577. // Debug purposes 
  578. if ( 1 == pods_v( 'pods_debug_params', 'get', 0 ) && pods_is_admin( array( 'pods' ) ) ) 
  579. pods_debug( $params ); 
  580.  
  581. // Get from cache if enabled 
  582. if ( null !== pods_v( 'expires', $params, null, false ) ) { 
  583. $cache_key = md5( (string) $this->pod . serialize( $params ) ); 
  584.  
  585. $results = pods_view_get( $cache_key, pods_v( 'cache_mode', $params, 'cache', true ), 'pods_data_select' ); 
  586.  
  587. if ( empty( $results ) ) 
  588. $results = false; 
  589.  
  590. if ( empty( $results ) ) { 
  591. // Build 
  592. $this->sql = $this->build( $params ); 
  593.  
  594. // Debug purposes 
  595. if ( ( 1 == pods_v( 'pods_debug_sql', 'get', 0 ) || 1 == pods_v( 'pods_debug_sql_all', 'get', 0 ) ) && pods_is_admin( array( 'pods' ) ) ) 
  596. echo '<textarea cols="100" rows="24">' . esc_textarea( str_replace( array( '@wp_users', '@wp_' ), array( $wpdb->users, $wpdb->prefix ), $this->sql ) ) . '</textarea>'; 
  597.  
  598. if ( empty( $this->sql ) ) 
  599. return array(); 
  600.  
  601. // Get Data 
  602. $results = pods_query( $this->sql, $this ); 
  603.  
  604. // Cache if enabled 
  605. if ( false !== $cache_key ) 
  606. pods_view_set( $cache_key, $results, pods_v( 'expires', $params, 0, false ), pods_v( 'cache_mode', $params, 'cache', true ), 'pods_data_select' ); 
  607.  
  608. $results = apply_filters( 'pods_data_select', $results, $params, $this ); 
  609.  
  610. $this->data = $results; 
  611.  
  612. $this->row_number = -1; 
  613. $this->row = null; 
  614.  
  615. // Fill in empty field data (if none provided) 
  616. if ( ( !isset( $this->fields ) || empty( $this->fields ) ) && !empty( $this->data ) ) { 
  617. $this->fields = array(); 
  618. $data = (array) @current( $this->data ); 
  619.  
  620. foreach ( $data as $data_key => $data_value ) { 
  621. $this->fields[ $data_key ] = array( 'label' => ucwords( str_replace( '-', ' ', str_replace( '_', ' ', $data_key ) ) ) ); 
  622. if ( isset( $this->pod_data[ 'object_fields' ][ $data_key ] ) ) { 
  623. $this->fields[ $data_key ] = $this->pod_data[ 'object_fields' ][ $data_key ]; 
  624.  
  625. $this->fields = PodsForm::fields_setup( $this->fields ); 
  626.  
  627. $this->total_found_calculated = false; 
  628.  
  629. $this->total = 0; 
  630.  
  631. if ( ! empty( $this->data ) ) { 
  632. $this->total = count( (array) $this->data ); 
  633.  
  634. return $this->data; 
  635.  
  636. public function calculate_totals () { 
  637. /** 
  638. * @var $wpdb wpdb 
  639. */ 
  640. global $wpdb; 
  641.  
  642. // Set totals 
  643. if ( false !== $this->total_sql ) 
  644. $total = @current( $wpdb->get_col( $this->get_sql( $this->total_sql ) ) ); 
  645. else 
  646. $total = @current( $wpdb->get_col( "SELECT FOUND_ROWS()" ) ); 
  647.  
  648. $total = $this->do_hook( 'select_total', $total ); 
  649. $this->total_found = 0; 
  650. $this->total_found_calculated = true; 
  651.  
  652. if ( is_numeric( $total ) ) 
  653. $this->total_found = $total; 
  654.  
  655. /** 
  656. * Build/Rewrite dynamic SQL and handle search/filter/sort 
  657. * @param array $params 
  658. * @return bool|mixed|string 
  659. * @since 2.0 
  660. */ 
  661. public function build ( $params ) { 
  662. $simple_tableless_objects = PodsForm::simple_tableless_objects(); 
  663. $file_field_types = PodsForm::file_field_types(); 
  664.  
  665. $defaults = array( 
  666. 'select' => '*',  
  667. 'calc_rows' => false,  
  668. 'distinct' => true,  
  669. 'table' => null,  
  670. 'join' => null,  
  671. 'where' => null,  
  672. 'groupby' => null,  
  673. 'having' => null,  
  674. 'orderby' => null,  
  675. 'limit' => -1,  
  676. 'offset' => null,  
  677.  
  678. 'id' => null,  
  679. 'index' => null,  
  680.  
  681. 'page' => 1,  
  682. 'pagination' => $this->pagination,  
  683. 'search' => $this->search,  
  684. 'search_query' => null,  
  685. 'search_mode' => null,  
  686. 'search_across' => false,  
  687. 'search_across_picks' => false,  
  688. 'search_across_files' => false,  
  689. 'filters' => array(),  
  690.  
  691. 'fields' => array(),  
  692. 'object_fields' => array(),  
  693. 'pod_table_prefix' => null,  
  694.  
  695. 'traverse' => array(),  
  696.  
  697. 'sql' => null,  
  698.  
  699. 'strict' => false 
  700. ); 
  701.  
  702. $params = (object) array_merge( $defaults, (array) $params ); 
  703.  
  704. if ( 0 < strlen( $params->sql ) ) 
  705. return $params->sql; 
  706.  
  707. $pod = false; 
  708.  
  709. if ( is_array( $this->pod_data ) ) { 
  710. $pod = $this->pod_data; 
  711.  
  712. // Validate 
  713. $params->page = pods_absint( $params->page ); 
  714.  
  715. $params->pagination = (boolean) $params->pagination; 
  716.  
  717. if ( 0 == $params->page || !$params->pagination ) 
  718. $params->page = 1; 
  719.  
  720. $params->limit = (int) $params->limit; 
  721.  
  722. if ( 0 == $params->limit ) 
  723. $params->limit = -1; 
  724.  
  725. $this->limit = $params->limit; 
  726.  
  727. $offset = ( $params->limit * ( $params->page - 1 ) ); 
  728.  
  729. if ( 0 < (int) $params->offset ) 
  730. $params->offset += $offset; 
  731. else 
  732. $params->offset = $offset; 
  733.  
  734. if ( !$params->pagination || -1 == $params->limit ) { 
  735. $params->page = 1; 
  736. $params->offset = 0; 
  737.  
  738. if ( ( empty( $params->fields ) || !is_array( $params->fields ) ) && !empty( $pod ) && isset( $this->fields ) && !empty( $this->fields ) ) 
  739. $params->fields = $this->fields; 
  740.  
  741. if ( ( empty( $params->object_fields ) || !is_array( $params->object_fields ) ) && !empty( $pod ) && isset( $pod[ 'object_fields' ] ) && !empty( $pod[ 'object_fields' ] ) ) 
  742. $params->object_fields = $pod[ 'object_fields' ]; 
  743.  
  744. if ( empty( $params->filters ) && $params->search ) 
  745. $params->filters = array_keys( $params->fields ); 
  746. elseif ( empty( $params->filters ) ) 
  747. $params->filters = array(); 
  748.  
  749. if ( empty( $params->index ) ) 
  750. $params->index = $this->field_index; 
  751.  
  752. if ( empty( $params->id ) ) 
  753. $params->id = $this->field_id; 
  754.  
  755. if ( empty( $params->table ) && !empty( $pod ) && isset( $this->table ) && !empty( $this->table ) ) 
  756. $params->table = $this->table; 
  757.  
  758. if ( empty( $params->pod_table_prefix ) ) 
  759. $params->pod_table_prefix = 't'; 
  760.  
  761. if ( !empty( $pod ) && !in_array( $pod[ 'type' ], array( 'pod', 'table' ) ) && 'table' == $pod[ 'storage' ] ) 
  762. $params->pod_table_prefix = 'd'; 
  763.  
  764. $params->meta_fields = false; 
  765.  
  766. if ( !empty( $pod ) && !in_array( $pod[ 'type' ], array( 'pod', 'table' ) ) && ( 'meta' == $pod[ 'storage' ] || ( 'none' == $pod[ 'storage' ] && function_exists( 'get_term_meta' ) ) ) ) 
  767. $params->meta_fields = true; 
  768.  
  769. if ( empty( $params->table ) ) 
  770. return false; 
  771.  
  772. if ( false === strpos( $params->table, '(' ) && false === strpos( $params->table, '`' ) ) 
  773. $params->table = '`' . $params->table . '`'; 
  774.  
  775. if ( !empty( $params->join ) ) 
  776. $params->join = array_merge( (array) $this->join, (array) $params->join ); 
  777. elseif ( false === $params->strict ) 
  778. $params->join = $this->join; 
  779.  
  780. $params->where_defaulted = false; 
  781. $params->where_default = $this->where_default; 
  782.  
  783. if ( false === $params->strict ) { 
  784. // Set default where 
  785. if ( !empty( $this->where_default ) && empty( $params->where ) ) { 
  786. $params->where = array_values( (array) $this->where_default ); 
  787.  
  788. $params->where_defaulted = true; 
  789.  
  790. if ( !empty( $this->where ) ) { 
  791. if ( is_array( $params->where ) && isset( $params->where[ 'relation' ] ) && 'OR' == strtoupper( $params->where[ 'relation' ] ) ) { 
  792. $params->where = array_merge( array( $params->where ), array_values( (array) $this->where ) ); 
  793. else { 
  794. $params->where = array_merge( (array) $params->where, array_values( (array) $this->where ) ); 
  795.  
  796. // Allow where array ( 'field' => 'value' ) and WP_Query meta_query syntax 
  797. if ( ! empty( $params->where ) ) { 
  798. $params->where = $this->query_fields( (array) $params->where, $pod, $params ); 
  799.  
  800. if ( empty( $params->where ) ) { 
  801. $params->where = array(); 
  802. } else { 
  803. $params->where = (array) $params->where; 
  804.  
  805. // Allow having array ( 'field' => 'value' ) and WP_Query meta_query syntax 
  806. if ( ! empty( $params->having ) ) { 
  807. $params->having = $this->query_fields( (array) $params->having, $pod, $params ); 
  808.  
  809. if ( empty( $params->having ) ) { 
  810. $params->having = array(); 
  811. } else { 
  812. $params->having = (array) $params->having; 
  813.  
  814. if ( !empty( $params->orderby ) ) { 
  815. if ( 'post_type' == $pod[ 'type' ] && 'meta' == $pod[ 'storage' ] && is_array( $params->orderby ) ) { 
  816.  
  817. foreach ( $params->orderby as $i => $orderby ) { 
  818. if ( strpos( $orderby, '.meta_value_num' ) ) { 
  819. $params->orderby[ $i ] = 'CAST(' . str_replace( '.meta_value_num', '.meta_value', $orderby ) . ' AS DECIMAL)'; 
  820. } elseif ( strpos( $orderby, '.meta_value_date' ) ) { 
  821. $params->orderby[ $i ] = 'CAST(' . str_replace( '.meta_value_date', '.meta_value', $orderby ) . ' AS DATE)'; 
  822.  
  823.  
  824.  
  825. $params->orderby = (array) $params->orderby; 
  826. } else { 
  827. $params->orderby = array(); 
  828.  
  829.  
  830. if ( false === $params->strict && !empty( $this->orderby ) ) 
  831. $params->orderby = array_merge( $params->orderby, (array) $this->orderby ); 
  832.  
  833. if ( !empty( $params->traverse ) ) 
  834. $this->traverse = $params->traverse; 
  835.  
  836. $allowed_search_modes = array( 'int', 'text', 'text_like' ); 
  837.  
  838. if ( !empty( $params->search_mode ) && in_array( $params->search_mode, $allowed_search_modes ) ) 
  839. $this->search_mode = $params->search_mode; 
  840.  
  841. $params->search = (boolean) $params->search; 
  842.  
  843. if ( 1 == pods_v( 'pods_debug_params_all', 'get', 0 ) && pods_is_admin( array( 'pods' ) ) ) 
  844. pods_debug( $params ); 
  845.  
  846. $params->field_table_alias = 't'; 
  847.  
  848. // Get Aliases for future reference 
  849. $selectsfound = ''; 
  850.  
  851. if ( !empty( $params->select ) ) { 
  852. if ( is_array( $params->select ) ) 
  853. $selectsfound = implode( ', ', $params->select ); 
  854. else 
  855. $selectsfound = $params->select; 
  856.  
  857. // Pull Aliases from SQL query too 
  858. if ( null !== $params->sql ) { 
  859. $temp_sql = ' ' . trim( str_replace( array( "\n", "\r" ), ' ', $params->sql ) ); 
  860. $temp_sql = preg_replace( array( 
  861. '/\sSELECT\sSQL_CALC_FOUND_ROWS\s/i',  
  862. '/\sSELECT\s/i' 
  863. ),  
  864. array( 
  865. ' SELECT ',  
  866. ' SELECT SQL_CALC_FOUND_ROWS ' 
  867. ),  
  868. $temp_sql ); 
  869. preg_match( '/\sSELECT SQL_CALC_FOUND_ROWS\s(.*)\sFROM/i', $temp_sql, $selectmatches ); 
  870. if ( isset( $selectmatches[ 1 ] ) && !empty( $selectmatches[ 1 ] ) && false !== stripos( $selectmatches[ 1 ], ' AS ' ) ) 
  871. $selectsfound .= ( !empty( $selectsfound ) ? ', ' : '' ) . $selectmatches[ 1 ]; 
  872.  
  873. // Build Alias list 
  874. $this->aliases = array(); 
  875.  
  876. if ( !empty( $selectsfound ) && false !== stripos( $selectsfound, ' AS ' ) ) { 
  877. $theselects = array_filter( explode( ', ', $selectsfound ) ); 
  878.  
  879. if ( empty( $theselects ) ) 
  880. $theselects = array_filter( explode( ', ', $selectsfound ) ); 
  881.  
  882. foreach ( $theselects as $selected ) { 
  883. $selected = trim( $selected ); 
  884.  
  885. if ( strlen( $selected ) < 1 ) 
  886. continue; 
  887.  
  888. $selectfield = explode( ' AS ', str_replace( ' as ', ' AS ', $selected ) ); 
  889.  
  890. if ( 2 == count( $selectfield ) ) { 
  891. $field = trim( trim( $selectfield[ 1 ] ), '`' ); 
  892. $real_field = trim( trim( $selectfield[ 0 ] ), '`' ); 
  893. $this->aliases[ $field ] = $real_field; 
  894.  
  895. // Search 
  896. if ( !empty( $params->search ) && !empty( $params->fields ) ) { 
  897. if ( false !== $params->search_query && 0 < strlen( $params->search_query ) ) { 
  898. $where = $having = array(); 
  899.  
  900. if ( false !== $params->search_across ) { 
  901. foreach ( $params->fields as $key => $field ) { 
  902. if ( is_array( $field ) ) { 
  903. $attributes = $field; 
  904. $field = pods_v( 'name', $field, $key, true ); 
  905. else { 
  906. $attributes = array( 
  907. 'type' => '',  
  908. 'options' => array() 
  909. ); 
  910.  
  911. if ( isset( $attributes[ 'options' ][ 'search' ] ) && !$attributes[ 'options' ][ 'search' ] ) 
  912. continue; 
  913.  
  914. if ( in_array( $attributes[ 'type' ], array( 'date', 'time', 'datetime', 'number', 'decimal', 'currency', 'phone', 'password', 'boolean' ) ) ) 
  915. continue; 
  916.  
  917. $fieldfield = '`' . $field . '`'; 
  918.  
  919. if ( 'pick' == $attributes[ 'type' ] && !in_array( pods_v( 'pick_object', $attributes ), $simple_tableless_objects ) ) { 
  920. if ( false === $params->search_across_picks ) 
  921. continue; 
  922. else { 
  923. if ( empty( $attributes[ 'table_info' ] ) ) 
  924. $attributes[ 'table_info' ] = $this->api->get_table_info( pods_v( 'pick_object', $attributes ), pods_v( 'pick_val', $attributes ) ); 
  925.  
  926. if ( empty( $attributes[ 'table_info' ][ 'field_index' ] ) ) 
  927. continue; 
  928.  
  929. $fieldfield = $fieldfield . '.`' . $attributes[ 'table_info' ][ 'field_index' ] . '`'; 
  930. elseif ( in_array( $attributes[ 'type' ], $file_field_types ) ) { 
  931. if ( false === $params->search_across_files ) 
  932. continue; 
  933. else 
  934. $fieldfield = $fieldfield . '.`post_title`'; 
  935. elseif ( isset( $params->fields[ $field ] ) ) { 
  936. if ( $params->meta_fields ) 
  937. $fieldfield = $fieldfield . '.`' . $params->pod_table_prefix . '`'; 
  938. else 
  939. $fieldfield = '`' . $params->pod_table_prefix . '`.' . $fieldfield; 
  940. elseif ( !empty( $params->object_fields ) && !isset( $params->object_fields[ $field ] ) && 'meta' == $pod['storage'] ) 
  941. $fieldfield = $fieldfield . '.`meta_value`'; 
  942. else 
  943. $fieldfield = '`t`.' . $fieldfield; 
  944.  
  945. if ( isset( $this->aliases[ $field ] ) ) 
  946. $fieldfield = '`' . $this->aliases[ $field ] . '`'; 
  947.  
  948. if ( !empty( $attributes[ 'real_name' ] ) ) 
  949. $fieldfield = $attributes[ 'real_name' ]; 
  950.  
  951. if ( isset( $attributes[ 'group_related' ] ) && false !== $attributes[ 'group_related' ] ) 
  952. $having[] = "{$fieldfield} LIKE '%" . pods_sanitize_like( $params->search_query ) . "%'"; 
  953. else 
  954. $where[] = "{$fieldfield} LIKE '%" . pods_sanitize_like( $params->search_query ) . "%'"; 
  955. elseif ( !empty( $params->index ) ) { 
  956. $attributes = array(); 
  957.  
  958. $fieldfield = '`t`.`' . $params->index . '`'; 
  959.  
  960. if ( isset( $params->fields[ $params->index ] ) ) { 
  961. if ( $params->meta_fields ) 
  962. $fieldfield = '`' . $params->index . '`.`' . $params->pod_table_prefix . '`'; 
  963. else 
  964. $fieldfield = '`' . $params->pod_table_prefix . '`.`' . $params->index . '`'; 
  965. elseif ( !empty( $params->object_fields ) && !isset( $params->object_fields[ $params->index ] ) && 'meta' == $pod['storage'] ) 
  966. $fieldfield = '`' . $params->index . '`.`meta_value`'; 
  967.  
  968. if ( isset( $attributes[ 'real_name' ] ) && false !== $attributes[ 'real_name' ] && !empty( $attributes[ 'real_name' ] ) ) 
  969. $fieldfield = $attributes[ 'real_name' ]; 
  970.  
  971. if ( isset( $attributes[ 'group_related' ] ) && false !== $attributes[ 'group_related' ] ) 
  972. $having[] = "{$fieldfield} LIKE '%" . pods_sanitize_like( $params->search_query ) . "%'"; 
  973. else 
  974. $where[] = "{$fieldfield} LIKE '%" . pods_sanitize_like( $params->search_query ) . "%'"; 
  975.  
  976. if ( !empty( $where ) ) 
  977. $params->where[] = '( ' . implode( ' OR ', $where ) . ' )'; 
  978.  
  979. if ( !empty( $having ) ) 
  980. $params->having[] = '( ' . implode( ' OR ', $having ) . ' )'; 
  981.  
  982. // Filter 
  983. foreach ( $params->filters as $filter ) { 
  984. $where = $having = array(); 
  985.  
  986. if ( !isset( $params->fields[ $filter ] ) ) 
  987. continue; 
  988.  
  989. $attributes = $params->fields[ $filter ]; 
  990. $field = pods_v( 'name', $attributes, $filter, true ); 
  991.  
  992. $filterfield = '`' . $field . '`'; 
  993.  
  994. if ( 'pick' == $attributes[ 'type' ] && !in_array( pods_v( 'pick_object', $attributes ), $simple_tableless_objects ) ) { 
  995. if ( empty( $attributes[ 'table_info' ] ) ) 
  996. $attributes[ 'table_info' ] = $this->api->get_table_info( pods_v( 'pick_object', $attributes ), pods_v( 'pick_val', $attributes ) ); 
  997.  
  998. if ( empty( $attributes[ 'table_info' ][ 'field_index' ] ) ) 
  999. continue; 
  1000.  
  1001. $filterfield = $filterfield . '.`' . $attributes[ 'table_info' ][ 'field_index' ] . '`'; 
  1002. elseif ( in_array( $attributes[ 'type' ], $file_field_types ) ) 
  1003. $filterfield = $filterfield . '.`post_title`'; 
  1004. elseif ( isset( $params->fields[ $field ] ) ) { 
  1005. if ( $params->meta_fields && 'meta' == $pod['storage'] ) 
  1006. $filterfield = $filterfield . '.`meta_value`'; 
  1007. else 
  1008. $filterfield = '`' . $params->pod_table_prefix . '`.' . $filterfield; 
  1009. elseif ( !empty( $params->object_fields ) && !isset( $params->object_fields[ $field ] ) && 'meta' == $pod['storage'] ) 
  1010. $filterfield = $filterfield . '.`meta_value`'; 
  1011. else 
  1012. $filterfield = '`t`.' . $filterfield; 
  1013.  
  1014. if ( isset( $this->aliases[ $field ] ) ) 
  1015. $filterfield = '`' . $this->aliases[ $field ] . '`'; 
  1016.  
  1017. if ( !empty( $attributes[ 'real_name' ] ) ) 
  1018. $filterfield = $attributes[ 'real_name' ]; 
  1019.  
  1020. if ( 'pick' == $attributes[ 'type' ] ) { 
  1021. $filter_value = pods_v( 'filter_' . $field, 'get' ); 
  1022.  
  1023. if ( !is_array( $filter_value ) ) 
  1024. $filter_value = (array) $filter_value; 
  1025.  
  1026. foreach ( $filter_value as $filter_v ) { 
  1027. if ( in_array( pods_v( 'pick_object', $attributes ), $simple_tableless_objects ) ) { 
  1028. if ( strlen( $filter_v ) < 1 ) 
  1029. continue; 
  1030.  
  1031. if ( isset( $attributes[ 'group_related' ] ) && false !== $attributes[ 'group_related' ] ) { 
  1032. $having[] = "( {$filterfield} = '" . pods_sanitize( $filter_v ) . "'" 
  1033. . " OR {$filterfield} LIKE '%\"" . pods_sanitize_like( $filter_v ) . "\"%' )"; 
  1034. else { 
  1035. $where[] = "( {$filterfield} = '" . pods_sanitize( $filter_v ) . "'" 
  1036. . " OR {$filterfield} LIKE '%\"" . pods_sanitize_like( $filter_v ) . "\"%' )"; 
  1037. else { 
  1038. $filter_v = (int) $filter_v; 
  1039.  
  1040. if ( empty( $filter_v ) || empty( $attributes[ 'table_info' ] ) || empty( $attributes[ 'table_info' ][ 'field_id' ] ) ) 
  1041. continue; 
  1042.  
  1043. $filterfield = '`' . $field . '`.`' . $attributes[ 'table_info' ][ 'field_id' ] . '`'; 
  1044.  
  1045. if ( isset( $attributes[ 'group_related' ] ) && false !== $attributes[ 'group_related' ] ) 
  1046. $having[] = "{$filterfield} = " . $filter_v; 
  1047. else 
  1048. $where[] = "{$filterfield} = " . $filter_v; 
  1049. elseif ( in_array( $attributes[ 'type' ], array( 'date', 'datetime' ) ) ) { 
  1050. $start_value = pods_v( 'filter_' . $field . '_start', 'get', false ); 
  1051. $end_value = pods_v( 'filter_' . $field . '_end', 'get', false ); 
  1052.  
  1053. if ( empty( $start_value ) && empty( $end_value ) ) 
  1054. continue; 
  1055.  
  1056. if ( !empty( $start_value ) ) 
  1057. $start = date_i18n( 'Y-m-d', strtotime( $start_value ) ) . ( 'datetime' == $attributes[ 'type' ] ? ' 00:00:00' : '' ); 
  1058. else 
  1059. $start = date_i18n( 'Y-m-d' ) . ( 'datetime' == $attributes[ 'type' ] ) ? ' 00:00:00' : ''; 
  1060.  
  1061. if ( !empty( $end_value ) ) 
  1062. $end = date_i18n( 'Y-m-d', strtotime( $end_value ) ) . ( 'datetime' == $attributes[ 'type' ] ? ' 23:59:59' : '' ); 
  1063. else 
  1064. $end = date_i18n( 'Y-m-d' ) . ( 'datetime' == $attributes[ 'type' ] ) ? ' 23:59:59' : ''; 
  1065.  
  1066. if ( isset( $attributes[ 'date_ongoing' ] ) && true === $attributes[ 'date_ongoing' ] ) { 
  1067. $date_ongoing = '`' . $attributes[ 'date_ongoing' ] . '`'; 
  1068.  
  1069. if ( isset( $this->aliases[ $date_ongoing ] ) ) 
  1070. $date_ongoing = '`' . $this->aliases[ $date_ongoing ] . '`'; 
  1071.  
  1072. if ( isset( $attributes[ 'group_related' ] ) && false !== $attributes[ 'group_related' ] ) 
  1073. $having[] = "(({$filterfield} <= '$start' OR ({$filterfield} >= '$start' AND {$filterfield} <= '$end')) AND ({$date_ongoing} >= '$start' OR ({$date_ongoing} >= '$start' AND {$date_ongoing} <= '$end')))"; 
  1074. else 
  1075. $where[] = "(({$filterfield} <= '$start' OR ({$filterfield} >= '$start' AND {$filterfield} <= '$end')) AND ({$date_ongoing} >= '$start' OR ({$date_ongoing} >= '$start' AND {$date_ongoing} <= '$end')))"; 
  1076. else { 
  1077. if ( isset( $attributes[ 'group_related' ] ) && false !== $attributes[ 'group_related' ] ) 
  1078. $having[] = "({$filterfield} BETWEEN '$start' AND '$end')"; 
  1079. else 
  1080. $where[] = "({$filterfield} BETWEEN '$start' AND '$end')"; 
  1081. else { 
  1082. $filter_value = pods_v( 'filter_' . $field, 'get', '' ); 
  1083.  
  1084. if ( strlen( $filter_value ) < 1 ) 
  1085. continue; 
  1086.  
  1087. if ( isset( $attributes[ 'group_related' ] ) && false !== $attributes[ 'group_related' ] ) 
  1088. $having[] = "{$filterfield} LIKE '%" . pods_sanitize_like( $filter_value ) . "%'"; 
  1089. else 
  1090. $where[] = "{$filterfield} LIKE '%" . pods_sanitize_like( $filter_value ) . "%'"; 
  1091.  
  1092. if ( !empty( $where ) ) 
  1093. $params->where[] = implode( ' AND ', $where ); 
  1094.  
  1095. if ( !empty( $having ) ) 
  1096. $params->having[] = implode( ' AND ', $having ); 
  1097.  
  1098. // Traverse the Rabbit Hole 
  1099. if ( !empty( $this->pod ) ) { 
  1100. $haystack = implode( ' ', (array) $params->select ) 
  1101. . ' ' . implode( ' ', (array) $params->where ) 
  1102. . ' ' . implode( ' ', (array) $params->groupby ) 
  1103. . ' ' . implode( ' ', (array) $params->having ) 
  1104. . ' ' . implode( ' ', (array) $params->orderby ); 
  1105. $haystack = preg_replace( '/\s/', ' ', $haystack ); 
  1106. $haystack = preg_replace( '/\w\(/', ' ', $haystack ); 
  1107. $haystack = str_replace( array( '(', ')', ' ', '\\\'', "\\\"" ), ' ', $haystack ); 
  1108.  
  1109. preg_match_all( '/`?[\w\-]+`?(?:\\.`?[\w\-]+`?)+(?=[^"\']*(?:"[^"]*"[^"]*|\'[^\']*\'[^\']*)*$)/', $haystack, $found, PREG_PATTERN_ORDER ); 
  1110.  
  1111. $found = (array) @current( $found ); 
  1112. $find = $replace = $traverse = array(); 
  1113.  
  1114. foreach ( $found as $key => $value ) { 
  1115. $value = str_replace( '`', '', $value ); 
  1116. $value = explode( '.', $value ); 
  1117. $dot = $last_value = array_pop( $value ); 
  1118.  
  1119. if ( 't' == $value[ 0 ] ) 
  1120. continue; 
  1121. elseif ( array_key_exists( $value[ 0 ], $params->join ) ) 
  1122. // Don't traverse for tables we are already going to join 
  1123. continue; 
  1124. elseif ( 1 == count( $value ) && '' == preg_replace( '/[0-9]*/', '', $value[ 0 ] ) && '' == preg_replace( '/[0-9]*/', '', $last_value ) ) 
  1125. continue; 
  1126.  
  1127. $found_value = str_replace( '`', '', $found[ $key ] ); 
  1128. $found_value = '([`]{1}|\b)' . str_replace( '.', '[`]*\.[`]*', $found_value ) . '([`]{1}|\b)'; 
  1129. $found_value = '/' . $found_value . '(?=[^"\']*(?:"[^"]*"[^"]*|\'[^\']*\'[^\']*)*$)/'; 
  1130.  
  1131. if ( in_array( $found_value, $find ) ) { 
  1132. continue; 
  1133.  
  1134. $find[ $key ] = $found_value; 
  1135.  
  1136. if ( '*' != $dot ) 
  1137. $dot = '`' . $dot . '`'; 
  1138.  
  1139. $replace[ $key ] = '`' . implode( '_', $value ) . '`.' . $dot; 
  1140.  
  1141. $value[] = $last_value; 
  1142.  
  1143. if ( !in_array( $value, $traverse ) ) 
  1144. $traverse[ $key ] = $value; 
  1145.  
  1146. if ( !empty( $this->traverse ) ) { 
  1147. foreach ( (array) $this->traverse as $key => $traverse ) { 
  1148. $traverse = str_replace( '`', '', $traverse ); 
  1149. $already_found = false; 
  1150.  
  1151. foreach ( $traverse as $traversal ) { 
  1152. if ( is_array( $traversal ) ) 
  1153. $traversal = implode( '.', $traversal ); 
  1154.  
  1155. if ( $traversal == $traverse ) { 
  1156. $already_found = true; 
  1157. break; 
  1158.  
  1159. if ( !$already_found ) 
  1160. $traverse[ 'traverse_' . $key ] = explode( '.', $traverse ); 
  1161.  
  1162. $joins = array(); 
  1163.  
  1164. if ( !empty( $find ) ) { 
  1165. // See: "#3294 OrderBy Failing on PHP7" Non-zero array keys 
  1166. // here in PHP 7 cause odd behavior so just strip the keys 
  1167. $find = array_values( $find ); 
  1168. $replace = array_values( $replace ); 
  1169.  
  1170. $params->select = preg_replace( $find, $replace, $params->select ); 
  1171. $params->where = preg_replace( $find, $replace, $params->where ); 
  1172. $params->groupby = preg_replace( $find, $replace, $params->groupby ); 
  1173. $params->having = preg_replace( $find, $replace, $params->having ); 
  1174. $params->orderby = preg_replace( $find, $replace, $params->orderby ); 
  1175.  
  1176. if ( !empty( $traverse ) ) 
  1177. $joins = $this->traverse( $traverse, $params->fields, $params ); 
  1178. elseif ( false !== $params->search ) 
  1179. $joins = $this->traverse( null, $params->fields, $params ); 
  1180.  
  1181. // Traversal Search 
  1182. if ( !empty( $params->search ) && !empty( $this->search_where ) ) 
  1183. $params->where = array_merge( (array) $this->search_where, $params->where ); 
  1184.  
  1185. if ( !empty( $params->join ) && !empty( $joins ) ) 
  1186. $params->join = array_merge( $joins, (array) $params->join ); 
  1187. elseif ( !empty( $joins ) ) 
  1188. $params->join = $joins; 
  1189.  
  1190. // Build 
  1191. if ( null === $params->sql ) { 
  1192. $sql = " 
  1193. SELECT 
  1194. " . ( $params->calc_rows ? 'SQL_CALC_FOUND_ROWS' : '' ) . " 
  1195. " . ( $params->distinct ? 'DISTINCT' : '' ) . " 
  1196. " . ( !empty( $params->select ) ? ( is_array( $params->select ) ? implode( ', ', $params->select ) : $params->select ) : '*' ) . " 
  1197. FROM {$params->table} AS `t` 
  1198. " . ( !empty( $params->join ) ? ( is_array( $params->join ) ? implode( "\n ", $params->join ) : $params->join ) : '' ) . " 
  1199. " . ( !empty( $params->where ) ? 'WHERE ' . ( is_array( $params->where ) ? implode( ' AND ', $params->where ) : $params->where ) : '' ) . " 
  1200. " . ( !empty( $params->groupby ) ? 'GROUP BY ' . ( is_array( $params->groupby ) ? implode( ', ', $params->groupby ) : $params->groupby ) : '' ) . " 
  1201. " . ( !empty( $params->having ) ? 'HAVING ' . ( is_array( $params->having ) ? implode( ' AND ', $params->having ) : $params->having ) : '' ) . " 
  1202. " . ( !empty( $params->orderby ) ? 'ORDER BY ' . ( is_array( $params->orderby ) ? implode( ', ', $params->orderby ) : $params->orderby ) : '' ) . " 
  1203. " . ( ( 0 < $params->page && 0 < $params->limit ) ? 'LIMIT ' . $params->offset . ', ' . ( $params->limit ) : '' ) . " 
  1204. "; 
  1205.  
  1206. if ( !$params->calc_rows ) { 
  1207. // Handle COUNT() SELECT 
  1208. $total_sql_select = "COUNT( " . ( $params->distinct ? 'DISTINCT `t`.`' . $params->id . '`' : '*' ) . " )"; 
  1209.  
  1210. // If 'having' is set, we have to select all so it has access to anything it needs 
  1211. if ( ! empty( $params->having ) ) { 
  1212. $total_sql_select .= ', ' . ( !empty( $params->select ) ? ( is_array( $params->select ) ? implode( ', ', $params->select ) : $params->select ) : '*' ); 
  1213.  
  1214. $this->total_sql = " 
  1215. SELECT {$total_sql_select} 
  1216. FROM {$params->table} AS `t` 
  1217. " . ( !empty( $params->join ) ? ( is_array( $params->join ) ? implode( "\n ", $params->join ) : $params->join ) : '' ) . " 
  1218. " . ( !empty( $params->where ) ? 'WHERE ' . ( is_array( $params->where ) ? implode( ' AND ', $params->where ) : $params->where ) : '' ) . " 
  1219. " . ( !empty( $params->groupby ) ? 'GROUP BY ' . ( is_array( $params->groupby ) ? implode( ', ', $params->groupby ) : $params->groupby ) : '' ) . " 
  1220. " . ( !empty( $params->having ) ? 'HAVING ' . ( is_array( $params->having ) ? implode( ' AND ', $params->having ) : $params->having ) : '' ) . " 
  1221. "; 
  1222. // Rewrite 
  1223. else { 
  1224. $sql = ' ' . trim( str_replace( array( "\n", "\r" ), ' ', $params->sql ) ); 
  1225. $sql = preg_replace( array( 
  1226. '/\sSELECT\sSQL_CALC_FOUND_ROWS\s/i',  
  1227. '/\sSELECT\s/i' 
  1228. ),  
  1229. array( 
  1230. ' SELECT ',  
  1231. ' SELECT SQL_CALC_FOUND_ROWS ' 
  1232. ),  
  1233. $sql ); 
  1234.  
  1235. // Insert variables based on existing statements 
  1236. if ( false === stripos( $sql, '%%SELECT%%' ) ) 
  1237. $sql = preg_replace( '/\sSELECT\sSQL_CALC_FOUND_ROWS\s/i', ' SELECT SQL_CALC_FOUND_ROWS %%SELECT%% ', $sql ); 
  1238. if ( false === stripos( $sql, '%%WHERE%%' ) ) 
  1239. $sql = preg_replace( '/\sWHERE\s(?!.*\sWHERE\s)/i', ' WHERE %%WHERE%% ', $sql ); 
  1240. if ( false === stripos( $sql, '%%GROUPBY%%' ) ) 
  1241. $sql = preg_replace( '/\sGROUP BY\s(?!.*\sGROUP BY\s)/i', ' GROUP BY %%GROUPBY%% ', $sql ); 
  1242. if ( false === stripos( $sql, '%%HAVING%%' ) ) 
  1243. $sql = preg_replace( '/\sHAVING\s(?!.*\sHAVING\s)/i', ' HAVING %%HAVING%% ', $sql ); 
  1244. if ( false === stripos( $sql, '%%ORDERBY%%' ) ) 
  1245. $sql = preg_replace( '/\sORDER BY\s(?!.*\sORDER BY\s)/i', ' ORDER BY %%ORDERBY%% ', $sql ); 
  1246.  
  1247. // Insert variables based on other existing statements 
  1248. if ( false === stripos( $sql, '%%JOIN%%' ) ) { 
  1249. if ( false !== stripos( $sql, ' WHERE ' ) ) 
  1250. $sql = preg_replace( '/\sWHERE\s(?!.*\sWHERE\s)/i', ' %%JOIN%% WHERE ', $sql ); 
  1251. elseif ( false !== stripos( $sql, ' GROUP BY ' ) ) 
  1252. $sql = preg_replace( '/\sGROUP BY\s(?!.*\sGROUP BY\s)/i', ' %%WHERE%% GROUP BY ', $sql ); 
  1253. elseif ( false !== stripos( $sql, ' ORDER BY ' ) ) 
  1254. $sql = preg_replace( '/\ORDER BY\s(?!.*\ORDER BY\s)/i', ' %%WHERE%% ORDER BY ', $sql ); 
  1255. else 
  1256. $sql .= ' %%JOIN%% '; 
  1257. if ( false === stripos( $sql, '%%WHERE%%' ) ) { 
  1258. if ( false !== stripos( $sql, ' GROUP BY ' ) ) 
  1259. $sql = preg_replace( '/\sGROUP BY\s(?!.*\sGROUP BY\s)/i', ' %%WHERE%% GROUP BY ', $sql ); 
  1260. elseif ( false !== stripos( $sql, ' ORDER BY ' ) ) 
  1261. $sql = preg_replace( '/\ORDER BY\s(?!.*\ORDER BY\s)/i', ' %%WHERE%% ORDER BY ', $sql ); 
  1262. else 
  1263. $sql .= ' %%WHERE%% '; 
  1264. if ( false === stripos( $sql, '%%GROUPBY%%' ) ) { 
  1265. if ( false !== stripos( $sql, ' HAVING ' ) ) 
  1266. $sql = preg_replace( '/\sHAVING\s(?!.*\sHAVING\s)/i', ' %%GROUPBY%% HAVING ', $sql ); 
  1267. elseif ( false !== stripos( $sql, ' ORDER BY ' ) ) 
  1268. $sql = preg_replace( '/\ORDER BY\s(?!.*\ORDER BY\s)/i', ' %%GROUPBY%% ORDER BY ', $sql ); 
  1269. else 
  1270. $sql .= ' %%GROUPBY%% '; 
  1271. if ( false === stripos( $sql, '%%HAVING%%' ) ) { 
  1272. if ( false !== stripos( $sql, ' ORDER BY ' ) ) 
  1273. $sql = preg_replace( '/\ORDER BY\s(?!.*\ORDER BY\s)/i', ' %%HAVING%% ORDER BY ', $sql ); 
  1274. else 
  1275. $sql .= ' %%HAVING%% '; 
  1276. if ( false === stripos( $sql, '%%ORDERBY%%' ) ) 
  1277. $sql .= ' %%ORDERBY%% '; 
  1278. if ( false === stripos( $sql, '%%LIMIT%%' ) ) 
  1279. $sql .= ' %%LIMIT%% '; 
  1280.  
  1281. // Replace variables 
  1282. if ( 0 < strlen( $params->select ) ) { 
  1283. if ( false === stripos( $sql, '%%SELECT%% FROM ' ) ) 
  1284. $sql = str_ireplace( '%%SELECT%%', $params->select . ', ', $sql ); 
  1285. else 
  1286. $sql = str_ireplace( '%%SELECT%%', $params->select, $sql ); 
  1287. if ( 0 < strlen( $params->join ) ) 
  1288. $sql = str_ireplace( '%%JOIN%%', $params->join, $sql ); 
  1289. if ( 0 < strlen( $params->where ) ) { 
  1290. if ( false !== stripos( $sql, ' WHERE ' ) ) { 
  1291. if ( false !== stripos( $sql, ' WHERE %%WHERE%% ' ) ) 
  1292. $sql = str_ireplace( '%%WHERE%%', $params->where . ' AND ', $sql ); 
  1293. else 
  1294. $sql = str_ireplace( '%%WHERE%%', ' AND ' . $params->where, $sql ); 
  1295. else 
  1296. $sql = str_ireplace( '%%WHERE%%', ' WHERE ' . $params->where, $sql ); 
  1297. if ( 0 < strlen( $params->groupby ) ) { 
  1298. if ( false !== stripos( $sql, ' GROUP BY ' ) ) { 
  1299. if ( false !== stripos( $sql, ' GROUP BY %%GROUPBY%% ' ) ) 
  1300. $sql = str_ireplace( '%%GROUPBY%%', $params->groupby . ', ', $sql ); 
  1301. else 
  1302. $sql = str_ireplace( '%%GROUPBY%%', ', ' . $params->groupby, $sql ); 
  1303. else 
  1304. $sql = str_ireplace( '%%GROUPBY%%', ' GROUP BY ' . $params->groupby, $sql ); 
  1305. if ( 0 < strlen( $params->having ) && false !== stripos( $sql, ' GROUP BY ' ) ) { 
  1306. if ( false !== stripos( $sql, ' HAVING ' ) ) { 
  1307. if ( false !== stripos( $sql, ' HAVING %%HAVING%% ' ) ) 
  1308. $sql = str_ireplace( '%%HAVING%%', $params->having . ' AND ', $sql ); 
  1309. else 
  1310. $sql = str_ireplace( '%%HAVING%%', ' AND ' . $params->having, $sql ); 
  1311. else 
  1312. $sql = str_ireplace( '%%HAVING%%', ' HAVING ' . $params->having, $sql ); 
  1313. if ( 0 < strlen( $params->orderby ) ) { 
  1314. if ( false !== stripos( $sql, ' ORDER BY ' ) ) { 
  1315. if ( false !== stripos( $sql, ' ORDER BY %%ORDERBY%% ' ) ) 
  1316. $sql = str_ireplace( '%%ORDERBY%%', $params->groupby . ', ', $sql ); 
  1317. else 
  1318. $sql = str_ireplace( '%%ORDERBY%%', ', ' . $params->groupby, $sql ); 
  1319. else 
  1320. $sql = str_ireplace( '%%ORDERBY%%', ' ORDER BY ' . $params->groupby, $sql ); 
  1321. if ( 0 < $params->page && 0 < $params->limit ) { 
  1322. $start = ( $params->page - 1 ) * $params->limit; 
  1323. $end = $start + $params->limit; 
  1324. $sql .= 'LIMIT ' . (int) $start . ', ' . (int) $end; 
  1325.  
  1326. // Clear any unused variables 
  1327. $sql = str_ireplace( array( 
  1328. '%%SELECT%%',  
  1329. '%%JOIN%%',  
  1330. '%%WHERE%%',  
  1331. '%%GROUPBY%%',  
  1332. '%%HAVING%%',  
  1333. '%%ORDERBY%%',  
  1334. '%%LIMIT%%' 
  1335. ), '', $sql ); 
  1336. $sql = str_replace( array( '``', '`' ), array( ' ', ' ' ), $sql ); 
  1337.  
  1338. return $sql; 
  1339.  
  1340. /** 
  1341. * Fetch the total row count returned 
  1342. * @return int Number of rows returned by select() 
  1343. * @since 2.0 
  1344. */ 
  1345. public function total () { 
  1346. return (int) $this->total; 
  1347.  
  1348. /** 
  1349. * Fetch the total row count total 
  1350. * @return int Number of rows found by select() 
  1351. * @since 2.0 
  1352. */ 
  1353. public function total_found () { 
  1354. if(false === $this->total_found_calculated) 
  1355. $this->calculate_totals(); 
  1356.  
  1357. return (int) $this->total_found; 
  1358.  
  1359. /** 
  1360. * Fetch the zebra state 
  1361. * @return bool Zebra state 
  1362. * @since 1.12 
  1363. * @see PodsData::nth 
  1364. */ 
  1365. public function zebra () { 
  1366. return $this->nth( 'odd' ); // Odd numbers 
  1367.  
  1368. /** 
  1369. * Fetch the nth state 
  1370. * @param int|string $nth The $nth to match on the PodsData::row_number 
  1371. * @return bool Whether $nth matches 
  1372. * @since 2.3 
  1373. */ 
  1374. public function nth ( $nth ) { 
  1375. if ( empty( $nth ) ) 
  1376. $nth = 2; 
  1377.  
  1378. $offset = 0; 
  1379. $negative = false; 
  1380.  
  1381. if ( 'even' == $nth ) 
  1382. $nth = 2; 
  1383. elseif ( 'odd' == $nth ) { 
  1384. $negative = true; 
  1385. $nth = 2; 
  1386. elseif ( false !== strpos( $nth, '+' ) ) { 
  1387. $nth = explode( '+', $nth ); 
  1388.  
  1389. if ( isset( $nth[ 1 ] ) ) 
  1390. $offset += (int) trim( $nth[ 1 ] ); 
  1391.  
  1392. $nth = (int) trim( $nth[ 0 ], ' n' ); 
  1393. elseif ( false !== strpos( $nth, '-' ) ) { 
  1394. $nth = explode( '-', $nth ); 
  1395.  
  1396. if ( isset( $nth[ 1 ] ) ) 
  1397. $offset -= (int) trim( $nth[ 1 ] ); 
  1398.  
  1399. $nth = (int) trim( $nth[ 0 ], ' n' ); 
  1400.  
  1401. $nth = (int) $nth; 
  1402. $offset = (int) $offset; 
  1403.  
  1404. if ( 0 == ( ( $this->row_number % $nth ) + $offset ) ) 
  1405. return ( $negative ? false: true ); 
  1406.  
  1407. return ( $negative ? true : false ); 
  1408.  
  1409. /** 
  1410. * Fetch the current position in the loop (starting at 1) 
  1411. * @return int Current row number (+1) 
  1412. * @since 2.3 
  1413. */ 
  1414. public function position () { 
  1415. return $this->row_number + 1; 
  1416.  
  1417. /** 
  1418. * Create a Table 
  1419. * @param string $table Table name 
  1420. * @param string $fields 
  1421. * @param boolean $if_not_exists Check if the table exists. 
  1422. * @return array|bool|mixed|null|void 
  1423. * @uses PodsData::query 
  1424. * @since 2.0 
  1425. */ 
  1426. public static function table_create ( $table, $fields, $if_not_exists = false ) { 
  1427. /** 
  1428. * @var $wpdb wpdb 
  1429. */ 
  1430. global $wpdb; 
  1431.  
  1432. $sql = "CREATE TABLE"; 
  1433.  
  1434. if ( true === $if_not_exists ) 
  1435. $sql .= " IF NOT EXISTS"; 
  1436.  
  1437. $sql .= " `{$wpdb->prefix}" . self::$prefix . "{$table}` ({$fields})"; 
  1438.  
  1439. if ( !empty( $wpdb->charset ) ) 
  1440. $sql .= " DEFAULT CHARACTER SET {$wpdb->charset}"; 
  1441.  
  1442. if ( !empty( $wpdb->collate ) ) 
  1443. $sql .= " COLLATE {$wpdb->collate}"; 
  1444.  
  1445. return self::query( $sql ); 
  1446.  
  1447. /** 
  1448. * Alter a Table 
  1449. * @param string $table Table name 
  1450. * @param string $changes 
  1451. * @return array|bool|mixed|null|void 
  1452. * @uses PodsData::query 
  1453. * @since 2.0 
  1454. */ 
  1455. public static function table_alter ( $table, $changes ) { 
  1456. /** 
  1457. * @var $wpdb wpdb 
  1458. */ 
  1459. global $wpdb; 
  1460.  
  1461. $sql = "ALTER TABLE `{$wpdb->prefix}" . self::$prefix . "{$table}` {$changes}"; 
  1462.  
  1463. return self::query( $sql ); 
  1464.  
  1465. /** 
  1466. * Truncate a Table 
  1467. * @param string $table Table name 
  1468. * @return array|bool|mixed|null|void 
  1469. * @uses PodsData::query 
  1470. * @since 2.0 
  1471. */ 
  1472. public static function table_truncate ( $table ) { 
  1473. /** 
  1474. * @var $wpdb wpdb 
  1475. */ 
  1476. global $wpdb; 
  1477.  
  1478. $sql = "TRUNCATE TABLE `{$wpdb->prefix}" . self::$prefix . "{$table}`"; 
  1479.  
  1480. return self::query( $sql ); 
  1481.  
  1482. /** 
  1483. * Drop a Table 
  1484. * @param string $table Table name 
  1485. * @uses PodsData::query 
  1486. * @return array|bool|mixed|null|void 
  1487. * @uses PodsData::query 
  1488. * @since 2.0 
  1489. */ 
  1490. public static function table_drop ( $table ) { 
  1491. /** 
  1492. * @var $wpdb wpdb 
  1493. */ 
  1494. global $wpdb; 
  1495.  
  1496. $sql = "DROP TABLE `{$wpdb->prefix}" . self::$prefix . "{$table}`"; 
  1497.  
  1498. return self::query( $sql ); 
  1499.  
  1500. /** 
  1501. * Reorder Items 
  1502. * @param string $table Table name 
  1503. * @param string $weight_field 
  1504. * @param string $id_field 
  1505. * @param array $ids 
  1506. * @return bool 
  1507. * @uses PodsData::update 
  1508. * @since 2.0 
  1509. */ 
  1510. public function reorder ( $table, $weight_field, $id_field, $ids ) { 
  1511. $success = false; 
  1512. $ids = (array) $ids; 
  1513.  
  1514. list( $table, $weight_field, $id_field, $ids ) = $this->do_hook( 'reorder', array( 
  1515. $table,  
  1516. $weight_field,  
  1517. $id_field,  
  1518. $ids 
  1519. ) ); 
  1520.  
  1521. if ( !empty( $ids ) ) { 
  1522. $success = true; 
  1523.  
  1524. foreach ( $ids as $weight => $id ) { 
  1525. $updated = $this->update( $table, array( $weight_field => $weight ), array( $id_field => $id ), array( '%d' ), array( '%d' ) ); 
  1526.  
  1527. if ( false === $updated ) 
  1528. $success = false; 
  1529.  
  1530. return $success; 
  1531.  
  1532. /** 
  1533. * Fetch a new row for the current pod_data 
  1534. * @param int $row Row number to fetch 
  1535. * @param bool $explicit_set Whether to set explicitly (use false when in loop) 
  1536. * @return mixed 
  1537. * @since 2.0 
  1538. */ 
  1539. public function fetch ( $row = null, $explicit_set = true ) { 
  1540. global $wpdb; 
  1541.  
  1542. if ( null === $row ) 
  1543. $explicit_set = false; 
  1544.  
  1545. $already_cached = false; 
  1546. $id = $row; 
  1547.  
  1548. $tableless_field_types = PodsForm::tableless_field_types(); 
  1549.  
  1550. if ( null === $row ) { 
  1551. $this->row_number++; 
  1552.  
  1553. $this->row = false; 
  1554.  
  1555. if ( isset( $this->data[ $this->row_number ] ) ) { 
  1556. $this->row = get_object_vars( $this->data[ $this->row_number ] ); 
  1557.  
  1558. $current_row_id = false; 
  1559.  
  1560. if ( in_array( $this->pod_data[ 'type' ], array( 'post_type', 'media' ) ) ) 
  1561. $current_row_id = pods_var_raw( 'ID', $this->row ); 
  1562. elseif ( 'taxonomy' == $this->pod_data[ 'type' ] ) 
  1563. $current_row_id = pods_var_raw( 'term_id', $this->row ); 
  1564. elseif ( 'user' == $this->pod_data[ 'type' ] ) 
  1565. $current_row_id = pods_var_raw( 'ID', $this->row ); 
  1566. elseif ( 'comment' == $this->pod_data[ 'type' ] ) 
  1567. $current_row_id = pods_var_raw( 'comment_ID', $this->row ); 
  1568. elseif ( 'settings' == $this->pod_data[ 'type' ] ) 
  1569. $current_row_id = $this->pod_data[ 'id' ]; 
  1570.  
  1571. if ( 0 < $current_row_id ) 
  1572. $row = $current_row_id; 
  1573.  
  1574. if ( null !== $row || 'settings' == $this->pod_data[ 'type' ] ) { 
  1575. if ( $explicit_set ) 
  1576. $this->row_number = -1; 
  1577.  
  1578. $mode = 'id'; 
  1579. $id = pods_absint( $row ); 
  1580.  
  1581. if ( !is_numeric( $row ) || 0 === strpos( $row, '0' ) || $row != preg_replace( '/[^0-9]/', '', $row ) ) { 
  1582. $mode = 'slug'; 
  1583. $id = $row; 
  1584.  
  1585. $row = false; 
  1586.  
  1587. if ( !empty( $this->pod ) ) { 
  1588. $row = pods_cache_get( $id, 'pods_items_' . $this->pod ); 
  1589. if ( false !== $row ) { 
  1590. $already_cached = true; 
  1591.  
  1592. $current_row_id = false; 
  1593. $get_table_data = false; 
  1594.  
  1595. $old_row = $this->row; 
  1596.  
  1597. if ( false !== $row && is_array( $row ) ) 
  1598. $this->row = $row; 
  1599. elseif ( in_array( $this->pod_data[ 'type' ], array( 'post_type', 'media' ) ) ) { 
  1600. if ( 'post_type' == $this->pod_data[ 'type' ] ) { 
  1601. if ( empty( $this->pod_data[ 'object' ] ) ) { 
  1602. $post_type = $this->pod_data[ 'name' ]; 
  1603. else { 
  1604. $post_type = $this->pod_data[ 'object' ]; 
  1605. else 
  1606. $post_type = 'attachment'; 
  1607.  
  1608. if ( 'id' == $mode ) { 
  1609. $this->row = get_post( $id, ARRAY_A ); 
  1610.  
  1611. if ( is_array( $this->row ) && $this->row[ 'post_type' ] != $post_type ) 
  1612. $this->row = false; 
  1613. else { 
  1614. $args = array( 
  1615. 'post_type' => $post_type,  
  1616. 'name' => $id,  
  1617. 'numberposts' => 5 
  1618. ); 
  1619.  
  1620. $find = get_posts( $args ); 
  1621.  
  1622. if ( !empty( $find ) ) 
  1623. $this->row = get_object_vars( $find[ 0 ] ); 
  1624.  
  1625. if ( is_wp_error( $this->row ) || empty( $this->row ) ) 
  1626. $this->row = false; 
  1627. else 
  1628. $current_row_id = $this->row[ 'ID' ]; 
  1629.  
  1630. $get_table_data = true; 
  1631. elseif ( 'taxonomy' == $this->pod_data[ 'type' ] ) { 
  1632. $taxonomy = $this->pod_data[ 'object' ]; 
  1633.  
  1634. if ( empty( $taxonomy ) ) 
  1635. $taxonomy = $this->pod_data[ 'name' ]; 
  1636.  
  1637. // Taxonomies are registered during init, so they aren't available before then 
  1638. if ( !did_action( 'init' ) ) { 
  1639. // hackaround :( 
  1640. if ( 'id' == $mode ) 
  1641. $term_where = 't.term_id = %d'; 
  1642. else 
  1643. $term_where = 't.slug = %s'; 
  1644.  
  1645. $filter = 'raw'; 
  1646. $term = $id; 
  1647.  
  1648. if ( 'id' != $mode || !$_term = wp_cache_get( $term, $taxonomy ) ) { 
  1649. $_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND {$term_where} LIMIT 1", $taxonomy, $term ) ); 
  1650.  
  1651. if ( $_term ) 
  1652. wp_cache_add( $term, $_term, $taxonomy ); 
  1653.  
  1654. $_term = apply_filters( 'get_term', $_term, $taxonomy ); 
  1655. $_term = apply_filters( "get_$taxonomy", $_term, $taxonomy ); 
  1656. $_term = sanitize_term( $_term, $taxonomy, $filter ); 
  1657.  
  1658. if ( is_object( $_term ) ) 
  1659. $this->row = get_object_vars( $_term ); 
  1660. elseif ( 'id' == $mode ) 
  1661. $this->row = get_term( $id, $taxonomy, ARRAY_A ); 
  1662. else 
  1663. $this->row = get_term_by( 'slug', $id, $taxonomy, ARRAY_A ); 
  1664.  
  1665. if ( is_wp_error( $this->row ) || empty( $this->row ) ) 
  1666. $this->row = false; 
  1667. else 
  1668. $current_row_id = $this->row[ 'term_id' ]; 
  1669.  
  1670. $get_table_data = true; 
  1671. elseif ( 'user' == $this->pod_data[ 'type' ] ) { 
  1672. if ( 'id' == $mode ) 
  1673. $this->row = get_userdata( $id ); 
  1674. else 
  1675. $this->row = get_user_by( 'slug', $id ); 
  1676.  
  1677. if ( is_wp_error( $this->row ) || empty( $this->row ) ) 
  1678. $this->row = false; 
  1679. else { 
  1680. // Get other vars 
  1681. $roles = $this->row->roles; 
  1682. $caps = $this->row->caps; 
  1683. $allcaps = $this->row->allcaps; 
  1684.  
  1685. $this->row = get_object_vars( $this->row->data ); 
  1686.  
  1687. // Set other vars 
  1688. $this->row[ 'roles' ] = $roles; 
  1689. $this->row[ 'caps' ] = $caps; 
  1690. $this->row[ 'allcaps' ] = $allcaps; 
  1691.  
  1692. unset( $this->row[ 'user_pass' ] ); 
  1693.  
  1694. $current_row_id = $this->row[ 'ID' ]; 
  1695.  
  1696. $get_table_data = true; 
  1697. elseif ( 'comment' == $this->pod_data[ 'type' ] ) { 
  1698. $this->row = get_comment( $id, ARRAY_A ); 
  1699.  
  1700. // No slug handling here 
  1701.  
  1702. if ( is_wp_error( $this->row ) || empty( $this->row ) ) 
  1703. $this->row = false; 
  1704. else 
  1705. $current_row_id = $this->row[ 'comment_ID' ]; 
  1706.  
  1707. $get_table_data = true; 
  1708. elseif ( 'settings' == $this->pod_data[ 'type' ] ) { 
  1709. $this->row = array(); 
  1710.  
  1711. if ( empty( $this->fields ) ) 
  1712. $this->row = false; 
  1713. else { 
  1714. foreach ( $this->fields as $field ) { 
  1715. if ( !in_array( $field[ 'type' ], $tableless_field_types ) ) 
  1716. $this->row[ $field[ 'name' ] ] = get_option( $this->pod_data[ 'name' ] . '_' . $field[ 'name' ], null ); 
  1717.  
  1718. // Force ID 
  1719. $this->id = $this->pod_data[ 'id' ]; 
  1720. $this->row[ 'option_id' ] = $this->id; 
  1721. else { 
  1722. $params = array( 
  1723. 'table' => $this->table,  
  1724. 'where' => "`t`.`{$this->field_id}` = " . (int) $id,  
  1725. 'orderby' => "`t`.`{$this->field_id}` DESC",  
  1726. 'page' => 1,  
  1727. 'limit' => 1,  
  1728. 'search' => false 
  1729. ); 
  1730.  
  1731. if ( 'slug' == $mode && !empty( $this->field_slug ) ) { 
  1732. $id = pods_sanitize( $id ); 
  1733. $params[ 'where' ] = "`t`.`{$this->field_slug}` = '{$id}'"; 
  1734.  
  1735. $this->row = pods_data()->select( $params ); 
  1736.  
  1737. if ( empty( $this->row ) ) 
  1738. $this->row = false; 
  1739. else { 
  1740. $current_row = (array) $this->row; 
  1741. $this->row = get_object_vars( (object) @current( $current_row ) ); 
  1742.  
  1743. if ( !$explicit_set && !empty( $this->row ) && is_array( $this->row ) && !empty( $old_row ) ) { 
  1744. $this->row = array_merge( $old_row, $this->row ); 
  1745.  
  1746. if ( 'table' == $this->pod_data[ 'storage' ] && false !== $get_table_data && is_numeric( $current_row_id ) ) { 
  1747. $params = array( 
  1748. 'table' => $wpdb->prefix . "pods_",  
  1749. 'where' => "`t`.`id` = {$current_row_id}",  
  1750. 'orderby' => "`t`.`id` DESC",  
  1751. 'page' => 1,  
  1752. 'limit' => 1,  
  1753. 'search' => false,  
  1754. 'strict' => true 
  1755. ); 
  1756.  
  1757. if ( empty( $this->pod_data[ 'object' ] ) ) 
  1758. $params[ 'table' ] .= $this->pod_data[ 'name' ]; 
  1759. else 
  1760. $params[ 'table' ] .= $this->pod_data[ 'object' ]; 
  1761.  
  1762. $row = pods_data()->select( $params ); 
  1763.  
  1764. if ( !empty( $row ) ) { 
  1765. $current_row = (array) $row; 
  1766. $row = get_object_vars( (object) @current( $current_row ) ); 
  1767.  
  1768. if ( is_array( $this->row ) && !empty( $this->row ) ) 
  1769. $this->row = array_merge( $this->row, $row ); 
  1770. else 
  1771. $this->row = $row; 
  1772.  
  1773. if ( !empty( $this->pod ) && ! $already_cached ) { 
  1774. pods_cache_set( $id, $this->row, 'pods_items_' . $this->pod, 0 ); 
  1775.  
  1776. $this->row = apply_filters( 'pods_data_fetch', $this->row, $id, $this->row_number, $this ); 
  1777.  
  1778. return $this->row; 
  1779.  
  1780. /** 
  1781. * Reset the current data 
  1782. * @param int $row Row number to reset to 
  1783. * @return mixed 
  1784. * @since 2.0 
  1785. */ 
  1786. public function reset ( $row = null ) { 
  1787. $row = pods_absint( $row ); 
  1788.  
  1789. $this->row = false; 
  1790.  
  1791. if ( isset( $this->data[ $row ] ) ) 
  1792. $this->row = get_object_vars( $this->data[ $row ] ); 
  1793.  
  1794. if ( empty( $row ) ) 
  1795. $this->row_number = -1; 
  1796. else 
  1797. $this->row_number = $row - 1; 
  1798.  
  1799. return $this->row; 
  1800.  
  1801. /** 
  1802. * @static 
  1803. * Do a query on the database 
  1804. * @param string|array $sql The SQL to execute 
  1805. * @param string $error Error to throw on problems 
  1806. * @param null $results_error (optional) 
  1807. * @param null $no_results_error (optional) 
  1808. * @return array|bool|mixed|null|void Result of the query 
  1809. * @since 2.0 
  1810. */ 
  1811. public static function query ( $sql, $error = 'Database Error', $results_error = null, $no_results_error = null ) { 
  1812. /** 
  1813. * @var $wpdb wpdb 
  1814. */ 
  1815. global $wpdb; 
  1816.  
  1817. if ( $wpdb->show_errors ) 
  1818. self::$display_errors = true; 
  1819.  
  1820. $display_errors = self::$display_errors; 
  1821.  
  1822. if ( is_object( $error ) ) { 
  1823. if ( isset( $error->display_errors ) && false === $error->display_errors ) 
  1824. $display_errors = false; 
  1825.  
  1826. $error = 'Database Error'; 
  1827. elseif ( is_bool( $error ) ) { 
  1828. $display_errors = $error; 
  1829.  
  1830. if ( false !== $error ) 
  1831. $error = 'Database Error'; 
  1832.  
  1833. $params = (object) array( 
  1834. 'sql' => $sql,  
  1835. 'error' => $error,  
  1836. 'results_error' => $results_error,  
  1837. 'no_results_error' => $no_results_error,  
  1838. 'display_errors' => $display_errors 
  1839. ); 
  1840.  
  1841. // Handle Preparations of Values (sprintf format) 
  1842. if ( is_array( $sql ) ) { 
  1843. if ( isset( $sql[ 0 ] ) && 1 < count( $sql ) ) { 
  1844. if ( 2 == count( $sql ) ) { 
  1845. if ( !is_array( $sql[ 1 ] ) ) 
  1846. $sql[ 1 ] = array( $sql[ 1 ] ); 
  1847.  
  1848. $params->sql = self::prepare( $sql[ 0 ], $sql[ 1 ] ); 
  1849. elseif ( 3 == count( $sql ) ) 
  1850. $params->sql = self::prepare( $sql[ 0 ], array( $sql[ 1 ], $sql[ 2 ] ) ); 
  1851. else 
  1852. $params->sql = self::prepare( $sql[ 0 ], array( $sql[ 1 ], $sql[ 2 ], $sql[ 3 ] ) ); 
  1853. else 
  1854. $params = array_merge( $params, $sql ); 
  1855.  
  1856. if ( 1 == pods_var( 'pods_debug_sql_all', 'get', 0 ) && pods_is_admin( array( 'pods' ) ) ) 
  1857. echo '<textarea cols="100" rows="24">' . esc_textarea( str_replace( array( '@wp_users', '@wp_' ), array( $wpdb->users, $wpdb->prefix ), $params->sql ) ) . '</textarea>'; 
  1858.  
  1859. $params->sql = trim( $params->sql ); 
  1860.  
  1861. // Run Query 
  1862. $params->sql = apply_filters( 'pods_data_query', $params->sql, $params ); 
  1863.  
  1864. $result = $wpdb->query( $params->sql ); 
  1865.  
  1866. $result = apply_filters( 'pods_data_query_result', $result, $params ); 
  1867.  
  1868. if ( false === $result && !empty( $params->error ) && !empty( $wpdb->last_error ) ) 
  1869. return pods_error( "{$params->error}; SQL: {$params->sql}; Response: {$wpdb->last_error}", $params->display_errors ); 
  1870.  
  1871. if ( 'INSERT' == strtoupper( substr( $params->sql, 0, 6 ) ) || 'REPLACE' == strtoupper( substr( $params->sql, 0, 7 ) ) ) 
  1872. $result = $wpdb->insert_id; 
  1873. elseif ( preg_match( '/^[\s\r\n\(]*SELECT/', strtoupper( $params->sql ) ) ) { 
  1874. $result = (array) $wpdb->last_result; 
  1875.  
  1876. if ( !empty( $result ) && !empty( $params->results_error ) ) 
  1877. return pods_error( $params->results_error, $params->display_errors ); 
  1878. elseif ( empty( $result ) && !empty( $params->no_results_error ) ) 
  1879. return pods_error( $params->no_results_error, $params->display_errors ); 
  1880.  
  1881. return $result; 
  1882.  
  1883. /** 
  1884. * Gets all tables in the WP database, optionally exclude WP core 
  1885. * tables, and/or Pods table by settings the parameters to false. 
  1886. * @param boolean $wp_core 
  1887. * @param boolean $pods_tables restrict Pods 2.x tables 
  1888. * @return array 
  1889. * @since 2.0 
  1890. */ 
  1891. public static function get_tables ( $wp_core = true, $pods_tables = true ) { 
  1892. global $wpdb; 
  1893.  
  1894. $core_wp_tables = array( 
  1895. $wpdb->options,  
  1896. $wpdb->comments,  
  1897. $wpdb->commentmeta,  
  1898. $wpdb->posts,  
  1899. $wpdb->postmeta,  
  1900. $wpdb->users,  
  1901. $wpdb->usermeta,  
  1902. $wpdb->links,  
  1903. $wpdb->terms,  
  1904. $wpdb->term_taxonomy,  
  1905. $wpdb->term_relationships 
  1906. ); 
  1907.  
  1908. $showTables = $wpdb->get_results( 'SHOW TABLES in ' . DB_NAME, ARRAY_A ); 
  1909.  
  1910. $finalTables = array(); 
  1911.  
  1912. foreach ( $showTables as $table ) { 
  1913. if ( !$pods_tables && 0 === ( strpos( $table[ 0 ], $wpdb->prefix . rtrim( self::$prefix, '_' ) ) ) ) // don't include pods tables 
  1914. continue; 
  1915. elseif ( !$wp_core && in_array( $table[ 0 ], $core_wp_tables ) ) 
  1916. continue; 
  1917. else 
  1918. $finalTables[] = $table[ 0 ]; 
  1919.  
  1920. return $finalTables; 
  1921.  
  1922. /** 
  1923. * Gets column information from a table 
  1924. * @param string $table Table Name 
  1925. * @return array 
  1926. * @since 2.0 
  1927. */ 
  1928. public static function get_table_columns ( $table ) { 
  1929. global $wpdb; 
  1930.  
  1931. self::query( "SHOW COLUMNS FROM `{$table}` " ); 
  1932.  
  1933. $table_columns = $wpdb->last_result; 
  1934.  
  1935. $table_cols_and_types = array(); 
  1936.  
  1937. foreach ( $table_columns as $table_col ) { 
  1938. // Get only the type, not the attributes 
  1939. if ( false === strpos( $table_col->Type, '(' ) ) 
  1940. $modified_type = $table_col->Type; 
  1941. else 
  1942. $modified_type = substr( $table_col->Type, 0, ( strpos( $table_col->Type, '(' ) ) ); 
  1943.  
  1944. $table_cols_and_types[ $table_col->Field ] = $modified_type; 
  1945.  
  1946. return $table_cols_and_types; 
  1947.  
  1948. /** 
  1949. * Gets column data information from a table 
  1950. * @param string $column_name Column name 
  1951. * @param string $table Table name 
  1952. * @return array 
  1953. * @since 2.0 
  1954. */ 
  1955. public static function get_column_data ( $column_name, $table ) { 
  1956. global $wpdb; 
  1957.  
  1958. $column_data = $wpdb->get_results( 'DESCRIBE ' . $table, ARRAY_A ); 
  1959.  
  1960. foreach ( $column_data as $single_column ) { 
  1961. if ( $column_name == $single_column[ 'Field' ] ) 
  1962. return $single_column; 
  1963.  
  1964. return $column_data; 
  1965.  
  1966. /** 
  1967. * Prepare values for the DB 
  1968. * @param string $sql SQL to prepare 
  1969. * @param array $data Data to add to the sql prepare statement 
  1970. * @return bool|null|string 
  1971. * @since 2.0 
  1972. */ 
  1973. public static function prepare ( $sql, $data ) { 
  1974. /** 
  1975. * @var $wpdb wpdb 
  1976. */ 
  1977. global $wpdb; 
  1978. list( $sql, $data ) = apply_filters( 'pods_data_prepare', array( $sql, $data ) ); 
  1979. return $wpdb->prepare( $sql, $data ); 
  1980.  
  1981. /** 
  1982. * Get the string to use in a query for WHERE/HAVING, uses WP_Query meta_query arguments 
  1983. * @param array $fields Array of field matches for querying 
  1984. * @param array $pod Related Pod 
  1985. * @param object $params Parameters passed from select() 
  1986. * @return string|null Query string for WHERE/HAVING 
  1987. * @static 
  1988. * @since 2.3 
  1989. */ 
  1990. public static function query_fields ( $fields, $pod = null, &$params = null ) { 
  1991. $query_fields = array(); 
  1992.  
  1993. if ( !is_object( $params ) ) { 
  1994. $params = new stdClass(); 
  1995.  
  1996. if ( !isset( $params->query_field_level ) || 0 == $params->query_field_level ) { 
  1997. $params->query_fields = array(); 
  1998. $params->query_field_syntax = false; 
  1999. $params->query_field_level = 1; 
  2000.  
  2001. if ( !isset( $params->where_default ) ) { 
  2002. $params->where_default = array(); 
  2003.  
  2004. if ( !isset( $params->where_defaulted ) ) { 
  2005. $params->where_defaulted = false; 
  2006.  
  2007. $current_level = $params->query_field_level; 
  2008.  
  2009. $relation = 'AND'; 
  2010.  
  2011. if ( isset( $fields[ 'relation' ] ) ) { 
  2012. $relation = strtoupper( trim( pods_var( 'relation', $fields, 'AND', null, true ) ) ); 
  2013.  
  2014. if ( 'AND' != $relation ) 
  2015. $relation = 'OR'; 
  2016.  
  2017. unset( $fields[ 'relation' ] ); 
  2018.  
  2019. foreach ( $fields as $field => $match ) { 
  2020. if ( is_array( $match ) && isset( $match[ 'relation' ] ) ) { 
  2021. $params->query_field_level = $current_level + 1; 
  2022.  
  2023. $query_field = self::query_fields( $match, $pod, $params ); 
  2024.  
  2025. $params->query_field_level = $current_level; 
  2026.  
  2027. if ( !empty( $query_field ) ) { 
  2028. $query_fields[] = $query_field; 
  2029. else { 
  2030. $query_field = self::query_field( $field, $match, $pod, $params ); 
  2031.  
  2032. if ( !empty( $query_field ) ) { 
  2033. $query_fields[] = $query_field; 
  2034.  
  2035. if ( !empty( $query_fields ) ) { 
  2036. // If post_status not sent, detect it 
  2037. if ( !empty( $pod ) && 'post_type' == $pod[ 'type' ] && 1 == $current_level && !$params->where_defaulted && !empty( $params->where_default ) ) { 
  2038. $post_status_found = false; 
  2039.  
  2040. if ( !$params->query_field_syntax ) { 
  2041. $haystack = implode( ' ', (array) $query_fields ); 
  2042. $haystack = preg_replace( '/\s/', ' ', $haystack ); 
  2043. $haystack = preg_replace( '/\w\(/', ' ', $haystack ); 
  2044. $haystack = str_replace( array( '(', ')', ' ', '\\\'', "\\\"" ), ' ', $haystack ); 
  2045.  
  2046. preg_match_all( '/`?[\w\-]+`?(?:\\.`?[\w\-]+`?)+(?=[^"\']*(?:"[^"]*"[^"]*|\'[^\']*\'[^\']*)*$)/', $haystack, $found, PREG_PATTERN_ORDER ); 
  2047.  
  2048. $found = (array) @current( $found ); 
  2049.  
  2050. foreach ( $found as $value ) { 
  2051. $value = str_replace( '`', '', $value ); 
  2052. $value = explode( '.', $value ); 
  2053.  
  2054. if ( ( 'post_status' == $value[ 0 ] && 1 == count( $value ) ) || ( 2 == count( $value ) && 't' == $value[ 0 ] && 'post_status' == $value[ 1 ] ) ) { 
  2055. $post_status_found = true; 
  2056.  
  2057. break; 
  2058. elseif ( !empty( $params->query_fields ) && in_array( 'post_status', $params->query_fields ) ) { 
  2059. $post_status_found = true; 
  2060.  
  2061. if ( !$post_status_found ) { 
  2062. $query_fields[] = $params->where_default; 
  2063.  
  2064. if ( 1 < count( $query_fields ) ) 
  2065. $query_fields = '( ( ' . implode( ' ) ' . $relation . ' ( ', $query_fields ) . ' ) )'; 
  2066. else 
  2067. $query_fields = '( ' . implode( ' ' . $relation . ' ', $query_fields ) . ' )'; 
  2068. else 
  2069. $query_fields = null; 
  2070.  
  2071. // query_fields level complete 
  2072. if ( 1 == $params->query_field_level ) { 
  2073. $params->query_field_level = 0; 
  2074.  
  2075. return $query_fields; 
  2076.  
  2077. /** 
  2078. * Get the string to use in a query for matching, uses WP_Query meta_query arguments 
  2079. * @param string|int $field Field name or array index 
  2080. * @param array|string $q Query array (meta_query) or string for matching 
  2081. * @param array $pod Related Pod 
  2082. * @param object $params Parameters passed from select() 
  2083. * @return string|null Query field string 
  2084. * @see PodsData::query_fields 
  2085. * @static 
  2086. * @since 2.3 
  2087. */ 
  2088. public static function query_field ( $field, $q, $pod = null, &$params = null ) { 
  2089. global $wpdb; 
  2090.  
  2091. $simple_tableless_objects = PodsForm::simple_tableless_objects(); 
  2092.  
  2093. $field_query = null; 
  2094.  
  2095. // Plain queries 
  2096. if ( is_numeric( $field ) && !is_array( $q ) ) { 
  2097. return $q; 
  2098. // key => value queries (backwards compatibility) 
  2099. elseif ( !is_numeric( $field ) && ( !is_array( $q ) || ( !isset( $q[ 'key' ] ) && !isset( $q[ 'field' ] ) ) ) ) { 
  2100. $new_q = array( 
  2101. 'field' => $field,  
  2102. 'compare' => pods_var_raw( 'compare', $q, '=', null, true ),  
  2103. 'value' => pods_var_raw( 'value', $q, $q, null, true ),  
  2104. 'sanitize' => pods_var_raw( 'sanitize', $q, true ),  
  2105. 'sanitize_format' => pods_var_raw( 'sanitize_format', $q ),  
  2106. 'cast' => pods_var_raw( 'cast', $q ) 
  2107. ); 
  2108.  
  2109. if ( is_array( $new_q[ 'value' ] ) ) { 
  2110. if ( '=' == $new_q[ 'compare' ] ) 
  2111. $new_q[ 'compare' ] = 'IN'; 
  2112.  
  2113. if ( isset( $new_q[ 'value' ][ 'compare' ] ) ) 
  2114. unset( $new_q[ 'value' ][ 'compare' ] ); 
  2115.  
  2116. $q = $new_q; 
  2117.  
  2118. $field_name = trim( pods_var_raw( 'field', $q, pods_var_raw( 'key', $q, $field, null, true ), null, true ) ); 
  2119. $field_type = strtoupper( trim( pods_var_raw( 'type', $q, 'CHAR', null, true ) ) ); 
  2120. $field_value = pods_var_raw( 'value', $q ); 
  2121. $field_compare = strtoupper( trim( pods_var_raw( 'compare', $q, ( is_array( $field_value ? 'IN' : '=' ) ), null, true ) ) ); 
  2122. $field_sanitize = (boolean) pods_var( 'sanitize', $q, true ); 
  2123. $field_sanitize_format = pods_var_raw( 'sanitize_format', $q, null, null, true ); 
  2124. $field_cast = pods_var_raw( 'cast', $q, null, null, true ); 
  2125.  
  2126. if ( is_object( $params ) ) { 
  2127. $params->meta_query_syntax = true; 
  2128. $params->query_fields[] = $field_name; 
  2129.  
  2130. // Deprecated WP type 
  2131. if ( 'NUMERIC' == $field_type ) 
  2132. $field_type = 'SIGNED'; 
  2133. // Restrict to supported types 
  2134. elseif ( !in_array( $field_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' ) ) ) 
  2135. $field_type = 'CHAR'; 
  2136.  
  2137. // Alias / Casting 
  2138. if ( empty( $field_cast ) ) { 
  2139. // Setup field casting from field name 
  2140. if ( false === strpos( $field_name, '`' ) && false === strpos( $field_name, '(' ) && false === strpos( $field_name, ' ' ) ) { 
  2141. // Handle field naming if Pod-based 
  2142. if ( !empty( $pod ) && false === strpos( $field_name, '.' ) ) { 
  2143. $field_cast = ''; 
  2144.  
  2145. $tableless_field_types = PodsForm::tableless_field_types(); 
  2146.  
  2147. if ( isset( $pod[ 'fields' ][ $field_name ] ) && in_array( $pod[ 'fields' ][ $field_name ][ 'type' ], $tableless_field_types ) ) { 
  2148. if ( in_array( $pod[ 'fields' ][ $field_name ][ 'pick_object' ], $simple_tableless_objects ) ) { 
  2149. if ( 'meta' == $pod[ 'storage' ] ) 
  2150. $field_cast = "`{$field_name}`.`meta_value`"; 
  2151. else 
  2152. $field_cast = "`t`.`{$field_name}`"; 
  2153. else { 
  2154. $table = pods_api()->get_table_info( $pod[ 'fields' ][ $field_name ][ 'pick_object' ], $pod[ 'fields' ][ $field_name ][ 'pick_val' ] ); 
  2155.  
  2156. if ( !empty( $table ) ) 
  2157. $field_cast = "`{$field_name}`.`" . $table[ 'field_index' ] . '`'; 
  2158.  
  2159. if ( empty( $field_cast ) ) { 
  2160. if ( !in_array( $pod[ 'type' ], array( 'pod', 'table' ) ) ) { 
  2161. if ( isset( $pod[ 'object_fields' ][ $field_name ] ) ) 
  2162. $field_cast = "`t`.`{$field_name}`"; 
  2163. elseif ( isset( $pod[ 'fields' ][ $field_name ] ) ) { 
  2164. if ( 'meta' == $pod['storage'] ) 
  2165. $field_cast = "`{$field_name}`.`meta_value`"; 
  2166. else 
  2167. $field_cast = "`d`.`{$field_name}`"; 
  2168. else { 
  2169. foreach ( $pod[ 'object_fields' ] as $object_field => $object_field_opt ) { 
  2170. if ( $object_field == $field_name || in_array( $field_name, $object_field_opt[ 'alias' ] ) ) { 
  2171. $field_cast = "`t`.`{$object_field}`"; 
  2172.  
  2173. break; 
  2174. elseif ( isset( $pod[ 'fields' ][ $field_name ] ) ) { 
  2175. if ( 'meta' == $pod['storage'] ) 
  2176. $field_cast = "`{$field_name}`.`meta_value`"; 
  2177. else 
  2178. $field_cast = "`t`.`{$field_name}`"; 
  2179.  
  2180. if ( empty( $field_cast ) ) { 
  2181. if ( 'meta' == $pod['storage'] ) { 
  2182. $field_cast = "`{$field_name}`.`meta_value`"; 
  2183. else 
  2184. $field_cast = "`t`.`{$field_name}`"; 
  2185. else { 
  2186. $field_cast = '`' . str_replace( '.', '`.`', $field_name ) . '`'; 
  2187. else { 
  2188. $field_cast = $field_name; 
  2189.  
  2190. // Cast field if needed 
  2191. if ( 'CHAR' != $field_type ) { 
  2192. $field_cast = 'CAST( ' . $field_cast . ' AS ' . $field_type .' )'; 
  2193.  
  2194. // Setup string sanitizing for $wpdb->prepare() 
  2195. if ( empty( $field_sanitize_format ) ) { 
  2196. // Sanitize as string 
  2197. $field_sanitize_format = '%s'; 
  2198.  
  2199. // Sanitize as integer if needed 
  2200. if ( in_array( $field_type, array( 'UNSIGNED', 'SIGNED' ) ) ) 
  2201. $field_sanitize_format = '%d'; 
  2202.  
  2203. // Restrict to supported comparisons 
  2204. if ( !in_array( $field_compare, array( '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'ALL', 'BETWEEN', 'NOT BETWEEN', 'EXISTS', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP', 'RLIKE' ) ) ) 
  2205. $field_compare = '='; 
  2206.  
  2207. // Restrict to supported array comparisons 
  2208. if ( is_array( $field_value ) && !in_array( $field_compare, array( 'IN', 'NOT IN', 'ALL', 'BETWEEN', 'NOT BETWEEN' ) ) ) { 
  2209. if ( in_array( $field_compare, array( '!=', 'NOT LIKE' ) ) ) 
  2210. $field_compare = 'NOT IN'; 
  2211. else 
  2212. $field_compare = 'IN'; 
  2213. // Restrict to supported string comparisons 
  2214. elseif ( !is_array( $field_value ) && in_array( $field_compare, array( 'IN', 'NOT IN', 'ALL', 'BETWEEN', 'NOT BETWEEN' ) ) ) { 
  2215. $check_value = preg_split( '/[, \s]+/', $field_value ); 
  2216.  
  2217. if ( 1 < count( $check_value ) ) 
  2218. $field_value = $check_value; 
  2219. elseif ( in_array( $field_compare, array( 'NOT IN', 'NOT BETWEEN' ) ) ) 
  2220. $field_compare = '!='; 
  2221. else 
  2222. $field_compare = '='; 
  2223.  
  2224. // Restrict to two values, force = and != if only one value provided 
  2225. if ( in_array( $field_compare, array( 'BETWEEN', 'NOT BETWEEN' ) ) ) { 
  2226. $field_value = array_values( array_slice( $field_value, 0, 2 ) ); 
  2227.  
  2228. if ( 1 == count( $field_value ) ) { 
  2229. if ( 'NOT IN' == $field_compare ) 
  2230. $field_compare = '!='; 
  2231. else 
  2232. $field_compare = '='; 
  2233.  
  2234. // Single array handling 
  2235. if ( 1 == count( $field_value ) && $field_compare == 'ALL' ) { 
  2236. $field_compare = '='; 
  2237. // Empty array handling 
  2238. elseif ( empty( $field_value ) && in_array( $field_compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) { 
  2239. $field_compare = 'EXISTS'; 
  2240.  
  2241. // Rebuild $q 
  2242. $q = array( 
  2243. 'field' => $field_name,  
  2244. 'type' => $field_type,  
  2245. 'value' => $field_value,  
  2246. 'compare' => $field_compare,  
  2247. 'sanitize' => $field_sanitize,  
  2248. 'sanitize_format' => $field_sanitize_format,  
  2249. 'cast' => $field_cast 
  2250. ); 
  2251.  
  2252. // Make the query 
  2253. if ( in_array( $field_compare, array( '=', '!=', '>', '>=', '<', '<=', 'REGEXP', 'NOT REGEXP', 'RLIKE' ) ) ) { 
  2254. if ( $field_sanitize ) { 
  2255. $field_query = $wpdb->prepare( $field_cast . ' ' . $field_compare . ' ' . $field_sanitize_format, $field_value ); 
  2256. else { 
  2257. $field_query = $field_cast . ' ' . $field_compare . ' "' . $field_value . '"'; 
  2258. elseif ( in_array( $field_compare, array( 'LIKE', 'NOT LIKE' ) ) ) { 
  2259. if ( $field_sanitize ) { 
  2260. $field_query = $field_cast . ' ' . $field_compare . ' "%' . pods_sanitize_like( $field_value ) . '%"'; 
  2261. else { 
  2262. $field_query = $field_cast . ' ' . $field_compare . ' "' . $field_value . '"'; 
  2263. elseif ( in_array( $field_compare, array( 'IN', 'NOT IN', 'ALL' ) ) ) { 
  2264. if ( $field_compare == 'ALL' ) { 
  2265. $field_compare = 'IN'; 
  2266.  
  2267. if ( ! empty( $pod ) ) { 
  2268. $params->having[] = 'COUNT( DISTINCT ' . $field_cast . ' ) = ' . count( $field_value ); 
  2269.  
  2270. if ( empty( $params->groupby ) || ( ! in_array( '`t`.`' . $pod['field_id'] . '`', $params->groupby ) && ! in_array( 't.' . $pod['field_id'] . '', $params->groupby ) ) ) { 
  2271. $params->groupby[] = '`t`.`' . $pod['field_id'] . '`'; 
  2272.  
  2273. if ( $field_sanitize ) { 
  2274. $field_query = $wpdb->prepare( $field_cast . ' ' . $field_compare . ' ( ' . substr( str_repeat( ', ' . $field_sanitize_format, count( $field_value ) ), 1 ) . ' )', $field_value ); 
  2275. else { 
  2276. $field_query = $field_cast . ' ' . $field_compare . ' ( "' . implode( '", "', $field_value ) . '" )'; 
  2277. elseif ( in_array( $field_compare, array( 'BETWEEN', 'NOT BETWEEN' ) ) ) { 
  2278. if ( $field_sanitize ) { 
  2279. $field_query = $wpdb->prepare( $field_cast . ' ' . $field_compare . ' ' . $field_sanitize_format . ' AND ' . $field_sanitize_format, $field_value ); 
  2280. else { 
  2281. $field_query = $field_cast . ' ' . $field_compare . ' "' . $field_value[ 0 ] . '" AND "' . $field_value[ 1 ] . '"'; 
  2282. elseif ( 'EXISTS' == $field_compare ) 
  2283. $field_query = $field_cast . ' IS NOT NULL'; 
  2284. elseif ( 'NOT EXISTS' == $field_compare ) 
  2285. $field_query = $field_cast . ' IS NULL'; 
  2286.  
  2287. $field_query = apply_filters( 'pods_data_field_query', $field_query, $q ); 
  2288.  
  2289. return $field_query; 
  2290.  
  2291. /** 
  2292. * Setup fields for traversal 
  2293. * @param array $fields Associative array of fields data 
  2294. * @return array Traverse feed 
  2295. * @param object $params (optional) Parameters from build() 
  2296. * @since 2.0 
  2297. */ 
  2298. function traverse_build ( $fields = null, $params = null ) { 
  2299. if ( null === $fields ) 
  2300. $fields = $this->fields; 
  2301.  
  2302. $feed = array(); 
  2303.  
  2304. foreach ( $fields as $field => $data ) { 
  2305. if ( !is_array( $data ) ) 
  2306. $field = $data; 
  2307.  
  2308. if ( !isset( $_GET[ 'filter_' . $field ] ) ) 
  2309. continue; 
  2310.  
  2311. $field_value = pods_var( 'filter_' . $field, 'get', false, null, true ); 
  2312.  
  2313. if ( !empty( $field_value ) || 0 < strlen( $field_value ) ) 
  2314. $feed[ 'traverse_' . $field ] = array( $field ); 
  2315.  
  2316. return $feed; 
  2317.  
  2318. /** 
  2319. * Recursively join tables based on fields 
  2320. * @param array $traverse_recurse Array of traversal options 
  2321. * @return array Array of table joins 
  2322. * @since 2.0 
  2323. */ 
  2324. function traverse_recurse ( $traverse_recurse ) { 
  2325. global $wpdb; 
  2326.  
  2327. $defaults = array( 
  2328. 'pod' => null,  
  2329. 'fields' => array(),  
  2330. 'joined' => 't',  
  2331. 'depth' => 0,  
  2332. 'joined_id' => 'id',  
  2333. 'joined_index' => 'id',  
  2334. 'params' => new stdClass(),  
  2335. 'last_table_info' => array() 
  2336. ); 
  2337.  
  2338. $traverse_recurse = array_merge( $defaults, $traverse_recurse ); 
  2339.  
  2340. $joins = array(); 
  2341.  
  2342. if ( 0 == $traverse_recurse[ 'depth' ] && !empty( $traverse_recurse[ 'pod' ] ) && !empty( $traverse_recurse [ 'last_table_info' ] ) && isset( $traverse_recurse [ 'last_table_info' ][ 'id' ] ) ) 
  2343. $pod_data = $traverse_recurse [ 'last_table_info' ]; 
  2344. elseif ( empty( $traverse_recurse[ 'pod' ] ) ) { 
  2345. if ( !empty( $traverse_recurse[ 'params' ] ) && !empty( $traverse_recurse[ 'params' ]->table ) && 0 === strpos( $traverse_recurse[ 'params' ]->table, $wpdb->prefix ) ) { 
  2346. if ( $wpdb->posts == $traverse_recurse[ 'params' ]->table ) 
  2347. $traverse_recurse[ 'pod' ] = 'post_type'; 
  2348. elseif ( $wpdb->terms == $traverse_recurse[ 'params' ]->table ) 
  2349. $traverse_recurse[ 'pod' ] = 'taxonomy'; 
  2350. elseif ( $wpdb->users == $traverse_recurse[ 'params' ]->table ) 
  2351. $traverse_recurse[ 'pod' ] = 'user'; 
  2352. elseif ( $wpdb->comments == $traverse_recurse[ 'params' ]->table ) 
  2353. $traverse_recurse[ 'pod' ] = 'comment'; 
  2354. else 
  2355. return $joins; 
  2356.  
  2357. $pod_data = array(); 
  2358.  
  2359. if ( in_array( $traverse_recurse[ 'pod' ], array( 'user', 'comment' ) ) ) { 
  2360. $pod = $this->api->load_pod( array( 'name' => $traverse_recurse[ 'pod' ], 'table_info' => true ) ); 
  2361.  
  2362. if ( !empty( $pod ) && $pod[ 'type' ] == $pod ) 
  2363. $pod_data = $pod; 
  2364.  
  2365. if ( empty( $pod_data ) ) { 
  2366. $default_storage = 'meta'; 
  2367.  
  2368. if ( 'taxonomy' == $traverse_recurse['pod'] && ! function_exists( 'get_term_meta' ) ) { 
  2369. $default_storage = 'none'; 
  2370.  
  2371. $pod_data = array( 
  2372. 'id' => 0,  
  2373. 'name' => '_table_' . $traverse_recurse[ 'pod' ],  
  2374. 'type' => $traverse_recurse[ 'pod' ],  
  2375. 'storage' => $default_storage,  
  2376. 'fields' => array(),  
  2377. 'object_fields' => $this->api->get_wp_object_fields( $traverse_recurse[ 'pod' ] ) 
  2378. ); 
  2379.  
  2380. $pod_data = array_merge( $this->api->get_table_info( $traverse_recurse[ 'pod' ], '' ), $pod_data ); 
  2381. } elseif ( 'taxonomy' == $pod_data['type'] && 'none' == $pod_data['storage'] && function_exists( 'get_term_meta' ) ) { 
  2382. $pod_data['storage'] = 'meta'; 
  2383.  
  2384. $traverse_recurse[ 'pod' ] = $pod_data[ 'name' ]; 
  2385. else 
  2386. return $joins; 
  2387. else { 
  2388. $pod_data = $this->api->load_pod( array( 'name' => $traverse_recurse[ 'pod' ], 'table_info' => true ), false ); 
  2389.  
  2390. if ( empty( $pod_data ) ) 
  2391. return $joins; 
  2392.  
  2393. if ( isset( $pod_data[ 'object_fields' ] ) ) { 
  2394. $pod_data[ 'fields' ] = array_merge( $pod_data[ 'fields' ], $pod_data[ 'object_fields' ] ); 
  2395.  
  2396. $tableless_field_types = PodsForm::tableless_field_types(); 
  2397. $simple_tableless_objects = PodsForm::simple_tableless_objects(); 
  2398. $file_field_types = PodsForm::file_field_types(); 
  2399.  
  2400. if ( !isset( $this->traversal[ $traverse_recurse[ 'pod' ] ] ) ) 
  2401. $this->traversal[ $traverse_recurse[ 'pod' ] ] = array(); 
  2402.  
  2403. if ( ( empty( $pod_data[ 'meta_table' ] ) || $pod_data[ 'meta_table' ] == $pod_data[ 'table' ] ) && ( empty( $traverse_recurse[ 'fields' ] ) || empty( $traverse_recurse[ 'fields' ][ $traverse_recurse[ 'depth' ] ] ) ) ) 
  2404. return $joins; 
  2405.  
  2406. $field = $traverse_recurse[ 'fields' ][ $traverse_recurse[ 'depth' ] ]; 
  2407.  
  2408. $ignore_aliases = array( 
  2409. 'wpml_languages',  
  2410. 'polylang_languages' 
  2411. ); 
  2412.  
  2413. $ignore_aliases = apply_filters( 'pods_data_traverse_recurse_ignore_aliases', $ignore_aliases, $field, $traverse_recurse, $this ); 
  2414.  
  2415. if ( in_array( $field, $ignore_aliases ) ) 
  2416. return $joins; 
  2417.  
  2418. $meta_data_table = false; 
  2419.  
  2420. if ( !isset( $pod_data[ 'fields' ][ $field ] ) && 'd' == $field && isset( $traverse_recurse[ 'fields' ][ $traverse_recurse[ 'depth' ] - 1 ] ) ) { 
  2421. $field = $traverse_recurse[ 'fields' ][ $traverse_recurse[ 'depth' ] - 1 ]; 
  2422.  
  2423. $field_type = 'pick'; 
  2424.  
  2425. if ( isset( $traverse_recurse[ 'last_table_info' ][ 'pod' ][ 'fields' ][ $field ] ) ) { 
  2426. $field_type = $traverse_recurse[ 'last_table_info' ][ 'pod' ][ 'fields' ][ $field ][ 'type' ]; 
  2427. elseif ( isset( $traverse_recurse[ 'last_table_info' ][ 'pod' ][ 'object_fields' ][ $field ] ) ) { 
  2428. $field_type = $traverse_recurse[ 'last_table_info' ][ 'pod' ][ 'object_fields' ][ $field ][ 'type' ]; 
  2429.  
  2430. $pod_data[ 'fields' ][ $field ] = array( 
  2431. 'id' => 0,  
  2432. 'name' => $field,  
  2433. 'type' => $field_type,  
  2434. 'pick_object' => $traverse_recurse[ 'last_table_info' ][ 'pod' ][ 'type' ],  
  2435. 'pick_val' => $traverse_recurse[ 'last_table_info' ][ 'pod' ][ 'name' ] 
  2436. ); 
  2437.  
  2438. $meta_data_table = true; 
  2439.  
  2440. // Fallback to meta table if the pod type supports it 
  2441. if ( !isset( $pod_data[ 'fields' ][ $field ] ) ) { 
  2442. $last = end( $traverse_recurse[ 'fields' ] ); 
  2443.  
  2444. if ( 'post_type' == $pod_data[ 'type' ] && !isset( $pod_data[ 'object_fields' ] ) ) 
  2445. $pod_data[ 'object_fields' ] = $this->api->get_wp_object_fields( 'post_type', $pod_data ); 
  2446.  
  2447. if ( 'post_type' == $pod_data[ 'type' ] && isset( $pod_data[ 'object_fields'][ $field ] ) && in_array( $pod_data[ 'object_fields' ][ $field ][ 'type' ], $tableless_field_types ) ) 
  2448. $pod_data[ 'fields' ][ $field ] = $pod_data[ 'object_fields' ][ $field ]; 
  2449. elseif ( 'meta_value' === $last && in_array( $pod_data[ 'type' ], array( 'post_type', 'media', 'taxonomy', 'user', 'comment' ) ) ) 
  2450. $pod_data[ 'fields' ][ $field ] = PodsForm::field_setup( array( 'name' => $field ) ); 
  2451. else { 
  2452. if ( 'post_type' == $pod_data[ 'type' ] ) { 
  2453. $pod_data[ 'object_fields' ] = $this->api->get_wp_object_fields( 'post_type', $pod_data, true ); 
  2454.  
  2455. if ( 'post_type' == $pod_data[ 'type' ] && isset( $pod_data[ 'object_fields' ][ $field ] ) && in_array( $pod_data[ 'object_fields' ][ $field ][ 'type' ], $tableless_field_types ) ) 
  2456. $pod_data[ 'fields' ][ $field ] = $pod_data[ 'object_fields' ][ $field ]; 
  2457. else 
  2458. return $joins; 
  2459. else 
  2460. return $joins; 
  2461. } elseif ( isset( $pod_data[ 'object_fields' ] ) && isset( $pod_data[ 'object_fields' ][ $field ] ) && ! in_array( $pod_data[ 'object_fields' ][ $field ][ 'type' ], $tableless_field_types ) ) { 
  2462. return $joins; 
  2463.  
  2464. $traverse = $pod_data[ 'fields' ][ $field ]; 
  2465.  
  2466. if ( 'taxonomy' == $traverse[ 'type' ] ) 
  2467. $traverse[ 'table_info' ] = $this->api->get_table_info( $traverse[ 'type' ], $traverse[ 'name' ] ); 
  2468. elseif ( in_array( $traverse[ 'type' ], $file_field_types ) ) 
  2469. $traverse[ 'table_info' ] = $this->api->get_table_info( 'post_type', 'attachment' ); 
  2470. elseif ( !in_array( $traverse[ 'type' ], $tableless_field_types ) ) 
  2471. $traverse[ 'table_info' ] = $this->api->get_table_info( $pod_data[ 'type' ], $pod_data[ 'name' ], $pod_data[ 'name' ], $pod_data ); 
  2472. elseif ( empty( $traverse[ 'table_info' ] ) || ( in_array( $traverse[ 'pick_object' ], $simple_tableless_objects ) && !empty( $traverse_recurse[ 'last_table_info' ] ) ) ) { 
  2473. if ( in_array( $traverse[ 'pick_object' ], $simple_tableless_objects ) && !empty( $traverse_recurse[ 'last_table_info' ] ) ) { 
  2474. $traverse[ 'table_info' ] = $traverse_recurse[ 'last_table_info' ]; 
  2475.  
  2476. if ( !empty( $traverse[ 'table_info' ][ 'meta_table' ] ) ) 
  2477. $meta_data_table = true; 
  2478. elseif ( !in_array( $traverse[ 'type' ], $tableless_field_types ) && !empty( $traverse_recurse[ 'last_table_info' ] ) && 0 == $traverse_recurse[ 'depth' ] ) 
  2479. $traverse[ 'table_info' ] = $traverse_recurse[ 'last_table_info' ]; 
  2480. else { 
  2481. if ( ! isset( $traverse[ 'pod' ] ) ) { 
  2482. $traverse[ 'pod' ] = null; 
  2483.  
  2484. $traverse[ 'table_info' ] = $this->api->get_table_info( $traverse[ 'pick_object' ], $traverse[ 'pick_val' ], null, $traverse[ 'pod' ], $traverse ); 
  2485.  
  2486. if ( isset( $this->traversal[ $traverse_recurse[ 'pod' ] ][ $traverse[ 'name' ] ] ) ) 
  2487. $traverse = array_merge( $traverse, (array) $this->traversal[ $traverse_recurse[ 'pod' ] ][ $traverse[ 'name' ] ] ); 
  2488.  
  2489. $traverse = apply_filters( 'pods_data_traverse', $traverse, compact( 'pod', 'fields', 'joined', 'depth', 'joined_id', 'params' ), $this ); 
  2490.  
  2491. if ( empty( $traverse ) ) 
  2492. return $joins; 
  2493.  
  2494. $traverse[ 'id' ] = (int) $traverse[ 'id' ]; 
  2495.  
  2496. if ( empty( $traverse[ 'id' ] ) ) 
  2497. $traverse[ 'id' ] = $field; 
  2498.  
  2499. $table_info = $traverse[ 'table_info' ]; 
  2500.  
  2501. $this->traversal[ $traverse_recurse[ 'pod' ] ][ $field ] = $traverse; 
  2502.  
  2503. $field_joined = $field; 
  2504.  
  2505. if ( 0 < $traverse_recurse[ 'depth' ] && 't' != $traverse_recurse[ 'joined' ] ) { 
  2506. if ( $meta_data_table && ( 'pick' != $traverse[ 'type' ] || !in_array( pods_var( 'pick_object', $traverse ), $simple_tableless_objects ) ) ) 
  2507. $field_joined = $traverse_recurse[ 'joined' ] . '_d'; 
  2508. else 
  2509. $field_joined = $traverse_recurse[ 'joined' ] . '_' . $field; 
  2510.  
  2511. $rel_alias = 'rel_' . $field_joined; 
  2512.  
  2513. if ( pods_v( 'search', $traverse_recurse[ 'params' ], false ) && empty( $traverse_recurse[ 'params' ]->filters ) ) { 
  2514. if ( 0 < strlen( pods_var( 'filter_' . $field_joined, 'get' ) ) ) { 
  2515. $val = absint( pods_var( 'filter_' . $field_joined, 'get' ) ); 
  2516.  
  2517. $search = "`{$field_joined}`.`{$table_info[ 'field_id' ]}` = {$val}"; 
  2518.  
  2519. if ( 'text' == $this->search_mode ) { 
  2520. $val = pods_var( 'filter_' . $field_joined, 'get' ); 
  2521.  
  2522. $search = "`{$field_joined}`.`{$traverse[ 'name' ]}` = '{$val}'"; 
  2523. elseif ( 'text_like' == $this->search_mode ) { 
  2524. $val = pods_sanitize( pods_sanitize_like( pods_var_raw( 'filter_' . $field_joined ) ) ); 
  2525.  
  2526. $search = "`{$field_joined}`.`{$traverse[ 'name' ]}` LIKE '%{$val}%'"; 
  2527.  
  2528. $this->search_where[] = " {$search} "; 
  2529.  
  2530. $the_join = null; 
  2531.  
  2532. $joined_id = $table_info[ 'field_id' ]; 
  2533. $joined_index = $table_info[ 'field_index' ]; 
  2534.  
  2535. if ( 'taxonomy' == $traverse[ 'type' ] ) { 
  2536. $rel_tt_alias = 'rel_tt_' . $field_joined; 
  2537.  
  2538. if ( pods_tableless() && function_exists( 'get_term_meta' ) ) { 
  2539. $the_join = " 
  2540. LEFT JOIN `{$table_info[ 'meta_table' ]}` AS `{$rel_alias}` ON 
  2541. `{$rel_alias}`.`{$table_info[ 'meta_field_index' ]}` = '{$traverse[ 'name' ]}' 
  2542. AND `{$rel_alias}`.`{$table_info[ 'meta_field_id' ]}` = `{$traverse_recurse[ 'joined' ]}`.`{$traverse_recurse[ 'joined_id' ]}` 
  2543.  
  2544. LEFT JOIN `{$table_info[ 'meta_table' ]}` AS `{$field_joined}` ON 
  2545. `{$field_joined}`.`{$table_info[ 'meta_field_index' ]}` = '{$traverse[ 'name' ]}' 
  2546. AND `{$field_joined}`.`{$table_info[ 'meta_field_id' ]}` = CONVERT( `{$rel_alias}`.`{$table_info[ 'meta_field_value' ]}`, SIGNED ) 
  2547. "; 
  2548.  
  2549. $joined_id = $table_info[ 'meta_field_id' ]; 
  2550. $joined_index = $table_info[ 'meta_field_index' ]; 
  2551. } elseif ( $meta_data_table ) { 
  2552. $the_join = " 
  2553. LEFT JOIN `{$table_info[ 'pod_table' ]}` AS `{$field_joined}` ON 
  2554. `{$field_joined}`.`{$table_info[ 'pod_field_id' ]}` = `{$traverse_recurse[ 'rel_alias' ]}`.`{$traverse_recurse[ 'joined_id' ]}` 
  2555. "; 
  2556. else { 
  2557. $the_join = " 
  2558. LEFT JOIN `{$wpdb->term_relationships}` AS `{$rel_alias}` ON 
  2559. `{$rel_alias}`.`object_id` = `{$traverse_recurse[ 'joined' ]}`.`ID` 
  2560.  
  2561. LEFT JOIN `{$wpdb->term_taxonomy}` AS `{$rel_tt_alias}` ON 
  2562. `{$rel_tt_alias}`.`taxonomy` = '{$traverse[ 'name' ]}' 
  2563. AND `{$rel_tt_alias}`.`term_taxonomy_id` = `{$rel_alias}`.`term_taxonomy_id` 
  2564.  
  2565. LEFT JOIN `{$table_info[ 'table' ]}` AS `{$field_joined}` ON 
  2566. `{$field_joined}`.`{$table_info[ 'field_id' ]}` = `{$rel_tt_alias}`.`{$table_info[ 'field_id' ]}` 
  2567. "; 
  2568.  
  2569. // Override $rel_alias 
  2570. $rel_alias = $field_joined; 
  2571.  
  2572. $joined_id = $table_info[ 'field_id' ]; 
  2573. $joined_index = $table_info[ 'field_index' ]; 
  2574. elseif ( in_array( $traverse[ 'type' ], $tableless_field_types ) && ( 'pick' != $traverse[ 'type' ] || !in_array( pods_v( 'pick_object', $traverse ), $simple_tableless_objects ) ) ) { 
  2575. if ( pods_tableless() ) { 
  2576. $the_join = " 
  2577. LEFT JOIN `{$table_info[ 'meta_table' ]}` AS `{$rel_alias}` ON 
  2578. `{$rel_alias}`.`{$table_info[ 'meta_field_index' ]}` = '{$traverse[ 'name' ]}' 
  2579. AND `{$rel_alias}`.`{$table_info[ 'meta_field_id' ]}` = `{$traverse_recurse[ 'joined' ]}`.`{$traverse_recurse[ 'joined_id' ]}` 
  2580.  
  2581. LEFT JOIN `{$table_info[ 'meta_table' ]}` AS `{$field_joined}` ON 
  2582. `{$field_joined}`.`{$table_info[ 'meta_field_index' ]}` = '{$traverse[ 'name' ]}' 
  2583. AND `{$field_joined}`.`{$table_info[ 'meta_field_id' ]}` = CONVERT( `{$rel_alias}`.`{$table_info[ 'meta_field_value' ]}`, SIGNED ) 
  2584. "; 
  2585.  
  2586. $joined_id = $table_info[ 'meta_field_id' ]; 
  2587. $joined_index = $table_info[ 'meta_field_index' ]; 
  2588. elseif ( $meta_data_table ) { 
  2589. if ( $traverse[ 'id' ] !== $traverse[ 'pick_val' ] ) { 
  2590. // This must be a relationship 
  2591. $joined_id = 'related_item_id'; 
  2592. } else { 
  2593. $joined_id = $traverse_recurse[ 'joined_id' ]; 
  2594.  
  2595. $the_join = " 
  2596. LEFT JOIN `{$table_info['pod_table']}` AS `{$field_joined}` ON 
  2597. `{$field_joined}`.`{$table_info['pod_field_id']}` = `{$traverse_recurse['rel_alias']}`.`{$joined_id}` 
  2598. "; 
  2599. else { 
  2600. $the_join = " 
  2601. LEFT JOIN `@wp_podsrel` AS `{$rel_alias}` ON 
  2602. `{$rel_alias}`.`field_id` = {$traverse[ 'id' ]} 
  2603. AND `{$rel_alias}`.`item_id` = `{$traverse_recurse[ 'joined' ]}`.`{$traverse_recurse[ 'joined_id' ]}` 
  2604.  
  2605. LEFT JOIN `{$table_info[ 'table' ]}` AS `{$field_joined}` ON 
  2606. `{$field_joined}`.`{$table_info[ 'field_id' ]}` = `{$rel_alias}`.`related_item_id` 
  2607. "; 
  2608. elseif ( 'meta' == $pod_data[ 'storage' ] ) { 
  2609. if ( 
  2610. ( $traverse_recurse[ 'depth' ] + 2 ) == count( $traverse_recurse[ 'fields' ] ) 
  2611. && ( 'pick' != $traverse[ 'type' ] || !in_array( pods_var( 'pick_object', $traverse ), $simple_tableless_objects ) ) 
  2612. && $table_info[ 'meta_field_value' ] == $traverse_recurse[ 'fields' ][ $traverse_recurse[ 'depth' ] + 1 ] ) { 
  2613. $the_join = " 
  2614. LEFT JOIN `{$table_info[ 'meta_table' ]}` AS `{$field_joined}` ON 
  2615. `{$field_joined}`.`{$table_info[ 'meta_field_index' ]}` = '{$traverse[ 'name' ]}' 
  2616. AND `{$field_joined}`.`{$table_info[ 'meta_field_id' ]}` = `{$traverse_recurse[ 'joined' ]}`.`{$traverse_recurse[ 'joined_id' ]}` 
  2617. "; 
  2618.  
  2619. $table_info[ 'recurse' ] = false; 
  2620. else { 
  2621. $the_join = " 
  2622. LEFT JOIN `{$table_info[ 'meta_table' ]}` AS `{$field_joined}` ON 
  2623. `{$field_joined}`.`{$table_info[ 'meta_field_index' ]}` = '{$traverse[ 'name' ]}' 
  2624. AND `{$field_joined}`.`{$table_info[ 'meta_field_id' ]}` = `{$traverse_recurse[ 'joined' ]}`.`{$traverse_recurse[ 'joined_id' ]}` 
  2625. "; 
  2626.  
  2627. $joined_id = $table_info[ 'meta_field_id' ]; 
  2628. $joined_index = $table_info[ 'meta_field_index' ]; 
  2629.  
  2630. $traverse_recursive = array( 
  2631. 'pod' => pods_var_raw( 'name', pods_var_raw( 'pod', $table_info ) ),  
  2632. 'fields' => $traverse_recurse[ 'fields' ],  
  2633. 'joined' => $field_joined,  
  2634. 'depth' => ( $traverse_recurse[ 'depth' ] + 1 ),  
  2635. 'joined_id' => $joined_id,  
  2636. 'joined_index' => $joined_index,  
  2637. 'params' => $traverse_recurse[ 'params' ],  
  2638. 'rel_alias' => $rel_alias,  
  2639. 'last_table_info' => $table_info 
  2640. ); 
  2641.  
  2642. $the_join = apply_filters( 'pods_data_traverse_the_join', $the_join, $traverse_recurse, $traverse_recursive, $this ); 
  2643.  
  2644. if ( empty( $the_join ) ) 
  2645. return $joins; 
  2646.  
  2647. $joins[ $traverse_recurse[ 'pod' ] . '_' . $traverse_recurse[ 'depth' ] . '_' . $traverse[ 'id' ] ] = $the_join; 
  2648.  
  2649. if ( ( $traverse_recurse[ 'depth' ] + 1 ) < count( $traverse_recurse[ 'fields' ] ) && !empty( $traverse_recurse[ 'pod' ] ) && false !== $table_info[ 'recurse' ] ) 
  2650. $joins = array_merge( $joins, $this->traverse_recurse( $traverse_recursive ) ); 
  2651.  
  2652. return $joins; 
  2653.  
  2654. /** 
  2655. * Recursively join tables based on fields 
  2656. * @param array $fields Fields to recurse 
  2657. * @param null $all_fields (optional) If $fields is empty then traverse all fields, argument does not need to be passed 
  2658. * @param object $params (optional) Parameters from build() 
  2659. * @return array Array of joins 
  2660. */ 
  2661. function traverse ( $fields = null, $all_fields = null, $params = null ) { 
  2662. $joins = array(); 
  2663.  
  2664. if ( null === $fields ) 
  2665. $fields = $this->traverse_build( $all_fields, $params ); 
  2666.  
  2667. foreach ( (array) $fields as $field_group ) { 
  2668. $traverse_recurse = array( 
  2669. 'pod' => $this->pod,  
  2670. 'fields' => $fields,  
  2671. 'params' => $params,  
  2672. 'last_table_info' => $this->pod_data,  
  2673. 'joined_id' => $this->pod_data[ 'field_id' ],  
  2674. 'joined_index' => $this->pod_data[ 'field_index' ] 
  2675. ); 
  2676.  
  2677. if ( is_array( $field_group ) ) { 
  2678. $traverse_recurse[ 'fields' ] = $field_group; 
  2679.  
  2680. $joins = array_merge( $joins, $this->traverse_recurse( $traverse_recurse ) ); 
  2681. else { 
  2682. $joins = array_merge( $joins, $this->traverse_recurse( $traverse_recurse ) ); 
  2683. $joins = array_filter( $joins ); 
  2684.  
  2685. return $joins; 
  2686.  
  2687. $joins = array_filter( $joins ); 
  2688.  
  2689. return $joins; 
  2690.  
  2691. /** 
  2692. * Handle filters / actions for the class 
  2693. * @since 2.0 
  2694. */ 
  2695. private static function do_hook () { 
  2696. $args = func_get_args(); 
  2697.  
  2698. if ( empty( $args ) ) 
  2699. return false; 
  2700.  
  2701. $name = array_shift( $args ); 
  2702.  
  2703. return pods_do_hook( 'data', $name, $args ); 
  2704.  
  2705. /** 
  2706. * Get the complete sql 
  2707. * @since 2.0.5 
  2708. */ 
  2709. public function get_sql ( $sql ) { 
  2710. global $wpdb; 
  2711.  
  2712. if ( empty( $sql ) ) 
  2713. $sql = $this->sql; 
  2714.  
  2715. $sql = str_replace( array( '@wp_users', '@wp_' ), array( $wpdb->users, $wpdb->prefix ), $sql ); 
  2716.  
  2717. $sql = str_replace( '{prefix}', '@wp_', $sql ); 
  2718. $sql = str_replace( '{/prefix/}', '{prefix}', $sql ); 
  2719.  
  2720. return $sql;