NF_Abstracts_Model

Class NF_Abstracts_Model.

Defined (1)

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

/includes/Abstracts/Model.php  
  1. class NF_Abstracts_Model 
  2. /** 
  3. * Database Object 
  4. * @var string 
  5. */ 
  6. protected $_db = ''; 
  7.  
  8. /** 
  9. * ID 
  10. * The ID is assigned after being saved to the database. 
  11. * @var int 
  12. */ 
  13. protected $_id = ''; 
  14.  
  15. /** 
  16. * Temporary ID 
  17. * The temporary ID is used to reference unsaved objects 
  18. * before they are stored in the database. 
  19. * @var string 
  20. */ 
  21. protected $_tmp_id = ''; 
  22.  
  23. /** 
  24. * Type 
  25. * The type is used to pragmatically identify the type 
  26. * of an object without inspecting the class. 
  27. * @var string 
  28. */ 
  29. protected $_type = ''; 
  30.  
  31. /** 
  32. * Parent ID 
  33. * The ID of the parent object. 
  34. * @var string 
  35. */ 
  36. protected $_parent_id = ''; 
  37.  
  38. /** 
  39. * Parent Type 
  40. * The type of the parent object. 
  41. * @var string 
  42. */ 
  43. protected $_parent_type = ''; 
  44.  
  45. /** 
  46. * Table Name 
  47. * The name of the table where the model objects are stored. 
  48. * @var string 
  49. */ 
  50. protected $_table_name = ''; 
  51.  
  52. /** 
  53. * Meta Table Name 
  54. * The name of the table where the object settings are stored. 
  55. * @var string 
  56. */ 
  57. protected $_meta_table_name = ''; 
  58.  
  59. /** 
  60. * ? Deprecated ? 
  61. * @var string 
  62. */ 
  63. protected $_relationships_table = 'nf3_relationships'; 
  64.  
  65. /** 
  66. * Columns 
  67. * A list of settings that are stored in the main table as columns. 
  68. * These settings are NOT stored in the meta table. 
  69. * @var array 
  70. */ 
  71. protected $_columns = array(); 
  72.  
  73. /** 
  74. * Settings 
  75. * A list of settings that are stored in the meta table. 
  76. * @var array 
  77. */ 
  78. protected $_settings = array(); 
  79.  
  80. /** 
  81. * Results 
  82. * The last results returned by a query. 
  83. * @var array 
  84. */ 
  85. protected $_results = array(); 
  86.  
  87. /** 
  88. * Cache 
  89. * A Flag for using or bypassing caching. 
  90. * @var bool 
  91. */ 
  92. protected $_cache = TRUE; 
  93.  
  94. //----------------------------------------------------- 
  95. // Public Methods 
  96. //----------------------------------------------------- 
  97.  
  98. /** 
  99. * NF_Abstracts_Model constructor. 
  100. * @param $db 
  101. * @param $id 
  102. * @param $parent_id 
  103. */ 
  104. public function __construct( $db, $id = NULL, $parent_id = '' ) 
  105. /** 
  106. * Injected the Database Dependency 
  107. */ 
  108. $this->_db = $db; 
  109.  
  110. /** 
  111. * Assign Database Tables using the DB prefix 
  112. */ 
  113. $this->_table_name = $this->_db->prefix . $this->_table_name; 
  114. $this->_meta_table_name = $this->_db->prefix . $this->_meta_table_name; 
  115. $this->_relationships_table = $this->_db->prefix . $this->_relationships_table; 
  116.  
  117. /** 
  118. * Set the object ID 
  119. * Check if the ID is Permanent (int) or Temporary (string) 
  120. */ 
  121. if( is_numeric( $id ) ) { 
  122. $this->_id = absint( $id ); 
  123. } elseif( $id ) { 
  124. $this->_tmp_id = $id; 
  125.  
  126. /** 
  127. * Set the Parent ID for context 
  128. */ 
  129. $this->_parent_id = $parent_id; 
  130.  
  131. /** 
  132. * Get the Permanent ID 
  133. * @return int 
  134. */ 
  135. public function get_id() 
  136. return intval( $this->_id ); 
  137.  
  138. /** 
  139. * Get the Temporary ID 
  140. * @return null|string 
  141. */ 
  142. public function get_tmp_id() 
  143. return $this->_tmp_id; 
  144.  
  145. /** 
  146. * Get the Type 
  147. * @return string 
  148. */ 
  149. public function get_type() 
  150. return $this->_type; 
  151.  
  152. /** 
  153. * Get a single setting with a default fallback 
  154. * @param string $setting 
  155. * @param bool $default optional 
  156. * @return string|int|bool 
  157. */ 
  158. public function get_setting( $setting, $default = FALSE ) 
  159. if( isset( $this->_settings[ $setting ] )) { 
  160. $return = $this->_settings[ $setting ]; 
  161. } else { 
  162. $return = $this->get_settings($setting); 
  163. if( is_array( $return ) && empty( $return ) ) $return = false; 
  164.  
  165. return ( $return !== false ) ? $return : $default; 
  166.  
  167. /** 
  168. * Get Settings 
  169. * @param string ...$only returns a subset of the object's settings 
  170. * @return array 
  171. */ 
  172. public function get_settings() 
  173. // If the ID is not set, then we cannot pull settings from the Database. 
  174. if( ! $this->_id ) return $this->_settings; 
  175.  
  176. if( ! $this->_settings && 'field' == $this->_type ) { 
  177. global $wpdb; 
  178. $results = $wpdb->get_results( 
  179. SELECT Meta.key, Meta.value 
  180. FROM $this->_table_name as Object 
  181. JOIN $this->_meta_table_name as Meta 
  182. ON Object.id = Meta.parent_id 
  183. WHERE Object.id = '$this->_id' 
  184. , ARRAY_A ); 
  185.  
  186. foreach( $results as $result ) { 
  187. $key = $result[ 'key' ]; 
  188. $this->_settings[ $key ] = $result[ 'value' ]; 
  189.  
  190. $field = $wpdb->get_row( 
  191. SELECT `label`, `key`, `type` 
  192. FROM $this->_table_name 
  193. WHERE `id` = '$this->_id' 
  194. ",  
  195. ARRAY_A 
  196. ); 
  197.  
  198. if( ! is_wp_error( $field ) ) { 
  199. $this->_settings[ 'label' ] = $field[ 'label' ]; 
  200. $this->_settings[ 'key' ] = $field[ 'key' ]; 
  201. $this->_settings[ 'type' ] = $field[ 'type' ]; 
  202.  
  203. if( ! $this->_settings ) { 
  204. $form_cache = get_option('nf_form_' . $this->_parent_id); 
  205. if ($form_cache) { 
  206.  
  207. if ('field' == $this->_type) { 
  208.  
  209. if (isset($form_cache['fields'])) { 
  210.  
  211. foreach ($form_cache['fields'] as $object) { 
  212. if ($this->_id != $object['id']) continue; 
  213.  
  214. $this->update_settings($object['settings']); 
  215. break; 
  216.  
  217. // Only query if settings haven't been already queried or cache is FALSE. 
  218. if( ! $this->_settings || ! $this->_cache ) { 
  219.  
  220. // Build query syntax from the columns property. 
  221. $columns = '`' . implode( '`, `', $this->_columns ) . '`'; 
  222.  
  223. // Query column settings 
  224. $results = $this->_db->get_row( 
  225. SELECT $columns 
  226. FROM `$this->_table_name` 
  227. WHERE `id` = $this->_id 
  228. ); 
  229.  
  230. /** 
  231. * If the query returns results then 
  232. * assign settings using the column name as the setting key. 
  233. */ 
  234. if( $results ) { 
  235. foreach ($this->_columns as $column) { 
  236. $this->_settings[$column] = $results->$column; 
  237.  
  238. // Query settings from the meta table. 
  239. $meta_results = $this->_db->get_results( 
  240. SELECT `key`, `value` 
  241. FROM `$this->_meta_table_name` 
  242. WHERE `parent_id` = $this->_id 
  243. ); 
  244.  
  245. // Assign settings to the settings property. 
  246. foreach ($meta_results as $meta) { 
  247. $this->_settings[ $meta->key ] = $meta->value; 
  248.  
  249. // Un-serialize queried settings results. 
  250. foreach( $this->_settings as $key => $value ) { 
  251. $this->_settings[ $key ] = maybe_unserialize( $value ); 
  252.  
  253. // Check for passed arguments to limit the returned settings. 
  254. $only = func_get_args(); 
  255. if ( $only && is_array($only) 
  256. // And if the array is NOT multidimensional 
  257. && (count($only) == count($only, COUNT_RECURSIVE))) { 
  258.  
  259. // If only one setting, return a single value 
  260. if( 1 == count( $only ) ) { 
  261.  
  262. if( isset( $this->_settings[ $only[0] ] ) ) { 
  263. return $this->_settings[$only[0]]; 
  264. } else { 
  265. return NULL; 
  266.  
  267. // Flip the array to match the settings property 
  268. $only_settings = array_flip( $only ); 
  269.  
  270. // Return only the requested settings 
  271. return array_intersect_key( $this->_settings, $only_settings ); 
  272.  
  273. // Return all settings 
  274. return $this->_settings; 
  275.  
  276. /** 
  277. * Update Setting 
  278. * @param $key 
  279. * @param $value 
  280. * @return bool|false|int 
  281. */ 
  282. public function update_setting( $key, $value ) 
  283. $this->_settings[ $key ] = $value; 
  284.  
  285. return $this; 
  286.  
  287. /** 
  288. * Update Settings 
  289. * @param $data 
  290. * @return bool 
  291. */ 
  292. public function update_settings( $data ) 
  293. if( is_array( $data ) ) { 
  294. foreach ($data as $key => $value) { 
  295. $this->update_setting($key, $value); 
  296.  
  297. return $this; 
  298.  
  299. /** 
  300. * Delete 
  301. * Delete the object, its children, and its relationships. 
  302. * @return bool 
  303. */ 
  304. public function delete() 
  305. if( ! $this->get_id() ) return; 
  306.  
  307. $results = array(); 
  308.  
  309. // Delete the object from the model's table 
  310. $results[] = $this->_db->delete( 
  311. $this->_table_name,  
  312. array( 
  313. 'id' => $this->_id 
  314. ); 
  315.  
  316. // Delete settings from the model's meta table. 
  317. $results[] = $this->_db->delete( 
  318. $this->_meta_table_name,  
  319. array( 
  320. 'parent_id' => $this->_id 
  321. ); 
  322.  
  323. // Query for child objects using the relationships table. 
  324.  
  325. $children = $this->_db->get_results( 
  326. SELECT child_id, child_type 
  327. FROM $this->_relationships_table 
  328. WHERE parent_id = $this->_id 
  329. AND parent_type = '$this->_type' 
  330. ); 
  331.  
  332. // Delete each child model 
  333. foreach( $children as $child ) { 
  334. $model = Ninja_Forms()->form()->get_model( $child->child_id, $child->child_type ); 
  335. $model->delete(); 
  336.  
  337. // Delete all relationships 
  338. $this->_db->delete( 
  339. $this->_relationships_table,  
  340. array( 
  341. 'parent_id' => $this->_id,  
  342. 'parent_type' => $this->_type 
  343. ); 
  344.  
  345. // return False if there are no query errors. 
  346. return in_array( FALSE, $results ); 
  347.  
  348. /** 
  349. * Find 
  350. * @param string $parent_id 
  351. * @param array $where 
  352. * @return array 
  353. */ 
  354. public function find( $parent_id = '', array $where = array() ) 
  355. // Build the query using the $where argument 
  356. $query = $this->build_meta_query( $parent_id, $where ); 
  357.  
  358. // Get object IDs from the query 
  359. $ids = $this->_db->get_col( $query ); 
  360.  
  361. // Get the current class name 
  362. $class = get_class( $this ); 
  363.  
  364. $results = array(); 
  365. foreach( $ids as $id ) { 
  366.  
  367. // Instantiate a new object for each ID 
  368. $results[] = $object = new $class( $this->_db, $id, $parent_id ); 
  369.  
  370. // Return an array of objects 
  371. return $results; 
  372.  
  373. /** 
  374. * UTILITY METHODS 
  375. */ 
  376.  
  377. /** 
  378. * Save 
  379. */ 
  380. public function save() 
  381. // If the ID is not set, assign an ID 
  382. if( ! $this->_id ) { 
  383.  
  384. $data = array( 'created_at' => time() ); 
  385.  
  386. if( $this->_parent_id ) { 
  387. $data['parent_id'] = $this->_parent_id; 
  388.  
  389. // Create a new row in the database 
  390. $result = $this->_db->insert( 
  391. $this->_table_name,  
  392. $data 
  393. ); 
  394.  
  395. // Assign the New ID 
  396. $this->_id = $this->_db->insert_id; 
  397. } else { 
  398.  
  399. $result = $this->_db->get_row( "SELECT * FROM $this->_table_name WHERE id = $this->_id" ); 
  400.  
  401. if( ! $result ) { 
  402. $this->_insert_row( array( 'id' => $this->_id ) ); 
  403.  
  404. $this->_save_settings(); 
  405.  
  406. // If a Temporary ID is set, return it along with the newly assigned ID. 
  407. if( $this->_tmp_id ) { 
  408. return array( $this->_tmp_id => $this->_id ); 
  409.  
  410. public function _insert_row( $data = array() ) 
  411. $data[ 'created_at' ] = time(); 
  412.  
  413. if( $this->_parent_id ) { 
  414. $data['parent_id'] = $this->_parent_id; 
  415.  
  416. // Create a new row in the database 
  417. $result = $this->_db->insert( 
  418. $this->_table_name,  
  419. $data 
  420. ); 
  421.  
  422. /** 
  423. * Cache Flag 
  424. * @param string $cache 
  425. * @return $this 
  426. */ 
  427. public function cache( $cache = '' ) 
  428. // Set the Cache Flag Property. 
  429. if( $cache !== '' ) { 
  430. $this->_cache = $cache; 
  431.  
  432. // Return the current object for method chaining. 
  433. return $this; 
  434.  
  435. /** 
  436. * Add Parent 
  437. * Set the Parent ID and Parent Type properties 
  438. * @param $parent_id 
  439. * @param $parent_type 
  440. * @return $this 
  441. */ 
  442. public function add_parent( $parent_id, $parent_type ) 
  443. $this->_parent_id = $parent_id; 
  444.  
  445. $this->_parent_type = $parent_type; 
  446.  
  447. // Return the current object for method chaining. 
  448. return $this; 
  449.  
  450. //----------------------------------------------------- 
  451. // Protected Methods 
  452. //----------------------------------------------------- 
  453.  
  454. /** 
  455. * Save Setting 
  456. * Save a single setting. 
  457. * @param $key 
  458. * @param $value 
  459. * @return bool|false|int 
  460. */ 
  461. protected function _save_setting( $key, $value ) 
  462. // If the setting is a column, save the settings to the model's table. 
  463. if( in_array( $key, $this->_columns ) ) { 
  464.  
  465. return $this->_db->update( 
  466. $this->_table_name,  
  467. array( 
  468. $key => $value 
  469. ),  
  470. array( 
  471. 'id' => $this->_id 
  472. ); 
  473.  
  474. $meta_row = $this->_db->get_row( 
  475. SELECT `value` 
  476. FROM `$this->_meta_table_name` 
  477. WHERE `parent_id` = $this->_id 
  478. AND `key` = '$key' 
  479. ); 
  480.  
  481. if( $meta_row ) { 
  482.  
  483. $result = $this->_db->update( 
  484. $this->_meta_table_name,  
  485. array( 
  486. 'value' => $value 
  487. ),  
  488. array( 
  489. 'key' => $key,  
  490. 'parent_id' => $this->_id 
  491. ); 
  492.  
  493. } else { 
  494.  
  495. $result = $this->_db->insert( 
  496. $this->_meta_table_name,  
  497. array( 
  498. 'key' => $key,  
  499. 'value' => $value,  
  500. 'parent_id' => $this->_id 
  501. ),  
  502. array( 
  503. '%s',  
  504. '%s',  
  505. '%d' 
  506. ); 
  507.  
  508.  
  509. return $result; 
  510.  
  511. /** 
  512. * Save Settings 
  513. * Save all settings. 
  514. * @return bool 
  515. */ 
  516. protected function _save_settings() 
  517. if( ! $this->_settings ) return; 
  518.  
  519. foreach( $this->_settings as $key => $value ) { 
  520. $value = maybe_serialize( $value ); 
  521. $this->_results[] = $this->_save_setting( $key, $value ); 
  522.  
  523. $this->_save_parent_relationship(); 
  524.  
  525. return $this->_results; 
  526.  
  527. /** 
  528. * Save Parent Relationship 
  529. * @return $this 
  530. */ 
  531. protected function _save_parent_relationship() 
  532. // ID, Type, Parent ID, and Parent Type are required for creating a relationship. 
  533. if( ! $this->_id || ! $this->_type || ! $this->_parent_id || ! $this->_parent_type ) return $this; 
  534.  
  535. // Check to see if a relationship exists. 
  536. $this->_db->get_results( 
  537. SELECT * 
  538. FROM $this->_relationships_table 
  539. WHERE `child_id` = $this->_id 
  540. AND `child_type` = '$this->_type' 
  541. ); 
  542.  
  543. // If a relationship does not exists, then create one. 
  544. if( 0 == $this->_db->num_rows ) { 
  545.  
  546. $this->_db->insert( 
  547. $this->_relationships_table,  
  548. array( 
  549. 'child_id' => $this->_id,  
  550. 'child_type' => $this->_type,  
  551. 'parent_id' => $this->_parent_id,  
  552. 'parent_type' => $this->_parent_type 
  553. ),  
  554. array( 
  555. '%d',  
  556. '%s',  
  557. '%d',  
  558. '%s',  
  559. ); 
  560.  
  561. // Return the current object for method chaining. 
  562. return $this; 
  563.  
  564. /** 
  565. * Build Meta Query 
  566. * @param string $parent_id 
  567. * @param array $where 
  568. * @return string 
  569. */ 
  570. protected function build_meta_query( $parent_id = '', array $where = array() ) 
  571. $join_statement = array(); 
  572. $where_statement = array(); 
  573.  
  574. if( $where AND is_array( $where ) ) { 
  575.  
  576. $where_conditions = array(); 
  577. foreach ($where as $key => $value) { 
  578. $conditions['key'] = $key; 
  579. $conditions['value'] = $value; 
  580.  
  581. $where_conditions[] = $conditions; 
  582.  
  583. $count = count($where); 
  584. for ($i = 0; $i < $count; $i++) { 
  585.  
  586. $join_statement[] = "INNER JOIN " . $this->_meta_table_name . " as meta$i on meta$i.parent_id = " . $this->_table_name . ".id"; 
  587. $where_statement[] = "( meta$i.key = '" . $where_conditions[$i]['key'] . "' AND meta$i.value = '" . $where_conditions[$i]['value'] . "' )"; 
  588.  
  589.  
  590. $join_statement = implode( ' ', $join_statement ); 
  591.  
  592. $where_statement = implode( ' AND ', $where_statement ); 
  593.  
  594. // TODO: Breaks SQL. Needs more testing. 
  595. // if( $where_statement ) $where_statement = "AND " . $where_statement; 
  596.  
  597. if( $parent_id ) { 
  598. $where_statement = "$this->_table_name.parent_id = $parent_id $where_statement"; 
  599.  
  600. if( ! empty( $where_statement ) ) { 
  601. $where_statement = "WHERE $where_statement"; 
  602.  
  603. return "SELECT DISTINCT $this->_table_name.id FROM $this->_table_name $join_statement $where_statement"; 
  604.  
  605.  
  606.