This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php namespace Myth\Models; |
||
2 | /** |
||
3 | * Sprint |
||
4 | * |
||
5 | * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow. |
||
6 | * |
||
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
||
8 | * of this software and associated documentation files (the "Software"), to deal |
||
9 | * in the Software without restriction, including without limitation the rights |
||
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||
11 | * copies of the Software, and to permit persons to whom the Software is |
||
12 | * furnished to do so, subject to the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice shall be included in |
||
15 | * all copies or substantial portions of the Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||
23 | * THE SOFTWARE. |
||
24 | * |
||
25 | * @package Sprint |
||
26 | * @author Lonnie Ezell |
||
27 | * @copyright Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com) |
||
28 | * @license http://opensource.org/licenses/MIT (MIT) |
||
29 | * @link http://sprintphp.com |
||
30 | * @since Version 1.0 |
||
31 | */ |
||
32 | |||
33 | //-------------------------------------------------------------------- |
||
34 | |||
35 | /** |
||
36 | * BF_Model |
||
37 | * |
||
38 | * An extension of CodeIgniter's built-in model that provides a convenient |
||
39 | * base to quickly and easily build your database-backed models off of. |
||
40 | * |
||
41 | * Provides observers, soft-deletes, basic CRUD functions, helpful functions, |
||
42 | * and more. |
||
43 | * |
||
44 | * This pulls many ideas and inspiration from Jamie Rumbelow's excellent MY_Model |
||
45 | * and the ideas described in his CodeIgniter Handbook, as well as from Laravel |
||
46 | * and Rails. |
||
47 | * |
||
48 | * NOTE: The methods in this model do not take advantage of the clean syntax of |
||
49 | * method chaining. THIS IS BY DESIGN! and allows our mocking of the database |
||
50 | * class to work in a simple and clean way. Do not change this. |
||
51 | * |
||
52 | * @package Bonfire |
||
53 | * @author Bonfire Dev Team |
||
54 | * @license http://opensource.org/licenses/MIT |
||
55 | * |
||
56 | * /** |
||
57 | * The following properties are used to provide autocomplete for IDE's. |
||
58 | * |
||
59 | * Thanks to: https://gist.github.com/topdown/1697338 |
||
60 | * |
||
61 | * @property \CI_DB_query_builder $db |
||
62 | * @property \CI_DB_utility $dbutil |
||
63 | * @property \CI_DB_forge $dbforge |
||
64 | * @property \CI_Benchmark $benchmark |
||
65 | * @property \CI_Calendar $calendar |
||
66 | * @property \CI_Cart $cart |
||
67 | * @property \CI_Config $config |
||
68 | * @property \CI_Controller $controller |
||
69 | * @property \CI_Email $email |
||
70 | * @property \CI_Encrypt $encrypt |
||
71 | * @property \CI_Exceptions $exceptions |
||
72 | * @property \CI_Form_validation $form_validation |
||
73 | * @property \CI_Ftp $ftp |
||
74 | * @property \CI_Hooks $hooks |
||
75 | * @property \CI_Image_lib $image_lib |
||
76 | * @property \CI_Input $input |
||
77 | * @property \CI_Lang $lang |
||
78 | * @property \CI_Loader $load |
||
79 | * @property \CI_Log $log |
||
80 | * @property \CI_Model $model |
||
81 | * @property \CI_Output $output |
||
82 | * @property \CI_Pagination $pagination |
||
83 | * @property \CI_Parser $parser |
||
84 | * @property \CI_Profiler $profiler |
||
85 | * @property \CI_Router $router |
||
86 | * @property \CI_Session $session |
||
87 | * @property \CI_Table $table |
||
88 | * @property \CI_Trackback $trackback |
||
89 | * @property \CI_Typography $typography |
||
90 | * @property \CI_Unit_test $unit_test |
||
91 | * @property \CI_Upload $upload |
||
92 | * @property \CI_URI $uri |
||
93 | * @property \CI_User_agent $user_agent |
||
94 | * @property \CI_Xmlrpc $xmlrpc |
||
95 | * @property \CI_Xmlrpcs $xmlrpcs |
||
96 | * @property \CI_Zip $zip |
||
97 | * @property \CI_Javascript $javascript |
||
98 | * @property \CI_Jquery $jquery |
||
99 | * @property \CI_Utf8 $utf8 |
||
100 | * @property \CI_Security $security |
||
101 | */ |
||
102 | class CIDbModel |
||
103 | { |
||
104 | |||
105 | /** |
||
106 | * The model's default table name. |
||
107 | * |
||
108 | * @var string; |
||
109 | */ |
||
110 | protected $table_name; |
||
111 | |||
112 | /** |
||
113 | * The model's default primary key. |
||
114 | * |
||
115 | * @var string |
||
116 | */ |
||
117 | protected $primary_key = 'id'; |
||
118 | |||
119 | /** |
||
120 | * The type of date/time field used for created_on and modified_on fields. |
||
121 | * Valid types are: 'int', 'datetime', 'date' |
||
122 | * |
||
123 | * @var string |
||
124 | * @access protected |
||
125 | */ |
||
126 | protected $date_format = 'datetime'; |
||
127 | |||
128 | /* |
||
0 ignored issues
–
show
|
|||
129 | Var: $log_user |
||
130 | If TRUE, will log user id for 'created_by', 'modified_by' and 'deleted_by'. |
||
131 | |||
132 | Access: |
||
133 | Protected |
||
134 | */ |
||
135 | protected $log_user = FALSE; |
||
136 | |||
137 | |||
138 | |||
139 | /** |
||
140 | * Whether or not to auto-fill a 'created_on' field on inserts. |
||
141 | * |
||
142 | * @var boolean |
||
143 | * @access protected |
||
144 | */ |
||
145 | protected $set_created = TRUE; |
||
146 | |||
147 | /** |
||
148 | * Field name to use to the created time column in the DB table. |
||
149 | * |
||
150 | * @var string |
||
151 | * @access protected |
||
152 | */ |
||
153 | protected $created_field = 'created_on'; |
||
154 | |||
155 | /* |
||
156 | Var: $created_by_field |
||
157 | Field name to use to the created by column in the DB table. |
||
158 | |||
159 | Access: |
||
160 | Protected |
||
161 | */ |
||
162 | protected $created_by_field = 'created_by'; |
||
163 | |||
164 | |||
165 | |||
166 | /** |
||
167 | * Whether or not to auto-fill a 'modified_on' field on updates. |
||
168 | * |
||
169 | * @var boolean |
||
170 | * @access protected |
||
171 | */ |
||
172 | protected $set_modified = TRUE; |
||
173 | |||
174 | /** |
||
175 | * Field name to use to the modified time column in the DB table. |
||
176 | * |
||
177 | * @var string |
||
178 | * @access protected |
||
179 | */ |
||
180 | protected $modified_field = 'modified_on'; |
||
181 | |||
182 | /* |
||
183 | Var: $modified_by_field |
||
184 | Field name to use to the modified by column in the DB table. |
||
185 | |||
186 | Access: |
||
187 | Protected |
||
188 | */ |
||
189 | protected $modified_by_field = 'modified_by'; |
||
190 | |||
191 | |||
192 | /** |
||
193 | * Support for soft_deletes. |
||
194 | */ |
||
195 | protected $soft_deletes = FALSE; |
||
196 | protected $soft_delete_key = 'deleted'; |
||
197 | protected $temp_with_deleted = FALSE; |
||
198 | |||
199 | /* |
||
200 | Var: $deleted_by_field |
||
201 | Field name to use for the deleted by column in the DB table. |
||
202 | |||
203 | Access: |
||
204 | Protected |
||
205 | */ |
||
206 | protected $deleted_by_field = 'deleted_by'; |
||
207 | |||
208 | |||
209 | |||
210 | /** |
||
211 | * Various callbacks available to the class. They are simple lists of |
||
212 | * method names (methods will be ran on $this). |
||
213 | */ |
||
214 | protected $before_insert = array(); |
||
215 | protected $after_insert = array(); |
||
216 | protected $before_update = array(); |
||
217 | protected $after_update = array(); |
||
218 | protected $before_find = array(); |
||
219 | protected $after_find = array(); |
||
220 | protected $before_delete = array(); |
||
221 | protected $after_delete = array(); |
||
222 | |||
223 | protected $callback_parameters = array(); |
||
224 | |||
225 | |||
226 | |||
227 | /* |
||
228 | If TRUE, inserts will return the last_insert_id. However, |
||
229 | this can potentially slow down large imports drastically |
||
230 | so you can turn it off with the return_insert_id(false) method. |
||
231 | */ |
||
232 | protected $return_insert_id = true; |
||
233 | |||
234 | /** |
||
235 | * By default, we return items as objects. You can change this for the |
||
236 | * entire class by setting this value to 'array' instead of 'object'. |
||
237 | * Alternatively, you can do it on a per-instance basis using the |
||
238 | * 'as_array()' and 'as_object()' methods. |
||
239 | */ |
||
240 | protected $return_type = 'object'; |
||
241 | protected $temp_return_type = NULL; |
||
242 | |||
243 | /** |
||
244 | * Protected, non-modifiable attributes |
||
245 | */ |
||
246 | protected $protected_attributes = array(); |
||
247 | |||
248 | |||
249 | |||
250 | /** |
||
251 | * An array of validation rules. This needs to be the same format |
||
252 | * as validation rules passed to the Form_validation library. |
||
253 | */ |
||
254 | protected $validation_rules = array(); |
||
255 | |||
256 | /** |
||
257 | * Optionally skip the validation. Used in conjunction with |
||
258 | * skip_validation() to skip data validation for any future calls. |
||
259 | */ |
||
260 | protected $skip_validation = FALSE; |
||
261 | |||
262 | /** |
||
263 | * An array of extra rules to add to validation rules during inserts only. |
||
264 | * Often used for adding 'required' rules to fields on insert, but not udpates. |
||
265 | * |
||
266 | * array( 'username' => 'required|strip_tags' ); |
||
267 | * @var array |
||
268 | */ |
||
269 | protected $insert_validate_rules = array(); |
||
270 | |||
271 | |||
272 | |||
273 | /** |
||
274 | * @var Array Columns for the model's database fields |
||
275 | * |
||
276 | * This can be set to avoid a database call if using $this->prep_data() |
||
277 | */ |
||
278 | protected $fields = array(); |
||
279 | |||
280 | //-------------------------------------------------------------------- |
||
281 | |||
282 | /** |
||
283 | * Does basic setup. Can pass the database connection into the constructor |
||
284 | * to use that $db instead of the global CI one. |
||
285 | * |
||
286 | * @param object $db // A database/driver instance |
||
287 | * @param object $form_validation // A form_validation library instance |
||
288 | */ |
||
289 | public function __construct($db = null, $form_validation = null) |
||
290 | { |
||
291 | // Always protect our attributes |
||
292 | array_unshift($this->before_insert, 'protect_attributes'); |
||
293 | array_unshift($this->before_update, 'protect_attributes'); |
||
294 | |||
295 | // Check our auto-set features and make sure they are part of |
||
296 | // our observer system. |
||
297 | if ($this->set_created === true) array_unshift($this->before_insert, 'created_on'); |
||
298 | if ($this->set_modified === true) array_unshift($this->before_update, 'modified_on'); |
||
299 | |||
300 | // Make sure our temp return type is correct. |
||
301 | $this->temp_return_type = $this->return_type; |
||
302 | |||
303 | // Make sure our database is loaded |
||
304 | if (!is_null($db)) { |
||
305 | $this->db = $db; |
||
306 | } |
||
307 | else { |
||
308 | // Auto Init the damn database.... |
||
309 | $this->load->database(); |
||
310 | } |
||
311 | |||
312 | // Do we have a form_validation library? |
||
313 | if (! is_null($form_validation)) { |
||
314 | $this->form_validation = $form_validation; |
||
315 | } |
||
316 | else { |
||
317 | $this->load->library('form_validation'); |
||
318 | } |
||
319 | |||
320 | log_message('debug', 'CIDbModel Class Initialized'); |
||
321 | } |
||
322 | |||
323 | //-------------------------------------------------------------------- |
||
324 | |||
325 | //-------------------------------------------------------------------- |
||
326 | // CRUD Methods |
||
327 | //-------------------------------------------------------------------- |
||
328 | |||
329 | /** |
||
330 | * A simple way to grab the first result of a search only. |
||
331 | */ |
||
332 | public function first() |
||
333 | { |
||
334 | $rows = $this->limit(1, 0)->find_all(); |
||
335 | |||
336 | if (is_array($rows) && count($rows)) { |
||
337 | return $rows[0]; |
||
338 | } |
||
339 | |||
340 | return $rows; |
||
341 | } |
||
342 | |||
343 | //-------------------------------------------------------------------- |
||
344 | |||
345 | |||
346 | /** |
||
347 | * Finds a single record based on it's primary key. Will ignore deleted rows. |
||
348 | * |
||
349 | * @param mixed $id The primary_key value of the object to retrieve. |
||
350 | * @return object |
||
351 | */ |
||
352 | public function find($id) |
||
353 | { |
||
354 | $this->trigger('before_find', ['id' => $id, 'method' => 'find']); |
||
355 | |||
356 | // Ignore any soft-deleted rows |
||
357 | View Code Duplication | if ($this->soft_deletes) { |
|
358 | // We only need to modify the where statement if |
||
359 | // temp_with_deleted is false. |
||
360 | if ($this->temp_with_deleted !== true) { |
||
361 | $this->db->where($this->soft_delete_key, false); |
||
362 | } |
||
363 | |||
364 | $this->temp_with_deleted = false; |
||
365 | } |
||
366 | |||
367 | $this->db->where($this->primary_key, $id); |
||
368 | $row = $this->db->get($this->table_name); |
||
369 | $row = $this->temp_return_type == 'array' ? $row->row_array() : $row->row(0, $this->temp_return_type); |
||
370 | |||
371 | View Code Duplication | if ( ! empty($row)) |
|
372 | { |
||
373 | $row = $this->trigger('after_find', ['id' => $id, 'method' => 'find', 'fields' => $row]); |
||
374 | } |
||
375 | |||
376 | // Reset our return type |
||
377 | $this->temp_return_type = $this->return_type; |
||
378 | |||
379 | return $row; |
||
380 | } |
||
381 | |||
382 | //-------------------------------------------------------------------- |
||
383 | |||
384 | /** |
||
385 | * Fetch a single record based on an arbitrary WHERE call. Can be |
||
386 | * any valid value to $this->db->where(). Will not pull in deleted rows |
||
387 | * if using soft deletes. |
||
388 | * |
||
389 | * @return object |
||
390 | */ |
||
391 | public function find_by() |
||
392 | { |
||
393 | $where = func_get_args(); |
||
394 | $this->_set_where($where); |
||
395 | |||
396 | // Ignore any soft-deleted rows |
||
397 | View Code Duplication | if ($this->soft_deletes) { |
|
398 | // We only need to modify the where statement if |
||
399 | // temp_with_deleted is false. |
||
400 | if ($this->temp_with_deleted !== true) { |
||
401 | $this->db->where($this->soft_delete_key, false); |
||
402 | } |
||
403 | |||
404 | $this->temp_with_deleted = false; |
||
405 | } |
||
406 | |||
407 | $this->trigger('before_find', ['method' => 'find_by', 'fields' => $where]); |
||
408 | |||
409 | $row = $this->db->get($this->table_name); |
||
410 | $row = $this->temp_return_type == 'array' ? $row->row_array() : $row->row(0, $this->temp_return_type); |
||
411 | |||
412 | View Code Duplication | if ( ! empty($row)) |
|
413 | { |
||
414 | $row = $this->trigger('after_find', ['method' => 'find_by', 'fields' => $row]); |
||
415 | } |
||
416 | |||
417 | // Reset our return type |
||
418 | $this->temp_return_type = $this->return_type; |
||
419 | |||
420 | return $row; |
||
421 | } |
||
422 | |||
423 | //-------------------------------------------------------------------- |
||
424 | |||
425 | /** |
||
426 | * Retrieves a number of items based on an array of primary_values passed in. |
||
427 | * |
||
428 | * @param array $values An array of primary key values to find. |
||
429 | * |
||
430 | * @return object or FALSE |
||
431 | */ |
||
432 | public function find_many($values) |
||
433 | { |
||
434 | $this->db->where_in($this->primary_key, $values); |
||
435 | |||
436 | return $this->find_all(); |
||
437 | } |
||
438 | |||
439 | //-------------------------------------------------------------------- |
||
440 | |||
441 | /** |
||
442 | * Retrieves a number of items based on an arbitrary WHERE call. Can be |
||
443 | * any set of parameters valid to $db->where. |
||
444 | * |
||
445 | * @return object or FALSE |
||
446 | */ |
||
447 | public function find_many_by() |
||
448 | { |
||
449 | $where = func_get_args(); |
||
450 | $this->_set_where($where); |
||
451 | |||
452 | return $this->find_all(); |
||
453 | } |
||
454 | |||
455 | //-------------------------------------------------------------------- |
||
456 | |||
457 | /** |
||
458 | * Fetch all of the records in the table. Can be used with scoped calls |
||
459 | * to restrict the results. |
||
460 | * |
||
461 | * @return object or FALSE |
||
462 | */ |
||
463 | public function find_all() |
||
464 | { |
||
465 | $this->trigger('before_find', ['method' => 'find_all']); |
||
466 | |||
467 | // Ignore any soft-deleted rows |
||
468 | View Code Duplication | if ($this->soft_deletes) { |
|
469 | // We only need to modify the where statement if |
||
470 | // temp_with_deleted is false. |
||
471 | if ($this->temp_with_deleted !== true) { |
||
472 | $this->db->where($this->soft_delete_key, false); |
||
473 | } |
||
474 | |||
475 | $this->temp_with_deleted = false; |
||
476 | } |
||
477 | |||
478 | $rows = $this->db->get($this->table_name); |
||
479 | $rows = $this->temp_return_type == 'array' ? $rows->result_array() : $rows->result($this->temp_return_type); |
||
480 | |||
481 | if (is_array($rows)) { |
||
482 | foreach ($rows as $key => &$row) { |
||
483 | $row = $this->trigger('after_find', ['method' => 'find_all', 'fields' => $row] ); |
||
484 | } |
||
485 | } |
||
486 | |||
487 | // Reset our return type |
||
488 | $this->temp_return_type = $this->return_type; |
||
489 | |||
490 | return $rows; |
||
491 | } |
||
492 | |||
493 | //-------------------------------------------------------------------- |
||
494 | |||
495 | /** |
||
496 | * Inserts data into the database. |
||
497 | * |
||
498 | * @param array $data An array of key/value pairs to insert to database. |
||
499 | * @param array $skip_validation If TRUE, will skip validation of data for this call only. |
||
500 | * @return mixed The primary_key value of the inserted record, or FALSE. |
||
501 | */ |
||
502 | View Code Duplication | public function insert($data, $skip_validation = null) |
|
503 | { |
||
504 | $skip_validation = is_null($skip_validation) ? $this->skip_validation : $skip_validation; |
||
505 | |||
506 | if ($skip_validation === FALSE) { |
||
507 | $data = $this->validate($data, 'insert', $skip_validation); |
||
508 | } |
||
509 | |||
510 | if ($data !== FALSE) { |
||
511 | $data = $this->trigger('before_insert', ['method' => 'insert', 'fields' => $data]); |
||
512 | |||
513 | $this->db->insert($this->table_name, $this->prep_data($data) ); |
||
514 | |||
515 | if ($this->return_insert_id) { |
||
516 | $id = $this->db->insert_id(); |
||
517 | |||
518 | $this->trigger('after_insert', ['id' => $id, 'fields' => $data, 'method' => 'insert']); |
||
519 | |||
520 | return $id; |
||
521 | } |
||
522 | |||
523 | return TRUE; |
||
524 | } else { |
||
525 | return FALSE; |
||
526 | } |
||
527 | } |
||
528 | |||
529 | //-------------------------------------------------------------------- |
||
530 | |||
531 | /** |
||
532 | * Inserts multiple rows into the database at once. Takes an associative |
||
533 | * array of value pairs. |
||
534 | * |
||
535 | * $data = array( |
||
536 | * array( |
||
537 | * 'title' => 'My title' |
||
538 | * ), |
||
539 | * array( |
||
540 | * 'title' => 'My Other Title' |
||
541 | * ) |
||
542 | * ); |
||
543 | * |
||
544 | * @param array $data An associate array of rows to insert |
||
545 | * @param array $skip_validation If TRUE, will skip validation of data for this call only. |
||
546 | * @return bool |
||
547 | */ |
||
548 | public function insert_batch($data, $skip_validation = null) |
||
549 | { |
||
550 | $skip_validation = is_null($skip_validation) ? $this->skip_validation : $skip_validation; |
||
551 | |||
552 | if ($skip_validation === FALSE) { |
||
553 | $data = $this->validate($data, 'insert', $skip_validation); |
||
554 | } |
||
555 | |||
556 | if ($data !== FALSE) { |
||
557 | $data['batch'] = true; |
||
558 | $data = $this->trigger('before_insert', ['method' => 'insert_batch', 'fields' => $data] ); |
||
559 | unset($data['batch']); |
||
560 | |||
561 | return $this->db->insert_batch($this->table_name, $data); |
||
562 | } else { |
||
563 | return FALSE; |
||
564 | } |
||
565 | } |
||
566 | |||
567 | //-------------------------------------------------------------------- |
||
568 | |||
569 | /** |
||
570 | * Performs the SQL standard for a combined DELETE + INSERT, using |
||
571 | * PRIMARY and UNIQUE keys to determine which row to replace. |
||
572 | * |
||
573 | * See CI's documentation for the replace method. We simply wrap |
||
574 | * our validation and triggers around their method. |
||
575 | * |
||
576 | * @param $data |
||
577 | * @param null $skip_validation |
||
578 | * @return bool |
||
579 | */ |
||
580 | public function replace($data, $skip_validation=null) |
||
581 | { |
||
582 | $skip_validation = is_null($skip_validation) ? $this->skip_validation : $skip_validation; |
||
583 | |||
584 | if ($skip_validation === FALSE) { |
||
585 | $data = $this->validate($data, 'insert', $skip_validation); |
||
586 | } |
||
587 | |||
588 | if ($data !== FALSE) { |
||
589 | $this->db->replace($this->table_name, $this->prep_data($data)); |
||
590 | |||
591 | if ($this->return_insert_id) { |
||
592 | $id = $this->db->insert_id(); |
||
593 | |||
594 | $this->trigger('after_insert', ['id' => $id, 'fields' => $data, 'method'=>'replace']); |
||
595 | |||
596 | return $id; |
||
597 | } |
||
598 | |||
599 | return TRUE; |
||
600 | } else { |
||
601 | return FALSE; |
||
602 | } |
||
603 | } |
||
604 | |||
605 | //-------------------------------------------------------------------- |
||
606 | |||
607 | |||
608 | /** |
||
609 | * Updates an existing record in the database. |
||
610 | * |
||
611 | * @param mixed $id The primary_key value of the record to update. |
||
612 | * @param array $data An array of value pairs to update in the record. |
||
613 | * @param array $skip_validation If TRUE, will skip validation of data for this call only. |
||
614 | * @return bool |
||
615 | */ |
||
616 | public function update($id, $data, $skip_validation = null) |
||
617 | { |
||
618 | $skip_validation = is_null($skip_validation) ? $this->skip_validation : $skip_validation; |
||
619 | |||
620 | if ($skip_validation === FALSE) { |
||
621 | $data = $this->validate($data); |
||
622 | } |
||
623 | |||
624 | // Will be false if it didn't validate. |
||
625 | if ($data !== FALSE) { |
||
626 | |||
627 | $data = $this->trigger('before_update', ['id' => $id, 'method' =>'update', 'fields' => $data] ); |
||
628 | |||
629 | $this->db->where($this->primary_key, $id); |
||
630 | $this->db->set( $this->prep_data($data) ); |
||
631 | $result = $this->db->update($this->table_name); |
||
632 | |||
633 | $this->trigger('after_update', ['id' => $id, 'fields' => $data, 'result' => $result, 'method' => 'update']); |
||
634 | |||
635 | return $result; |
||
636 | } else { |
||
637 | return FALSE; |
||
638 | } |
||
639 | } |
||
640 | |||
641 | //-------------------------------------------------------------------- |
||
642 | |||
643 | /** |
||
644 | * Updates multiple records in the database at once. |
||
645 | * |
||
646 | * $data = array( |
||
647 | * array( |
||
648 | * 'title' => 'My title', |
||
649 | * 'body' => 'body 1' |
||
650 | * ), |
||
651 | * array( |
||
652 | * 'title' => 'Another Title', |
||
653 | * 'body' => 'body 2' |
||
654 | * ) |
||
655 | * ); |
||
656 | * |
||
657 | * The $where_key should be the name of the column to match the record on. |
||
658 | * If $where_key == 'title', then each record would be matched on that |
||
659 | * 'title' value of the array. This does mean that the array key needs |
||
660 | * to be provided with each row's data. |
||
661 | * |
||
662 | * @param array $data An associate array of row data to update. |
||
663 | * @param string $where_key The column name to match on. |
||
664 | * @return bool |
||
665 | */ |
||
666 | public function update_batch($data, $where_key) |
||
667 | { |
||
668 | foreach ($data as &$row) { |
||
669 | $row = $this->trigger('before_update', ['method' => 'update_batch', 'fields' => $row] ); |
||
670 | } |
||
671 | |||
672 | $result = $this->db->update_batch($this->table_name, $data, $where_key); |
||
673 | |||
674 | foreach ($data as &$row) { |
||
675 | $this->trigger('after_update', ['fields' => $data, 'result' => $result, 'method' => 'update_batch']); |
||
676 | } |
||
677 | |||
678 | return $result; |
||
679 | } |
||
680 | |||
681 | //-------------------------------------------------------------------- |
||
682 | |||
683 | /** |
||
684 | * Updates many records by an array of ids. |
||
685 | * |
||
686 | * While update_batch() allows modifying multiple, arbitrary rows of data |
||
687 | * on each row, update_many() sets the same values for each row. |
||
688 | * |
||
689 | * $ids = array(1, 2, 3, 5, 12); |
||
690 | * $data = array( |
||
691 | * 'deleted_by' => 1 |
||
692 | * ); |
||
693 | * |
||
694 | * $this->model->update_many($ids, $data); |
||
695 | * |
||
696 | * @param array $ids An array of primary_key values to update. |
||
697 | * @param array $data An array of value pairs to modify in each row. |
||
698 | * @param array $skip_validation If TRUE, will skip validation of data for this call only. |
||
699 | * @return bool |
||
700 | */ |
||
701 | public function update_many($ids, $data, $skip_validation = null) |
||
702 | { |
||
703 | if (!is_array($ids) || count($ids) == 0) return NULL; |
||
704 | |||
705 | $skip_validation = is_null($skip_validation) ? $this->skip_validation : $skip_validation; |
||
706 | |||
707 | if ($skip_validation === FALSE) { |
||
708 | $data = $this->validate($data, 'update', $skip_validation); |
||
709 | } |
||
710 | |||
711 | $data = $this->trigger('before_update', ['ids' => $ids, 'method' => 'update_many', 'fields' => $data]); |
||
712 | |||
713 | // Will be false if it didn't validate. |
||
714 | if ($data !== FALSE) { |
||
715 | $this->db->where_in($this->primary_key, $ids); |
||
716 | $this->db->set($data); |
||
717 | $result = $this->db->update($this->table_name); |
||
718 | |||
719 | $this->trigger('after_update', ['ids' => $ids, 'fields' => $data, 'result'=>$result, 'method' => 'update_many']); |
||
720 | |||
721 | return $result; |
||
722 | } else { |
||
723 | return FALSE; |
||
724 | } |
||
725 | } |
||
726 | |||
727 | //-------------------------------------------------------------------- |
||
728 | |||
729 | /** |
||
730 | * Update records in the database using a standard WHERE clause. |
||
731 | * |
||
732 | * Your last parameter should be the $data array with values to update |
||
733 | * on the rows. Any additional parameters should be provided to make up |
||
734 | * a typical WHERE clause. This could be a single array, or a column name |
||
735 | * and a value. |
||
736 | * |
||
737 | * $data = array('deleted_by' => 1); |
||
738 | * $wheres = array('user_id' => 15); |
||
739 | * |
||
740 | * $this->update_by($wheres, $data); |
||
741 | * $this->update_by('user_id', 15, $data); |
||
742 | * |
||
743 | * @param array $data An array of data pairs to update |
||
744 | * @param one or more WHERE-acceptable entries. |
||
745 | * @return bool |
||
746 | */ |
||
747 | public function update_by() |
||
748 | { |
||
749 | $args = func_get_args(); |
||
750 | $data = array_pop($args); |
||
751 | $this->_set_where($args); |
||
752 | |||
753 | $data = $this->trigger('before_update', ['method' => 'update_by', 'fields' => $data]); |
||
754 | |||
755 | // Will be false if it didn't validate. |
||
756 | if ($this->validate($data) !== FALSE) { |
||
757 | $this->db->set( $this->prep_data($data) ); |
||
758 | $result = $this->db->update($this->table_name); |
||
759 | |||
760 | $this->trigger('after_update', ['method' => 'update_by', 'fields' => $data, 'result' => $result] ); |
||
761 | |||
762 | return $result; |
||
763 | } else { |
||
764 | return FALSE; |
||
765 | } |
||
766 | } |
||
767 | |||
768 | //-------------------------------------------------------------------- |
||
769 | |||
770 | /** |
||
771 | * Updates all records and sets the value pairs passed in the array. |
||
772 | * |
||
773 | * @param array $data An array of value pairs with the data to change. |
||
774 | * @param array $skip_validation If TRUE, will skip validation of data for this call only. |
||
775 | * @return bool |
||
776 | */ |
||
777 | View Code Duplication | public function update_all($data, $skip_validation = FALSE) |
|
778 | { |
||
779 | $data = $this->trigger('before_update', ['method' => 'update_all', 'fields' => $data] ); |
||
780 | |||
781 | $skip_validation = is_null($skip_validation) ? $this->skip_validation : $skip_validation; |
||
782 | |||
783 | if ($skip_validation === FALSE) { |
||
784 | $data = $this->validate($data); |
||
785 | } |
||
786 | |||
787 | // Will be false if it didn't validate. |
||
788 | if ($data !== FALSE) { |
||
789 | $this->db->set( $this->prep_data($data) ); |
||
790 | $result = $this->db->update($this->table_name); |
||
791 | |||
792 | $this->trigger('after_update', ['method' => 'update_all', 'fields' => $data, 'result' => $result] ); |
||
793 | |||
794 | return $result; |
||
795 | } else { |
||
796 | return FALSE; |
||
797 | } |
||
798 | } |
||
799 | |||
800 | //-------------------------------------------------------------------- |
||
801 | |||
802 | /** |
||
803 | * Increments the value of field for a given row, selected by the |
||
804 | * primary key for the table. |
||
805 | * |
||
806 | * @param $id |
||
807 | * @param $field |
||
808 | * @param int $value |
||
809 | * @return mixed |
||
810 | */ |
||
811 | View Code Duplication | public function increment($id, $field, $value=1) |
|
812 | { |
||
813 | $value = (int)abs($value); |
||
814 | |||
815 | $this->db->where($this->primary_key, $id); |
||
816 | $this->db->set($field, "{$field}+{$value}", false); |
||
817 | |||
818 | return $this->db->update($this->table_name); |
||
819 | } |
||
820 | |||
821 | //-------------------------------------------------------------------- |
||
822 | |||
823 | /** |
||
824 | * Increments the value of field for a given row, selected by the |
||
825 | * primary key for the table. |
||
826 | * |
||
827 | * @param $id |
||
828 | * @param $field |
||
829 | * @param int $value |
||
830 | * @return mixed |
||
831 | */ |
||
832 | View Code Duplication | public function decrement($id, $field, $value=1) |
|
833 | { |
||
834 | $value = (int)abs($value); |
||
835 | |||
836 | $this->db->where($this->primary_key, $id); |
||
837 | $this->db->set($field, "{$field}-{$value}", false); |
||
838 | |||
839 | return $this->db->update($this->table_name); |
||
840 | } |
||
841 | |||
842 | //-------------------------------------------------------------------- |
||
843 | |||
844 | /** |
||
845 | * Deletes a row by it's primary key value. |
||
846 | * |
||
847 | * @param mixed $id The primary key value of the row to delete. |
||
848 | * @return bool |
||
849 | */ |
||
850 | public function delete($id) |
||
851 | { |
||
852 | $this->trigger('before_delete', ['id' => $id, 'method' => 'delete'] ); |
||
853 | |||
854 | $this->db->where($this->primary_key, $id); |
||
855 | |||
856 | View Code Duplication | if ($this->soft_deletes) { |
|
857 | $sets = $this->log_user && is_object($this->authenticate) |
||
858 | ? array($this->soft_delete_key => 1, $this->deleted_by_field => $this->authenticate->id()) |
||
859 | : array($this->soft_delete_key => 1); |
||
860 | |||
861 | $result = $this->db->update($this->table_name, $sets); |
||
862 | } // Hard Delete |
||
863 | else { |
||
864 | $result = $this->db->delete($this->table_name); |
||
865 | } |
||
866 | |||
867 | $this->trigger('after_delete', ['id' => $id, 'method' => 'delete', 'result' => $result] ); |
||
868 | |||
869 | return $result; |
||
870 | } |
||
871 | |||
872 | //-------------------------------------------------------------------- |
||
873 | |||
874 | public function delete_by() |
||
875 | { |
||
876 | $where = func_get_args(); |
||
877 | $this->_set_where($where); |
||
878 | |||
879 | $where = $this->trigger('before_delete', ['method' => 'delete_by', 'fields' => $where]); |
||
880 | |||
881 | View Code Duplication | if ($this->soft_deletes) { |
|
882 | $sets = $this->log_user && is_object($this->authenticate) |
||
883 | ? array($this->soft_delete_key => 1, $this->deleted_by_field => $this->authenticate->id()) |
||
884 | : array($this->soft_delete_key => 1); |
||
885 | |||
886 | $result = $this->db->update($this->table_name, $sets); |
||
887 | } else { |
||
888 | $result = $this->db->delete($this->table_name); |
||
889 | } |
||
890 | |||
891 | $this->trigger('after_delete', ['method' => 'delete_by', 'fields' => $where, 'result' => $result] ); |
||
892 | |||
893 | return $result; |
||
894 | } |
||
895 | |||
896 | //-------------------------------------------------------------------- |
||
897 | |||
898 | public function delete_many($ids) |
||
899 | { |
||
900 | if (!is_array($ids) || count($ids) == 0) return NULL; |
||
901 | |||
902 | $ids = $this->trigger('before_delete', ['ids' => $ids, 'method' => 'delete_many'] ); |
||
903 | |||
904 | $this->db->where_in($this->primary_key, $ids); |
||
905 | |||
906 | View Code Duplication | if ($this->soft_deletes) { |
|
907 | $sets = $this->log_user && is_object($this->authenticate) |
||
908 | ? array($this->soft_delete_key => 1, $this->deleted_by_field => $this->authenticate->id()) |
||
909 | : array($this->soft_delete_key => 1); |
||
910 | |||
911 | $result = $this->db->update($this->table_name, $sets); |
||
912 | } else { |
||
913 | $result = $this->db->delete($this->table_name); |
||
914 | } |
||
915 | |||
916 | $this->trigger('after_delete', ['ids' => $ids, 'method' => 'delete_many', 'result' => $result]); |
||
917 | |||
918 | return $result; |
||
919 | } |
||
920 | |||
921 | //-------------------------------------------------------------------- |
||
922 | |||
923 | //-------------------------------------------------------------------- |
||
924 | // Scope Methods |
||
925 | //-------------------------------------------------------------------- |
||
926 | |||
927 | /** |
||
928 | * Sets the value of the soft deletes flag. |
||
929 | * |
||
930 | * @param boolean $val If TRUE, should perform a soft delete. If FALSE, a hard delete. |
||
931 | */ |
||
932 | public function soft_delete($val = TRUE) |
||
933 | { |
||
934 | $this->soft_deletes = $val; |
||
935 | |||
936 | return $this; |
||
937 | } |
||
938 | |||
939 | //-------------------------------------------------------------------- |
||
940 | |||
941 | /** |
||
942 | * Temporarily sets our return type to an array. |
||
943 | */ |
||
944 | public function as_array() |
||
945 | { |
||
946 | $this->temp_return_type = 'array'; |
||
947 | |||
948 | return $this; |
||
949 | } |
||
950 | |||
951 | //-------------------------------------------------------------------- |
||
952 | |||
953 | /** |
||
954 | * Temporarily sets our return type to an object. |
||
955 | * |
||
956 | * If $class is provided, the rows will be returned as objects that |
||
957 | * are instances of that class. $class MUST be an fully qualified |
||
958 | * class name, meaning that it must include the namespace, if applicable. |
||
959 | * |
||
960 | * @param string $class |
||
961 | * @return $this |
||
962 | */ |
||
963 | public function as_object($class=null) |
||
964 | { |
||
965 | $this->temp_return_type = ! empty($class) ? $class : 'object'; |
||
966 | |||
967 | return $this; |
||
968 | } |
||
969 | |||
970 | //-------------------------------------------------------------------- |
||
971 | |||
972 | /** |
||
973 | * Also fetches deleted items for this request only. |
||
974 | */ |
||
975 | public function with_deleted() |
||
976 | { |
||
977 | $this->temp_with_deleted = TRUE; |
||
978 | |||
979 | return $this; |
||
980 | } |
||
981 | |||
982 | //-------------------------------------------------------------------- |
||
983 | |||
984 | /** |
||
985 | * Returns whether the current setup will return |
||
986 | * soft deleted rows. |
||
987 | * |
||
988 | * @return bool |
||
989 | */ |
||
990 | public function get_with_deleted() |
||
991 | { |
||
992 | return $this->temp_with_deleted; |
||
993 | } |
||
994 | |||
995 | //-------------------------------------------------------------------- |
||
996 | |||
997 | |||
998 | /** |
||
999 | * Sets the $skip_validation parameter. |
||
1000 | * |
||
1001 | * @param bool $skip |
||
1002 | * @return $this |
||
1003 | */ |
||
1004 | public function skip_validation($skip = true) |
||
1005 | { |
||
1006 | $this->skip_validation = $skip; |
||
1007 | |||
1008 | return $this; |
||
1009 | } |
||
1010 | |||
1011 | //-------------------------------------------------------------------- |
||
1012 | |||
1013 | |||
1014 | //-------------------------------------------------------------------- |
||
1015 | // Utility Methods |
||
1016 | //-------------------------------------------------------------------- |
||
1017 | |||
1018 | /** |
||
1019 | * Counts number of rows modified by an arbitrary WHERE call. |
||
1020 | * @return INT |
||
1021 | */ |
||
1022 | public function count_by() |
||
1023 | { |
||
1024 | $where = func_get_args(); |
||
1025 | $this->_set_where($where); |
||
1026 | |||
1027 | return $this->db->count_all_results($this->table_name); |
||
1028 | } |
||
1029 | |||
1030 | //-------------------------------------------------------------------- |
||
1031 | |||
1032 | /** |
||
1033 | * Counts total number of records, disregarding any previous conditions. |
||
1034 | * |
||
1035 | * @return int |
||
1036 | */ |
||
1037 | public function count_all() |
||
1038 | { |
||
1039 | return $this->db->count_all($this->table_name); |
||
1040 | } |
||
1041 | |||
1042 | //-------------------------------------------------------------------- |
||
1043 | |||
1044 | /** |
||
1045 | * Getter for the table name. |
||
1046 | * |
||
1047 | * @return string The name of the table used by this class. |
||
1048 | */ |
||
1049 | public function table() |
||
1050 | { |
||
1051 | return $this->table_name; |
||
1052 | } |
||
1053 | |||
1054 | //-------------------------------------------------------------------- |
||
1055 | |||
1056 | /** |
||
1057 | * Set the return_insert_id value. |
||
1058 | * |
||
1059 | * @param boolean $return If TRUE, insert will return the insert_id. |
||
1060 | */ |
||
1061 | public function return_insert_id($return = true) |
||
1062 | { |
||
1063 | $this->return_insert_id = (bool)$return; |
||
1064 | |||
1065 | return $this; |
||
1066 | } |
||
1067 | |||
1068 | //-------------------------------------------------------------------- |
||
1069 | |||
1070 | /** |
||
1071 | * A convenience method to return only a single field of the specified row. |
||
1072 | * |
||
1073 | * @param mixed $id The primary_key value to match against. |
||
1074 | * @param string $field The field to search for. |
||
1075 | * |
||
1076 | * @return bool|mixed The value of the field. |
||
1077 | */ |
||
1078 | public function get_field($id = NULL, $field = '') |
||
1079 | { |
||
1080 | $this->db->select($field); |
||
1081 | $this->db->where($this->primary_key, $id); |
||
1082 | $query = $this->db->get($this->table_name); |
||
1083 | |||
1084 | if ($query && $query->num_rows() > 0) { |
||
1085 | return $query->row()->$field; |
||
1086 | } |
||
1087 | |||
1088 | return FALSE; |
||
1089 | |||
1090 | } |
||
1091 | |||
1092 | //--------------------------------------------------------------- |
||
1093 | |||
1094 | /** |
||
1095 | * Checks whether a field/value pair exists within the table. |
||
1096 | * |
||
1097 | * @param string $field The field to search for. |
||
1098 | * @param string $value The value to match $field against. |
||
1099 | * |
||
1100 | * @return bool TRUE/FALSE |
||
1101 | */ |
||
1102 | public function is_unique($field, $value) |
||
1103 | { |
||
1104 | $this->db->where($field, $value); |
||
1105 | $query = $this->db->get($this->table_name); |
||
1106 | |||
1107 | if ($query && $query->num_rows() == 0) { |
||
1108 | return TRUE; |
||
1109 | } |
||
1110 | |||
1111 | return FALSE; |
||
1112 | |||
1113 | } |
||
1114 | |||
1115 | //--------------------------------------------------------------- |
||
1116 | |||
1117 | /** |
||
1118 | * Adds a field to the protected_attributes array. |
||
1119 | * |
||
1120 | * @param $field |
||
1121 | * |
||
1122 | * @return mixed |
||
1123 | */ |
||
1124 | public function protect($field) |
||
1125 | { |
||
1126 | $this->protected_attributes[] = $field; |
||
1127 | |||
1128 | return $this; |
||
1129 | } |
||
1130 | |||
1131 | //-------------------------------------------------------------------- |
||
1132 | |||
1133 | /** |
||
1134 | * Get the field names for this model's table. |
||
1135 | * |
||
1136 | * Returns the model's database fields stored in $this->fields |
||
1137 | * if set, else it tries to retrieve the field list from |
||
1138 | * $this->db->list_fields($this->table_name); |
||
1139 | * |
||
1140 | * @return array Returns the database fields for this model |
||
1141 | */ |
||
1142 | public function get_fields() |
||
1143 | { |
||
1144 | if (empty($this->fields)) { |
||
1145 | $this->fields = $this->db->list_fields($this->table_name); |
||
1146 | } |
||
1147 | |||
1148 | return $this->fields; |
||
1149 | } |
||
1150 | |||
1151 | //-------------------------------------------------------------------- |
||
1152 | |||
1153 | /** |
||
1154 | * Extracts the model's fields (except the key and those handled by |
||
1155 | * Observers) from the $post_data and returns an array of name => value pairs |
||
1156 | * |
||
1157 | * @param Array $post_data The post data, usually $this->input->post() when called from the controller |
||
1158 | * |
||
1159 | * @return Array An array of name => value pairs containing the data for the model's fields |
||
1160 | */ |
||
1161 | public function prep_data($post_data) |
||
1162 | { |
||
1163 | $data = array(); |
||
1164 | $skippedFields = array(); |
||
1165 | |||
1166 | if (empty($post_data)) |
||
1167 | { |
||
1168 | return []; |
||
1169 | } |
||
1170 | |||
1171 | // Though the model doesn't support multiple keys well, $this->key |
||
1172 | // could be an array or a string... |
||
1173 | $skippedFields = array_merge($skippedFields, (array)$this->primary_key); |
||
1174 | |||
1175 | // Remove any protected attributes |
||
1176 | $skippedFields = array_merge($skippedFields, $this->protected_attributes); |
||
1177 | |||
1178 | $fields = $this->get_fields(); |
||
1179 | |||
1180 | // If the field is the primary key, one of the created/modified/deleted |
||
1181 | // fields, or has not been set in the $post_data, skip it |
||
1182 | foreach ($post_data as $field => $value) { |
||
1183 | if (in_array($field, $skippedFields) || |
||
1184 | ! in_array($field, $fields)) |
||
1185 | { |
||
1186 | continue; |
||
1187 | } |
||
1188 | |||
1189 | $data[$field] = $value; |
||
1190 | } |
||
1191 | |||
1192 | return $data; |
||
1193 | } |
||
1194 | |||
1195 | //-------------------------------------------------------------------- |
||
1196 | |||
1197 | /** |
||
1198 | * Returns the last query string, if available. Simply a wrapper for |
||
1199 | * CodeIgniter's database method of the same name. |
||
1200 | * |
||
1201 | * @return string |
||
1202 | */ |
||
1203 | public function last_query () |
||
1204 | { |
||
1205 | return $this->db->last_query(); |
||
1206 | } |
||
1207 | |||
1208 | //-------------------------------------------------------------------- |
||
1209 | |||
1210 | /** |
||
1211 | * Returns the elapsed time for the last query that was executed, if |
||
1212 | * available, or NULL if not available, like if debug mode is off. |
||
1213 | * |
||
1214 | * @return mixed |
||
1215 | */ |
||
1216 | public function last_query_time () |
||
1217 | { |
||
1218 | $times = $this->db->query_times; |
||
1219 | |||
1220 | if (! is_array($this->db->query_times) || ! count($this->db->query_times)) |
||
1221 | { |
||
1222 | return null; |
||
1223 | } |
||
1224 | |||
1225 | return end($times); |
||
1226 | } |
||
1227 | |||
1228 | //-------------------------------------------------------------------- |
||
1229 | |||
1230 | //-------------------------------------------------------------------- |
||
1231 | // Observers |
||
1232 | //-------------------------------------------------------------------- |
||
1233 | |||
1234 | /** |
||
1235 | * Sets the created on date for the object based on the |
||
1236 | * current date/time and date_format. Will not overwrite existing. |
||
1237 | * |
||
1238 | * @param array $row The array of data to be inserted |
||
1239 | * |
||
1240 | * @return array |
||
1241 | */ |
||
1242 | View Code Duplication | public function created_on($row) |
|
1243 | { |
||
1244 | if (empty($row['fields'])) |
||
1245 | { |
||
1246 | return null; |
||
1247 | } |
||
1248 | |||
1249 | $row = $row['fields']; |
||
1250 | |||
1251 | // Created_on |
||
1252 | if (! array_key_exists($this->created_field, $row)) |
||
1253 | { |
||
1254 | $row[$this->created_field] = $this->set_date(); |
||
1255 | } |
||
1256 | |||
1257 | // Created by |
||
1258 | if ($this->log_user && ! array_key_exists($this->created_by_field, $row) && is_object($this->authenticate)) |
||
1259 | { |
||
1260 | // If you're here because of an error with $this->authenticate |
||
1261 | // not being available, it's likely due to you not using |
||
1262 | // the AuthTrait and/or setting log_user after model is instantiated. |
||
1263 | $row[$this->created_by_field] = (int)$this->authenticate->id(); |
||
1264 | } |
||
1265 | |||
1266 | return $row; |
||
1267 | } // end created_on() |
||
1268 | |||
1269 | //-------------------------------------------------------------------- |
||
1270 | |||
1271 | /** |
||
1272 | * Sets the modified_on date for the object based on the |
||
1273 | * current date/time and date_format. Will not overwrite existing. |
||
1274 | * |
||
1275 | * @param array $row The array of data to be inserted |
||
1276 | * |
||
1277 | * @return array |
||
1278 | */ |
||
1279 | View Code Duplication | public function modified_on($row) |
|
1280 | { |
||
1281 | if (empty($row['fields'])) |
||
1282 | { |
||
1283 | return null; |
||
1284 | } |
||
1285 | |||
1286 | $row = $row['fields']; |
||
1287 | |||
1288 | if (is_array($row) && ! array_key_exists($this->modified_field, $row)) |
||
1289 | { |
||
1290 | $row[$this->modified_field] = $this->set_date(); |
||
1291 | } |
||
1292 | |||
1293 | // Modified by |
||
1294 | if ($this->log_user && ! array_key_exists($this->modified_by_field, $row) && is_object($this->authenticate)) |
||
1295 | { |
||
1296 | // If you're here because of an error with $this->authenticate |
||
1297 | // not being available, it's likely due to you not using |
||
1298 | // the AuthTrait and/or setting log_user after model is instantiated. |
||
1299 | $row[$this->modified_by_field] = $this->authenticate->id(); |
||
1300 | } |
||
1301 | |||
1302 | return $row; |
||
1303 | } |
||
1304 | |||
1305 | //-------------------------------------------------------------------- |
||
1306 | |||
1307 | //-------------------------------------------------------------------- |
||
1308 | // Internal Methods |
||
1309 | //-------------------------------------------------------------------- |
||
1310 | |||
1311 | /** |
||
1312 | * Set WHERE parameters |
||
1313 | */ |
||
1314 | protected function _set_where($params) |
||
1315 | { |
||
1316 | if (count($params) == 1) { |
||
1317 | $this->db->where($params[0]); |
||
1318 | } else { |
||
1319 | $this->db->where($params[0], $params[1]); |
||
1320 | } |
||
1321 | } |
||
1322 | |||
1323 | //-------------------------------------------------------------------- |
||
1324 | |||
1325 | /** |
||
1326 | * Triggers a model-specific event and call each of it's observers. |
||
1327 | * |
||
1328 | * @param string $event The name of the event to trigger |
||
1329 | * @param mixed $data The data to be passed to the callback functions. |
||
1330 | * |
||
1331 | * @return mixed |
||
1332 | */ |
||
1333 | public function trigger($event, $data = false) |
||
1334 | { |
||
1335 | if (! isset($this->$event) || ! is_array($this->$event)) |
||
1336 | { |
||
1337 | if (isset($data['fields'])) |
||
1338 | { |
||
1339 | return $data['fields']; |
||
1340 | } |
||
1341 | |||
1342 | return $data; |
||
1343 | } |
||
1344 | |||
1345 | foreach ($this->$event as $method) |
||
1346 | { |
||
1347 | if (strpos($method, '(')) |
||
1348 | { |
||
1349 | preg_match('/([a-zA-Z0-9\_\-]+)(\(([a-zA-Z0-9\_\-\., ]+)\))?/', $method, $matches); |
||
1350 | $this->callback_parameters = explode(',', $matches[3]); |
||
1351 | } |
||
1352 | |||
1353 | $data = call_user_func_array(array($this, $method), array($data)); |
||
1354 | } |
||
1355 | |||
1356 | // In case no method called or method returned |
||
1357 | // the entire data array, we typically just need the $fields |
||
1358 | if (isset($data['fields'])) |
||
1359 | { |
||
1360 | return $data['fields']; |
||
1361 | } |
||
1362 | |||
1363 | // A few methods might need to return 'ids' |
||
1364 | if (isset($data['ids'])) |
||
1365 | { |
||
1366 | return $data['ids']; |
||
1367 | } |
||
1368 | |||
1369 | return $data; |
||
1370 | } |
||
1371 | |||
1372 | //-------------------------------------------------------------------- |
||
1373 | |||
1374 | /** |
||
1375 | * Validates the data passed into it based upon the form_validation rules |
||
1376 | * setup in the $this->validate property. |
||
1377 | * |
||
1378 | * If $type == 'insert', any additional rules in the class var $insert_validate_rules |
||
1379 | * for that field will be added to the rules. |
||
1380 | * |
||
1381 | * @param array $data An array of validation rules |
||
1382 | * @param string $type Either 'update' or 'insert'. |
||
1383 | * @return array/bool The original data or FALSE |
||
1384 | */ |
||
1385 | public function validate($data, $type = 'update', $skip_validation = null) |
||
1386 | { |
||
1387 | $skip_validation = is_null($skip_validation) ? $this->skip_validation : $skip_validation; |
||
1388 | |||
1389 | if ($skip_validation) { |
||
1390 | return $data; |
||
1391 | } |
||
1392 | |||
1393 | // We need the database to be loaded up at this point in case |
||
1394 | // we want to use callbacks that hit the database. |
||
1395 | if (empty($this->db)) |
||
1396 | { |
||
1397 | $this->load->database(); |
||
1398 | } |
||
1399 | |||
1400 | if (!empty($this->validation_rules)) { |
||
1401 | $this->form_validation->set_data($data); |
||
1402 | |||
1403 | if (is_array($this->validation_rules)) { |
||
1404 | // Any insert additions? |
||
1405 | if ($type == 'insert' |
||
1406 | && !empty($this->insert_validate_rules) |
||
1407 | && is_array($this->insert_validate_rules) |
||
1408 | ) { |
||
1409 | foreach ($this->validation_rules as &$row) { |
||
1410 | if (isset($this->insert_validate_rules[$row['field']])) { |
||
1411 | $row ['rules'] .= '|' . $this->insert_validate_rules[$row['field']]; |
||
1412 | } |
||
1413 | } |
||
1414 | } |
||
1415 | |||
1416 | $this->form_validation->set_rules($this->validation_rules); |
||
1417 | |||
1418 | if ($this->form_validation->run('', $this) === TRUE) { |
||
1419 | return $data; |
||
1420 | } else { |
||
1421 | return FALSE; |
||
1422 | } |
||
1423 | } else { |
||
1424 | if ($this->form_validation->run($this->validate, $this) === TRUE) { |
||
1425 | return $data; |
||
1426 | } else { |
||
1427 | return FALSE; |
||
1428 | } |
||
1429 | } |
||
1430 | } else { |
||
1431 | return $data; |
||
1432 | } |
||
1433 | } |
||
1434 | |||
1435 | //-------------------------------------------------------------------- |
||
1436 | |||
1437 | /** |
||
1438 | * Protect attributes by removing them from $row array. Useful for |
||
1439 | * removing id, or submit buttons names if you simply throw your $_POST |
||
1440 | * array at your model. :) |
||
1441 | * |
||
1442 | * @param object /array $row The value pair item to remove. |
||
1443 | */ |
||
1444 | public function protect_attributes($row) |
||
1445 | { |
||
1446 | foreach ($this->protected_attributes as $attr) { |
||
1447 | if (is_object($row)) { |
||
1448 | unset($row->$attr); |
||
1449 | } else { |
||
1450 | unset($row[$attr]); |
||
1451 | } |
||
1452 | } |
||
1453 | |||
1454 | return $row; |
||
1455 | } |
||
1456 | |||
1457 | //-------------------------------------------------------------------- |
||
1458 | |||
1459 | /** |
||
1460 | * A utility function to allow child models to use the type of |
||
1461 | * date/time format that they prefer. This is primarily used for |
||
1462 | * setting created_on and modified_on values, but can be used by |
||
1463 | * inheriting classes. |
||
1464 | * |
||
1465 | * The available time formats are: |
||
1466 | * * 'int' - Stores the date as an integer timestamp. |
||
1467 | * * 'datetime' - Stores the date and time in the SQL datetime format. |
||
1468 | * * 'date' - Stores teh date (only) in the SQL date format. |
||
1469 | * |
||
1470 | * @param mixed $user_date An optional PHP timestamp to be converted. |
||
1471 | * |
||
1472 | * @access protected |
||
1473 | * |
||
1474 | * @return int|null|string The current/user time converted to the proper format. |
||
1475 | */ |
||
1476 | protected function set_date($user_date = NULL) |
||
1477 | { |
||
1478 | $curr_date = !empty($user_date) ? $user_date : time(); |
||
1479 | |||
1480 | switch ($this->date_format) { |
||
1481 | case 'int': |
||
1482 | return $curr_date; |
||
1483 | break; |
||
1484 | case 'datetime': |
||
1485 | return date('Y-m-d H:i:s', $curr_date); |
||
1486 | break; |
||
1487 | case 'date': |
||
1488 | return date('Y-m-d', $curr_date); |
||
1489 | break; |
||
1490 | } |
||
1491 | |||
1492 | }//end set_date() |
||
1493 | |||
1494 | //-------------------------------------------------------------------- |
||
1495 | |||
1496 | /** |
||
1497 | * Returns an array containing the 'code' and 'message' of the |
||
1498 | * database's error, as provided by CI's database drivers. |
||
1499 | * |
||
1500 | * @return mixed |
||
1501 | */ |
||
1502 | public function error($db_array_only=false) |
||
1503 | { |
||
1504 | // Send any validation errors if we have any. |
||
1505 | if (function_exists('validation_errors') && validation_errors() && ! $db_array_only) |
||
1506 | { |
||
1507 | return validation_errors(); |
||
1508 | } |
||
1509 | |||
1510 | // No validation errors? Return the db error. |
||
1511 | $error = $this->db->error(); |
||
1512 | |||
1513 | if ($db_array_only) |
||
1514 | { |
||
1515 | return $error; |
||
1516 | } |
||
1517 | |||
1518 | if (! empty($error['code'])) |
||
1519 | { |
||
1520 | return "Database Error {$error['code']}: {$error['message']}."; |
||
1521 | } |
||
1522 | |||
1523 | // No errors found. |
||
1524 | return ''; |
||
1525 | } |
||
1526 | |||
1527 | //-------------------------------------------------------------------- |
||
1528 | |||
1529 | //-------------------------------------------------------------------- |
||
1530 | // Magic Methods |
||
1531 | //-------------------------------------------------------------------- |
||
1532 | |||
1533 | /** |
||
1534 | * __get magic |
||
1535 | * |
||
1536 | * Allows models to access CI's loaded classes using the same |
||
1537 | * syntax as controllers. |
||
1538 | * |
||
1539 | * This is the same as what CI's model uses, but we keep it |
||
1540 | * here since that's the ONLY thing that CI's model does. |
||
1541 | * |
||
1542 | * @param string $key |
||
1543 | */ |
||
1544 | public function __get($key) |
||
1545 | { |
||
1546 | // Give them first crack at any protected class vars |
||
1547 | if (isset($this->$key)) |
||
1548 | { |
||
1549 | return $this->$key; |
||
1550 | } |
||
1551 | |||
1552 | // Debugging note: |
||
1553 | // If you're here because you're getting an error message |
||
1554 | // saying 'Undefined Property: system/core/Model.php', it's |
||
1555 | // most likely a typo in your model code. |
||
1556 | return get_instance()->$key; |
||
1557 | } |
||
1558 | |||
1559 | //-------------------------------------------------------------------- |
||
1560 | |||
1561 | /** |
||
1562 | * Provide direct access to any of CodeIgniter's DB methods but |
||
1563 | * make it look like it's part of the class, purely for convenience. |
||
1564 | * |
||
1565 | * @param $name |
||
1566 | * @param $params |
||
1567 | */ |
||
1568 | public function __call($name, $params) |
||
1569 | { |
||
1570 | if (method_exists($this->db, $name)) |
||
1571 | { |
||
1572 | call_user_func_array([$this->db, $name], $params); |
||
1573 | return $this; |
||
1574 | } |
||
1575 | } |
||
1576 | |||
1577 | //-------------------------------------------------------------------- |
||
1578 | |||
1579 | |||
1580 | } |
||
1581 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.