PluginProbe
ShiftController Employee Shift Scheduling / 4.9.85
ShiftController Employee Shift Scheduling v4.9.85
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 / twoweeks.php

twoweeks.php in ShiftController Employee Shift Scheduling 4.9.85, at sh4/schedule/html/view/twoweeks.php

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