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.  
  164. return ( $return ) ? $return : $default; 
  165.  
  166. /** 
  167. * Get Settings 
  168. * @param string ...$only returns a subset of the object's settings 
  169. * @return array 
  170. */ 
  171. public function get_settings() 
  172. // If the ID is not set, then we cannot pull settings from the Database. 
  173. if( ! $this->_id ) return $this->_settings; 
  174.  
  175. $form_cache = get_option( 'nf_form_' . $this->_parent_id ); 
  176. if( $form_cache ) { 
  177.  
  178. if( 'field'== $this->_type ) { 
  179.  
  180. if (isset($form_cache[ 'fields' ])) { 
  181.  
  182. foreach ($form_cache[ 'fields' ] as $object_id => $object) { 
  183. if ($this->_id != $object_id) continue; 
  184.  
  185. $this->update_settings($object['settings']); 
  186. break; 
  187.  
  188. // Only query if settings haven't been already queried or cache is FALSE. 
  189. if( ! $this->_settings || ! $this->_cache ) { 
  190.  
  191. // Build query syntax from the columns property. 
  192. $columns = '`' . implode( '`, `', $this->_columns ) . '`'; 
  193.  
  194. // Query column settings 
  195. $results = $this->_db->get_row( 
  196. SELECT $columns 
  197. FROM `$this->_table_name` 
  198. WHERE `id` = $this->_id 
  199. ); 
  200.  
  201. /** 
  202. * If the query returns results then 
  203. * assign settings using the column name as the setting key. 
  204. */ 
  205. if( $results ) { 
  206. foreach ($this->_columns as $column) { 
  207. $this->_settings[$column] = $results->$column; 
  208.  
  209. // Query settings from the meta table. 
  210. $meta_results = $this->_db->get_results( 
  211. SELECT `key`, `value` 
  212. FROM `$this->_meta_table_name` 
  213. WHERE `parent_id` = $this->_id 
  214. ); 
  215.  
  216. // Assign settings to the settings property. 
  217. foreach ($meta_results as $meta) { 
  218. $this->_settings[ $meta->key ] = $meta->value; 
  219.  
  220. // Un-serialize queried settings results. 
  221. foreach( $this->_settings as $key => $value ) { 
  222. $this->_settings[ $key ] = maybe_unserialize( $value ); 
  223.  
  224. // Check for passed arguments to limit the returned settings. 
  225. $only = func_get_args(); 
  226. if ( $only && is_array($only) 
  227. // And if the array is NOT multidimensional 
  228. && (count($only) == count($only, COUNT_RECURSIVE))) { 
  229.  
  230. // If only one setting, return a single value 
  231. if( 1 == count( $only ) ) { 
  232.  
  233. if( isset( $this->_settings[ $only[0] ] ) ) { 
  234. return $this->_settings[$only[0]]; 
  235. } else { 
  236. return NULL; 
  237.  
  238. // Flip the array to match the settings property 
  239. $only_settings = array_flip( $only ); 
  240.  
  241. // Return only the requested settings 
  242. return array_intersect_key( $this->_settings, $only_settings ); 
  243.  
  244. // Return all settings 
  245. return $this->_settings; 
  246.  
  247. /** 
  248. * Update Setting 
  249. * @param $key 
  250. * @param $value 
  251. * @return bool|false|int 
  252. */ 
  253. public function update_setting( $key, $value ) 
  254. $this->_settings[ $key ] = $value; 
  255.  
  256. return $this; 
  257.  
  258. /** 
  259. * Update Settings 
  260. * @param $data 
  261. * @return bool 
  262. */ 
  263. public function update_settings( $data ) 
  264. foreach( $data as $key => $value ) { 
  265. $this->update_setting( $key, $value ); 
  266.  
  267. return $this; 
  268.  
  269. /** 
  270. * Delete 
  271. * Delete the object, its children, and its relationships. 
  272. * @return bool 
  273. */ 
  274. public function delete() 
  275. if( ! $this->get_id() ) return; 
  276.  
  277. $results = array(); 
  278.  
  279. // Delete the object from the model's table 
  280. $results[] = $this->_db->delete( 
  281. $this->_table_name,  
  282. array( 
  283. 'id' => $this->_id 
  284. ); 
  285.  
  286. // Delete settings from the model's meta table. 
  287. $results[] = $this->_db->delete( 
  288. $this->_meta_table_name,  
  289. array( 
  290. 'parent_id' => $this->_id 
  291. ); 
  292.  
  293. // Query for child objects using the relationships table. 
  294.  
  295. $children = $this->_db->get_results( 
  296. SELECT child_id, child_type 
  297. FROM $this->_relationships_table 
  298. WHERE parent_id = $this->_id 
  299. AND parent_type = '$this->_type' 
  300. ); 
  301.  
  302. // Delete each child model 
  303. foreach( $children as $child ) { 
  304. $model = Ninja_Forms()->form()->get_model( $child->child_id, $child->child_type ); 
  305. $model->delete(); 
  306.  
  307. // Delete all relationships 
  308. $this->_db->delete( 
  309. $this->_relationships_table,  
  310. array( 
  311. 'parent_id' => $this->_id,  
  312. 'parent_type' => $this->_type 
  313. ); 
  314.  
  315. // return False if there are no query errors. 
  316. return in_array( FALSE, $results ); 
  317.  
  318. /** 
  319. * Find 
  320. * @param string $parent_id 
  321. * @param array $where 
  322. * @return array 
  323. */ 
  324. public function find( $parent_id = '', array $where = array() ) 
  325. // Build the query using the $where argument 
  326. $query = $this->build_meta_query( $parent_id, $where ); 
  327.  
  328. // Get object IDs from the query 
  329. $ids = $this->_db->get_col( $query ); 
  330.  
  331. // Get the current class name 
  332. $class = get_class( $this ); 
  333.  
  334. $results = array(); 
  335. foreach( $ids as $id ) { 
  336.  
  337. // Instantiate a new object for each ID 
  338. $results[] = $object = new $class( $this->_db, $id, $parent_id ); 
  339.  
  340. // Return an array of objects 
  341. return $results; 
  342.  
  343. /** 
  344. * UTILITY METHODS 
  345. */ 
  346.  
  347. /** 
  348. * Save 
  349. */ 
  350. public function save() 
  351. // If the ID is not set, assign an ID 
  352. if( ! $this->_id ) { 
  353.  
  354. $data = array( 'created_at' => time() ); 
  355.  
  356. if( $this->_parent_id ) { 
  357. $data['parent_id'] = $this->_parent_id; 
  358.  
  359. // Create a new row in the database 
  360. $result = $this->_db->insert( 
  361. $this->_table_name,  
  362. $data 
  363. ); 
  364.  
  365. // Assign the New ID 
  366. $this->_id = $this->_db->insert_id; 
  367. } else { 
  368.  
  369. $result = $this->_db->get_row( "SELECT * FROM $this->_table_name WHERE id = $this->_id" ); 
  370.  
  371. if( ! $result ) { 
  372. $this->_insert_row( array( 'id' => $this->_id ) ); 
  373.  
  374. $this->_save_settings(); 
  375.  
  376. // If a Temporary ID is set, return it along with the newly assigned ID. 
  377. if( $this->_tmp_id ) { 
  378. return array( $this->_tmp_id => $this->_id ); 
  379.  
  380. public function _insert_row( $data = array() ) 
  381. $data[ 'created_at' ] = time(); 
  382.  
  383. if( $this->_parent_id ) { 
  384. $data['parent_id'] = $this->_parent_id; 
  385.  
  386. // Create a new row in the database 
  387. $result = $this->_db->insert( 
  388. $this->_table_name,  
  389. $data 
  390. ); 
  391.  
  392. /** 
  393. * Cache Flag 
  394. *  
  395. * @param string $cache 
  396. * @return $this 
  397. */ 
  398. public function cache( $cache = '' ) 
  399. // Set the Cache Flag Property. 
  400. if( $cache !== '' ) { 
  401. $this->_cache = $cache; 
  402.  
  403. // Return the current object for method chaining. 
  404. return $this; 
  405.  
  406. /** 
  407. * Add Parent 
  408. * Set the Parent ID and Parent Type properties 
  409. * @param $parent_id 
  410. * @param $parent_type 
  411. * @return $this 
  412. */ 
  413. public function add_parent( $parent_id, $parent_type ) 
  414. $this->_parent_id = $parent_id; 
  415.  
  416. $this->_parent_type = $parent_type; 
  417.  
  418. // Return the current object for method chaining. 
  419. return $this; 
  420.  
  421. //----------------------------------------------------- 
  422. // Protected Methods 
  423. //----------------------------------------------------- 
  424.  
  425. /** 
  426. * Save Setting 
  427. * Save a single setting. 
  428. * @param $key 
  429. * @param $value 
  430. * @return bool|false|int 
  431. */ 
  432. protected function _save_setting( $key, $value ) 
  433. // If the setting is a column, save the settings to the model's table. 
  434. if( in_array( $key, $this->_columns ) ) { 
  435.  
  436. return $this->_db->update( 
  437. $this->_table_name,  
  438. array( 
  439. $key => $value 
  440. ),  
  441. array( 
  442. 'id' => $this->_id 
  443. ); 
  444.  
  445. $meta_row = $this->_db->get_row( 
  446. SELECT `value` 
  447. FROM `$this->_meta_table_name` 
  448. WHERE `parent_id` = $this->_id 
  449. AND `key` = '$key' 
  450. ); 
  451.  
  452. if( $meta_row ) { 
  453.  
  454. $result = $this->_db->update( 
  455. $this->_meta_table_name,  
  456. array( 
  457. 'value' => $value 
  458. ),  
  459. array( 
  460. 'key' => $key,  
  461. 'parent_id' => $this->_id 
  462. ); 
  463.  
  464. } else { 
  465.  
  466. $result = $this->_db->insert( 
  467. $this->_meta_table_name,  
  468. array( 
  469. 'key' => $key,  
  470. 'value' => $value,  
  471. 'parent_id' => $this->_id 
  472. ),  
  473. array( 
  474. '%s',  
  475. '%s',  
  476. '%d' 
  477. ); 
  478.  
  479.  
  480. return $result; 
  481.  
  482. /** 
  483. * Save Settings 
  484. * Save all settings. 
  485. * @return bool 
  486. */ 
  487. protected function _save_settings() 
  488. if( ! $this->_settings ) return; 
  489.  
  490. foreach( $this->_settings as $key => $value ) { 
  491. $value = maybe_serialize( $value ); 
  492. $this->_results[] = $this->_save_setting( $key, $value ); 
  493.  
  494. $this->_save_parent_relationship(); 
  495.  
  496. return $this->_results; 
  497.  
  498. /** 
  499. * Save Parent Relationship 
  500. * @return $this 
  501. */ 
  502. protected function _save_parent_relationship() 
  503. // ID, Type, Parent ID, and Parent Type are required for creating a relationship. 
  504. if( ! $this->_id || ! $this->_type || ! $this->_parent_id || ! $this->_parent_type ) return $this; 
  505.  
  506. // Check to see if a relationship exists. 
  507. $this->_db->get_results( 
  508. SELECT * 
  509. FROM $this->_relationships_table 
  510. WHERE `child_id` = $this->_id 
  511. AND `child_type` = '$this->_type' 
  512. ); 
  513.  
  514. // If a relationship does not exists, then create one. 
  515. if( 0 == $this->_db->num_rows ) { 
  516.  
  517. $this->_db->insert( 
  518. $this->_relationships_table,  
  519. array( 
  520. 'child_id' => $this->_id,  
  521. 'child_type' => $this->_type,  
  522. 'parent_id' => $this->_parent_id,  
  523. 'parent_type' => $this->_parent_type 
  524. ),  
  525. array( 
  526. '%d',  
  527. '%s',  
  528. '%d',  
  529. '%s',  
  530. ); 
  531.  
  532. // Return the current object for method chaining. 
  533. return $this; 
  534.  
  535. /** 
  536. * Build Meta Query 
  537. * @param string $parent_id 
  538. * @param array $where 
  539. * @return string 
  540. */ 
  541. protected function build_meta_query( $parent_id = '', array $where = array() ) 
  542. $join_statement = array(); 
  543. $where_statement = array(); 
  544.  
  545. if( $where AND is_array( $where ) ) { 
  546.  
  547. $where_conditions = array(); 
  548. foreach ($where as $key => $value) { 
  549. $conditions['key'] = $key; 
  550. $conditions['value'] = $value; 
  551.  
  552. $where_conditions[] = $conditions; 
  553.  
  554. $count = count($where); 
  555. for ($i = 0; $i < $count; $i++) { 
  556.  
  557. $join_statement[] = "INNER JOIN " . $this->_meta_table_name . " as meta$i on meta$i.parent_id = " . $this->_table_name . ".id"; 
  558. $where_statement[] = "( meta$i.key = '" . $where_conditions[$i]['key'] . "' AND meta$i.value = '" . $where_conditions[$i]['value'] . "' )"; 
  559.  
  560.  
  561. $join_statement = implode( ' ', $join_statement ); 
  562.  
  563. $where_statement = implode( ' AND ', $where_statement ); 
  564.  
  565. // TODO: Breaks SQL. Needs more testing. 
  566. // if( $where_statement ) $where_statement = "AND " . $where_statement; 
  567.  
  568. if( $parent_id ) { 
  569. $where_statement = "$this->_table_name.parent_id = $parent_id $where_statement"; 
  570.  
  571. if( ! empty( $where_statement ) ) { 
  572. $where_statement = "WHERE $where_statement"; 
  573.  
  574. return "SELECT DISTINCT $this->_table_name.id FROM $this->_table_name $join_statement $where_statement"; 
  575.  
  576.  
  577.