PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 1ms

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

http://github.com/daylightstudio/FUEL-CMS
PHP | 6155 lines | 3215 code | 666 blank | 2274 comment | 521 complexity | 266772252fbaf929c36ee511c364879c MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception

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

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