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 / fourweeks.php

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

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