View source
<?php
namespace AKlump\LoftDataGrids;
class ScheduleData extends ExportData {
protected $startDate;
protected $datesOff = array();
protected $hoursKey = 'hours';
protected $weekdaysOff = array();
protected $hoursPerDay = 8;
protected $pageIdFormat = 'm/d/Y';
protected $stats = array();
protected $todoStatsPage = false;
public function makeSchedule() {
$items = $this
->getRows();
$id = $this
->getCurrentPageId();
$this
->deletePage($id);
$this->date = clone $this
->getStartDate();
$this
->avoidHolidaysAndWeekdaysOff();
$this->stats['start date'] = $this->date
->format($this
->getPageIdFormat());
$this->stats['hours per day'] = $this
->getHoursPerDay();
$this->stats['total items'] = count($items);
$this->stats['dates off'] = array();
$this
->setDatePage($this->date);
$dayTotal = 0;
$this->stats['total hours'] = 0;
while ($item = array_shift($items)) {
$this->stats['total hours'] += $item[$this
->getHoursKey()];
$this
->processItem($item, $item[$this
->getHoursKey()], $dayTotal);
}
$this->stats['end date'] = $this->date
->format($this
->getPageIdFormat());
if ($this->todoStatsPage) {
$this
->addStatsPage($this->todoStatsPage);
}
return $this;
}
public function getStartDate() {
return ($d = $this->startDate) ? $d : date_create('today');
}
public function setStartDate(\DateTime $startDate) {
$this->startDate = $startDate
->setTimezone(new \DateTimeZone('UTC'))
->setTime(0, 0, 0);
return $this;
}
protected function avoidHolidaysAndWeekdaysOff() {
while (in_array($this->date, $this->datesOff) || in_array($this->date
->format('D'), $this->weekdaysOff)) {
$this->stats['dates off'][] = $this->date
->format($this
->getPageIdFormat());
$this->date
->add(new \DateInterval('P1D'));
}
}
public function getPageIdFormat() {
return $this->pageIdFormat;
}
public function setPageIdFormat($pageIdFormat) {
$this->pageIdFormat = $pageIdFormat;
return $this;
}
public function getHoursPerDay() {
return $this->hoursPerDay;
}
public function setHoursPerDay($hoursPerDay) {
$this->hoursPerDay = intval($hoursPerDay);
return $this;
}
public function setDatePage(\DateTime $date) {
return $this
->setPage($date
->format($this
->getPageIdFormat()));
}
public function getHoursKey() {
return $this->hoursKey;
}
public function setHoursKey($hoursKey) {
$this->hoursKey = $hoursKey;
return $this;
}
protected function processItem($item, $hours, &$dayTotal) {
$available = $this
->getHoursPerDay() - $dayTotal;
if ($available === 0) {
$this
->nextDay();
$dayTotal = 0;
return $this
->processItem($item, $hours, $dayTotal);
}
elseif ($hours > $available) {
$this
->addTodoItem($item, $available);
$this
->nextDay();
$dayTotal = 0;
$remain = $hours - $available;
return $this
->processItem($item, $remain, $dayTotal);
}
$dayTotal += $hours;
return $this
->addTodoItem($item, $hours);
}
public function addStatsPage($title = 'Schedule Statistics') {
if (empty($this->stats)) {
$id = $this
->getCurrentPageId();
$this
->setPage($title);
$this
->add('start date', null);
$this->todoStatsPage = $title;
$this
->setPage($id);
}
else {
$this
->setPage($title);
$this
->add('days off', count($this->stats['dates off']));
$this
->add('weekdays off', implode(', ', $this->weekdaysOff));
$this->stats['dates off'] = implode(', ', $this->stats['dates off']);
foreach ($this->stats as $key => $value) {
$this
->add($key, $value);
}
$this
->next();
$this
->setKeys('start date', 'end date', 'total hours', 'total items', 'hours per day', 'days off', 'weekdays off', 'dates off');
}
return $this;
}
protected function nextDay() {
$this->date
->add(new \DateInterval('P1D'));
$this
->avoidHolidaysAndWeekdaysOff();
$this
->setDatePage($this->date);
}
protected function addTodoItem($item, $hours) {
foreach ($item as $key => $value) {
switch ($key) {
case $this
->getHoursKey():
$this
->add($key, $hours);
break;
default:
$this
->add($key, $value);
break;
}
}
$this
->next();
}
public function addWeekdayOff($value) {
$value = ucfirst(strtolower($value));
if (!date_create_from_format('D', $value)) {
throw new \InvalidArgumentException("Bad format of day of week.");
}
$this->weekdaysOff[] = $value;
return $this;
}
public function addDateOff(\DateTime $holiday) {
$this->datesOff[] = $holiday
->setTimezone(new \DateTimeZone('UTC'))
->setTime(0, 0, 0);
return $this;
}
}