PluginProbe
ShiftController Employee Shift Scheduling / 2.2.3
ShiftController Employee Shift Scheduling v2.2.3
4.9.97 4.9.96 4.9.95 4.9.74 4.9.75 4.9.76 4.9.77 4.9.78 4.9.84 4.9.85 4.9.87 4.9.91 4.9.92 trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.2.4 All 38 releases
← All changes | happ/application/core/MY_Model.php +871 -723 3.2.42.2.3 View file →
@@ -1,723 +1,871 @@
1 -<?php
2 -class MY_model extends DataMapper
3 -{
4 - static $relations = array();
5 - static $me_all = NULL;
6 -
7 - var $table = 'users';
8 - var $allow_none = TRUE;
9 - var $_old = array();
10 -
11 - private $_presenter = NULL;
12 -
13 - function __construct( $id = NULL )
14 - {
15 - parent::__construct( $id );
16 - $my_class = $this->my_class();
17 -
18 - /* runtime relations configuration */
19 - if( empty(self::$relations) ){
20 - $this->config->load('relations', TRUE, TRUE );
21 - }
22 -
23 - if( ! isset(self::$relations[$my_class]) ){
24 - self::$relations[$my_class] = array(
25 - 'has_many' => array(),
26 - 'has_one' => array(),
27 - );
28 - }
29 -
30 - $schema = $this->config->item( $my_class, 'relations' );
31 -
32 - if( $schema ){
33 - if( isset($schema['has_many']) ){
34 - self::$relations[$my_class]['has_many'] = array_merge( self::$relations[$my_class]['has_many'], $schema['has_many'] );
35 - }
36 -
37 - if( isset($schema['has_one']) ){
38 - self::$relations[$my_class]['has_one'] = array_merge( self::$relations[$my_class]['has_one'], $schema['has_one'] );
39 - }
40 - }
41 -
42 - reset( self::$relations[$my_class]['has_many'] );
43 - foreach( self::$relations[$my_class]['has_many'] as $c => $rel ){
44 - $this->has_many( $c, $rel );
45 - }
46 -
47 - reset( self::$relations[$my_class]['has_one'] );
48 - foreach( self::$relations[$my_class]['has_one'] as $c => $rel ){
49 - $this->has_one( $c, $rel );
50 - }
51 - }
52 -
53 - public function _const( $cname )
54 - {
55 - $name = get_class($this) . '::' . $cname;
56 - $return = constant($name);
57 - return $return;
58 - }
59 -
60 - public function update_relation( $relname, $new_rels = array() )
61 - {
62 - /* get current */
63 - $current = array();
64 - $this->{$relname}->select('id')->get();
65 - foreach( $this->{$relname} as $rel ){
66 - $current[ $rel->id ] = $rel;
67 - }
68 -
69 - $to_add = array();
70 - $to_delete = array();
71 - foreach( $new_rels as $new_rel ){
72 - if( isset($current[$new_rel->id]) ){
73 - // remain
74 - unset($current[$new_rel->id]);
75 - }
76 - else {
77 - // add new
78 - $to_add[$new_rel->id] = $new_rel;
79 - }
80 - }
81 -
82 - /* delete */
83 - if( $current ){
84 - foreach( $current as $rel ){
85 - $this->delete($rel, $relname);
86 - }
87 - }
88 -
89 - /* to add */
90 - $related = array(
91 - $relname => $to_add
92 - );
93 - return $this->save( $related );
94 - }
95 -
96 - public function my_relation_names( $other_model ){
97 - $return = array();
98 - $my_class = $this->my_class();
99 -
100 - foreach( $other_model->has_one as $class_test => $class_test_details ){
101 - $this_other_class = isset($class_test_details['class']) ? $class_test_details['class'] : $class_test;
102 - if( $this_other_class == $my_class ){
103 - $return[] = $class_test;
104 - }
105 - }
106 - foreach( $other_model->has_many as $class_test => $class_test_details ){
107 - $this_other_class = isset($class_test_details['class']) ? $class_test_details['class'] : $class_test;
108 - if( $this_other_class == $my_class ){
109 - $return[] = $class_test;
110 - }
111 - }
112 - return $return;
113 - }
114 -
115 - public function get_all()
116 - {
117 - if( self::$me_all === NULL ){
118 - self::$me_all = array();
119 - foreach( $this->get()->all as $m ){
120 - self::$me_all[$m->id] = $m;
121 - }
122 - // self::$me_all = $this->get()->all;
123 - }
124 - return self::$me_all;
125 - }
126 -
127 - function up()
128 - {
129 - /* my order */
130 - $my_order = $this->show_order;
131 -
132 - /* check which one is upper then flip */
133 - $other_one = clone $this;
134 - $other_one
135 - ->where( 'show_order <=', $my_order )
136 - ->where( 'id <>', $this->id )
137 - ->order_by( 'show_order', 'desc' )
138 - ->limit(1)
139 - ->get();
140 - if( $other_one->exists() ){
141 - $new_order = $other_one->show_order;
142 - $other_id = $other_one->id;
143 - if( $new_order == $my_order ){
144 - $my_order = $new_order + 1;
145 - }
146 - /* update other_one */
147 - $other_one->show_order = $my_order;
148 - $other_one->save();
149 - /* update me */
150 - $this->show_order = $new_order;
151 - $this->save();
152 - }
153 - return TRUE;
154 - }
155 -
156 - function down()
157 - {
158 - /* my order */
159 - $my_order = $this->show_order;
160 -
161 - /* check which one is lower then flip */
162 - $other_one = clone $this;
163 - $other_one
164 - ->where( 'show_order >=', $my_order )
165 - ->where( 'id <>', $this->id )
166 - ->order_by( 'show_order', 'asc' )
167 - ->limit(1)
168 - ->get();
169 - if( $other_one->exists() ){
170 - $new_order = $other_one->show_order;
171 - $other_id = $other_one->id;
172 - if( $new_order == $my_order ){
173 - $my_order = $new_order - 1;
174 - }
175 - /* update other_one */
176 - $other_one->show_order = $my_order;
177 - $other_one->save();
178 - /* update me */
179 - $this->show_order = $new_order;
180 - $this->save();
181 - }
182 - return TRUE;
183 - }
184 -
185 - protected function _prepare_get()
186 - {
187 - foreach( $this->has_many as $other => $info ){
188 - // echo "INCLUDE RELATED COUNT $other<br>";
189 - $this->include_related_count($other);
190 - }
191 - }
192 -
193 - public function get_slim( $limit = NULL, $offset = NULL )
194 - {
195 - return parent::get( $limit, $offset );
196 - }
197 -
198 - public function get_iterated_slim( $limit = NULL, $offset = NULL )
199 - {
200 - return parent::get_iterated( $limit, $offset );
201 - }
202 -
203 - function full_id()
204 - {
205 - $return = $this->my_class() . '.' . $this->id;
206 - return $return;
207 - }
208 -
209 - function valid()
210 - {
211 - return $this->valid;
212 - }
213 -
214 - function errors()
215 - {
216 - return $this->error->all;
217 - }
218 -
219 - function add_error( $field, $error )
220 - {
221 - return $this->error_message( $field, $error );
222 - }
223 -
224 - function remove_validation( $what )
225 - {
226 - unset( $this->validation[$what] );
227 - }
228 -
229 - function my_class()
230 - {
231 - $return = get_class($this);
232 - $return = strtolower($return);
233 -
234 - $CI =& ci_get_instance();
235 - $suffix = $CI->config->item('model_suffix');
236 -
237 - if( substr($return, -strlen($suffix)) == $suffix ){
238 - $return = substr( $return, 0, -strlen($suffix) );
239 - }
240 - return $return;
241 - }
242 -
243 - function prop_name( $pname )
244 - {
245 - if( substr($pname, -3) == '_id' ){
246 - $short_pname = substr($pname, 0, -3);
247 - if(
248 - isset($this->has_one[$short_pname])
249 - OR
250 - isset($this->has_many[$short_pname])
251 - ){
252 - $pname = $short_pname;
253 - }
254 - }
255 - return $pname;
256 - }
257 -
258 - public function trigger_event( $event, $force_class = '' )
259 - {
260 - /* check if we also have a method here */
261 - $method = '_' . $event;
262 - if( method_exists($this, $method)){
263 - $this->{$method}();
264 - }
265 -
266 - $CI =& ci_get_instance();
267 - if( isset($CI->hc_events) ){
268 - $event_class = $force_class ? $force_class : $this->my_class();
269 - $event = $event_class . '.' . $event;
270 - $object = clone $this;
271 - $args = array( $event, $object );
272 - call_user_func_array( array($CI->hc_events, 'trigger'), $args );
273 - }
274 - }
275 -
276 - public function get_copy($force_db = FALSE)
277 - {
278 - /* reset changes */
279 - $this->_old = array();
280 - return parent::get_copy($force_db);
281 - }
282 -
283 -/* with triggered events */
284 - public function save($object = '', $related_field = '')
285 - {
286 - $is_new = FALSE;
287 - if( $this->_force_save_as_new OR (! $this->id) ){
288 - $is_new = TRUE;
289 - }
290 -
291 - $this->trigger_event( 'before_save' );
292 -
293 - /* keep copy of the stored because it resets to new after save */
294 - $this->_keep_old();
295 -
296 - $return = parent::save($object, $related_field);
297 -
298 - /* if new then get it to load relations */
299 - if(
300 - $return
301 - &&
302 - $is_new
303 - &&
304 - ( $this->has_one OR $this->has_many )
305 - ){
306 - $this
307 - ->where('id', $this->id)
308 - ->get()
309 - ;
310 - }
311 -
312 - if( $return ){
313 - $this->trigger_event( 'after_save' );
314 - }
315 - return $return;
316 - }
317 -
318 - public function delete($object = '', $related_field = '')
319 - {
320 - if( ! ($object OR $related_field) ){
321 - $this->trigger_event( 'before_delete' );
322 - }
323 -
324 - $return = parent::delete($object, $related_field);
325 -
326 - if( $return ){
327 - if( ! ($object OR $related_field) ){
328 - $this->trigger_event('after_delete');
329 - }
330 - }
331 - return $return;
332 - }
333 -
334 - private function _keep_old()
335 - {
336 - $this->_old = (array) $this->stored;
337 - /* also include has_one */
338 - reset( $this->has_one );
339 - foreach( array_keys($this->has_one) as $k ){
340 - if( is_object($this->{$k}) )
341 - $this->_old[$k] = $this->{$k}->id;
342 - else
343 - $this->_old[$k] = $this->{$k};
344 - }
345 - }
346 -
347 -/* gives the array of changed properties with their old values, useful after save */
348 - public function get_changes( $relations = NULL )
349 - {
350 - $return = array();
351 - $new = $this->to_array();
352 - if( $relations ){
353 - reset( $relations );
354 - foreach( $relations as $k => $o ){
355 - $new[ $k ] = $o->id;
356 - }
357 - }
358 -
359 - foreach( $new as $k => $v ){
360 - if( array_key_exists($k, $this->_old) ){
361 - if( $this->_old[$k] !== $v )
362 - $return[$k] = $this->_old[$k];
363 - }
364 - else {
365 - $return[$k] = NULL;
366 - }
367 - }
368 - return $return;
369 - }
370 -
371 -/* rewrite from_array() to not to modify database */
372 - function from_array( $data )
373 - {
374 - // keep track of newly related objects
375 - $new_related_objects = array();
376 - $fields = array_keys( $data );
377 -
378 - // If $fields is provided, assume all $fields should exist.
379 - foreach($fields as $f){
380 - if(array_key_exists($f, $this->has_one)){
381 - // Store $has_one relationships
382 - $c = get_class($this->{$f});
383 - $rel = new $c();
384 - $id = isset($data[$f]) ? $data[$f] : 0;
385 - $rel->get_by_id($id);
386 -
387 - if($rel->exists()){
388 - // The new relationship exists, save it.
389 - $new_related_objects[$f] = $rel;
390 - // if( ! $this->id ){
391 - $this->{$f} = $rel;
392 - // }
393 - }
394 - else {
395 - // The new relationship does not exist, delete the old one.
396 -// $object->delete($object->{$f}->get());
397 - /* CHANGE */
398 -// $new_related_objects[$f] = NULL;
399 - $new_related_objects[$f] = NULL;
400 - // if( ! $this->id ){
401 - $this->{$f}->clear();
402 - // }
403 - }
404 - $idid = $f . '_id';
405 - $this->{$idid} = $id;
406 - }
407 - else if(array_key_exists($f, $this->has_many)) {
408 - // Store $has_many relationships
409 - $c = get_class($this->{$f});
410 - $rels = new $c();
411 - $ids = isset($data[$f]) ? $data[$f] : FALSE;
412 - if(empty($ids)) {
413 - // if no IDs were provided, delete all old relationships.
414 -// $object->delete($object->{$f}->select('id')->get()->all);
415 - /* CHANGE */
416 - $new_related_objects[$f] = array();
417 - // if( ! $this->id ){
418 - $this->{$f}->clear();
419 - // }
420 - }
421 - else {
422 - // Otherwise, get the new ones...
423 - $rels->where_in('id', $ids)->select('id')->get();
424 - // Store them...
425 -
426 - $new_related_objects[$f] = $rels->all;
427 - // if( ! $this->id ){
428 - $this->{$f} = $rels->all;
429 - // }
430 -
431 - // And delete any old ones that do not exist.
432 -// $old_rels = $object->{$f}->where_not_in('id', $ids)->select('id')->get();
433 -// $object->delete($old_rels->all);
434 - /* CHANGE */
435 - }
436 - }
437 - elseif(
438 - in_array($f, $this->fields) OR
439 - isset($this->validation[$f])
440 - ){
441 - if( isset($data[$f])){
442 - $this->{$f} = $data[$f];
443 - }
444 - }
445 - }
446 -
447 - // return new objects
448 - return $new_related_objects;
449 - }
450 -
451 - public function set( $pname, $pvalue )
452 - {
453 - $this->{$pname} = $pvalue;
454 - return $this;
455 - }
456 -
457 -/* prepare for presenters */
458 - public function presenter()
459 - {
460 - return $this->_presenter;
461 - }
462 - public function set_presenter( $presenter )
463 - {
464 - $this->_presenter = $presenter;
465 - }
466 -
467 - public function __call($key, $args = array())
468 - {
469 - $prfx = 'present_';
470 - if( substr($key, 0, strlen($prfx)) == $prfx ){
471 - $short_key = substr($key, strlen($prfx));
472 - $presenter = $this->presenter();
473 -
474 - if( $presenter === NULL ){
475 - // attempt to load presenter
476 - $presenter = HC_App::presenter( $this->my_class(), $this );
477 - if( $presenter ){
478 - $this->set_presenter( $presenter );
479 - }
480 - else {
481 - $this->set_presenter( FALSE );
482 - }
483 - }
484 -
485 - if( $presenter && method_exists($presenter, $short_key) ){
486 - array_unshift( $args, $this );
487 - return call_user_func_array( array($presenter, $short_key), $args );
488 - // return $presenter->{$short_key}( $this );
489 - }
490 - else {
491 - if( property_exists($this, $short_key) ){
492 - return $this->{$short_key};
493 - }
494 - else {
495 - return NULL;
496 - }
497 - }
498 - }
499 - return parent::__call($key, $args);
500 - }
501 -
502 -/* validation */
503 - public function _save_array( $field )
504 - {
505 - if ( ! empty($this->{$field}) ){
506 - $this->{$field} = join( '||', $this->{$field} );
507 - }
508 - else {
509 - $this->{$field} = '';
510 - }
511 - return TRUE;
512 - }
513 -
514 - public function _load_array( $field )
515 - {
516 - if ( ! empty($this->{$field}) ){
517 - $this->{$field} = explode( '||', $this->{$field} );
518 - }
519 - else {
520 - $this->{$field} = array();
521 - }
522 - }
523 -
524 - public function _check_show_order( $field )
525 - {
526 - if( (! $this->id) && (! $this->show_order) ){
527 - $max_show_order = 0;
528 - $query = $this->db
529 - ->select_max('show_order')
530 - ->get($this->table)
531 - ;
532 - if( $row = $query->row() ){
533 - $max_show_order = $row->show_order;
534 - }
535 - $this->show_order = $max_show_order + 1;
536 - }
537 - return TRUE;
538 - }
539 -
540 - public function _enum( $field, $compare )
541 - {
542 - if (
543 - ( isset($this->{$field}) )
544 - )
545 - {
546 - return in_array( $this->{$field}, $compare );
547 - }
548 - return FALSE;
549 - }
550 -
551 - public function _greater_equal_than_field($me, $other)
552 - {
553 - if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
554 - return FALSE;
555 - return $this->{$me} >= $this->{$other};
556 - }
557 -
558 - public function _less_equal_than_field($me, $other)
559 - {
560 - if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
561 - return FALSE;
562 - return $this->{$me} <= $this->{$other};
563 - }
564 -
565 - public function _greater_than_field($me, $other)
566 - {
567 - if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
568 - return FALSE;
569 - return $this->{$me} > $this->{$other};
570 - }
571 -
572 - public function _less_than_field($me, $other)
573 - {
574 - if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
575 - return FALSE;
576 - return $this->{$me} < $this->{$other};
577 - }
578 -
579 - protected function _differs($field, $other_field)
580 - {
581 - return ($this->{$field} !== $this->{$other_field}) ? TRUE : FALSE;
582 - }
583 -
584 - protected function _after_save()
585 - {
586 -/*
587 - $CI =& ci_get_instance();
588 - if( $this->keep_log && $CI->hc_modules->exists('logaudit') )
589 - {
590 - $log_changes = array();
591 - $changes = $this->get_changes();
592 - reset( $changes );
593 - foreach( $changes as $property_name => $old_value )
594 - {
595 - if( in_array($property_name, $this->keep_log) )
596 - {
597 - $log_changes[ $property_name ] = $old_value;
598 - }
599 - }
600 -
601 - if( $log_changes )
602 - {
603 - $log = HC_App::model('logaudit');
604 - $log->log( $this, $log_changes );
605 - }
606 - }
607 -*/
608 - }
609 -}
610 -
611 -class MY_Model_Virtual
612 -{
613 - private $_presenter = NULL;
614 -
615 - function my_class()
616 - {
617 - $return = get_class($this);
618 - $return = strtolower($return);
619 -
620 - $CI =& ci_get_instance();
621 - $suffix = $CI->config->item('model_suffix');
622 -
623 - if( substr($return, -strlen($suffix)) == $suffix ){
624 - $return = substr( $return, 0, -strlen($suffix) );
625 - }
626 - return $return;
627 - }
628 -
629 - public function trigger_event( $event )
630 - {
631 - $CI =& ci_get_instance();
632 - if( isset($CI->hc_events) ){
633 - $event = $this->my_class() . '.' . $event;
634 - $object = clone $this;
635 - $args = array( $event, $object );
636 - call_user_func_array( array($CI->hc_events, 'trigger'), $args );
637 - }
638 - }
639 -
640 - public function save($object = '', $related_field = '')
641 - {
642 - $this->trigger_event( 'before_save' );
643 -
644 - /* keep copy of the stored because it resets to new after save */
645 - $this->_keep_old();
646 -
647 - $return = parent::save($object, $related_field);
648 -
649 - if( $return ){
650 - $this->trigger_event( 'after_save' );
651 - }
652 - return $return;
653 - }
654 -
655 -/* prepare for presenters */
656 - public function presenter()
657 - {
658 - return $this->_presenter;
659 - }
660 - public function set_presenter( $presenter )
661 - {
662 - $this->_presenter = $presenter;
663 - }
664 -
665 - public function __call($key, $args = array())
666 - {
667 - $prfx = 'present_';
668 - if( substr($key, 0, strlen($prfx)) == $prfx ){
669 - $short_key = substr($key, strlen($prfx));
670 - $presenter = $this->presenter();
671 - if( $presenter === NULL ){
672 - // attempt to load presenter
673 - $presenter = HC_App::presenter( $this->my_class(), $this );
674 - if( $presenter ){
675 - $this->set_presenter( $presenter );
676 - }
677 - else {
678 - $this->set_presenter( FALSE );
679 - }
680 - }
681 -
682 - if( $presenter && method_exists($presenter, $short_key) ){
683 - array_unshift( $args, $this );
684 - return call_user_func_array( array($presenter, $short_key), $args );
685 - // return $presenter->{$short_key}( $this );
686 - }
687 - else {
688 - if( isset($this->{$short_key}) ){
689 - return $this->{$short_key};
690 - }
691 - }
692 - }
693 - return parent::__call($key, $args);
694 - }
695 -}
696 -
697 -function hc_presenter_autoload( $class )
698 -{
699 - $class = strtolower($class);
700 - $suffix = '_hc_presenter';
701 - if( substr($class, -strlen($suffix)) != $suffix ){
702 - return;
703 - }
704 -//echo "TRYING '$class'<br>";
705 -
706 - $CI =& ci_get_instance();
707 - $look_in_dirs = $CI->config->look_in_dirs();
708 -
709 - foreach( $look_in_dirs as $path ){
710 - // Prepare file
711 - $class_file = substr($class, 0, -strlen($suffix));
712 - $file = $path . '/presenters/' . $class_file . EXT;
713 - // echo $file .' <br>';
714 -
715 - // Check if file exists, require_once if it does
716 - if (file_exists($file)){
717 - include_once($file);
718 - break;
719 - }
720 - }
721 -}
722 -
723 -spl_autoload_register('hc_presenter_autoload');
1 +<?php
2 +class MY_model extends DataMapper
3 +{
4 + static $titles = array();
5 + static $relations = array();
6 +
7 + var $table = 'users';
8 + var $build_title = array(
9 + '_my_class()_',
10 + ': ',
11 + '_id_'
12 + );
13 + var $field_view = array();
14 + var $allow_none = TRUE;
15 + var $_old = array();
16 +
17 + function __construct( $id = NULL )
18 + {
19 + parent::__construct( $id );
20 + $my_class = $this->my_class();
21 +
22 + /* runtime relations configuration */
23 + if( empty(self::$relations) )
24 + {
25 + $this->config->load('relations', TRUE, TRUE );
26 + }
27 +
28 + if( ! isset(self::$relations[$my_class]) )
29 + {
30 + self::$relations[$my_class] = array(
31 + 'has_many' => array(),
32 + 'has_one' => array(),
33 + );
34 + }
35 +
36 + $schema = $this->config->item( $my_class, 'relations' );
37 +
38 + if( $schema )
39 + {
40 + if( isset($schema['has_many']) )
41 + {
42 + self::$relations[$my_class]['has_many'] = array_merge( self::$relations[$my_class]['has_many'], $schema['has_many'] );
43 + }
44 +
45 + if( isset($schema['has_one']) )
46 + {
47 + self::$relations[$my_class]['has_one'] = array_merge( self::$relations[$my_class]['has_one'], $schema['has_one'] );
48 + }
49 + }
50 +
51 + reset( self::$relations[$my_class]['has_many'] );
52 + foreach( self::$relations[$my_class]['has_many'] as $c => $rel )
53 + {
54 + $this->has_many( $c, $rel );
55 + }
56 +
57 + reset( self::$relations[$my_class]['has_one'] );
58 + foreach( self::$relations[$my_class]['has_one'] as $c => $rel )
59 + {
60 + $this->has_one( $c, $rel );
61 + }
62 +
63 + /* fill in defaults */
64 + if( ! $id )
65 + {
66 + if( $my_class == 'shift' )
67 + {
68 + $my_fields = $this->get_fields();
69 + foreach( $my_fields as $mf )
70 + {
71 + if( isset($mf['default']) )
72 + {
73 + $this->{$mf['name']} = $mf['default'];
74 + }
75 + }
76 + }
77 + }
78 + }
79 +
80 + function title(){
81 + $return = array();
82 + reset( $this->build_title );
83 + foreach( $this->build_title as $bt )
84 + {
85 + if(
86 + (substr($bt, 0, 1) == '_') &&
87 + (substr($bt, -1) == '_')
88 + )
89 + {
90 + $prop = substr($bt, 1, -1);
91 + if( substr($prop, -2) == '()' ) // my method
92 + {
93 + $func = substr($prop, 0, -2);
94 + $return[] = $this->{$func}();
95 + }
96 + else // my prop
97 + {
98 + $return[] = $this->{$prop};
99 + }
100 + }
101 + else // just string like space or brackets
102 + {
103 + $return[] = $bt;
104 + }
105 + }
106 + $return = join( '', $return );
107 + return $return;
108 + }
109 +
110 + private function _build_title_select()
111 + {
112 + $return = array();
113 + reset( $this->build_title );
114 + foreach( $this->build_title as $bt )
115 + {
116 + if(
117 + (substr($bt, 0, 1) == '_') &&
118 + (substr($bt, -1) == '_')
119 + )
120 + {
121 + $prop = substr($bt, 1, -1);
122 + if( substr($prop, -2) == '()' )
123 + {
124 + }
125 + else
126 + {
127 + $return[] = $prop;
128 + }
129 + }
130 + else
131 + {
132 + $return[] = "\"" . $bt . "\"";
133 + }
134 + }
135 + $return = join( ',', $return );
136 + return $return;
137 + }
138 +
139 + function titles()
140 + {
141 + $class = get_class($this);
142 + if( ! isset(self::$titles[$class]) )
143 + {
144 + self::$titles[$class] = $this->_load_titles();
145 + }
146 + return self::$titles[$class];
147 + }
148 +
149 + protected function _load_titles()
150 + {
151 + $return = array();
152 + $this->clear();
153 + $select = $this->_build_title_select();
154 +// $this->select( 'id' );
155 + $this->select( '*' );
156 + $this->select( 'CONCAT(' . $select . ') AS title', FALSE );
157 + $this->get();
158 +
159 + foreach( $this as $u )
160 + {
161 + $return[ $u->id ] = $u->title;
162 + }
163 + return $return;
164 + }
165 +
166 + function csv_upload( $file_name = 'userfile', $separator = ',' )
167 + {
168 + $return = NULL;
169 + $fields = $this->get_fields();
170 + reset( $fields );
171 + foreach( $fields as $f )
172 + {
173 + $my_fields[] = $f['name'];
174 + }
175 +
176 + if( isset($_FILES[$file_name]) && is_uploaded_file($_FILES[$file_name]['tmp_name']) )
177 + {
178 + $tmp_name = $_FILES[$file_name]['tmp_name'];
179 + $return = array();
180 +
181 + $parse_error = FALSE;
182 + if( ($handle = fopen($tmp_name, "r")) !== FALSE)
183 + {
184 + $line_no = 0;
185 + while( ($line = fgetcsv($handle, 1000, $separator)) !== FALSE )
186 + {
187 + // titles
188 + if( ! $line_no )
189 + {
190 + $prop_names = $line;
191 + for( $ii = 0; $ii < count($prop_names); $ii++ )
192 + {
193 + reset( $fields );
194 + foreach( $fields as $f )
195 + {
196 + if( strtolower($prop_names[$ii]) == $f['name'] )
197 + {
198 + $prop_names[$ii] = strtolower($prop_names[$ii]);
199 + }
200 + }
201 + }
202 + $prop_count = count( $prop_names );
203 +
204 + // check for mandatory fields
205 + $missing_fields = array();
206 + reset( $fields );
207 + foreach( $fields as $f )
208 + {
209 + if( isset($f['required']) && $f['required'] ){
210 + if( ! in_array($f['name'], $prop_names) ){
211 + $missing_fields[] = $f['name'];
212 + }
213 + }
214 + }
215 + if( $missing_fields )
216 + {
217 + $err_msg = lang('conf_import_error_fields_missing') . ': ' . join(', ', $missing_fields);
218 + $this->error_message( 'import', $err_msg );
219 + $parse_error = TRUE;
220 + break;
221 + }
222 +
223 + // check if any fields are not parsed
224 + $not_parsed_fields = array();
225 + reset( $prop_names );
226 + foreach( $prop_names as $f )
227 + {
228 + $f = trim( $f );
229 + if( ! $f )
230 + continue;
231 +
232 + if( ! (in_array($f, $my_fields) OR in_array(strtolower($f), $my_fields)) )
233 + {
234 + $not_parsed_fields[] = $f;
235 + }
236 + }
237 + if( $not_parsed_fields )
238 + {
239 + $err_msg = lang('conf_import_message_fields_not_recognized') . ': ' . join(', ', $not_parsed_fields);
240 + $this->error_message( 'import', $err_msg );
241 + }
242 + }
243 + else
244 + {
245 + $values = array();
246 + for( $i = 0; $i < $prop_count; $i++ )
247 + {
248 + $check_name = strtolower($prop_names[$i]);
249 + if( in_array($check_name, $my_fields) )
250 + {
251 + if( isset($line[$i]) )
252 + $values[ $check_name ] = $line[$i];
253 + else
254 + $values[ $check_name ] = '';
255 + }
256 + }
257 + $return[] = $values;
258 + }
259 + $line_no++;
260 + }
261 + fclose($handle);
262 + }
263 +
264 + if( $parse_error )
265 + {
266 + $return = NULL;
267 + }
268 + }
269 + return $return;
270 + }
271 +
272 + function csv( $separator = ',', $skip = array() )
273 + {
274 + $related_fields = array_merge( $this->has_one, $this->has_many );
275 +
276 + // header
277 + $headers = array();
278 + $fields = $this->get_fields();
279 + reset( $fields );
280 + foreach( $fields as $f )
281 + {
282 + if( in_array($f['name'], $skip) )
283 + continue;
284 +// $headers[ $f['name'] ] = Hc_lib::parse_lang( $f['label'] );
285 + $headers[ $f['name'] ] = $f['name'];
286 + }
287 +
288 + $data = array();
289 + $data[] = join( $separator, $headers );
290 +
291 + // entries
292 + $keys = array_keys( $headers );
293 + $this->clear();
294 + $this->get();
295 + foreach( $this as $s )
296 + {
297 + $e = array();
298 + reset( $keys );
299 + foreach( $keys as $k )
300 + {
301 + if( isset($related_fields[$k]) )
302 + {
303 + $e[] = $s->{$k}->get()->title();
304 + }
305 + else
306 + {
307 + $e[] = $s->{$k};
308 + }
309 + }
310 + $data[] = hc_build_csv( $e, $separator );
311 + }
312 + $return = join( "\n", $data );
313 + return $return;
314 + }
315 +
316 + function my_class()
317 + {
318 + $return = get_class($this);
319 + $return = strtolower($return);
320 + $suffix = '_model';
321 + if( substr($return, -strlen($suffix)) == $suffix )
322 + {
323 + $return = substr( $return, 0, -strlen($suffix) );
324 + }
325 + return $return;
326 + }
327 +
328 + public function get_fields()
329 + {
330 + return $this->my_fields;
331 + }
332 +
333 + public function get_form_fields()
334 + {
335 + $return = array();
336 +
337 + $fields = $this->get_fields();
338 + foreach( $fields as $tf )
339 + {
340 + $return[$tf['name']] = $tf;
341 + }
342 +
343 + $fnames = array_keys($return);
344 + /* assign options to dropdowns */
345 + foreach( $fnames as $fn )
346 + {
347 + if(
348 + ( isset($return[$fn]['type']) && ($return[$fn]['type'] != 'dropdown') ) OR
349 + ( isset($return[$fn]['options']) )
350 + )
351 + {
352 + continue;
353 + }
354 +
355 + $options = array();
356 + /* enum fields */
357 + if(
358 + isset($this->validation[$fn]) && isset($this->validation[$fn]['rules']) &&
359 + array_key_exists('enum', $this->validation[$fn]['rules']) &&
360 + is_array($this->validation[$fn]['rules']['enum'])
361 + )
362 + {
363 + $options = array();
364 + foreach( $this->validation[$fn]['rules']['enum'] as $o_id )
365 + {
366 + $options[ $o_id ] = $this->prop_text($fn, FALSE, $o_id);
367 + }
368 + }
369 + /* has one ? */
370 + elseif( isset($this->has_one[$fn]) )
371 + {
372 + $rel_props = $this->has_one[$fn];
373 + $other_model = new $rel_props['class'];
374 +
375 + $options = array();
376 + $select_label = '';
377 + if(
378 + isset($this->validation[$fn]) &&
379 + isset($this->validation[$fn]['rules']) &&
380 + in_array('required', $this->validation[$fn]['rules'])
381 + )
382 + {
383 + if( ! $this->id )
384 + {
385 + $select_label = lang('common_select');
386 + }
387 + }
388 + else
389 + {
390 + $select_label = lang('common_select_later');
391 + }
392 +
393 + if( $select_label )
394 + {
395 + $options[0] = ' - ' . $select_label . ' - ';
396 + }
397 +
398 + $other_titles = $other_model->titles();
399 + if( count($other_titles) > 1 )
400 + {
401 + reset( $other_titles );
402 + foreach( $other_titles as $other_id => $other_title )
403 + {
404 + $options[ $other_id ] = $other_title;
405 + }
406 + }
407 + else
408 + {
409 + $other_ids = array_keys( $other_titles );
410 + $return[$fn]['type'] = 'hidden';
411 + $return[$fn]['default'] = $other_ids[0];
412 + $options = NULL;
413 + }
414 + }
415 + if( $options === NULL )
416 + unset( $return[$fn]['options'] );
417 + else
418 + $return[$fn]['options'] = $options;
419 + }
420 + return $return;
421 + }
422 +
423 + function get_field( $pname )
424 + {
425 + $return = array();
426 + $fields = $this->get_fields();
427 + reset( $fields );
428 + foreach( $fields as $f )
429 + {
430 + if( $pname == $f['name'] )
431 + {
432 + $return = $f;
433 + break;
434 + }
435 + }
436 + return $return;
437 + }
438 +
439 + function prop_name( $pname )
440 + {
441 + if( substr($pname, -3) == '_id' )
442 + {
443 + $short_pname = substr($pname, 0, -3);
444 + if(
445 + isset($this->has_one[$short_pname]) OR
446 + isset($this->has_many[$short_pname])
447 + )
448 + {
449 + $pname = $short_pname;
450 + }
451 + }
452 + return $pname;
453 + }
454 +
455 + function prop_label( $pname )
456 + {
457 + $return = '';
458 + $pname = $this->prop_name( $pname );
459 +
460 + $field = $this->get_field( $pname );
461 + if( ! $field )
462 + return;
463 +
464 + if( isset($field['label']) )
465 + {
466 + $return = $field['label'];
467 + $return = Hc_lib::parse_lang( $return );
468 + }
469 + else
470 + {
471 + $return = $field['name'];
472 + }
473 + return $return;
474 + }
475 +
476 + function view_text( $skip = array() )
477 + {
478 + $return = array();
479 + $fields = $this->get_fields();
480 + reset( $fields );
481 + foreach( $fields as $f )
482 + {
483 + if( in_array($f['name'], $skip) )
484 + continue;
485 + $label = isset($f['label']) ? $f['label'] : $f['name'];
486 + $label = Hc_lib::parse_lang( $label );
487 + $return[ $f['name'] ] = array( $label, $this->prop_text($f['name']) );
488 + }
489 + return $return;
490 + }
491 +
492 + function prop_text_class( $pname, $force_value = NULL )
493 + {
494 + $return = '';
495 + if( isset($args[1]) )
496 + {
497 + $value = $args[1];
498 + }
499 + else
500 + {
501 + $method = 'get_' . $pname;
502 + if( method_exists($this, $method) )
503 + $value = $this->{$method}();
504 + else
505 + $value = $this->{$pname};
506 + }
507 +
508 + /* prop_text explicitely defined */
509 + if( (! is_object($value)) && isset($this->prop_text[$pname][$value]) && is_array($this->prop_text[$pname][$value]) )
510 + {
511 + $return = $this->prop_text[$pname][$value][1];
512 + }
513 + return $return;
514 + }
515 +
516 + function decorate_prop( $pname, $value = NULL, $text = NULL, $add_title = '' )
517 + {
518 + if( $value === NULL )
519 + $value = $this->{$pname};
520 + if( $text === NULL )
521 + $text = $value;
522 + $return = $text;
523 + if( isset($this->prop_text[$pname][$value][1]) )
524 + {
525 + $class = $this->prop_text[$pname][$value][1];
526 + $title = Hc_lib::parse_lang( $this->prop_text[$pname][$value][0] );
527 + if( $add_title )
528 + $title = $add_title . ': ' . $title;
529 + $return = '<span title="' . $title . '" class="label label-' . $class . '">' . $return . '</span>';
530 + }
531 + return $return;
532 + }
533 +
534 + function prop_text( $pname, $decorate = FALSE, $force_value = NULL )
535 + {
536 + $return = '';
537 + $CI =& ci_get_instance();
538 +
539 + $args = func_get_args();
540 + if( isset($args[2]) )
541 + {
542 + $value = $args[2];
543 + }
544 + else
545 + {
546 + $method = 'get_' . $pname;
547 + if( method_exists($this, $method) )
548 + $value = $this->{$method}();
549 + else
550 + $value = $this->{$pname};
551 + }
552 +
553 + /* prop_text explicitely defined */
554 + if( (! is_object($value)) && isset($this->prop_text[$pname][$value]) )
555 + {
556 + $return = is_array($this->prop_text[$pname][$value]) ? $this->prop_text[$pname][$value][0] : $this->prop_text[$pname][$value];
557 + $return = Hc_lib::parse_lang( $return );
558 + if( $decorate && is_array($this->prop_text[$pname][$value]) )
559 + {
560 + $class = $this->prop_text[$pname][$value][1];
561 + $return = '<span class="label label-' . $class . '">' . $return . '</span>';
562 + }
563 + return $return;
564 + }
565 +
566 + $f = $this->get_field( $pname );
567 + if( ! $f )
568 + return $value;
569 +
570 + $type = isset($f['type']) ? $f['type'] : 'text';
571 + switch( $type )
572 + {
573 + case 'date':
574 + $CI->load->library( 'hc_time' );
575 + $CI->hc_time->setDateDb( $value );
576 + $return = $CI->hc_time->formatDateFull();
577 + break;
578 + case 'time':
579 + $CI->load->library( 'hc_time' );
580 + $return = $CI->hc_time->formatTimeOfDay( $value );
581 + break;
582 + case 'boolean':
583 + $return = $value ? lang('common_yes') : lang('common_no');
584 + break;
585 + default:
586 + if( is_object($value) )
587 + {
588 + $return = $value->get()->title();
589 + }
590 + else
591 + {
592 + $return = $value;
593 + }
594 + break;
595 + }
596 + return $return;
597 + }
598 +
599 + function trigger_event( $event, $payload )
600 + {
601 + /* check if we also have a method here */
602 + $method = '_' . $event;
603 + if( method_exists($this, $method))
604 + {
605 + $this->{$method}();
606 + }
607 +
608 + $CI =& ci_get_instance();
609 + if( isset($CI->hc_events) )
610 + {
611 + $event = $this->my_class() . '.' . $event;
612 + $args = func_get_args();
613 + $args[0] = $event;
614 + call_user_func_array( array($CI->hc_events, 'trigger'), $args );
615 + }
616 + }
617 +
618 +/* with triggered events */
619 + public function save($object = '', $related_field = '')
620 + {
621 + $this->trigger_event( 'before_save', $this );
622 +
623 + /* keep copy of the stored because it resets to new after save */
624 + $this->_keep_old();
625 +
626 + $return = parent::save($object, $related_field);
627 + if( $return )
628 + {
629 + $this->trigger_event( 'after_save', $this );
630 + }
631 + return $return;
632 + }
633 +
634 + public function delete($object = '', $related_field = '')
635 + {
636 + $this->trigger_event( 'before_delete', $this );
637 + $return = parent::delete($object, $related_field);
638 + if( $return )
639 + {
640 + $this->trigger_event( 'after_delete', $this );
641 + }
642 + return $return;
643 + }
644 +
645 + private function _keep_old()
646 + {
647 + $this->_old = (array) $this->stored;
648 + /* also include has_one */
649 + reset( $this->has_one );
650 + foreach( array_keys($this->has_one) as $k )
651 + {
652 + if( is_object($this->{$k}) )
653 + $this->_old[$k] = $this->{$k}->id;
654 + else
655 + $this->_old[$k] = $this->{$k};
656 + }
657 + }
658 +
659 +/* gives the array of changed properties with their old values, useful after save */
660 + public function get_changes( $relations = NULL )
661 + {
662 + $return = array();
663 + $new = $this->to_array();
664 + if( $relations )
665 + {
666 + reset( $relations );
667 + foreach( $relations as $k => $o )
668 + {
669 + $new[ $k ] = $o->id;
670 + }
671 + }
672 +
673 + foreach( $new as $k => $v )
674 + {
675 + if( array_key_exists($k, $this->_old) )
676 + {
677 + if( $this->_old[$k] !== $v )
678 + $return[$k] = $this->_old[$k];
679 + }
680 + else
681 + {
682 + $return[$k] = NULL;
683 + }
684 + }
685 + return $return;
686 + }
687 +
688 + function get_field_names()
689 + {
690 + $return = array();
691 + $fields = $this->get_fields();
692 + reset( $fields );
693 + foreach( $fields as $f )
694 + {
695 + $return[] = $f['name'];
696 + }
697 + return $return;
698 + }
699 +
700 + function is_changed( $check = array(), $post = array() )
701 + {
702 + $copy = $this->get_clone();
703 +
704 + $return = array();
705 + if( ! $check )
706 + {
707 + $check = array();
708 + $all_fields = $copy->get_fields();
709 + foreach( $all_fields as $f )
710 + {
711 + $check[] = $f['name'];
712 + }
713 + }
714 +
715 + reset( $check );
716 + foreach( $check as $c )
717 + {
718 + if( ! isset($post[$c]) )
719 + continue;
720 + $old[$c] = $copy->{$c};
721 + $copy->{$c} = $post[$c];
722 + }
723 +
724 + $copy->validate();
725 +
726 + reset( $check );
727 + foreach( $check as $c )
728 + {
729 + if( ! isset($post[$c]) )
730 + continue;
731 + if( $copy->{$c} != $old[$c] )
732 + {
733 + $return[$c] = array( $copy->{$c}, $old[$c] );
734 + }
735 + }
736 + return $return;
737 + }
738 +
739 +/* validation */
740 + public function _save_array( $field )
741 + {
742 + if ( ! empty($this->{$field}) )
743 + {
744 + $this->{$field} = join( '||', $this->{$field} );
745 + }
746 + else
747 + {
748 + $this->{$field} = '';
749 + }
750 + return TRUE;
751 + }
752 +
753 + public function _load_array( $field )
754 + {
755 + if ( ! empty($this->{$field}) )
756 + {
757 + $this->{$field} = explode( '||', $this->{$field} );
758 + }
759 + else
760 + {
761 + $this->{$field} = array();
762 + }
763 + }
764 +
765 + public function _enum( $field, $compare )
766 + {
767 + if (
768 + ( isset($this->{$field}) )
769 + )
770 + {
771 + return in_array( $this->{$field}, $compare );
772 + }
773 + return FALSE;
774 + }
775 +
776 + public function _greater_equal_than_field($me, $other)
777 + {
778 + if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
779 + return FALSE;
780 + return $this->{$me} >= $this->{$other};
781 + }
782 +
783 + public function _less_equal_than_field($me, $other)
784 + {
785 + if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
786 + return FALSE;
787 + return $this->{$me} <= $this->{$other};
788 + }
789 +
790 + public function _greater_than_field($me, $other)
791 + {
792 + if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
793 + return FALSE;
794 + return $this->{$me} > $this->{$other};
795 + }
796 +
797 + public function _less_than_field($me, $other)
798 + {
799 + if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
800 + return FALSE;
801 + return $this->{$me} < $this->{$other};
802 + }
803 +
804 + protected function _after_save()
805 + {
806 +/*
807 + $CI =& ci_get_instance();
808 + if( $this->keep_log && $CI->hc_modules->exists('logaudit') )
809 + {
810 + $log_changes = array();
811 + $changes = $this->get_changes();
812 + reset( $changes );
813 + foreach( $changes as $property_name => $old_value )
814 + {
815 + if( in_array($property_name, $this->keep_log) )
816 + {
817 + $log_changes[ $property_name ] = $old_value;
818 + }
819 + }
820 +
821 + if( $log_changes )
822 + {
823 + $log = new Logaudit_model;
824 + $log->log( $this, $log_changes );
825 + }
826 + }
827 +*/
828 + }
829 +}
830 +
831 +class MY_Model_Virtual
832 +{
833 + function my_class()
834 + {
835 + $return = get_class($this);
836 + $return = strtolower($return);
837 + $suffix = '_model';
838 + if( substr($return, -strlen($suffix)) == $suffix )
839 + {
840 + $return = substr( $return, 0, -strlen($suffix) );
841 + }
842 + return $return;
843 + }
844 +
845 + function trigger_event( $event, $payload )
846 + {
847 + $CI =& ci_get_instance();
848 + if( isset($CI->hc_events) )
849 + {
850 + $event = $this->my_class() . '.' . $event;
851 + $args = func_get_args();
852 + $args[0] = $event;
853 + call_user_func_array( array($CI->hc_events, 'trigger'), $args );
854 + }
855 + }
856 +
857 + public function save($object = '', $related_field = '')
858 + {
859 + $this->trigger_event( 'before_save', $this );
860 +
861 + /* keep copy of the stored because it resets to new after save */
862 + $this->_keep_old();
863 +
864 + $return = parent::save($object, $related_field);
865 + if( $return )
866 + {
867 + $this->trigger_event( 'after_save', $this );
868 + }
869 + return $return;
870 + }
871 +}