PluginProbe
ShiftController Employee Shift Scheduling / 2.1.0
ShiftController Employee Shift Scheduling v2.1.0
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
shiftcontroller / happ / application / core / MY_Model.php

MY_Model.php in ShiftController Employee Shift Scheduling 2.1.0, at happ/application/core/MY_Model.php

800 lines 17.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 $modules = $this->config->item('modules');
26 reset( $modules );
27 foreach( $modules as $m )
28 {
29 $this->config->load('relations', TRUE, TRUE, $m );
30 }
31 }
32
33 if( ! isset(self::$relations[$my_class]) )
34 {
35 self::$relations[$my_class] = array(
36 'has_many' => array(),
37 'has_one' => array(),
38 );
39
40 $schema = $this->config->item( $my_class, 'relations' );
41 if( $schema )
42 {
43 if( isset($schema['has_many']) )
44 {
45 self::$relations[$my_class]['has_many'] = $schema['has_many'];
46 }
47
48 if( isset($schema['has_one']) )
49 {
50 self::$relations[$my_class]['has_one'] = $schema['has_one'];
51 }
52 }
53 }
54
55 reset( self::$relations[$my_class]['has_many'] );
56 foreach( self::$relations[$my_class]['has_many'] as $c => $rel )
57 {
58 $this->has_many( $c, $rel );
59 }
60
61 reset( self::$relations[$my_class]['has_one'] );
62 foreach( self::$relations[$my_class]['has_one'] as $c => $rel )
63 {
64 $this->has_one( $c, $rel );
65 }
66 }
67
68 function title(){
69 $return = array();
70 reset( $this->build_title );
71 foreach( $this->build_title as $bt )
72 {
73 if(
74 (substr($bt, 0, 1) == '_') &&
75 (substr($bt, -1) == '_')
76 )
77 {
78 $prop = substr($bt, 1, -1);
79 if( substr($prop, -2) == '()' ) // my method
80 {
81 $func = substr($prop, 0, -2);
82 $return[] = $this->{$func}();
83 }
84 else // my prop
85 {
86 $return[] = $this->{$prop};
87 }
88 }
89 else // just string like space or brackets
90 {
91 $return[] = $bt;
92 }
93 }
94 $return = join( '', $return );
95 return $return;
96 }
97
98 private function _build_title_select()
99 {
100 $return = array();
101 reset( $this->build_title );
102 foreach( $this->build_title as $bt )
103 {
104 if(
105 (substr($bt, 0, 1) == '_') &&
106 (substr($bt, -1) == '_')
107 )
108 {
109 $prop = substr($bt, 1, -1);
110 if( substr($prop, -2) == '()' )
111 {
112 }
113 else
114 {
115 $return[] = $prop;
116 }
117 }
118 else
119 {
120 $return[] = "\"" . $bt . "\"";
121 }
122 }
123 $return = join( ',', $return );
124 return $return;
125 }
126
127 function titles()
128 {
129 $class = get_class($this);
130 if( ! isset(self::$titles[$class]) )
131 {
132 $return = array();
133 $this->clear();
134 $select = $this->_build_title_select();
135 $this->select( 'id' );
136 $this->select( 'CONCAT(' . $select . ') AS title', FALSE );
137 $this->get();
138
139 foreach( $this as $u )
140 {
141 $return[ $u->id ] = $u->title;
142 }
143 self::$titles[$class] = $return;
144 }
145 return self::$titles[$class];
146 }
147
148 function csv_upload( $file_name = 'userfile', $separator = ',' )
149 {
150 $return = NULL;
151 $fields = $this->get_fields();
152 reset( $fields );
153 foreach( $fields as $f )
154 {
155 $my_fields[] = $f['name'];
156 }
157
158 if( isset($_FILES[$file_name]) && is_uploaded_file($_FILES[$file_name]['tmp_name']) )
159 {
160 $tmp_name = $_FILES[$file_name]['tmp_name'];
161 $return = array();
162
163 $parse_error = FALSE;
164 if( ($handle = fopen($tmp_name, "r")) !== FALSE)
165 {
166 $line_no = 0;
167 while( ($line = fgetcsv($handle, 1000, $separator)) !== FALSE )
168 {
169 // titles
170 if( ! $line_no )
171 {
172 $prop_names = $line;
173 for( $ii = 0; $ii < count($prop_names); $ii++ )
174 {
175 reset( $fields );
176 foreach( $fields as $f )
177 {
178 if( strtolower($prop_names[$ii]) == $f['name'] )
179 {
180 $prop_names[$ii] = strtolower($prop_names[$ii]);
181 }
182 }
183 }
184 $prop_count = count( $prop_names );
185
186 // check for mandatory fields
187 $missing_fields = array();
188 reset( $fields );
189 foreach( $fields as $f )
190 {
191 if( isset($f['required']) && $f['required'] ){
192 if( ! in_array($f['name'], $prop_names) ){
193 $missing_fields[] = $f['name'];
194 }
195 }
196 }
197 if( $missing_fields )
198 {
199 $err_msg = lang('conf_import_error_fields_missing') . ': ' . join(', ', $missing_fields);
200 $this->error_message( 'import', $err_msg );
201 $parse_error = TRUE;
202 break;
203 }
204
205 // check if any fields are not parsed
206 $not_parsed_fields = array();
207 reset( $prop_names );
208 foreach( $prop_names as $f )
209 {
210 $f = trim( $f );
211 if( ! $f )
212 continue;
213
214 if( ! (in_array($f, $my_fields) OR in_array(strtolower($f), $my_fields)) )
215 {
216 $not_parsed_fields[] = $f;
217 }
218 }
219 if( $not_parsed_fields )
220 {
221 $err_msg = lang('conf_import_message_fields_not_recognized') . ': ' . join(', ', $not_parsed_fields);
222 $this->error_message( 'import', $err_msg );
223 }
224 }
225 else
226 {
227 $values = array();
228 for( $i = 0; $i < $prop_count; $i++ )
229 {
230 $check_name = strtolower($prop_names[$i]);
231 if( in_array($check_name, $my_fields) )
232 {
233 if( isset($line[$i]) )
234 $values[ $check_name ] = $line[$i];
235 else
236 $values[ $check_name ] = '';
237 }
238 }
239 $return[] = $values;
240 }
241 $line_no++;
242 }
243 fclose($handle);
244 }
245
246 if( $parse_error )
247 {
248 $return = NULL;
249 }
250 }
251 return $return;
252 }
253
254 function csv( $separator = ',', $skip = array() )
255 {
256 $related_fields = array_merge( $this->has_one, $this->has_many );
257
258 // header
259 $headers = array();
260 $fields = $this->get_fields();
261 reset( $fields );
262 foreach( $fields as $f )
263 {
264 if( in_array($f['name'], $skip) )
265 continue;
266 // $headers[ $f['name'] ] = hc_parse_lang( $f['label'] );
267 $headers[ $f['name'] ] = $f['name'];
268 }
269
270 $data = array();
271 $data[] = join( $separator, $headers );
272
273 // entries
274 $keys = array_keys( $headers );
275 $this->clear();
276 $this->get();
277 foreach( $this as $s )
278 {
279 $e = array();
280 reset( $keys );
281 foreach( $keys as $k )
282 {
283 if( isset($related_fields[$k]) )
284 {
285 $e[] = $s->{$k}->get()->title();
286 }
287 else
288 {
289 $e[] = $s->{$k};
290 }
291 }
292 $data[] = hc_build_csv( $e, $separator );
293 }
294 $return = join( "\n", $data );
295 return $return;
296 }
297
298 function my_class()
299 {
300 $return = get_class($this);
301 $return = strtolower($return);
302 $suffix = '_model';
303 if( substr($return, -strlen($suffix)) == $suffix )
304 {
305 $return = substr( $return, 0, -strlen($suffix) );
306 }
307 return $return;
308 }
309
310 public function get_fields()
311 {
312 return $this->my_fields;
313 }
314
315 public function get_form_fields()
316 {
317 $return = array();
318
319 $fields = $this->get_fields();
320 foreach( $fields as $tf )
321 {
322 $return[$tf['name']] = $tf;
323 }
324
325 $fnames = array_keys($return);
326 /* assign options to dropdowns */
327 foreach( $fnames as $fn )
328 {
329 if(
330 ( isset($return[$fn]['type']) && ($return[$fn]['type'] != 'dropdown') ) OR
331 ( isset($return[$fn]['options']) )
332 )
333 {
334 continue;
335 }
336
337 $options = array();
338 /* enum fields */
339 if(
340 isset($this->validation[$fn]) && isset($this->validation[$fn]['rules']) &&
341 array_key_exists('enum', $this->validation[$fn]['rules']) &&
342 is_array($this->validation[$fn]['rules']['enum'])
343 )
344 {
345 $options = array();
346 foreach( $this->validation[$fn]['rules']['enum'] as $o_id )
347 {
348 $options[ $o_id ] = $this->prop_text($fn, FALSE, $o_id);
349 }
350 }
351 /* has one ? */
352 elseif( isset($this->has_one[$fn]) )
353 {
354 $rel_props = $this->has_one[$fn];
355 $other_model = new $rel_props['class'];
356
357 $options = array();
358 $select_label = '';
359 if(
360 isset($this->validation[$fn]) &&
361 isset($this->validation[$fn]['rules']) &&
362 in_array('required', $this->validation[$fn]['rules'])
363 )
364 {
365 if( ! $this->id )
366 {
367 $select_label = lang('common_select');
368 }
369 }
370 else
371 {
372 $select_label = lang('common_select_later');
373 }
374
375 if( $select_label )
376 {
377 $options[0] = ' - ' . $select_label . ' - ';
378 }
379
380 $other_titles = $other_model->titles();
381 if( count($other_titles) > 1 )
382 {
383 reset( $other_titles );
384 foreach( $other_titles as $other_id => $other_title )
385 {
386 $options[ $other_id ] = $other_title;
387 }
388 }
389 else
390 {
391 $other_ids = array_keys( $other_titles );
392 $return[$fn]['type'] = 'hidden';
393 $return[$fn]['default'] = $other_ids[0];
394 }
395 }
396 $return[$fn]['options'] = $options;
397 }
398 return $return;
399 }
400
401 function get_field( $pname )
402 {
403 $return = array();
404 $fields = $this->get_fields();
405 reset( $fields );
406 foreach( $fields as $f )
407 {
408 if( $pname == $f['name'] )
409 {
410 $return = $f;
411 break;
412 }
413 }
414 return $return;
415 }
416
417 function view_text()
418 {
419 $return = array();
420 $fields = $this->get_fields();
421 reset( $fields );
422 foreach( $fields as $f )
423 {
424 $label = isset($f['label']) ? $f['label'] : $f['name'];
425 $label = hc_parse_lang( $label );
426 $return[ $f['name'] ] = array( $label, $this->prop_text($f['name']) );
427 }
428 return $return;
429 }
430
431 function prop_text_class( $pname, $force_value = NULL )
432 {
433 $return = '';
434 if( isset($args[1]) )
435 {
436 $value = $args[1];
437 }
438 else
439 {
440 $method = 'get_' . $pname;
441 if( method_exists($this, $method) )
442 $value = $this->{$method}();
443 else
444 $value = $this->{$pname};
445 }
446
447 /* prop_text explicitely defined */
448 if( (! is_object($value)) && isset($this->prop_text[$pname][$value]) && is_array($this->prop_text[$pname][$value]) )
449 {
450 $return = $this->prop_text[$pname][$value][1];
451 }
452 return $return;
453 }
454
455 function decorate_prop( $pname, $value = NULL, $text = NULL, $add_title = '' )
456 {
457 if( $value === NULL )
458 $value = $this->{$pname};
459 if( $text === NULL )
460 $text = $value;
461 $return = $text;
462 if( isset($this->prop_text[$pname][$value][1]) )
463 {
464 $class = $this->prop_text[$pname][$value][1];
465 $title = hc_parse_lang( $this->prop_text[$pname][$value][0] );
466 if( $add_title )
467 $title = $add_title . ': ' . $title;
468 $return = '<span title="' . $title . '" class="label label-' . $class . '">' . $return . '</span>';
469 }
470 return $return;
471 }
472
473 function prop_text( $pname, $decorate = FALSE, $force_value = NULL )
474 {
475 $return = '';
476 $CI =& ci_get_instance();
477
478 $args = func_get_args();
479 if( isset($args[2]) )
480 {
481 $value = $args[2];
482 }
483 else
484 {
485 $method = 'get_' . $pname;
486 if( method_exists($this, $method) )
487 $value = $this->{$method}();
488 else
489 $value = $this->{$pname};
490 }
491
492 /* prop_text explicitely defined */
493 if( (! is_object($value)) && isset($this->prop_text[$pname][$value]) )
494 {
495 $return = is_array($this->prop_text[$pname][$value]) ? $this->prop_text[$pname][$value][0] : $this->prop_text[$pname][$value];
496 $return = hc_parse_lang( $return );
497 if( $decorate && is_array($this->prop_text[$pname][$value]) )
498 {
499 $class = $this->prop_text[$pname][$value][1];
500 $return = '<span class="label label-' . $class . '">' . $return . '</span>';
501 }
502 return $return;
503 }
504
505 $f = $this->get_field( $pname );
506 if( ! $f )
507 return $value;
508
509 $type = isset($f['type']) ? $f['type'] : 'text';
510 switch( $type )
511 {
512 case 'date':
513 $CI->hc_time->setDateDb( $value );
514 $return = $CI->hc_time->formatDateFull();
515 break;
516 case 'time':
517 $return = $CI->hc_time->formatTimeOfDay( $value );
518 break;
519 default:
520 if( is_object($value) )
521 {
522 $return = $value->get()->title();
523 }
524 else
525 {
526 $return = $value;
527 }
528 break;
529 }
530 return $return;
531 }
532
533 function trigger_event( $event, $payload )
534 {
535 /* check if we also have a method here */
536 $method = '_' . $event;
537 if( method_exists($this, $method))
538 {
539 $this->{$method}();
540 }
541
542 $CI =& ci_get_instance();
543 if( isset($CI->hc_events) )
544 {
545 $event = $this->my_class() . '.' . $event;
546 $args = func_get_args();
547 $args[0] = $event;
548 call_user_func_array( array($CI->hc_events, 'trigger'), $args );
549 }
550 }
551
552 /* with triggered events */
553 public function save($object = '', $related_field = '')
554 {
555 $this->trigger_event( 'before_save', $this );
556
557 /* keep copy of the stored because it resets to new after save */
558 $this->_keep_old();
559
560 $return = parent::save($object, $related_field);
561 if( $return )
562 {
563 $this->trigger_event( 'after_save', $this, $object );
564 }
565 return $return;
566 }
567
568 public function delete($object = '', $related_field = '')
569 {
570 $this->trigger_event( 'before_delete', $this );
571 $return = parent::delete($object, $related_field);
572 if( $return )
573 {
574 $this->trigger_event( 'after_delete', $this );
575 }
576 return $return;
577 }
578
579 private function _keep_old()
580 {
581 $this->_old = (array) $this->stored;
582 /* also include has_one */
583 reset( $this->has_one );
584 foreach( array_keys($this->has_one) as $k )
585 {
586 if( is_object($this->{$k}) )
587 $this->_old[$k] = $this->{$k}->id;
588 else
589 $this->_old[$k] = $this->{$k};
590 }
591 }
592
593 /* gives the array of changed properties with their old values, useful after save */
594 public function get_changes( $relations = NULL )
595 {
596 $return = array();
597 $new = $this->to_array();
598 if( $relations )
599 {
600 reset( $relations );
601 foreach( $relations as $k => $o )
602 {
603 $new[ $k ] = $o->id;
604 }
605 }
606
607 foreach( $new as $k => $v )
608 {
609 if( isset($this->_old[$k]) )
610 {
611 if( $this->_old[$k] != $v )
612 $return[$k] = $this->_old[$k];
613 }
614 else
615 {
616 $return[$k] = NULL;
617 }
618 }
619 return $return;
620 }
621
622 function get_field_names()
623 {
624 $return = array();
625 $fields = $this->get_fields();
626 reset( $fields );
627 foreach( $fields as $f )
628 {
629 $return[] = $f['name'];
630 }
631 return $return;
632 }
633
634 function is_changed( $check = array(), $post = array() )
635 {
636 $copy = $this->get_clone();
637
638 $return = array();
639 if( ! $check )
640 {
641 $check = array();
642 $all_fields = $copy->get_fields();
643 foreach( $all_fields as $f )
644 {
645 $check[] = $f['name'];
646 }
647 }
648
649 reset( $check );
650 foreach( $check as $c )
651 {
652 if( ! isset($post[$c]) )
653 continue;
654 $old[$c] = $copy->{$c};
655 $copy->{$c} = $post[$c];
656 }
657
658 $copy->validate();
659
660 reset( $check );
661 foreach( $check as $c )
662 {
663 if( ! isset($post[$c]) )
664 continue;
665 if( $copy->{$c} != $old[$c] )
666 {
667 $return[$c] = array( $copy->{$c}, $old[$c] );
668 }
669 }
670 return $return;
671 }
672
673 /* validation */
674 public function _save_array( $field )
675 {
676 if ( ! empty($this->{$field}) )
677 {
678 $this->{$field} = join( '||', $this->{$field} );
679 }
680 else
681 {
682 $this->{$field} = '';
683 }
684 return TRUE;
685 }
686
687 public function _load_array( $field )
688 {
689 if ( ! empty($this->{$field}) )
690 {
691 $this->{$field} = explode( '||', $this->{$field} );
692 }
693 else
694 {
695 $this->{$field} = array();
696 }
697 }
698
699 public function _enum( $field, $compare )
700 {
701 if (
702 ( isset($this->{$field}) )
703 )
704 {
705 return in_array( $this->{$field}, $compare );
706 }
707 return FALSE;
708 }
709
710 public function _greater_equal_than_field($me, $other)
711 {
712 if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
713 return FALSE;
714 return $this->{$me} >= $this->{$other};
715 }
716
717 public function _less_equal_than_field($me, $other)
718 {
719 if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
720 return FALSE;
721 return $this->{$me} <= $this->{$other};
722 }
723
724 public function _greater_than_field($me, $other)
725 {
726 if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
727 return FALSE;
728 return $this->{$me} > $this->{$other};
729 }
730
731 public function _less_than_field($me, $other)
732 {
733 if ( (! is_numeric($this->{$me})) OR (! is_numeric($this->{$other})) )
734 return FALSE;
735 return $this->{$me} < $this->{$other};
736 }
737
738 protected function _add_log( $log )
739 {
740 $defaults = array(
741 'action_name' => 'create',
742 'user_id' => 0,
743 'object_class' => $this->my_class(),
744 'object_id' => $this->id,
745 'action_time' => time(),
746 'action_details' => ''
747 );
748 reset( $defaults );
749 foreach( $defaults as $k => $v )
750 {
751 if( ! isset($log[$k]) )
752 {
753 $log[$k] = $v;
754 }
755 }
756 }
757 }
758
759 class MY_Model_Virtual
760 {
761 function my_class()
762 {
763 $return = get_class($this);
764 $return = strtolower($return);
765 $suffix = '_model';
766 if( substr($return, -strlen($suffix)) == $suffix )
767 {
768 $return = substr( $return, 0, -strlen($suffix) );
769 }
770 return $return;
771 }
772
773 function trigger_event( $event, $payload )
774 {
775 $CI =& ci_get_instance();
776 if( isset($CI->hc_events) )
777 {
778 $event = $this->my_class() . '.' . $event;
779 $args = func_get_args();
780 $args[0] = $event;
781 call_user_func_array( array($CI->hc_events, 'trigger'), $args );
782 }
783 }
784
785 public function save($object = '', $related_field = '')
786 {
787 $this->trigger_event( 'before_save', $this );
788
789 /* keep copy of the stored because it resets to new after save */
790 $this->_keep_old();
791
792 $return = parent::save($object, $related_field);
793 if( $return )
794 {
795 $this->trigger_event( 'after_save', $this, $object );
796 }
797 return $return;
798 }
799 }
800