Passed
Push — 1.0.0-dev ( 632010...3e5cd9 )
by nguereza
02:59
created

Model::unserialize()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 9
rs 10
1
<?php
2
    defined('ROOT_PATH') || exit('Access denied');
3
    /**
4
     * TNH Framework
5
     *
6
     * A simple PHP framework using HMVC architecture
7
     *
8
     * This content is released under the GNU GPL License (GPL)
9
     *
10
     * Copyright (C) 2017 Tony NGUEREZA
11
     *
12
     * This program is free software; you can redistribute it and/or
13
     * modify it under the terms of the GNU General Public License
14
     * as published by the Free Software Foundation; either version 3
15
     * of the License, or (at your option) any later version.
16
     *
17
     * This program is distributed in the hope that it will be useful,
18
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
     * GNU General Public License for more details.
21
     *
22
     * You should have received a copy of the GNU General Public License
23
     * along with this program; if not, write to the Free Software
24
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25
     */
26
27
28
    /**
29
     * A base model with a series of CRUD functions (powered by CI's query builder),
30
     * validation-in-model support, event callbacks and more.
31
     *
32
     * @link http://github.com/jamierumbelow/codeigniter-base-model
33
     * @copyright Copyright (c) 2012, Jamie Rumbelow <http://jamierumbelow.net>
34
     */
35
36
    class Model {
37
38
        /* --------------------------------------------------------------
39
         * VARIABLES
40
         * ------------------------------------------------------------ */
41
42
        /**
43
         * This model's default database table. Automatically
44
         * guessed by pluralising the model name.
45
         */
46
        protected $_table;
47
48
        /**
49
         * The database connection object. Will be set to the default
50
         * connection. This allows individual models to use different DBs
51
         * without overwriting the global database connection.
52
         */
53
        protected $_database;
54
55
        /**
56
         * This model's default primary key or unique identifier.
57
         * Used by the get(), update() and delete() functions.
58
         */
59
        protected $primary_key = 'id';
60
61
        /**
62
         * Support for soft deletes and this model's 'deleted' key
63
         */
64
        protected $soft_delete = false;
65
        protected $soft_delete_key = 'is_deleted';
66
        protected $_temporary_with_deleted = FALSE;
67
        protected $_temporary_only_deleted = FALSE;
68
69
        /**
70
         * The various callbacks available to the model. Each are
71
         * simple lists of method names (methods will be run on $this).
72
         */
73
        protected $before_create = array();
74
        protected $after_create = array();
75
        protected $before_update = array();
76
        protected $after_update = array();
77
        protected $before_get = array();
78
        protected $after_get = array();
79
        protected $before_delete = array();
80
        protected $after_delete = array();
81
82
        protected $callback_parameters = array();
83
84
        /**
85
         * Protected, non-modifiable attributes
86
         */
87
        protected $protected_attributes = array();
88
89
        /**
90
         * Relationship arrays. Use flat strings for defaults or string
91
         * => array to customise the class name and primary key
92
         */
93
        protected $belongs_to = array();
94
        protected $has_many = array();
95
96
        protected $_with = array();
97
98
        /**
99
         * An array of validation rules. This needs to be the same format
100
         * as validation rules passed to the FormValidation library.
101
         */
102
        protected $validate = array();
103
104
        /**
105
         * Optionally skip the validation. Used in conjunction with
106
         * skip_validation() to skip data validation for any future calls.
107
         */
108
        protected $skip_validation = FALSE;
109
110
        /**
111
         * By default we return our results as objects. If we need to override
112
         * this, we can, or, we could use the `as_array()` and `as_object()` scopes.
113
         */
114
        protected $return_type = 'object';
115
116
        /**
117
         * Set return type array or object
118
         * @var string
119
         */
120
        protected $_temporary_return_type = NULL;
121
    	
122
    	
123
        /**
124
    		The database cache time 
125
         */
126
        protected $dbCacheTime = 0;
127
128
        /**
129
         * Instance of the Loader class
130
         * @var Loader
131
         */
132
        protected $loaderInstance = null;
133
134
        /**
135
         * Instance of the FormValidation library
136
         * @var FormValidation
137
         */
138
        protected $formValidationInstance = null;
139
		
140
        /* --------------------------------------------------------------
141
         * GENERIC METHODS
142
         * ------------------------------------------------------------ */
143
144
        /**
145
         * Initialise the model, tie into the CodeIgniter superobject and
146
         * try our best to guess the table name.
147
         */
148
        public function __construct(Database $db = null) {
149
            $instance = null;
150
            if (is_object($db)) {
151
                $instance = $db;
152
            } else {
153
                $obj = & get_instance();
154
                if (isset($obj->database)){
155
                    /**
156
                     * NOTE: Need use "clone" because some Model need have the personal instance of the database library
157
                     * to prevent duplication
158
                     */
159
                    $instance = clone $obj->database;
160
                }
161
            }
162
            //Note: don't use the property direct access here as some update is done in the method
163
            //$this->setDatabaseInstance
164
            $this->setDatabaseInstance($instance);
165
166
            array_unshift($this->before_create, 'protect_attributes');
167
            array_unshift($this->before_update, 'protect_attributes');
168
            $this->_temporary_return_type = $this->return_type;
169
        }
170
171
        /* --------------------------------------------------------------
172
         * CRUD INTERFACE
173
         * ------------------------------------------------------------ */
174
175
        /**
176
         * Fetch a single record based on the primary key. Returns an object.
177
         */
178
        public function get($primary_value) {
179
            return $this->get_by($this->primary_key, $primary_value);
180
        }
181
182
183
        /**
184
         * Fetch a single record based on an arbitrary WHERE call. Can be
185
         * any valid value to DatabaseQueryBuilder->where().
186
         */
187
        public function get_by() {
188
            $where = func_get_args();
189
            $this->checkForSoftDelete();
190
            $this->_set_where($where);
191
            $this->trigger('before_get');
192
            $type = $this->getReturnType();
193
            $this->getQueryBuilder()->from($this->_table);
194
            $row = $this->_database->get($type);
195
            $this->_temporary_return_type = $this->return_type;
196
            $row = $this->trigger('after_get', $row);
197
            $this->_with = array();
198
            return $row;
199
        }
200
201
        /**
202
         * Fetch an array of records based on an array of primary values.
203
         */
204
        public function get_many($values) {
205
            $this->getQueryBuilder()->in($this->primary_key, $values);
206
            return $this->get_all();
207
        }
208
209
        /**
210
         * Fetch an array of records based on an arbitrary WHERE call.
211
         */
212
        public function get_many_by() {
213
            $where = func_get_args();
214
            $this->_set_where($where);
215
            return $this->get_all();
216
        }
217
218
        /**
219
         * Fetch all the records in the table. Can be used as a generic call
220
         * to $this->_database->get() with scoped methods.
221
         */
222
        public function get_all() {
223
            $this->trigger('before_get');
224
            $this->checkForSoftDelete();
225
            $type = $this->getReturnType();
226
            $this->getQueryBuilder()->from($this->_table);
227
            $result = $this->_database->getAll($type);
228
            $this->_temporary_return_type = $this->return_type;
229
            foreach ($result as $key => &$row) {
230
                $row = $this->trigger('after_get', $row, ($key == count($result) - 1));
231
            }
232
            $this->_with = array();
233
            return $result;
234
        }
235
236
        /**
237
         * Insert a new row into the table. $data should be an associative array
238
         * of data to be inserted. Returns newly created ID.
239
         * @see Database::insert
240
         */
241
        public function insert($data = array(), $skip_validation = FALSE, $escape = true) {
242
            if ($this->validateData($data, $skip_validation) !== FALSE) {
243
                $data = $this->trigger('before_create', $data);
244
                $this->getQueryBuilder()->from($this->_table);
245
                $this->_database->insert($data, $escape);
246
                $insert_id = $this->_database->insertId();
247
                $this->trigger('after_create', $insert_id);
248
                //if the table doesn't have the auto increment field or sequence, the value of 0 will be returned 
249
                $id = $insert_id;
250
                if (!$id) {
251
                    $id = true;
252
                }
253
                return $id;
254
            } 
255
            return FALSE;
256
            
257
        }
258
259
        /**
260
         * Insert multiple rows into the table. Returns an array of multiple IDs.
261
         */
262
        public function insert_many($data = array(), $skip_validation = FALSE, $escape = true) {
263
            $ids = array();
264
            foreach ($data as $key => $row) {
265
                $ids[] = $this->insert($row, $skip_validation, $escape);
266
            }
267
            return $ids;
268
        }
269
270
        /**
271
         * Updated a record based on the primary value.
272
         */
273
        public function update($primary_value, $data = array(), $skip_validation = FALSE, $escape = true) {
274
            $data = $this->trigger('before_update', $data);
275
            if ($this->validateData($data, $skip_validation) !== FALSE) {
276
                $this->getQueryBuilder()->where($this->primary_key, $primary_value)
277
                                        ->from($this->_table);
278
                $result = $this->_database->update($data, $escape);
279
                $this->trigger('after_update', array($data, $result));
280
                return $result;
281
            } 
282
            return FALSE;
283
        }
284
285
        /**
286
         * Update many records, based on an array of primary values.
287
         */
288
        public function update_many($primary_values, $data = array(), $skip_validation = FALSE, $escape = true) {
289
            $data = $this->trigger('before_update', $data);
290
            if ($this->validateData($data, $skip_validation) !== FALSE) {
291
                $this->getQueryBuilder()->in($this->primary_key, $primary_values)
292
                                        ->from($this->_table);
293
                $result = $this->_database->update($data, $escape);
294
                $this->trigger('after_update', array($data, $result));
295
                return $result;
296
            }
297
            return FALSE;
298
        }
299
300
        /**
301
         * Updated a record based on an arbitrary WHERE clause.
302
         */
303
        public function update_by() {
304
            $args = func_get_args();
305
            $data = array();
306
            if (count($args) == 2) {
307
                if (is_array($args[1])) {
308
                    $data = array_pop($args);
309
                }
310
            } else if (count($args) == 3) {
311
                if (is_array($args[2])) {
312
                    $data = array_pop($args);
313
                }
314
            }
315
            $data = $this->trigger('before_update', $data);
316
            if ($this->validate($data) !== FALSE) {
317
                $this->_set_where($args);
318
                $this->getQueryBuilder()->from($this->_table);
319
                $result = $this->_database->update($data);
320
                $this->trigger('after_update', array($data, $result));
321
                return $result;
322
            }
323
            return FALSE;
324
        }
325
326
        /**
327
         * Update all records
328
         */
329
        public function update_all($data = array(), $escape = true) {
330
            $data = $this->trigger('before_update', $data);
331
            $this->getQueryBuilder()->from($this->_table);
332
            $result = $this->_database->update($data, $escape);
333
            $this->trigger('after_update', array($data, $result));
334
            return $result;
335
        }
336
337
        /**
338
         * Delete a row from the table by the primary value
339
         */
340
        public function delete($id) {
341
            $this->trigger('before_delete', $id);
342
            $this->getQueryBuilder()->where($this->primary_key, $id);
343
            $result = false;
344
            $this->getQueryBuilder()->from($this->_table);  
345
            if ($this->soft_delete) {
346
                $result = $this->_database->update(array($this->soft_delete_key => TRUE));
347
            } else {
348
                $result = $this->_database->delete();
349
            }
350
            $this->trigger('after_delete', $result);
351
            return $result;
352
        }
353
354
        /**
355
         * Delete a row from the database table by an arbitrary WHERE clause
356
         */
357
        public function delete_by() {
358
            $where = func_get_args();
359
            $where = $this->trigger('before_delete', $where);
360
            $this->_set_where($where);
361
            $result = false;
362
            $this->getQueryBuilder()->from($this->_table);  
363
            if ($this->soft_delete) {
364
                $result = $this->_database->update(array($this->soft_delete_key => TRUE));
365
            } else {
366
                $result = $this->_database->delete();
367
            }
368
            $this->trigger('after_delete', $result);
369
            return $result;
370
        }
371
372
        /**
373
         * Delete many rows from the database table by multiple primary values
374
         */
375
        public function delete_many($primary_values) {
376
            $primary_values = $this->trigger('before_delete', $primary_values);
377
            $this->getQueryBuilder()->in($this->primary_key, $primary_values);
378
            $result = false;
379
            $this->getQueryBuilder()->from($this->_table);  
380
            if ($this->soft_delete) {
381
                $result = $this->_database->update(array($this->soft_delete_key => TRUE));
382
            } else {
383
                $result = $this->_database->delete();
384
            }
385
            $this->trigger('after_delete', $result);
386
            return $result;
387
        }
388
389
390
        /**
391
         * Truncates the table
392
         */
393
        public function truncate() {
394
            $this->getQueryBuilder()->from($this->_table); 
395
            $result = $this->_database->delete();
396
            return $result;
397
        }
398
399
        /* --------------------------------------------------------------
400
         * RELATIONSHIPS
401
         * ------------------------------------------------------------ */
402
403
        public function with($relationship) {
404
            $this->_with[] = $relationship;
405
            if (!in_array('relate', $this->after_get)) {
406
                $this->after_get[] = 'relate';
407
            }
408
            return $this;
409
        }
410
		
411
        /**
412
         * Relationship
413
         */
414
        public function relate($row) {
415
            if (empty($row)) {
416
                return $row;
417
            }
418
            $row = $this->relateBelongsTo($row);
419
            $row = $this->relateHasMany($row);
420
            return $row;
421
        }
422
423
        /* --------------------------------------------------------------
424
         * UTILITY METHODS
425
         * ------------------------------------------------------------ */
426
427
        /**
428
         * Retrieve and generate a form_dropdown friendly array
429
         */
430
        public function dropdown() {
431
            $args = func_get_args();
432
            if (count($args) == 2) {
433
                list($key, $value) = $args;
434
            } else {
435
                $key = $this->primary_key;
436
                $value = $args[0];
437
            }
438
            $this->trigger('before_dropdown', array($key, $value));
439
            $this->checkForSoftDelete();
440
            $this->getQueryBuilder()->select(array($key, $value))
441
                                    ->from($this->_table);
442
            $result = $this->_database->getAll();
443
            $options = array();
444
            foreach ($result as $row) {
445
                $options[$row->{$key}] = $row->{$value};
446
            }
447
            $options = $this->trigger('after_dropdown', $options);
448
            return $options;
449
        }
450
451
        /**
452
         * Fetch a count of rows based on an arbitrary WHERE call.
453
         */
454
        public function count_by() {
455
            $this->checkForSoftDelete();
456
            $where = func_get_args();
457
            $this->_set_where($where);
458
            $this->getQueryBuilder()->from($this->_table);
459
            $this->_database->getAll();
460
            return $this->_database->numRows();
461
        }
462
463
        /**
464
         * Fetch a total count of rows, disregarding any previous conditions
465
         */
466
        public function count_all() {
467
            $this->checkForSoftDelete();
468
            $this->getQueryBuilder()->from($this->_table);
469
            $this->_database->getAll();
470
            return $this->_database->numRows();
471
        }
472
		
473
        /**
474
         * Enabled cache temporary
475
         */
476
        public function cached($ttl = 0) {
477
            $this->_database = $this->_database->cached($ttl);
478
            return $this;
479
        }
480
481
        /**
482
         * Tell the class to skip the insert validation
483
         */
484
        public function skip_validation() {
485
            $this->skip_validation = TRUE;
486
            return $this;
487
        }
488
489
        /**
490
         * Get the skip validation status
491
         */
492
        public function get_skip_validation() {
493
            return $this->skip_validation;
494
        }
495
496
        /**
497
         * Return the next auto increment of the table. Only tested on MySQL.
498
         */
499
        public function get_next_id() {
500
            $this->getQueryBuilder()->select('AUTO_INCREMENT')
501
                                    ->from('information_schema.TABLES')
502
                                    ->where('TABLE_NAME', $this->_table)
503
                                    ->where('TABLE_SCHEMA', $this->_database->getDatabaseName());
504
            return (int) $this->_database->get()->AUTO_INCREMENT;
505
        }
506
507
        /**
508
         * Getter for the table name
509
         */
510
        public function table() {
511
            return $this->_table;
512
        }
513
514
        /* --------------------------------------------------------------
515
         * GLOBAL SCOPES
516
         * ------------------------------------------------------------ */
517
518
        /**
519
         * Return the next call as an array rather than an object
520
         */
521
        public function as_array() {
522
            $this->_temporary_return_type = 'array';
523
            return $this;
524
        }
525
526
        /**
527
         * Return the next call as an object rather than an array
528
         */
529
        public function as_object() {
530
            $this->_temporary_return_type = 'object';
531
            return $this;
532
        }
533
534
        /**
535
         * Don't care about soft deleted rows on the next call
536
         */
537
        public function with_deleted() {
538
            $this->_temporary_with_deleted = TRUE;
539
            return $this;
540
        }
541
542
        /**
543
         * Only get deleted rows on the next call
544
         */
545
        public function only_deleted() {
546
            $this->_temporary_only_deleted = TRUE;
547
            return $this;
548
        }
549
550
        /* --------------------------------------------------------------
551
         * OBSERVERS
552
         * ------------------------------------------------------------ */
553
554
        /**
555
         * MySQL DATETIME created_at and updated_at
556
         */
557
        public function created_at($row) {
558
            if (is_object($row)) {
559
                $row->created_at = date('Y-m-d H:i:s');
560
            } else {
561
                $row['created_at'] = date('Y-m-d H:i:s');
562
            }
563
            return $row;
564
        }
565
566
        public function updated_at($row) {
567
            if (is_object($row)) {
568
                $row->updated_at = date('Y-m-d H:i:s');
569
            } else {
570
                $row['updated_at'] = date('Y-m-d H:i:s');
571
            }
572
            return $row;
573
        }
574
575
        /**
576
         * Serialises data for you automatically, allowing you to pass
577
         * through objects and let it handle the serialisation in the background
578
         */
579
        public function serialize($row) {
580
            foreach ($this->callback_parameters as $column) {
581
                $row[$column] = serialize($row[$column]);
582
            }
583
            return $row;
584
        }
585
586
        public function unserialize($row) {
587
            foreach ($this->callback_parameters as $column) {
588
                if (is_array($row)) {
589
                    $row[$column] = unserialize($row[$column]);
590
                } else {
591
                    $row->$column = unserialize($row->$column);
592
                }
593
            }
594
            return $row;
595
        }
596
597
        /**
598
         * Protect attributes by removing them from $row array
599
         */
600
        public function protect_attributes($row) {
601
            foreach ($this->protected_attributes as $attr) {
602
                if (is_object($row) && isset($row->$attr)) {
603
                    unset($row->$attr);
604
                } else if (isset($row[$attr])) {
605
                    unset($row[$attr]);
606
                }
607
            }
608
            return $row;
609
        }
610
		
611
            /**
612
             * Return the database instance
613
             * @return Database the database instance
614
             */
615
        public function getDatabaseInstance() {
616
            return $this->_database;
617
        }
618
619
        /**
620
         * set the Database instance for future use
621
         * @param Database $db the database object
622
         */
623
        public function setDatabaseInstance($db) {
624
            $this->_database = $db;
625
            if ($this->dbCacheTime > 0) {
626
                $this->_database->setCache($this->dbCacheTime);
627
            }
628
            return $this;
629
        }
630
631
        /**
632
         * Return the loader instance
633
         * @return Loader the loader instance
634
         */
635
        public function getLoader() {
636
            return $this->loaderInstance;
637
        }
638
639
        /**
640
         * Set the loader instance for future use
641
         * @param Loader $loader the loader object
642
         * @return object
643
         */
644
        public function setLoader($loader) {
645
            $this->loaderInstance = $loader;
646
            return $this;
647
        }
648
649
        /**
650
         * Return the queryBuilder instance this is the shortcut to database queryBuilder
651
         * @return object the DatabaseQueryBuilder instance
652
         */
653
        public function getQueryBuilder() {
654
            return $this->_database->getQueryBuilder();
655
        }
656
657
        /**
658
         * Set the DatabaseQueryBuilder instance for future use
659
         * @param object $queryBuilder the DatabaseQueryBuilder object
660
         * @return object
661
         */
662
        public function setQueryBuilder($queryBuilder) {
663
            $this->_database->setQueryBuilder($queryBuilder);
664
            return $this;
665
        }
666
667
        /**
668
         * Return the FormValidation instance
669
         * @return FormValidation the form validation instance
670
         */
671
        public function getFormValidation() {
672
            return $this->formValidationInstance;
673
        }
674
675
        /**
676
         * Set the form validation instance for future use
677
         * @param FormValidation $fv the form validation object
678
         * @return object
679
         */
680
        public function setFormValidation($fv) {
681
            $this->formValidationInstance = $fv;
682
            return $this;
683
        }
684
685
        /* --------------------------------------------------------------
686
         * QUERY BUILDER DIRECT ACCESS METHODS
687
         * ------------------------------------------------------------ */
688
689
        /**
690
         * A wrapper to $this->getQueryBuilder()->orderBy()
691
         */
692
        public function order_by($criteria, $order = 'ASC') {
693
            if (is_array($criteria)) {
694
                foreach ($criteria as $key => $value) {
695
                    $this->getQueryBuilder()->orderBy($key, $value);
696
                }
697
            } else {
698
                $this->getQueryBuilder()->orderBy($criteria, $order);
699
            }
700
            return $this;
701
        }
702
703
        /**
704
         * A wrapper to $this->getQueryBuilder()->limit()
705
         */
706
        public function limit($offset = 0, $limit = 10) {
707
            $this->getQueryBuilder()->limit($offset, $limit);
708
            return $this;
709
        }
710
711
        /* --------------------------------------------------------------
712
         * INTERNAL METHODS
713
         * ------------------------------------------------------------ */
714
        
715
        /**
716
         * Validate the data using the validation rules
717
         * @param  mixed $data the data to validate before insert, update, etc.
718
         * @param boolean $skipValidation whether to skip validation or not
719
         * @return mixed
720
         */
721
        protected function validateData($data, $skipValidation) {
722
            if ($skipValidation === FALSE) {
723
                $data = $this->validate($data);
724
            }
725
            return $data;
726
        }
727
        
728
        /**
729
         * Return the loader instance or create
730
         * @return object
731
         */
732
        protected function getLoaderInstanceOrCreate() {
733
            if (! is_object($this->loaderInstance)) {
734
                $this->loaderInstance = & get_instance()->loader;
735
            } 
736
            return $this->loaderInstance;
737
        }
738
739
         /**
740
         * Get the return type array or object
741
         * @return string|boolean
742
         */
743
        protected function getReturnType(){
744
            $type = false;
745
            if ($this->_temporary_return_type == 'array') {
746
               $type = 'array';
747
            }
748
            return $type;
749
        }
750
751
         /**
752
         * Check if soft delete is enable setting the condition
753
         * @return object the current instance 
754
         */
755
        protected function checkForSoftDelete(){
756
            if ($this->soft_delete && $this->_temporary_with_deleted !== true) {
757
                $this->getQueryBuilder()->where($this->soft_delete_key, (bool) $this->_temporary_only_deleted);
758
            }
759
            return $this;
760
        }
761
762
         /**
763
         * Relate for "belongs_to" and "has_many"
764
         * @param  string $relationship the name of relation
765
         * @param  string|array $options      the model and primary key values
766
         * @param  object|array $row          the row to update
767
         * @param  string $type         the type can be "belongs_to", "has_many"
768
         * @return mixed               the final row values
769
         */
770
        protected function relateBelongsToAndHasMany($relationship, $options, $row, $type){
771
            if (in_array($relationship, $this->_with)) {
772
                $loaderInstance = $this->getLoaderInstanceOrCreate();
773
                $loaderInstance->model($options['model'], $relationship . '_model');
774
775
                if($type == 'belongs_to'){
776
                    if (is_object($row)) {
777
                        $row->{$relationship} = $this->{$relationship . '_model'}->get($row->{$options['primary_key']});
778
                    } else {
779
                        $row[$relationship] = $this->{$relationship . '_model'}->get($row[$options['primary_key']]);
780
                    }
781
                } else {
782
                    if (is_object($row)) {
783
                        $row->{$relationship} = $this->{$relationship . '_model'}->get_many_by($options['primary_key'], $row->{$this->primary_key});
784
                    } else {
785
                        $row[$relationship] = $this->{$relationship . '_model'}->get_many_by($options['primary_key'], $row[$this->primary_key]);
786
                    }
787
                }
788
            }
789
            return $row;
790
        }
791
792
        /**
793
         * relate for the relation "belongs_to"
794
         * @return mixed
795
         */
796
        protected function relateBelongsTo($row) {
797
            foreach ($this->belongs_to as $key => $value) {
798
                if (is_string($value)) {
799
                    $relationship = $value;
800
                    $options = array('primary_key' => $value . '_id', 'model' => $value . '_model');
801
                } else {
802
                    $relationship = $key;
803
                    $options = $value;
804
                }
805
                $row = $this->relateBelongsToAndHasMany($relationship, $options, $row, 'belongs_to');
806
            }
807
            return $row;
808
        }
809
810
        /**
811
         * relate for the relation "has_many"
812
         * @return mixed
813
         */
814
        protected function relateHasMany($row) {
815
            foreach ($this->has_many as $key => $value) {
816
                if (is_string($value)) {
817
                    $relationship = $value;
818
                    $options = array('primary_key' => $this->_table . '_id', 'model' => $value . '_model');
819
                } else {
820
                    $relationship = $key;
821
                    $options = $value;
822
                }
823
                $row = $this->relateBelongsToAndHasMany($relationship, $options, $row, 'belongs_to');
824
            }
825
            return $row;
826
        }
827
		
828
        /**
829
         * Trigger an event and call its observers. Pass through the event name
830
         * (which looks for an instance variable $this->event_name), an array of
831
         * parameters to pass through and an optional 'last in interation' boolean
832
         */
833
        protected function trigger($event, $data = FALSE, $last = TRUE) {
834
            if (isset($this->$event) && is_array($this->$event)) {
835
                foreach ($this->$event as $method) {
836
                    if (strpos($method, '(')) {
837
                        preg_match('/([a-zA-Z0-9\_\-]+)(\(([a-zA-Z0-9\_\-\., ]+)\))?/', $method, $matches);
838
                        $method = $matches[1];
839
                        $this->callback_parameters = explode(',', $matches[3]);
840
                    }
841
                    $data = call_user_func_array(array($this, $method), array($data, $last));
842
                }
843
            }
844
            return $data;
845
        }
846
847
        /**
848
         * Run validation on the passed data
849
         */
850
        protected function validate(array $data) {
851
            if ($this->skip_validation || empty($this->validate)) {
852
                return $data;
853
            }
854
            $fv = $this->formValidationInstance;
855
            if (!is_object($fv)) {
856
                Loader::library('FormValidation');
857
                $fv = $this->formvalidation;
0 ignored issues
show
Bug Best Practice introduced by
The property formvalidation does not exist on Model. Since you implemented __get, consider adding a @property annotation.
Loading history...
858
                $this->setFormValidation($fv);  
859
            }
860
            $fv->setData($data);
861
            $fv->setRules($this->validate);
862
863
            if ($fv->run()) {
864
                return $data;
865
            }
866
            return FALSE;
867
        }
868
		
869
		
870
        /**
871
         * Set WHERE parameters, when is array
872
         * @param array $params
873
         */
874
        protected function _set_where_array(array $params) {
875
            foreach ($params as $field => $filter) {
876
                if (is_array($filter)) {
877
                    $this->getQueryBuilder()->in($field, $filter);
878
                } else {
879
                    if (is_int($field)) {
880
                        $this->getQueryBuilder()->where($filter);
881
                    } else {
882
                        $this->getQueryBuilder()->where($field, $filter);
883
                    }
884
                }
885
            }
886
        }
887
888
889
        /**
890
         * Set WHERE parameters, cleverly
891
         */
892
        protected function _set_where($params) {
893
            if (count($params) == 1 && is_array($params[0])) {
894
                $this->_set_where_array($params[0]);
895
            } else if (count($params) == 1) {
896
                $this->getQueryBuilder()->where($params[0]);
897
            } else if (count($params) == 2) {
898
                if (is_array($params[1])) {
899
                    $this->getQueryBuilder()->in($params[0], $params[1]);
900
                } else {
901
                    $this->getQueryBuilder()->where($params[0], $params[1]);
902
                }
903
            } else if (count($params) == 3) {
904
                $this->getQueryBuilder()->where($params[0], $params[1], $params[2]);
905
            } else {
906
                if (is_array($params[1])) {
907
                    $this->getQueryBuilder()->in($params[0], $params[1]);
908
                } else {
909
                    $this->getQueryBuilder()->where($params[0], $params[1]);
910
                }
911
            }
912
        }
913
914
        /**
915
            Shortcut to controller
916
         */
917
        public function __get($key) {
918
            return get_instance()->{$key};
919
        }
920
921
    }
922