PageRenderTime 91ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 1ms

/fuel/modules/fuel/core/MY_Model.php

https://github.com/jamiegrand/FUEL-CMS
PHP | 5848 lines | 3047 code | 628 blank | 2173 comment | 491 complexity | c2aa7e239a44d91c712ed7c81bd6d4f1 MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * FUEL CMS
  4. * http://www.getfuelcms.com
  5. *
  6. * An open source Content Management System based on the
  7. * Codeigniter framework (http://codeigniter.com)
  8. *
  9. * @package FUEL CMS
  10. * @author David McReynolds @ Daylight Studio
  11. * @copyright Copyright (c) 2014, Run for Daylight LLC.
  12. * @license http://docs.getfuelcms.com/general/license
  13. * @link http://www.getfuelcms.com
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * MY_Model class
  18. *
  19. * An extension of the Model class to map data operations to a table.
  20. * Depends upon the Validator library, date helper and the string helper.
  21. *
  22. * Inspired from this post here Developer13:
  23. * http://codeigniter.com/forums/viewthread/88769/
  24. *
  25. * @package FUEL CMS
  26. * @subpackage Libraries
  27. * @category Libraries
  28. * @author David McReynolds @ Daylight Studio
  29. * @link http://docs.getfuelcms.com/libraries/my_model
  30. * @prefix $this->example_model->
  31. */
  32. require_once(FUEL_PATH.'libraries/Validator.php');
  33. class MY_Model extends CI_Model {
  34. public $auto_validate = TRUE; // use auto-validation before saving
  35. public $return_method = 'auto'; // object, array, query, auto
  36. // fields to auto validate
  37. public $auto_validate_fields = array(
  38. 'email|email_address' => 'valid_email',
  39. 'phone|phone_number' => 'valid_phone'
  40. );
  41. public $required = array(); // an array of required fields. If a key => val is provided, the key is name of the field and the value is the error message to display
  42. public $default_required_message = "Please fill out the required field '%1s'"; // the default required validator message
  43. public $auto_date_add = array('date_added', 'entry_date'); // field names to automatically set the date when the value is NULL
  44. public $auto_date_update = array('last_modified', 'last_updated'); // field names to automatically set the date on updates
  45. public $date_use_gmt = FALSE; // determines whether to use GMT time when storing dates and times
  46. public $default_date = 0; // default date value that get's passed to the model on save. Using 0000-00-00 will not work if it is a required field since it is not seen as an empty value
  47. public $auto_trim = TRUE; // will trim on clean
  48. public $auto_encode_entities = TRUE; // determines whether to automatically encode html entities. An array can be set instead of a boolean value for the names of the fields to perform the safe_htmlentities on
  49. public $xss_clean = FALSE; // determines whether automatically run the xss_clean. An array can be set instead of a boolean value for the names of the fields to perform the xss_clean on
  50. public $readonly = FALSE; // sets the model to readonly mode where you can't save or delete data
  51. public $hidden_fields = array(); // fields to hide when creating a form
  52. public $unique_fields = array(); // fields that are not IDs but are unique. Can also be an array of arrays for compound keys
  53. public $linked_fields = array(); // fields that are linked meaning one value helps to determine another. Key is the field, value is a function name to transform it. (e.g. array('slug' => 'title'), or array('slug' => arry('name' => 'strtolower')));
  54. public $serialized_fields = array(); // fields that contain serialized data. This will automatically serialize before saving and unserialize data upon retrieving
  55. public $default_serialization_method = 'json'; // the default serialization method. Options are 'json' and 'serialize'
  56. public $boolean_fields = array(); // fields that are tinyint and should be treated as boolean
  57. public $suffix = '_model'; // the suffix used for the data record class
  58. public $foreign_keys = array(); // map foreign keys to table models
  59. public $has_many = array(); // keys are model, which can be a key value pair with the key being the module and the value being the model, module (if not specified in model parameter), relationships_model, foreign_key, candidate_key
  60. public $belongs_to = array(); // keys are model, which can be a key value pair with the key being the module and the value being the model, module (if not specified in model parameter), relationships_model, foreign_key, candidate_key
  61. public $representatives = array(); // an array of fields that have arrays or regular expression values to match against different field types (e.g. 'number'=>'bigint|smallint|tinyint|int')
  62. public $custom_fields = array(); // an array of field names/types that map to a specific class
  63. public $formatters = array(); // an array of helper formatter functions related to a specific field type (e.g. string, datetime, number), or name (e.g. title, content) that can augment field results
  64. protected $db; // CI database object
  65. protected $table_name; // the table name to associate the model with
  66. protected $key_field = 'id'; // usually the tables primary key(s)... can be an array if compound key
  67. protected $normalized_save_data = NULL; // the saved data before it is cleaned
  68. protected $cleaned_data = NULL; // data after it is cleaned
  69. protected $dsn = ''; // the DSN string to connect to the database... if blank it will pull in from database config file
  70. protected $has_auto_increment = TRUE; // does the table have auto_increment?
  71. protected $record_class = ''; // the name of the record class (if it can't be determined)
  72. protected $friendly_name = ''; // a friendlier name of the group of objects
  73. protected $singular_name = ''; // a friendly singular name of the object
  74. protected $rules = array(); // validation rules
  75. protected $fields = array(); // fields in the table
  76. protected $use_common_query = TRUE; // include the _common_query method for each query
  77. protected $validator = NULL; // the validator object
  78. protected $clear_related_on_save = 'AUTO'; // clears related records before saving
  79. protected $_tables = array(); // an array of table names with the key being the alias and the value being the actual table
  80. /**
  81. * Constructor - Sets MY_Model preferences
  82. *
  83. * The constructor can be passed an array of config values
  84. */
  85. public function __construct($table = NULL, $params = array())
  86. {
  87. parent::__construct();
  88. $this->load->helper('string');
  89. $this->load->helper('date');
  90. $this->load->helper('security');
  91. $this->load->helper('inflector');
  92. $this->load->helper('language');
  93. $this->load->module_language(FUEL_FOLDER, 'model');
  94. $this->initialize($table, $params);
  95. }
  96. // --------------------------------------------------------------------
  97. /**
  98. * Initialize the user preferences
  99. *
  100. * Accepts an associative array as input, containing display preferences
  101. *
  102. * @access public
  103. * @param string the table name
  104. * @param array config preferences
  105. * @return void
  106. */
  107. public function initialize($table = NULL, $params = array())
  108. {
  109. if (!empty($table))
  110. {
  111. $this->table_name = $table;
  112. }
  113. else
  114. {
  115. $this->table_name = strtolower(get_class($this));
  116. }
  117. if (!empty($params))
  118. {
  119. foreach ($params as $key => $val)
  120. {
  121. if (isset($this->$key))
  122. {
  123. $this->$key = $val;
  124. }
  125. }
  126. }
  127. // if a DSN property is set,then we will load that database in
  128. if (!empty($this->dsn))
  129. {
  130. $this->db = $this->load->database($this->dsn, TRUE, TRUE);
  131. }
  132. else
  133. {
  134. // else we use the database set on the CI object
  135. if (empty($this->db))
  136. {
  137. $this->load->database($this->dsn);
  138. }
  139. $CI =& get_instance();
  140. if (isset($CI->db))
  141. {
  142. // create a copy of the DB object to prevent cross model interference
  143. unset($this->db);
  144. $this->db = clone $CI->db;
  145. }
  146. else
  147. {
  148. $CI->load->language('db');
  149. show_error(lang('db_unable_to_connect'));
  150. }
  151. }
  152. $this->validator = new Validator();
  153. $this->validator->register_to_global_errors = FALSE;
  154. // load any additional classes needed for custom fields
  155. $this->load_custom_field_classes();
  156. }
  157. // --------------------------------------------------------------------
  158. /**
  159. * Returns the database object
  160. *
  161. <code>
  162. $db = $this->examples_model->db();
  163. </code>
  164. *
  165. * @access public
  166. * @return array
  167. */
  168. public function &db()
  169. {
  170. //$this->_check_readonly();
  171. return $this->db;
  172. }
  173. // --------------------------------------------------------------------
  174. /**
  175. * Gets the short name minus the suffix
  176. *
  177. <code>
  178. echo $this->examples_model->short_name(TRUE);
  179. // examples
  180. </code>
  181. *
  182. * @access public
  183. * @param boolean lower case the name (optional)
  184. * @param boolean return the record clas name (optional)
  185. * @return array
  186. */
  187. public function short_name($lower = FALSE, $record_class = FALSE)
  188. {
  189. $class_name = ($record_class) ? $this->record_class_name() : get_class($this);
  190. $end_index = strlen($class_name) - strlen($this->suffix);
  191. $short_name = substr($class_name, 0, $end_index);
  192. if ($lower)
  193. {
  194. return strtolower($short_name);
  195. }
  196. else
  197. {
  198. return $short_name;
  199. }
  200. }
  201. // --------------------------------------------------------------------
  202. /**
  203. * Gets the name of the model object. By default it will be the same as the short_name(FALSE, FALSE) if no "friendly_name" value is specfied on the model
  204. *
  205. <code>
  206. echo $this->examples_model->friendly_name(TRUE);
  207. // examples
  208. </code>
  209. *
  210. * @access public
  211. * @param boolean lower case the name (optional)
  212. * @return array
  213. */
  214. public function friendly_name($lower = FALSE)
  215. {
  216. if (!empty($this->friendly_name))
  217. {
  218. if ($lower)
  219. {
  220. return strtolower($this->friendly_name);
  221. }
  222. return $this->friendly_name;
  223. }
  224. $friendly_name = $this->short_name($lower, FALSE);
  225. $friendly_name = ucfirst(str_replace('_', ' ', $friendly_name));
  226. return $friendly_name;
  227. }
  228. // --------------------------------------------------------------------
  229. /**
  230. * Gets the singular name of the model object. By default it will be the same as the short_name(FALSE, TRUE) if no "singular_name" value is specfied on the model
  231. *
  232. <code>
  233. echo $this->examples_model->singular_name(TRUE);
  234. // example
  235. </code>
  236. *
  237. * @access public
  238. * @param boolean lower case the name (optional)
  239. * @return array
  240. */
  241. public function singular_name($lower = FALSE)
  242. {
  243. if (!empty($this->singular_name))
  244. {
  245. if ($lower)
  246. {
  247. return strtolower($this->singular_name);
  248. }
  249. return $this->singular_name;
  250. }
  251. $singular_name = $this->short_name($lower, TRUE);
  252. $singular_name = ucfirst(str_replace('_', ' ', $singular_name));
  253. return $singular_name;
  254. }
  255. // --------------------------------------------------------------------
  256. /**
  257. * Get the table name
  258. *
  259. <code>
  260. echo $this->examples_model->table_name();
  261. // examples
  262. </code>
  263. *
  264. * @access public
  265. * @return array
  266. */
  267. public function table_name()
  268. {
  269. return $this->table_name;
  270. }
  271. // --------------------------------------------------------------------
  272. /**
  273. * Sets the aliases to table(s) that you can use in your queries
  274. *
  275. <code>
  276. $my_tables = array('mytable' => 'my_table');
  277. $this->examples_model->set_tables($my_tables);
  278. </code>
  279. *
  280. * @access public
  281. * @param array an array of tables
  282. * @return void
  283. */
  284. public function set_tables($tables)
  285. {
  286. $this->_tables = array_merge($this->_tables, $tables);
  287. }
  288. // --------------------------------------------------------------------
  289. /**
  290. * Gets the table(s) name based on the configuration
  291. *
  292. <code>
  293. $table_name = $this->examples_model->tables('my_table');
  294. </code>
  295. *
  296. * @access public
  297. * @param string the table name (optional)
  298. * @return string
  299. */
  300. public function tables($table = NULL)
  301. {
  302. if (!empty($table))
  303. {
  304. if (isset($this->_tables[$table]))
  305. {
  306. return $this->_tables[$table];
  307. }
  308. else
  309. {
  310. return NULL;
  311. }
  312. }
  313. else
  314. {
  315. return $this->_tables;
  316. }
  317. return NULL;
  318. }
  319. // --------------------------------------------------------------------
  320. /**
  321. * Get the key field(s)
  322. *
  323. <code>
  324. $fields = $this->examples_model->key_field();
  325. </code>
  326. *
  327. * @access public
  328. * @return array
  329. */
  330. public function key_field()
  331. {
  332. return $this->key_field;
  333. }
  334. // --------------------------------------------------------------------
  335. /**
  336. * Get the fields of the table
  337. *
  338. <code>
  339. $fields = $this->examples_model->fields();
  340. foreach($fields as $field)
  341. {
  342. echo $field; // field name
  343. }
  344. </code>
  345. *
  346. * @access public
  347. * @return array
  348. */
  349. public function fields()
  350. {
  351. if (empty($this->fields)) $this->fields = $this->db->list_fields($this->table_name);
  352. return $this->fields;
  353. }
  354. // --------------------------------------------------------------------
  355. /**
  356. * Get the results of the query
  357. *
  358. <code>
  359. $rows = $this->examples_model->get(TRUE, 'object', FALSE);
  360. foreach($rows->result() as $row)
  361. {
  362. echo $row->name;
  363. }
  364. // The third parameter is the column name to be used as the array key value (if <dfn>$force_array</dfn> is set to <dfn>TRUE</dfn>)
  365. $rows = $this->examples_model->get(TRUE, 'object', 'id');
  366. foreach($rows->result() as $id => $row)
  367. {
  368. echo $id;
  369. }
  370. </code>
  371. *
  372. * @access public
  373. * @param boolean return multiple records (optional)
  374. * @param string method return type (object, array, query, auto) (optional)
  375. * @param string the column to use for an associative key array (optional)
  376. * @param boolean determine whether to use the _common_query method in the query (optional)
  377. * @return array
  378. */
  379. public function get($force_array = TRUE, $return_method = NULL, $assoc_key = NULL, $use_common_query = NULL){
  380. if (!empty($this->return_method) AND empty($return_method)) $return_method = $this->return_method;
  381. //$this->fields();
  382. if (!isset($use_common_query)) $use_common_query = $this->use_common_query;
  383. // common query if exists
  384. if (method_exists($this, '_common_query') AND $use_common_query)
  385. {
  386. $this->_common_query();
  387. }
  388. if (empty($this->db->ar_select))
  389. {
  390. $this->db->select($this->table_name.'.*'); // make select table specific
  391. }
  392. //Get the data out of the database
  393. $query = $this->db->get($this->table_name);
  394. if (empty($query)) $query = new MY_DB_mysql_result();
  395. if ($this->return_method == 'query')
  396. {
  397. return $query;
  398. }
  399. if ($return_method == 'array' OR !class_exists($this->record_class_name()))
  400. {
  401. if ($return_method == 'object')
  402. {
  403. $result_objects = (!empty($assoc_key)) ? $query->result_assoc($assoc_key) : $query->result() ;
  404. }
  405. else
  406. {
  407. $result_objects = (!empty($assoc_key)) ? $query->result_assoc_array($assoc_key) : $query->result_array();
  408. }
  409. $this->last_data_set = new Data_set($result_objects, $force_array);
  410. }
  411. else
  412. {
  413. $result_objects = $this->map_query_records($query, $assoc_key);
  414. $this->last_data_set = new Data_set($result_objects, $force_array);
  415. }
  416. $query->free_result();
  417. //This array holds all result data
  418. return $this->last_data_set;
  419. }
  420. // --------------------------------------------------------------------
  421. /**
  422. * Maps a query result object to an array of record objects
  423. *
  424. <code>
  425. ...
  426. $query = $this->db->query('SELECT * FROM USERS');
  427. $users = $this->examples_model->map_query_records($query, 'id');
  428. foreach($users as $id => $user)
  429. {
  430. echo $user->name;
  431. }
  432. </code>
  433. *
  434. * @access public
  435. * @param object the query object
  436. * @param string the field name to be used the key value (optional)
  437. * @return array
  438. */
  439. public function map_query_records($query, $assoc_key = NULL)
  440. {
  441. $result = $query->result_array();
  442. $result_objects = array();
  443. if (!empty($result))
  444. {
  445. foreach ($result as $row)
  446. {
  447. $record = $this->map_to_record_class($row);
  448. if (!empty($assoc_key))
  449. {
  450. $result_objects[$row[$assoc_key]] = $record;
  451. }
  452. else
  453. {
  454. $result_objects[] = $record;
  455. }
  456. }
  457. }
  458. return $result_objects;
  459. }
  460. // --------------------------------------------------------------------
  461. /**
  462. * Maps an associative record array to a record object
  463. *
  464. <code>
  465. $my_user['id'] = 1;
  466. $my_user['name'] = 'Darth Vader';
  467. $my_user['email'] = 'darth@deathstar.com';
  468. $my_custom_record = $this->examples_model->map_to_record_class($my_user);
  469. echo $my_custom_record->name;
  470. </code>
  471. *
  472. * @access public
  473. * @param array field values
  474. * @param array all the fields available for the object (optional)
  475. * @return array
  476. */
  477. public function map_to_record_class($row, $fields = NULL)
  478. {
  479. if (empty($fields))
  480. {
  481. $fields = array_keys($row);
  482. }
  483. $record_class = $this->record_class_name();
  484. $record = new $record_class();
  485. $record->initialize($this, $fields);
  486. $record->fill($row);
  487. return $record;
  488. }
  489. // --------------------------------------------------------------------
  490. /**
  491. * Get the results of the query
  492. *
  493. <code>
  494. $examples = $this->examples_model->find_all(array('published' => 'yes'), 'date_added desc');
  495. </code>
  496. *
  497. * @access public
  498. * @param string the type of find to perform. Options are "key", "one", "options", "all" and find_"{your_method}". By default it will perform a find_all (optional)
  499. * @param mixed an array or string containg the where paramters of a query (optional)
  500. * @param string the order by of the query (optional)
  501. * @param int the number of records to limit in the results (optional)
  502. * @param int the offset value for the results (optional)
  503. * @param string return type (object, array, query, auto) (optional)
  504. * @param string the column to use for an associative key array (optional)
  505. * @return array
  506. */
  507. public function find($find = 'all', $where = NULL, $order = NULL, $limit = NULL, $offset = NULL, $return_method = NULL, $assoc_key = NULL)
  508. {
  509. // allows for just a single parameter of arrays to be passed
  510. if (is_array($find))
  511. {
  512. extract($find);
  513. }
  514. $data = array();
  515. if ($find === 'key')
  516. {
  517. $data = $this->find_by_key($where, $return_method);
  518. }
  519. else if ($find === 'one')
  520. {
  521. $data = $this->find_one($where, $order, $return_method);
  522. }
  523. else if ($find === 'options')
  524. {
  525. $data = $this->options_list(NULL, NULL, $where, $order);
  526. }
  527. else
  528. {
  529. if (empty($find) OR $find == 'all')
  530. {
  531. $data = $this->find_all($where, $order, $limit, $offset, $return_method, $assoc_key);
  532. }
  533. else
  534. {
  535. $method = 'find_'.$find;
  536. if (is_callable(array($this, $method)))
  537. {
  538. $args = func_get_args();
  539. array_shift($args);
  540. $data = call_user_func_array(array($this, $method), $args);
  541. }
  542. else
  543. {
  544. return FALSE;
  545. }
  546. }
  547. }
  548. return $data;
  549. }
  550. // --------------------------------------------------------------------
  551. /**
  552. * Get one record result based on the key value
  553. *
  554. <code>
  555. $id = 1;
  556. $example = $this->examples_model->find_by_key($id, 'object');
  557. </code>
  558. *
  559. * @access public
  560. * @param string the key value to find a single record
  561. * @param mixed return type (object, array, query, auto) (optional)
  562. * @return array
  563. */
  564. public function find_by_key($key_val, $return_method = NULL)
  565. {
  566. $where = array();
  567. if (is_array($key_val))
  568. {
  569. $key_field = (array) $this->key_field;
  570. foreach($key_field as $val)
  571. {
  572. if (is_array($key_val))
  573. {
  574. foreach($key_val as $key2 => $val2)
  575. {
  576. if ($key2 == $val)
  577. {
  578. $where[$val] = $val2;
  579. }
  580. }
  581. }
  582. }
  583. }
  584. else
  585. {
  586. $where[$this->table_name.'.'.$this->key_field] = $key_val;
  587. }
  588. return $this->find_one($where, NULL, $return_method);
  589. }
  590. // --------------------------------------------------------------------
  591. /**
  592. * Get one record result
  593. *
  594. <code>
  595. $example = $this->examples_model->find_one(array('published' => 'yes'), ''asc');
  596. </code>
  597. *
  598. * @access public
  599. * @param mixed an array or string containg the where paramters of a query (optional)
  600. * @param string the order by of the query (optional)
  601. * @param string return type (object, array, query, auto) (optional)
  602. * @return array
  603. */
  604. public function find_one($where = array(), $order_by = NULL, $return_method = NULL)
  605. {
  606. $where = $this->_safe_where($where);
  607. $this->_handle_where($where);
  608. if (!empty($order_by)) $this->db->order_by($order_by);
  609. $this->db->limit(1);
  610. $query = $this->get(FALSE, $return_method);
  611. if ($return_method == 'query') return $query;
  612. $data = $query->result();
  613. // unserialize any data
  614. if ($return_method == 'array')
  615. {
  616. $data = $this->unserialize_field_values($data);
  617. }
  618. return $data;
  619. }
  620. // --------------------------------------------------------------------
  621. /**
  622. * Get one record result as an array
  623. *
  624. <code>
  625. $examples = $this->examples_model->find_one_array(array('published' => 'yes'), 'date_added desc');
  626. </code>
  627. *
  628. * @access public
  629. * @param mixed an array or string containg the where paramters of a query
  630. * @param string the order by of the query (optional)
  631. * @return array
  632. */
  633. public function find_one_array($where, $order_by = NULL)
  634. {
  635. return $this->find_one($where, $order_by, 'array');
  636. }
  637. // --------------------------------------------------------------------
  638. /**
  639. * Get the results of the query
  640. *
  641. <code>
  642. $examples = $this->examples_model->find_all(array('published' => 'yes'), 'date_added desc');
  643. </code>
  644. *
  645. * @access public
  646. * @param mixed an array or string containg the where paramters of a query (optional)
  647. * @param string the order by of the query (optional)
  648. * @param int the number of records to limit in the results (optional)
  649. * @param int the offset value for the results (optional)
  650. * @param string return type (object, array, query, auto) (optional)
  651. * @param string the column to use for an associative key array (optional)
  652. * @return array
  653. */
  654. public function find_all($where = array(), $order_by = NULL, $limit = NULL, $offset = NULL, $return_method = NULL, $assoc_key = NULL)
  655. {
  656. $where = $this->_safe_where($where);
  657. $this->_handle_where($where);
  658. $params = array('order_by', 'limit', 'offset');
  659. foreach($params as $method)
  660. {
  661. if (!empty($$method)) $this->db->$method($$method);
  662. }
  663. $query = $this->get(TRUE, $return_method, $assoc_key);
  664. if ($return_method == 'query') return $query;
  665. $data = $query->result();
  666. // unserialize any data if the return method is an array. If it is a custom object, then we let the object take care of it
  667. if ($return_method == 'array')
  668. {
  669. $data = $this->unserialize_field_values($data);
  670. }
  671. return $data;
  672. }
  673. // --------------------------------------------------------------------
  674. /**
  675. * Get the results of the query as an array
  676. *
  677. <code>
  678. $examples = $this->examples_model->find_all_array(array('published' => 'yes'), 'date_added desc');
  679. </code>
  680. *
  681. * @access public
  682. * @param mixed an array or string containg the where paramters of a query (optional)
  683. * @param string the order by of the query (optional)
  684. * @param int the number of records to limit in the results (optional)
  685. * @param int the offset value for the results (optional)
  686. * @return array
  687. */
  688. public function find_all_array($where = array(), $order_by = NULL, $limit = NULL, $offset = NULL)
  689. {
  690. return $this->find_all($where, $order_by, $limit, $offset, 'array');
  691. }
  692. // --------------------------------------------------------------------
  693. /**
  694. * Get the results of the query returned as a keyed array of objects
  695. *
  696. <code>
  697. $examples = $this->examples_model->find_all_assoc(array('published' => 'yes'), 'date_added desc');
  698. </code>
  699. *
  700. * @access public
  701. * @param string the column to use for an associative key array (optional)
  702. * @param mixed an array or string containg the where paramters of a query (optional)
  703. * @param string the order by of the query (optional)
  704. * @param int the number of records to limit in the results (optional)
  705. * @param int the offset value for the results (optional)
  706. * @return array
  707. */
  708. public function find_all_assoc($assoc_key = 'id', $where = array(), $order_by = NULL, $limit = NULL, $offset = NULL)
  709. {
  710. return $this->find_all($where, $order_by, $limit, $offset, 'object', $assoc_key);
  711. }
  712. // --------------------------------------------------------------------
  713. /**
  714. * Get the results of the query returned as a keyed array of arrays
  715. *
  716. <code>
  717. $examples = $this->examples_model->find_all_assoc(array('published' => 'yes'), 'date_added desc');
  718. </code>
  719. *
  720. * @access public
  721. * @param string the column to use for an associative key array (optional)
  722. * @param mixed an array or string containg the where paramters of a query (optional)
  723. * @param string the order by of the query (optional)
  724. * @param int the number of records to limit in the results (optional)
  725. * @param int the offset value for the results (optional)
  726. * @return array
  727. */
  728. public function find_all_array_assoc($assoc_key = 'id', $where = array(), $order_by = NULL, $limit = NULL, $offset = NULL)
  729. {
  730. return $this->find_all($where, $order_by, $limit, $offset, 'array', $assoc_key);
  731. }
  732. // --------------------------------------------------------------------
  733. /**
  734. * Get the results of a query from within a select group of key field values. Results are sorted by the order from within the group.
  735. *
  736. <code>
  737. $examples = $this->examples_model->find_within(array(1, 2, 3, 4), array('published' => 'yes'), 'date_added desc');
  738. </code>
  739. *
  740. * @access public
  741. * @param group an array of keys to limit the search results to
  742. * @param mixed an array or string containg the where paramters of a query (optional)
  743. * @param int the number of records to limit in the results (optional)
  744. * @param int the offset value for the results (optional)
  745. * @param string return type (object, array, query, auto) (optional)
  746. * @param string the column to use for an associative key array (optional)
  747. * @return array
  748. */
  749. public function find_within($group, $where = array(), $limit = NULL, $offset = NULL, $return_method = NULL, $assoc_key = NULL)
  750. {
  751. if (empty($group) OR !is_array($group))
  752. {
  753. return array();
  754. }
  755. // setup wherein for the group
  756. $this->db->where_in($this->key_field(), $group);
  757. // must set protect identifiers to FALSE in order for order by to work
  758. $_protect_identifiers = $this->db->_protect_identifiers;
  759. $this->db->_protect_identifiers = FALSE;
  760. // escape group
  761. foreach($group as $key => $val)
  762. {
  763. $group[$key] = $this->db->escape($val);
  764. }
  765. // remove any cached order by
  766. $this->db->ar_cache_orderby = array();
  767. $this->db->order_by('FIELD('.$this->key_field().', '.implode(', ', $group).')');
  768. // set it _protect_identifiers back to original value
  769. $this->db->_protect_identifiers = $_protect_identifiers;
  770. // do a normal find all
  771. $data = $this->find_all($where, NULL, $limit, $offset, $return_method, $assoc_key);
  772. return $data;
  773. }
  774. // --------------------------------------------------------------------
  775. /**
  776. * This method takes an associative array with the key values that map to CodeIgniter active record methods and returns a query result object.
  777. *
  778. * For more advanced, use CI Active Record. Below are the key values you can pass:
  779. <ul>
  780. <li><strong>select</strong></li>
  781. <li><strong>from</strong></li>
  782. <li><strong>join</strong></li>
  783. <li><strong>where</strong></li>
  784. <li><strong>or_where</strong></li>
  785. <li><strong>where_in</strong></li>
  786. <li><strong>or_where_in</strong></li>
  787. <li><strong>where_not_in</strong></li>
  788. <li><strong>or_where_not_in</strong></li>
  789. <li><strong>like</strong></li>
  790. <li><strong>or_like</strong></li>
  791. <li><strong>not_like</strong></li>
  792. <li><strong>or_not_like</strong></li>
  793. <li><strong>group_by</strong></li>
  794. <li><strong>order_by</strong></li>
  795. <li><strong>limit</strong></li>
  796. <li><strong>offset</strong></li>
  797. </ul>
  798. *
  799. <code>
  800. $where['select'] = 'id, name, published';
  801. $where['where'] = array('published' => 'yes');
  802. $where['order_by'] = 'name asc';
  803. $where['limit'] = 10;
  804. $query = $this->examples_model->query($where);
  805. $results = $query->result();
  806. </code>
  807. *
  808. * @access public
  809. * @param array an array of parameters to create a query (optional)
  810. * @param boolean determines whether to execute the query and return the results or not
  811. * @return array
  812. */
  813. public function query($params = array(), $exec = TRUE)
  814. {
  815. if (is_array($params))
  816. {
  817. $defaults = array(
  818. 'select' => $this->table_name.'.*',
  819. 'from' => $this->table_name,
  820. 'join' => array(),
  821. 'where' => array(),
  822. 'or_where' => array(),
  823. 'where_in' => array(),
  824. 'or_where_in' => array(),
  825. 'where_not_in' => array(),
  826. 'or_where_not_in' => array(),
  827. 'like' => array(),
  828. 'or_like' => array(),
  829. 'not_like' => array(),
  830. 'or_not_like' => array(),
  831. 'group_by' => NULL,
  832. 'order_by' => NULL,
  833. 'limit' => NULL,
  834. 'offset' => NULL
  835. );
  836. $defaults2 = array(
  837. 'join',
  838. 'from',
  839. 'where',
  840. 'or_where',
  841. 'where_in',
  842. 'or_where_in',
  843. 'where_not_in',
  844. 'or_where_not_in',
  845. 'like',
  846. 'or_like',
  847. 'not_like',
  848. 'or_not_like'
  849. );
  850. // merge params with defaults
  851. $params = array_merge($defaults, $params);
  852. // add joins
  853. if (!empty($params['join'][0]))
  854. {
  855. $join_select = '';
  856. if (is_array($params['join'][0]))
  857. {
  858. foreach($params['join'] as $join)
  859. {
  860. if (empty($join[2]))
  861. {
  862. $join[2] = 'left';
  863. }
  864. $this->db->join($join[0], $join[1], $join[2]);
  865. $join_select .= ', '.$this->db->safe_select($join[0]);
  866. }
  867. }
  868. else
  869. {
  870. if (empty($params['join'][2]))
  871. {
  872. $params['join'][2] = 'left';
  873. }
  874. $this->db->join($params['join'][0], $params['join'][1], $params['join'][2]);
  875. $join_select .= ', '.$this->db->safe_select($params['join'][0]);
  876. }
  877. //if (empty($params['select'])) $params['select'] = $join_select;
  878. $params['select'] = $params['select'].$join_select;
  879. }
  880. // select
  881. if (!empty($params['select'])) $this->db->select($params['select'], FALSE);
  882. if (!empty($params['join_select'])) $this->db->select($join_select, FALSE);
  883. // from
  884. if ($params['from'] != $this->table_name)
  885. {
  886. $this->db->from($params['from']);
  887. }
  888. // loop through list above to set params
  889. foreach($defaults2 as $val)
  890. {
  891. if ($val == 'where_in' OR $val == 'or_where_in' OR $val == 'where_not_in' OR $val == 'or_where_not_in')
  892. {
  893. foreach($params[$val] as $key => $val2)
  894. {
  895. $this->db->$val($key, $val2);
  896. }
  897. }
  898. else if ($val != 'join' AND $val != 'from' AND $val != 'order_by')
  899. {
  900. if (!empty($params[$val]))
  901. {
  902. if (is_array($params[$val]))
  903. {
  904. $this->db->$val($params[$val]);
  905. }
  906. else
  907. {
  908. $this->db->$val($params[$val]);
  909. }
  910. }
  911. }
  912. }
  913. // group by
  914. if (!empty($params['group_by'])) $this->db->group_by($params['group_by']);
  915. //order by
  916. if (!empty($params['order_by']))
  917. {
  918. if (is_array($params['order_by']))
  919. {
  920. foreach($params['order_by'] as $val)
  921. {
  922. $order_by = explode(' ', trim($val));
  923. $this->db->order_by($order_by[0], $order_by[1]);
  924. }
  925. }
  926. else
  927. {
  928. $this->db->order_by($params['order_by']);
  929. }
  930. }
  931. if ( ! empty($params['limit']))
  932. {
  933. $this->db->limit($params['limit']);
  934. }
  935. if ( ! empty($params['offset']))
  936. {
  937. $this->db->offset($params['offset']);
  938. }
  939. if ($exec === FALSE)
  940. {
  941. return;
  942. }
  943. $results = $this->get();
  944. }
  945. else
  946. {
  947. $results = $this->get();
  948. }
  949. return $results;
  950. }
  951. // --------------------------------------------------------------------
  952. /**
  953. * Get the results of a query as an associative array... good for form option lists
  954. *
  955. <code>
  956. $where['published'] = 'yes';
  957. $order = 'name, desc';
  958. $examples_list = $this->examples_model->options_list('id', 'name', $where, $order);
  959. </code>
  960. *
  961. * @access public
  962. * @param string the column to use for the value (optional)
  963. * @param string the column to use for the label (optional)
  964. * @param mixed an array or string containg the where paramters of a query (optional)
  965. * @param mixed the order by of the query. Defaults to TRUE which means it will sort by $val asc (optional)
  966. * @return array
  967. */
  968. public function options_list($key = NULL, $val = NULL, $where = array(), $order = TRUE)
  969. {
  970. if (empty($key))
  971. {
  972. if (!is_array($this->key_field))
  973. {
  974. $key = $this->key_field;
  975. }
  976. }
  977. if (empty($val))
  978. {
  979. $fields = $this->fields();
  980. $val = $fields[1];
  981. }
  982. // don't need extra model sql stuff so just use normal active record'
  983. if (!empty($order) AND is_bool($order))
  984. {
  985. $this->db->order_by($val, 'asc');
  986. }
  987. else if (!empty($order) AND is_string($order))
  988. {
  989. if (strpos($order, ' ') === FALSE) $order .= ' asc';
  990. $this->db->order_by($order);
  991. }
  992. $this->db->select($key.', '.$val, FALSE);
  993. if (!empty($where))
  994. {
  995. $this->db->where($where);
  996. }
  997. $query = $this->db->get($this->table_name);
  998. $key_arr = explode('.', $key);
  999. $clean_key = $key_arr[(count($key_arr) - 1)];
  1000. if (!empty($query))
  1001. {
  1002. $results = $query->result_assoc_array($clean_key);
  1003. return $results;
  1004. }
  1005. return FALSE;
  1006. }
  1007. // --------------------------------------------------------------------
  1008. /**
  1009. * Determine if a record exists in the database
  1010. *
  1011. <code>
  1012. $where['type'] = 'A';
  1013. if ($this->examples_model->record_exists($where))
  1014. {
  1015. echo 'record exists';
  1016. }
  1017. </code>
  1018. *
  1019. * @access public
  1020. * @param mixed an array or string containg the where paramters of a query
  1021. * @return boolean
  1022. */
  1023. public function record_exists($where)
  1024. {
  1025. $query = $this->db->get_where($this->table_name, $where);
  1026. return ($query->num_rows() != 0);
  1027. }
  1028. // --------------------------------------------------------------------
  1029. /**
  1030. * Create a new record if a custom record object exists
  1031. *
  1032. <code>
  1033. $example = $this->examples_model->create($_POST); // Be sure to always clean your $_POST variables before using them
  1034. </code>
  1035. *
  1036. * @access public
  1037. * @param mixed the record oject associated with this class (optional)
  1038. * @return boolean
  1039. */
  1040. public function create($values = array())
  1041. {
  1042. $record_class = $this->record_class_name();
  1043. if (class_exists($record_class))
  1044. {
  1045. $record = new $record_class();
  1046. $record->initialize($this, $this->table_info());
  1047. // call on_create hook
  1048. $values = $this->on_create($values);
  1049. if (!empty($values)) $record->fill($values);
  1050. return $record;
  1051. }
  1052. else
  1053. {
  1054. throw new Exception(lang('error_could_not_find_record_class', get_class($this)));
  1055. }
  1056. }
  1057. // --------------------------------------------------------------------
  1058. /**
  1059. * Clean the data before saving
  1060. *
  1061. <code>
  1062. $cleaned_data = $this->examples_model->clean($_POST); // Be sure to always clean your $_POST variables before using them
  1063. </code>
  1064. *
  1065. * @access public
  1066. * @param mixed an array of values to be saved (optional)
  1067. * @param boolean run on_before_clean hook or not (optional)
  1068. * @return array
  1069. */
  1070. public function clean($values = array(), $run_hook = FALSE)
  1071. {
  1072. $CI =& get_instance();
  1073. if (empty($values)) $values = $CI->input->post();
  1074. $original_values = $values;
  1075. // run clean hook
  1076. if ($run_hook)
  1077. {
  1078. $values = $this->on_before_clean($values);
  1079. }
  1080. // get table information to clean against
  1081. $fields = $this->table_info();
  1082. $clean = array();
  1083. $values = array();
  1084. foreach($fields as $key => $val)
  1085. {
  1086. if (is_array($original_values) AND array_key_exists($key, $original_values))
  1087. {
  1088. $values[$key] = ($this->auto_trim AND is_string($original_values[$key])) ? trim($original_values[$key]) : $original_values[$key];
  1089. }
  1090. // add the date fields if they don't exist to the values array
  1091. elseif(is_array($original_values) AND !array_key_exists($key, $original_values) AND (in_array($key, $this->auto_date_add) OR in_array($key, $this->auto_date_update)))
  1092. {
  1093. $values[$key] = NULL;
  1094. }
  1095. }
  1096. // process linked fields
  1097. $values = $this->process_linked($values);
  1098. foreach ($values as $key => $field)
  1099. {
  1100. $field = $fields[$key];
  1101. if ($field['type'] == 'datetime')
  1102. {
  1103. if (empty($values[$key]) OR (int)$values[$key] == 0)
  1104. {
  1105. $values[$key] = $this->default_date;
  1106. }
  1107. }
  1108. else if ($field['type'] == 'date')
  1109. {
  1110. if (empty($values[$key]) OR (int)$values[$key] == 0) $values[$key] = $this->default_date;
  1111. if (!empty($values[$key]) AND !is_date_db_format($values[$key])) $values[$key] = english_date_to_db_format($values[$key]);
  1112. }
  1113. $date_func = ($this->date_use_gmt) ? 'gmdate' : 'date';
  1114. // create dates for date added and last updated fields automatically
  1115. $is_date_field_type = ($field['type'] == 'datetime' OR $field['type'] == 'timestamp' OR $field['type'] == 'date');
  1116. if ($is_date_field_type AND in_array($key, $this->auto_date_add))
  1117. {
  1118. $test_date = (isset($values[$key])) ? (int) $values[$key] : 0;
  1119. // if no key field then we assume it is a new save and so we add the date if it's empty'
  1120. if (!$this->_has_key_field_value($values) AND empty($test_date))
  1121. {
  1122. $values[$key] = ($field['type'] == 'date') ? $date_func('Y-m-d') : $date_func('Y-m-d H:i:s');
  1123. }
  1124. }
  1125. else if ($is_date_field_type AND in_array($key, $this->auto_date_update))
  1126. {
  1127. $values[$key] = ($field['type'] == 'date') ? $date_func('Y-m-d') : $date_func('Y-m-d H:i:s');
  1128. }
  1129. if (is_array($values) AND array_key_exists($key, $values))
  1130. {
  1131. // format dates
  1132. if (!in_array($key, $this->auto_date_add))
  1133. {
  1134. if ($field['type'] == 'datetime' OR $field['type'] == 'timestamp' OR $field['type'] == 'date')
  1135. {
  1136. if (isset($values[$key]) AND strncmp($values[$key], '0000', 4) !== 0)
  1137. {
  1138. if ($field['type'] == 'date')
  1139. {
  1140. $values[$key] = ($values[$key] != 'invalid') ? $date_func('Y-m-d', strtotime($values[$key])) : $this->default_date;
  1141. }
  1142. else
  1143. {
  1144. $values[$key] = ($values[$key] != 'invalid') ? $date_func('Y-m-d H:i:s', strtotime($values[$key])) : $this->default_date;
  1145. }
  1146. }
  1147. }
  1148. }
  1149. // safe_htmlspecialchars is buggy for unserialize so we use the encode_and_clean
  1150. if (is_string($values[$key]))
  1151. {
  1152. $values[$key] = $this->encode_and_clean($values[$key], NULL, $key);
  1153. }
  1154. else if (is_array($values[$key]))
  1155. {
  1156. array_walk_recursive($values[$key], array($this, 'encode_and_clean'), $key);
  1157. }
  1158. $clean[$key] = $values[$key];
  1159. }
  1160. }
  1161. $this->cleaned_data = $clean;
  1162. return $clean;
  1163. }
  1164. public function encode_and_clean(&$val, $k, $key = NULL)
  1165. {
  1166. if (empty($key))
  1167. {
  1168. $key = $k;
  1169. }
  1170. if (is_string($val))
  1171. {
  1172. if ($this->auto_encode_entities)
  1173. {
  1174. if ((is_array($this->auto_encode_entities) AND in_array($key, $this->auto_encode_entities))
  1175. OR (is_string($this->auto_encode_entities) AND $key == $this->auto_encode_entities)
  1176. OR ($this->auto_encode_entities === TRUE)
  1177. )
  1178. {
  1179. $val = safe_htmlentities($val);
  1180. }
  1181. }
  1182. if ($this->xss_clean)
  1183. {
  1184. if ((is_array($this->xss_clean) AND in_array($key, $this->xss_clean))
  1185. OR (is_string($this->xss_clean) AND $key == $this->xss_clean)
  1186. OR ($this->xss_clean === TRUE)
  1187. )
  1188. {
  1189. $val = xss_clean(($val));
  1190. }
  1191. }
  1192. }
  1193. return $val;
  1194. }
  1195. // --------------------------------------------------------------------
  1196. /**
  1197. * Get the cleaned data
  1198. *
  1199. <code>
  1200. $cleaned_data = $this->examples_model->cleaned_data();
  1201. </code>
  1202. *
  1203. * @access public
  1204. * @return array
  1205. */
  1206. public function cleaned_data()
  1207. {
  1208. return $this->cleaned_data;
  1209. }
  1210. // --------------------------------------------------------------------
  1211. /**
  1212. * Returns number of query results
  1213. *
  1214. <code>
  1215. $where['published'] = 'yes';
  1216. echo $this->examples_model->record_count($where); // dislays the number of records
  1217. </code>
  1218. *
  1219. * @access public
  1220. * @param mixed where condition (optional)
  1221. * @return int
  1222. */
  1223. public function record_count($where = array())
  1224. {
  1225. $this->_handle_where($where);
  1226. $query = $this->db->get($this->table_name);
  1227. return $query->num_rows();
  1228. }
  1229. // --------------------------------------------------------------------
  1230. /**
  1231. * Returns number of records in the table
  1232. *
  1233. <code>
  1234. $total_count = $this->examples_model->total_record_count();
  1235. </code>
  1236. *
  1237. * @access public
  1238. * @return int
  1239. */
  1240. public function total_record_count()
  1241. {
  1242. return $this->db->count_all($this->table_name);
  1243. }
  1244. // --------------------------------------------------------------------
  1245. /**
  1246. * Saves record object, or array of data to the database
  1247. *
  1248. <code>
  1249. $this->examples_model->save($_POST, TRUE, TRUE); // Be sure to always clean your $_POST variables before using them
  1250. </code>
  1251. *
  1252. * @access public
  1253. * @param mixed an array or object to save to the database
  1254. * @param boolean validate the data before saving
  1255. * @param boolean ignore duplicate records on insert
  1256. * @return mixed
  1257. */
  1258. public function save($record = NULL, $validate = TRUE, $ignore_on_insert = TRUE, $clear_related = NULL)
  1259. {
  1260. $this->_check_readonly();
  1261. $CI =& get_instance();
  1262. if (!isset($record)) $record = $CI->input->post();
  1263. if ($this->_is_nested_array($record))
  1264. {
  1265. $saved = TRUE;
  1266. foreach($record as $rec)
  1267. {
  1268. if(!$this->save($rec, $validate, $ignore_on_insert, $clear_related))
  1269. {
  1270. $saved = FALSE;
  1271. }
  1272. }
  1273. return $saved;
  1274. }
  1275. else
  1276. {
  1277. $fields = array();
  1278. $old_clear_related_on_save = $this->clear_related_on_save;
  1279. if (isset($clear_related))
  1280. {
  1281. $this->clear_related_on_save = $clear_related;
  1282. }
  1283. $values = $this->normalize_save_values($record);
  1284. // reset validator here so that all validation set with hooks will not be lost
  1285. $this->validator->reset();
  1286. // clean the data before saving. on_before_clean hook now runs in the clean() method
  1287. $values = $this->on_before_clean($values);
  1288. $values = $this->clean($values);
  1289. $values = $this->on_before_validate($values);
  1290. // now validate. on_before_validate hook now runs inside validate() method
  1291. $validated = ($validate) ? $this->validate($values) : TRUE;
  1292. if ($validated AND !empty($values))
  1293. {
  1294. // now clean the data to be ready for database saving
  1295. $this->db->set($values);
  1296. if ($ignore_on_insert)
  1297. {
  1298. // execute on_before_insert/update hook methods
  1299. $values = $this->on_before_save($values);
  1300. // process serialized values
  1301. $values = $this->serialize_field_values($values);
  1302. if (!$this->_has_key_field_value($values))
  1303. {
  1304. $values = $this->on_before_insert($values);
  1305. }
  1306. else
  1307. {
  1308. $values = $this->on_before_update($values);
  1309. }
  1310. $insert_key = ($this->has_auto_increment) ? $this->key_field : NULL;
  1311. $this->db->insert_ignore($this->table_name, $values, $insert_key);
  1312. // execute on_insert/update hook methods
  1313. $no_key = FALSE;
  1314. $insert_id = $this->db->insert_id();
  1315. if (!$this->_has_key_field_value($values) AND $insert_id)
  1316. {
  1317. $no_key = TRUE;
  1318. if (is_string($this->key_field))
  1319. {
  1320. $values[$this->key_field] = $insert_id;
  1321. }
  1322. $this->on_after_insert($values);
  1323. }
  1324. else
  1325. {
  1326. $this->on_after_update($values);
  1327. }
  1328. // execute on_insert/update hook methods on the Date_record model if exists
  1329. if (is_object($record) AND ($record instanceof Data_record))
  1330. {
  1331. if ($no_key)
  1332. {
  1333. $record->on_after_insert($values);
  1334. }
  1335. else
  1336. {
  1337. $record->on_after_update($values);
  1338. }
  1339. }
  1340. }
  1341. else if (!$this->_has_key_field_value($values))
  1342. {
  1343. // execute on_before_insert/update hook methods
  1344. $values = $this->on_before_save($values);
  1345. $values = $this->on_before_insert($values);
  1346. // process serialized values
  1347. $values = $this->serialize_field_values($values);
  1348. $this->db->insert($this->table_name, $values);
  1349. $insert_id = $this->db->insert_id();
  1350. if (is_string($this->key_field))
  1351. {
  1352. $values[$this->key_field] = $insert_id;
  1353. }
  1354. $this->on_after_insert($values);
  1355. if ($record instanceof Data_record)
  1356. {
  1357. $record->on_after_insert($values);
  1358. }
  1359. }
  1360. else
  1361. {
  1362. $key_field = (array) $this->key_field;
  1363. foreach($key_field as $key)
  1364. {
  1365. $this->db->where($key, $values[$key]);
  1366. }
  1367. $values = $this->on_before_save($values);
  1368. $values = $this->on_before_update($values);
  1369. // process serialized values
  1370. $values = $this->serialize_field_values($values);
  1371. $this->db->update($this->table_name, $values);
  1372. $this->on_after_update($values);
  1373. if ($record instanceof Data_record)
  1374. {
  1375. $record->on_after_update();
  1376. }
  1377. }
  1378. }
  1379. else
  1380. {
  1381. return FALSE;
  1382. }
  1383. // returns the key value of the record upon save
  1384. if (isset($insert_id) AND ! empty($insert_id))
  1385. {
  1386. $return = $insert_id;
  1387. }
  1388. else
  1389. {
  1390. if ($record instanceof Data_record)
  1391. {
  1392. $key_field = $this->key_field;
  1393. if (is_string($this->key_field))
  1394. {
  1395. $return = $record->$key_field;
  1396. }
  1397. else
  1398. {
  1399. $return = array();
  1400. foreach($key_field as $key)
  1401. {
  1402. $return[$key] = $record->$key;
  1403. }
  1404. }
  1405. }
  1406. else if (is_string($this->key_field) AND !empty($values[$this->key_field]))
  1407. {
  1408. $return = $values[$this->key_field];
  1409. }
  1410. else if (is_array($this->key_field))
  1411. {
  1412. $return = array();
  1413. foreach($key_field as $key)
  1414. {
  1415. $return[$key] = $values[$key_field];
  1416. }
  1417. }
  1418. else
  1419. {
  1420. $return = TRUE;
  1421. // not valid test because a save could happen and no data is changed
  1422. //return (bool)($this->db->affected_rows()) ? TRUE : FALSE;
  1423. }
  1424. }
  1425. $this->on_after_save($values);
  1426. // set this back to the old value
  1427. $this->clear_related_on_save = $old_clear_related_on_save;
  1428. // check for errors here in case some are thrown in the hooks
  1429. if ($this->has_error())
  1430. {
  1431. return FALSE;
  1432. }
  1433. return $return;
  1434. }
  1435. }
  1436. // --------------------------------------------------------------------
  1437. /**
  1438. * Save related data to a many to many table. To be used in on_after_save hook
  1439. *
  1440. <code>
  1441. $this->examples_model->save_related('examples_to_categories', array('example_id' => $obj->id), array('categories_id' => $_POST['categories']));
  1442. </code>
  1443. *
  1444. * @access public
  1445. * @param mixed an array or object to save to the database
  1446. * @param array key is the column name, and value is the value to save
  1447. * @param array key is the column name, and the array of data to iterate over and save
  1448. * @return boolean
  1449. */
  1450. public function save_related($model, $key_field, $data)
  1451. {
  1452. $this->_check_readonly();
  1453. $CI =& get_instance();
  1454. $model = $this->load_model($model);
  1455. $id = current($key_field);
  1456. $key_field = key($key_field);
  1457. $other_field = key($data);
  1458. $data = current($data);
  1459. // first remove all the articles
  1460. $CI->$model->delete(array($key_field => $id));
  1461. // then read them
  1462. $return = TRUE;
  1463. foreach($data as $val)
  1464. {
  1465. $d = $CI->$model->create();
  1466. $d->$key_field = $id;
  1467. $d->$other_field = $val;
  1468. if ($d->save())
  1469. {
  1470. $return = FALSE;
  1471. }
  1472. }
  1473. return $return;
  1474. }
  1475. // --------------------------------------------------------------------
  1476. /**
  1477. * Handles grabbing of the related data's keys
  1478. *
  1479. <code>
  1480. </code>
  1481. *
  1482. * @access public
  1483. * @param array $values
  1484. * @param string $related_model
  1485. * @param string $mode, has_many or belongs_to (optional)
  1486. * @return array
  1487. */
  1488. public function get_related_keys($values, $related_model, $mode = 'has_many', $rel_config = '')
  1489. {
  1490. $CI =& get_instance();
  1491. $use_rel_tbl = $this->is_using_relationship_table($rel_config);
  1492. $fields = $this->relationship_field_names($mode);
  1493. if (is_array($related_model))
  1494. {
  1495. $related_model = $this->load_related_model($related_model);
  1496. }
  1497. $key_field = $this->key_field();
  1498. if ($use_rel_tbl == FALSE)
  1499. {
  1500. $assoc_where = array($rel_config['foreign_key'] => $values[$key_field]);
  1501. $related_keys = array_keys($CI->$related_model->find_all_array_assoc($CI->$related_model->key_field(), $assoc_where));
  1502. }
  1503. else
  1504. {
  1505. $relationships_model = $this->load_model($fields['relationships_model']);
  1506. $assoc_where = array();
  1507. if ($mode == 'belongs_to')
  1508. {
  1509. if (!empty($fields['candidate_table']) AND !empty($fields['foreign_table']))
  1510. {
  1511. $assoc_where = array($fields['candidate_table'] => $CI->$related_model->table_name, $fields['foreign_table'] => $this->table_name());
  1512. }
  1513. if ( ! empty($values) AND array_key_exists($key_field, $values))
  1514. {
  1515. $assoc_where[$fields['foreign_key']] = $values[$key_field];
  1516. }
  1517. $related_keys = array_keys($CI->$relationships_model->find_all_array_assoc($fields['candidate_key'], $assoc_where, $CI->$relationships_model->key_field()));
  1518. }
  1519. else
  1520. {
  1521. if (!empty($fields['foreign_table']) AND !empty($fields['candidate_table']))
  1522. {
  1523. $assoc_where = array($fields['candidate_table'] => $this->table_name(), $fields['foreign_table'] => $CI->$related_model->table_name);
  1524. }
  1525. if ( ! empty($values) AND array_key_exists($key_field, $values))
  1526. {
  1527. $assoc_where[$fields['candidate_key']] = $values[$key_field];
  1528. }
  1529. $related_keys = array_keys($CI->$relationships_model->find_all_array_assoc($fields['foreign_key'], $assoc_where, $CI->$relationships_model->key_field()));
  1530. }
  1531. }
  1532. return $related_keys;
  1533. }
  1534. // --------------------------------------------------------------------
  1535. /**
  1536. * Performs a simple insert to the database record.
  1537. *
  1538. <code>
  1539. $values['name'] = 'Darth Vader';
  1540. $values['email'] = 'dvader@deathstar.com';
  1541. $this->examples_model->insert($values);
  1542. </code>
  1543. *
  1544. * @access public
  1545. * @param mixed an array or object to save to the database
  1546. * @return boolean
  1547. */
  1548. public function insert($values)
  1549. {
  1550. $this->_check_readonly();
  1551. $values = $this->on_before_insert($values);
  1552. $values = $this->serialize_field_values($values);
  1553. $return = $this->db->insert($this->table_name, $values);
  1554. if (is_string($this->key_field))
  1555. {
  1556. $values[$this->key_field] = $this->db->insert_id();
  1557. }
  1558. $this->on_after_insert($values);
  1559. return $return;
  1560. }
  1561. // --------------------------------------------------------------------
  1562. /**
  1563. * Performs a simple update to the database rec…

Large files files are truncated, but you can click here to view the full file