PluginProbe
ShiftController Employee Shift Scheduling / 4.9.95
ShiftController Employee Shift Scheduling v4.9.95
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 / sh4 / schedule / html / view / month.php

month.php in ShiftController Employee Shift Scheduling 4.9.95, at sh4/schedule/html/view/month.php

1,013 lines 27.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if (! defined('ABSPATH')) exit; // Exit if accessed directly
2 #[AllowDynamicProperties]
3 class SH4_Schedule_Html_View_Month
4 {
5 protected $borderColor = 'gray';
6 protected $allCombos = array();
7 protected $allCombosShift = array();
8 protected $allCombosTimeoff = array();
9 protected $slimView = true;
10
11 public function __construct(
12 HC3_Hooks $hooks,
13 HC3_Ui $ui,
14 HC3_Request $request,
15 HC3_Time $t,
16 HC3_Settings $settings,
17
18 HC3_Uri $uri,
19
20 SH4_New_Acl $newAcl,
21
22 SH4_Shifts_Duration $shiftsDuration,
23 SH4_Schedule_Html_View_Week $viewWeek,
24 SH4_Shifts_View_Widget $widget,
25 SH4_Calendars_Query $calendarsQuery,
26 SH4_Calendars_Presenter $calendarsPresenter,
27 SH4_Employees_Presenter $employeesPresenter,
28 SH4_Schedule_Html_View_Common $common,
29 SH4_Shifts_View_Common $shiftsCommon
30 )
31 {
32 $this->self = $hooks->wrap($this);
33
34 $this->ui = $ui;
35
36 $this->uri = $uri;
37 $this->t = $t;
38 $this->request = $request;
39
40 $this->settings = $hooks->wrap( $settings );
41 $this->newAcl = $hooks->wrap( $newAcl );
42
43 $this->viewWeek = $hooks->wrap( $viewWeek );
44 $this->shiftsDuration = $hooks->wrap( $shiftsDuration );
45 $this->calendarsQuery = $hooks->wrap( $calendarsQuery );
46 $this->calendarsPresenter = $hooks->wrap( $calendarsPresenter );
47 $this->employeesPresenter = $hooks->wrap( $employeesPresenter );
48
49 $this->widget = $hooks->wrap( $widget );
50 $this->common = $hooks->wrap( $common );
51 $this->shiftsCommon = $hooks->wrap( $shiftsCommon );
52
53 $this->allCombos = $this->newAcl->findAllCombos();
54 $this->allCombosShift = $this->newAcl->findAllCombosShift();
55 $this->allCombosTimeoff = $this->newAcl->findAllCombosTimeoff();
56
57 $this->slimView = $this->settings->get( 'datetime_month_slim_view' ) ? true : false;
58 }
59
60 public function render()
61 {
62 $slug = $this->request->getSlug();
63 $today = $this->t->setNow()->formatDateDb();
64
65 $disabledWeekdays = $this->settings->get( 'skip_weekdays', TRUE );
66
67 $shifts = $this->common->getShifts();
68
69 $params = $this->request->getParams();
70 $startDate = $params['start'];
71
72 $startDate = $this->t->setDateDb( $startDate )->setStartMonth()->formatDateDb();
73 $endDate = $this->t->modify('+1 month')->modify('-1 day')->formatDateDb();
74
75 $this->t->setDateDb( $startDate );
76 $dates = array();
77 $rexDate = $startDate;
78 while( $rexDate <= $endDate ){
79 if( $disabledWeekdays ){
80 $wkd = $this->t->getWeekday();
81 if( in_array($wkd, $disabledWeekdays) ){
82 $rexDate = $this->t->modify('+1 day')->formatDateDb();
83 continue;
84 }
85 }
86
87 $dates[] = $rexDate;
88 $rexDate = $this->t->modify('+1 day')->formatDateDb();
89 }
90
91 $viewShifts = array();
92 $iknow = array('date');
93
94 $allCalendars = $this->common->findAllCalendars();
95 if( count($allCalendars) <= 1 ) $iknow[] = 'calendar';
96
97 $this->shiftsDuration->reset();
98 foreach( $shifts as $shift ){
99 $this->shiftsDuration->add( $shift );
100 $start = $shift->getStart();
101 $end = $shift->getEnd();
102
103 $startDayTime = substr($start, 8, 4);
104 $endDayTime = substr($end, 8, 4);
105 $shiftAllDay = ( (0 == $startDayTime) && (0 == $endDayTime) ) ? TRUE : FALSE;
106
107 $this->t->setDateTimeDb( $end )->modify('-1 second');
108 $shiftEndDate = $this->t->formatDateDb();
109
110 $this->t->setDateTimeDb( $start );
111 $shiftStartDate = $this->t->formatDateDb();
112
113 $rexDate = $shiftStartDate;
114 while( $rexDate <= $shiftEndDate ){
115 if( in_array($rexDate, $dates) ){
116 if( ! array_key_exists($rexDate, $viewShifts) ){
117 $viewShifts[$rexDate] = array();
118 }
119 $viewShifts[$rexDate][] = $shift;
120 }
121
122 if( ! $shiftAllDay ){
123 break;
124 }
125 $this->t->modify( '+1 day' );
126 $rexDate = $this->t->formatDateDb();
127 }
128 }
129
130 $daysInWeek = $this->settings->get('datetime_days_in_week');
131 if (!$daysInWeek) $daysInWeek = 7;
132 $this->t->setDateDb( $startDate );
133 $monthMatrix = $this->t->getMonthMatrix($disabledWeekdays, $daysInWeek);
134
135 $rows = array();
136 foreach( $monthMatrix as $week => $days ){
137 $row = array();
138
139 foreach( $days as $date ){
140 if( ! $date ){
141 $row[] = NULL;
142 continue;
143 }
144
145 $cell = array();
146
147 $dateView = $this->common->renderDateLabel( $date );
148 $cell[] = $dateView;
149
150 if( isset($viewShifts[$date]) ){
151 $shiftsView = $this->viewWeek->renderDay( $viewShifts[$date], $iknow );
152 $cell[] = $shiftsView;
153 }
154
155 $to = 'new';
156 $toParams = array(
157 'date' => $date
158 );
159 if( array_key_exists('employee', $params) && (count($params['employee']) == 1) ){
160 if( ! in_array(-1, $params['employee']) ){
161 $toParams['employee'] = $params['employee'][0];
162 }
163 }
164
165 $links = array();
166
167 if( $this->allCombosShift ){
168 $label = '+' . ' ' . '__Shift__';
169 $thisTo = 'new/shift';
170 $thisTo = array( $thisTo, $toParams );
171 $link = $this->ui->makeAhref( $thisTo, $label )
172 ->tag('tab-link')
173 ->tag('align', 'center')
174 // ->addAttr('title', '__Add New__')
175 ;
176 if( $today > $date ){
177 $link->tag('muted', 3);
178 }
179 $links[] = $link;
180 }
181
182 if( $this->allCombosTimeoff ){
183 $label = '+' . ' ' . '__Time Off__';
184 $thisTo = 'new/timeoff';
185 $thisTo = array( $thisTo, $toParams );
186 $link = $this->ui->makeAhref( $thisTo, $label )
187 ->tag('tab-link')
188 ->tag('align', 'center')
189 // ->addAttr('title', '__Add New__')
190 ;
191 if( $today > $date ){
192 $link->tag('muted', 3);
193 }
194 $links[] = $link;
195 }
196
197 $links = $this->ui->makeList( $links )->gutter(0);
198
199 $cell[] = $links;
200
201 $cell = $this->ui->makeList( $cell )
202 ->gutter(1)
203 ->tag('margin', 1)
204 ;
205
206 $row[] = $cell;
207 }
208
209 $rows[] = $row;
210 }
211
212 $out = $this->ui->makeTable( NULL, $rows, FALSE )
213 ->gutter(0)
214 ->setBordered( $this->borderColor )
215 // ->setSegments( $weekSegments )
216 ;
217
218 return $out;
219 }
220
221 public function renderByCalendar()
222 {
223 $slug = $this->request->getSlug();
224 $today = $this->t->setNow()->formatDateDb();
225
226 $disabledWeekdays = $this->settings->get( 'skip_weekdays', TRUE );
227
228 $calendars = $this->common->getCalendars();
229 $employees = $this->common->getEmployees();
230 $shifts = $this->common->getShifts();
231
232 // finalize calendars to include those that employee was removed from but still have shifts in
233 $listCalendarId = array_keys( $calendars );
234 $dictCalendarId = array_combine( $listCalendarId, $listCalendarId );
235 foreach( $shifts as $shift ){
236 $calendar = $shift->getCalendar();
237 if( ! $calendar ) continue;
238 $calendarId = $calendar->getId();
239 $dictCalendarId[ $calendarId ] = $calendarId;
240 }
241 if( count($dictCalendarId) > count($calendars) ){
242 $allCalendars = $this->common->findAllCalendars();
243 $calendars = array_intersect_key( $allCalendars, $dictCalendarId );
244 }
245
246 // we can probably have archived calendars so if such calendars have no shifts then skip them
247 $removeArchivedCalendars = array();
248 foreach( $calendars as $calendar ){
249 if( $calendar->isArchived() ){
250 $removeArchivedCalendars[ $calendar->getId() ] = $calendar->getId();
251 }
252 }
253 if( $removeArchivedCalendars ){
254 foreach( $shifts as $shift ){
255 $calendar = $shift->getCalendar();
256 $id = $calendar ? $calendar->getId() : 0;
257 if( isset($removeArchivedCalendars[$id]) ){
258 unset( $removeArchivedCalendars[$id] );
259 }
260 if( ! $removeArchivedCalendars ){
261 break;
262 }
263 }
264 foreach( $removeArchivedCalendars as $id ){
265 unset( $calendars[$id] );
266 }
267 reset( $shifts );
268 }
269
270 $params = $this->request->getParams();
271 $startDate = $params['start'];
272
273 $startDate = $this->t->setDateDb( $startDate )->setStartMonth()->formatDateDb();
274 $endDate = $this->t->modify('+1 month')->modify('-1 day')->formatDateDb();
275
276 $this->t->setDateDb( $startDate );
277 $dates = array();
278 $rexDate = $startDate;
279 while( $rexDate <= $endDate ){
280 if( $disabledWeekdays ){
281 $wkd = $this->t->getWeekday();
282 if( in_array($wkd, $disabledWeekdays) ){
283 $rexDate = $this->t->modify('+1 day')->formatDateDb();
284 continue;
285 }
286 }
287
288 $dates[] = $rexDate;
289 $rexDate = $this->t->modify('+1 day')->formatDateDb();
290 }
291
292 $viewCalendars = array();
293 foreach( $calendars as $calendar ){
294 $label = $this->calendarsPresenter->presentTitle( $calendar );
295 $title = htmlspecialchars( $calendar->getTitle() );
296 $description = $calendar->getDescription();
297 if( strlen($description) ){
298 $description = htmlspecialchars( $description );
299 $title .= "\n" . $description;
300 }
301
302 $label = $this->ui->makeSpan( $label )
303 ->addAttr( 'title', $title )
304 ;
305
306 $viewCalendars[ $calendar->getId() ] = $label;
307 }
308
309 $viewShifts = array();
310
311 $iknow = array('calendar', 'date');
312 foreach( $shifts as $shift ){
313 $calendar = $shift->getCalendar();
314 $id = $calendar ? $calendar->getId() : 0;
315
316 if( ! array_key_exists($id, $viewShifts) ){
317 $viewShifts[$id] = array();
318 }
319
320 $start = $shift->getStart();
321 $end = $shift->getEnd();
322
323 $startDayTime = substr($start, 8, 4);
324 $endDayTime = substr($end, 8, 4);
325 $shiftAllDay = ( (0 == $startDayTime) && (0 == $endDayTime) ) ? TRUE : FALSE;
326
327 $this->t->setDateTimeDb( $end )->modify('-1 second');
328 $shiftEndDate = $this->t->formatDateDb();
329
330 $this->t->setDateTimeDb( $start );
331 $shiftStartDate = $this->t->formatDateDb();
332
333 $rexDate = $shiftStartDate;
334 while( $rexDate <= $shiftEndDate ){
335 if( in_array($rexDate, $dates) ){
336 if( ! array_key_exists($rexDate, $viewShifts[$id]) ){
337 $viewShifts[$id][$rexDate] = array();
338 }
339 $viewShifts[$id][$rexDate][] = $shift;
340 }
341
342 if( ! $shiftAllDay ){
343 break;
344 }
345 $this->t->modify( '+1 day' );
346 $rexDate = $this->t->formatDateDb();
347 }
348 }
349
350 $header = array();
351 $header[] = NULL;
352
353 $weekStartsOn = $this->t->getWeekStartsOn();
354 $weekSegments = array();
355
356 $this->t->setDateDb( $startDate );
357 $monthMatrix = $this->t->getMonthMatrix( $disabledWeekdays );
358
359 foreach( $monthMatrix as $week => $days ){
360 $wdi = 0;
361 foreach( $days as $date ){
362 if( ! $date ){
363 continue;
364 }
365
366 $dateView = $this->common->renderDateLabelGrouped( $date );
367 $header[] = $dateView;
368
369 if( ! $wdi ){
370 $weekSegments[] = count($header);
371 }
372
373 $wdi++;
374 }
375 }
376
377 // while( count($header) < 32 ){
378 // $header[] = NULL;
379 // }
380
381 $rows = array();
382
383 // link templates to speed things up
384 $toParams = array(
385 'calendar' => '{CID}',
386 'date' => '{DATE}'
387 );
388 $thisTo = 'new/calendar';
389 $thisTo = array( $thisTo, $toParams );
390 $thisHref = $this->uri->makeUrl( $thisTo );
391
392 $linkTemplateShift = '<a title="__Add New__" class="hc-block hc-theme-tab-link hc-align-center" href="' . $thisHref . '">+</a>';
393 $linkTemplateShiftMuted = '<a title="__Add New__" class="hc-block hc-theme-tab-link hc-align-center hc-muted3" href="' . $thisHref . '">+</a>';
394 $isPrintView = $this->request->isPrintView();
395
396 foreach( $viewCalendars as $id => $calendarView ){
397 $row = array();
398
399 $this->shiftsDuration->reset();
400 if( isset($viewShifts[$id]) ){
401 foreach( $viewShifts[$id] as $date => $dateShifts ){
402 foreach( $dateShifts as $shift ){
403 $this->shiftsDuration->add( $shift );
404 }
405 }
406
407 $outReport = $this->common->renderReport( $this->shiftsDuration, FALSE );
408 $outReport = $this->ui->makeSpan( $outReport )
409 ->tag('font-size', 2)
410 ;
411 $calendarView = $this->ui->makeList( array($calendarView, $outReport) )
412 ->gutter(1)
413 ;
414 }
415
416 $calendarView = $this->ui->makeBlock( $calendarView )
417 ->tag('padding', array('x1', 'y2'))
418 ->tag('nowrap')
419 ;
420 $row[] = $calendarView;
421
422 $countDates = count( $dates );
423 foreach( $dates as $date ){
424 $cell = array();
425
426 if( isset($viewShifts[$id][$date]) ){
427 if( $countDates <= 10 ){
428 $shiftsView = $this->viewWeek->renderDay( $viewShifts[$id][$date], $iknow );
429 }
430 else {
431 $shiftsView = $this->self->renderDay( $viewShifts[$id][$date], $iknow );
432 }
433 $cell[] = $shiftsView;
434 }
435
436 $label = '+';
437
438 $to = 'new';
439 $toParams = array(
440 'date' => $date,
441 'calendar' => $id,
442 );
443 if( array_key_exists('employee', $params) && (count($params['employee']) == 1) ){
444 if( ! in_array(-1, $params['employee']) ){
445 $toParams['employee'] = $params['employee'][0];
446 }
447 }
448 $to = array( $to, $toParams );
449
450 $addOk = FALSE;
451 if( isset($toParams['employee']) ){
452 $testComboId = $id . '-' . $toParams['employee'];
453 if( isset($this->allCombos[$testComboId]) ){
454 $addOk = TRUE;
455 }
456 }
457 else {
458 $testComboId = $id . '-';
459 reset( $this->allCombos );
460 foreach( $this->allCombos as $comboId ){
461 if( $testComboId == substr($comboId, 0, strlen($testComboId)) ){
462 $addOk = TRUE;
463 break;
464 }
465 }
466 }
467
468 if( $isPrintView ) $addOk = false;
469
470 if( $addOk ){
471 /*
472 $link = $this->ui->makeAhref( $to, $label )
473 ->tag('tab-link')
474 ->tag('align', 'center')
475 ->addAttr('title', '__Add New__')
476 ;
477
478 if( $today > $date ){
479 $link->tag('muted', 3);
480 }
481 */
482
483 if( $today > $date ){
484 $link = str_replace( array('{CID}', '{DATE}'), array($id, $date), $linkTemplateShiftMuted );
485 }
486 else {
487 $link = str_replace( array('{CID}', '{DATE}'), array($id, $date), $linkTemplateShift );
488 }
489
490 $cell[] = $link;
491 }
492
493 $cell = $this->ui->makeList( $cell )
494 ->gutter(1)
495 ->tag('margin', '05')
496 ;
497
498 $row[] = $cell;
499 }
500
501 // while( count($row) < 32 ){
502 // $row[] = NULL;
503 // }
504 $rows[] = $row;
505 }
506
507 $out = $this->ui->makeTable( $header, $rows, FALSE )
508 ->gutter(0)
509 ->setBordered( $this->borderColor )
510 ->setSegments( $weekSegments )
511 ->setLabelled( TRUE )
512 ;
513
514 if( ! $this->slimView ){
515 $out->forceColWidth( '6rem' );
516 $out->forceRowHeaderWidth( '10rem' );
517 }
518
519 return $out;
520 }
521
522 public function renderByEmployee()
523 {
524 $slug = $this->request->getSlug();
525 $today = $this->t->setNow()->formatDateDb();
526
527 $disabledWeekdays = $this->settings->get( 'skip_weekdays', TRUE );
528
529 $calendars = $this->common->getCalendars();
530 $employees = $this->common->getEmployees();
531 $shifts = $this->common->getShifts();
532
533 // finalize employees to include those that employee was removed from but still have shifts in
534 $listEmployeeId = array_keys( $employees );
535 $dictEmployeeId = array_combine( $listEmployeeId, $listEmployeeId );
536 foreach( $shifts as $shift ){
537 $employee = $shift->getEmployee();
538 if( ! $employee ) continue;
539 $employeeId = $employee->getId();
540 $dictEmployeeId[ $employeeId ] = $employeeId;
541 }
542 if( count($dictEmployeeId) > count($employees) ){
543 $allEmployees = $this->common->findAllEmployees();
544 $employees = array_intersect_key( $allEmployees, $dictEmployeeId );
545 }
546
547 // we can probably have archived employees so if such employees have no shifts then skip them
548 $removeArchivedEmployees = array();
549 foreach( $employees as $employee ){
550 if( $employee->isArchived() ){
551 $removeArchivedEmployees[ $employee->getId() ] = $employee->getId();
552 }
553 }
554 if( $removeArchivedEmployees ){
555 foreach( $shifts as $shift ){
556 $employee = $shift->getEmployee();
557 $id = $employee ? $employee->getId() : 0;
558 if( isset($removeArchivedEmployees[$id]) ){
559 unset( $removeArchivedEmployees[$id] );
560 }
561 if( ! $removeArchivedEmployees ){
562 break;
563 }
564 }
565 foreach( $removeArchivedEmployees as $id ){
566 unset( $employees[$id] );
567 }
568 reset( $shifts );
569 }
570
571 $params = $this->request->getParams();
572 $startDate = $params['start'];
573
574 $startDate = $this->t->setDateDb( $startDate )->setStartMonth()->formatDateDb();
575 $endDate = $this->t->modify('+1 month')->modify('-1 day')->formatDateDb();
576
577 $this->t->setDateDb( $startDate );
578 $dates = array();
579 $rexDate = $startDate;
580 while( $rexDate <= $endDate ){
581 if( $disabledWeekdays ){
582 $wkd = $this->t->getWeekday();
583 if( in_array($wkd, $disabledWeekdays) ){
584 $rexDate = $this->t->modify('+1 day')->formatDateDb();
585 continue;
586 }
587 }
588
589 $dates[] = $rexDate;
590 $rexDate = $this->t->modify('+1 day')->formatDateDb();
591 }
592
593 $countDates = count( $dates );
594
595 $viewEmployees = array();
596 foreach( $employees as $employee ){
597 $label = $this->employeesPresenter->presentTitle( $employee );
598 $title = htmlspecialchars( $label );
599
600 $description = $employee->getDescription();
601 if( strlen($description) ){
602 $imgpos = strpos( $description, '<img' );
603 if( false !== $imgpos ){
604 $label = $this->ui->makeList( array($label, $description) );
605 }
606 else {
607 $title .= "\n" . htmlspecialchars( $description );
608 }
609 }
610
611 $label = $this->ui->makeSpan( $label )
612 ->tag( 'font-size', 4 )
613 ->addAttr( 'title', $title )
614 ;
615
616 $viewEmployees[ $employee->getId() ] = $label;
617 }
618
619 $viewShifts = array();
620
621 $iknow = array('employee', 'date');
622
623 $allCalendars = $this->common->findAllCalendars();
624 if( count($allCalendars) <= 1 ) $iknow[] = 'calendar';
625
626 foreach( $shifts as $shift ){
627 $employee = $shift->getEmployee();
628 $id = $employee ? $employee->getId() : 0;
629
630 if( ! array_key_exists($id, $viewShifts) ){
631 $viewShifts[$id] = array();
632 }
633
634 $start = $shift->getStart();
635 $end = $shift->getEnd();
636
637 $startDayTime = substr($start, 8, 4);
638 $endDayTime = substr($end, 8, 4);
639 $shiftAllDay = ( (0 == $startDayTime) && (0 == $endDayTime) ) ? TRUE : FALSE;
640
641 $this->t->setDateTimeDb( $end )->modify('-1 second');
642 $shiftEndDate = $this->t->formatDateDb();
643
644 $this->t->setDateTimeDb( $start );
645 $shiftStartDate = $this->t->formatDateDb();
646
647 $rexDate = $shiftStartDate;
648 while( $rexDate <= $shiftEndDate ){
649 if( in_array($rexDate, $dates) ){
650 if( ! array_key_exists($rexDate, $viewShifts[$id]) ){
651 $viewShifts[$id][$rexDate] = array();
652 }
653 $viewShifts[$id][$rexDate][] = $shift;
654 }
655
656 if( ! $shiftAllDay ){
657 break;
658 }
659 $this->t->modify( '+1 day' );
660 $rexDate = $this->t->formatDateDb();
661 }
662 }
663
664 $header = array();
665 $header[] = null;
666
667 $weekStartsOn = $this->t->getWeekStartsOn();
668 $weekSegments = array();
669
670 $this->t->setDateDb( $startDate );
671 $monthMatrix = $this->t->getMonthMatrix( $disabledWeekdays );
672
673 foreach( $monthMatrix as $week => $days ){
674 $wdi = 0;
675 foreach( $days as $date ){
676 if( ! $date ){
677 continue;
678 }
679
680 $dateView = $this->common->renderDateLabelGrouped( $date );
681 $header[] = $dateView;
682
683 if( ! $wdi ){
684 $weekSegments[] = count($header);
685 }
686
687 $wdi++;
688 }
689 }
690
691 // while( count($header) < 32 ){
692 // $header[] = NULL;
693 // }
694
695 $rows = array();
696
697 // link templates to speed things up
698 $toParams = array(
699 'employee' => '{EID}',
700 'date' => '{DATE}'
701 );
702 $thisTo = 'new';
703 $thisTo = array( $thisTo, $toParams );
704 $thisHref = $this->uri->makeUrl( $thisTo );
705
706 $linkTemplateShift = '<a title="__Add New__" class="hc-block hc-theme-tab-link hc-align-center" href="' . $thisHref . '">+</a>';
707 $linkTemplateShiftMuted = '<a title="__Add New__" class="hc-block hc-theme-tab-link hc-align-center hc-muted3" href="' . $thisHref . '">+</a>';
708 $isPrintView = $this->request->isPrintView();
709
710 foreach( $viewEmployees as $id => $employeeView ){
711 $row = array();
712
713 $this->shiftsDuration->reset();
714 if( isset($viewShifts[$id]) ){
715 $counted = 0;
716 foreach( $viewShifts[$id] as $date => $dateShifts ){
717 foreach( $dateShifts as $shift ){
718 $shiftCalendar = $shift->getCalendar();
719 // if( $shiftCalendar->isTimeoff() ){
720 // continue;
721 // }
722 $this->shiftsDuration->add( $shift );
723 $counted++;
724 }
725 }
726
727 if( $counted ){
728 $outReport = $this->common->renderReport( $this->shiftsDuration, FALSE );
729 $outReport = $this->ui->makeSpan( $outReport )
730 ->tag('font-size', 2)
731 ;
732 $employeeView = $this->ui->makeList( array($employeeView, $outReport) )
733 ->gutter(1)
734 ;
735 }
736 }
737
738 $thisShifts = isset( $view_shifts[$id] ) ? $view_shifts[$id] : array();
739 $employeeView = $this->common->employeeRowLabel( $employeeView, $id, 'month', $dates, $thisShifts );
740
741 $employeeView = $this->ui->makeBlock( $employeeView )
742 ->tag('padding', array('x1', 'y2'))
743 ->tag('nowrap')
744 ;
745 $row[] = $employeeView;
746
747 foreach( $dates as $date ){
748 $cell = array();
749
750 if( isset($viewShifts[$id][$date]) ){
751 if( $this->slimView ){
752 $shiftsView = $this->self->renderDay( $viewShifts[$id][$date], $iknow );
753 }
754 else {
755 $shiftsView = $this->viewWeek->renderDay( $viewShifts[$id][$date], $iknow );
756 }
757 $cell[] = $shiftsView;
758 }
759
760 $comboId = 0 . '-' . $id;
761 if( isset($this->allCombos[$comboId]) ){
762 /*
763 $label = '+';
764
765 $to = 'new';
766 $toParams = array(
767 'date' => $date,
768 'employee' => $id,
769 );
770 $to = array( $to, $toParams );
771
772 $link = $this->ui->makeAhref( $to, $label )
773 ->tag('tab-link')
774 ->tag('align', 'center')
775 ->addAttr('title', '__Add New__')
776 ;
777
778 if( $today > $date ){
779 $link->tag('muted', 3);
780 }
781 */
782 if( $today > $date ){
783 $link = str_replace( array('{EID}', '{DATE}'), array($id, $date), $linkTemplateShiftMuted );
784 }
785 else {
786 $link = str_replace( array('{EID}', '{DATE}'), array($id, $date), $linkTemplateShift );
787 }
788
789 if( ! $isPrintView ){
790 $cell[] = $link;
791 }
792 }
793
794 $cell = $this->ui->makeList( $cell )
795 ->gutter(1)
796 ->tag('margin', '05')
797 ;
798
799 $row[] = $cell;
800 }
801
802 // while( count($row) < 32 ){
803 // $row[] = NULL;
804 // }
805 $rows[] = $row;
806 }
807
808 /* append calendars summary */
809 $appendCalendars = $this->settings->get('datetime_summary_by_calendar');
810 if( $appendCalendars && $shifts ){
811 $calendarIds = array();
812 foreach( $shifts as $shift ){
813 $calendar = $shift->getCalendar();
814 $calendarId = $calendar ? $calendar->getId() : 0;
815 if( ! $calendarId ) continue;
816 $calendarIds[ $calendarId ] = $calendarId;
817 }
818
819 $calendars = $this->calendarsQuery->findManyById( $calendarIds );
820
821 $shiftsByCalendar = $shiftsByDate = array();
822 foreach( $shifts as $shift ){
823 $thisCalendar = $shift->getCalendar();
824 if( ! $thisCalendar ) continue;
825 $shiftId = $shift->getId();
826 $thisCalendarId = $thisCalendar->getId();
827 $shiftsByCalendar[ $thisCalendarId ][ $shiftId ] = $shift;
828
829 $start = $shift->getStart();
830 $end = $shift->getEnd();
831
832 $startDayTime = substr($start, 8, 4);
833 $endDayTime = substr($end, 8, 4);
834 $shiftAllDay = ( (0 == $startDayTime) && (0 == $endDayTime) ) ? TRUE : FALSE;
835
836 $this->t->setDateTimeDb( $end )->modify('-1 second');
837 $shiftEndDate = $this->t->formatDateDb();
838
839 $this->t->setDateTimeDb( $start );
840 $shiftStartDate = $this->t->formatDateDb();
841
842 $rexDate = $shiftStartDate;
843 while( $rexDate <= $shiftEndDate ){
844 if( in_array($rexDate, $dates) ){
845 $shiftsByDate[ $rexDate ][ $shiftId ] = $shift;
846 }
847
848 if( ! $shiftAllDay ){
849 break;
850 }
851 $this->t->modify( '+1 day' );
852 $rexDate = $this->t->formatDateDb();
853 }
854 }
855
856 foreach( $calendars as $calendarId => $calendar ){
857 $row = array();
858
859 $calendarView = $this->calendarsPresenter->presentTitle( $calendar );
860 $title = htmlspecialchars( $calendar->getTitle() );
861 $calendarView = $this->ui->makeSpan( $calendarView )
862 ->addAttr( 'title', $title )
863 ;
864
865 $this->shiftsDuration->reset();
866 foreach( $shiftsByCalendar[$calendarId] as $shift ){
867 $this->shiftsDuration->add( $shift );
868 }
869
870 $outReport = $this->common->renderReport( $this->shiftsDuration, false, true );
871 $outReport = $this->ui->makeSpan( $outReport )
872 ->tag('font-size', 2)
873 ;
874 $calendarView = $this->ui->makeList( array($calendarView, $outReport) )
875 ->gutter(1)
876 ;
877
878 $calendarView = $this->ui->makeBlock( $calendarView )
879 ->tag('padding', 2)
880 ->tag('nowrap')
881 ;
882 $row[] = $calendarView;
883
884 foreach( $dates as $date ){
885 $cell = '';
886 if( isset($shiftsByDate[$date]) ){
887 $thisShifts = array_intersect_key( $shiftsByDate[$date], $shiftsByCalendar[$calendarId] );
888 if( $thisShifts ){
889 $this->shiftsDuration->reset();
890 foreach( $thisShifts as $shift ){
891 $this->shiftsDuration->add( $shift );
892 }
893 $outReport = $this->common->renderReport( $this->shiftsDuration, FALSE );
894 $outReport = $this->ui->makeSpan( $outReport )
895 ->tag('font-size', 2)
896 ;
897 $outReport = $this->ui->makeBlock( $outReport )
898 ->tag('align', 'center')
899 ;
900 $cell = $outReport;
901 }
902 }
903 $row[] = $cell;
904 }
905 $rows[] = $row;
906 }
907 }
908
909 $out = $this->ui->makeTable( $header, $rows, false )
910 ->gutter(0)
911 ->setBordered( $this->borderColor )
912 ->setSegments( $weekSegments )
913 ->setLabelled( true )
914 ;
915
916 if( ! $this->slimView ){
917 $out->forceColWidth( '6rem' );
918 $out->forceRowHeaderWidth( '10rem' );
919 }
920
921 return $out;
922 }
923
924 public function renderDay( $shifts, $iknow )
925 {
926 $return = NULL;
927 if( ! $shifts ){
928 return $return;
929 }
930
931 $params = $this->request->getParams();
932
933 $hideui = $params['hideui'];
934 $noZoom = in_array('shiftdetails', $hideui);
935
936 if( array_key_exists('employee', $params) && (count($params['employee']) == 1) ){
937 if( ! in_array(-1, $params['employee']) ){
938 $iknow[] = 'employee';
939 }
940 }
941 if( array_key_exists('calendar', $params) && (count($params['calendar']) == 1) ){
942 $iknow[] = 'calendar';
943 }
944
945 // groups?
946 $groups = array();
947 $groupedShifts = array();
948 reset( $shifts );
949 foreach( $shifts as $shift ){
950 if( ! $shift->isOpen() ){
951 continue;
952 }
953
954 $groupId = $shift->getGroupingId();
955
956 if( ! isset($groups[$groupId]) ){
957 $groups[ $groupId ] = $shift->getId();
958 $groupedShifts[ $shift->getId() ] = array( $shift->getId() => $shift );
959 }
960 else {
961 $mainShiftId = $groups[ $groupId ];
962 $groupedShifts[ $mainShiftId ][ $shift->getId() ] = $shift;
963 $groupedShifts[ $shift->getId() ] = 0;
964 }
965 }
966
967 $return = array();
968 reset( $shifts );
969 foreach( $shifts as $shift ){
970 $id = $shift->getId();
971
972 if( isset($groupedShifts[$id]) && (! $groupedShifts[$id]) ){
973 continue;
974 }
975
976 $groupedQty = NULL;
977 if( isset($groupedShifts[$id]) && (count($groupedShifts[$id]) > 1) ){
978 $groupedQty = count($groupedShifts[$id]);
979 }
980
981 $thisView = $this->widget->renderCompact( $shift, $iknow, $groupedQty );
982
983 if( ! $noZoom ){
984 $to = 'shifts/' . $id;
985 $thisView = $this->ui->makeAhref( $to, $thisView )
986 ->tag('unstyled-link')
987 ->tag('block')
988 ->tag('print')
989 ->addAttr('class', 'sh4-widget-loader')
990 ;
991 }
992
993 $buildMenuFromShifts = isset($groupedShifts[$id]) ? $groupedShifts[$id] : array( $shift );
994 $menu = $this->shiftsCommon->bulkMenu( $buildMenuFromShifts );
995 if( $menu ){
996 $thisView = $this->ui->makeCollection( array($thisView, $menu) );
997 }
998
999 $thisView = $this->ui->makeBlock( $thisView )
1000 ->tag('block')
1001 ->addAttr('class', 'sh4-shift-widget')
1002 ;
1003
1004 $return[] = $thisView;
1005 }
1006
1007 $return = $this->ui->makeList( $return )
1008 ->gutter(1)
1009 ;
1010
1011 return $return;
1012 }
1013 }