auth = $auth; $this->configuration = $configuration; } /** * @param TimesheetEntity $timesheet * @param Constraint $constraint */ public function validate($timesheet, Constraint $constraint) { if (!($constraint instanceof TimesheetLockdown)) { throw new UnexpectedTypeException($constraint, TimesheetLockdown::class); } if (!\is_object($timesheet) || !($timesheet instanceof TimesheetEntity)) { throw new UnexpectedTypeException($timesheet, TimesheetEntity::class); } $timesheetStart = $timesheet->getBegin(); if (null === $timesheetStart) { return; } if (!$this->configuration->isLockdownActive()) { return; } $lockedStart = $this->configuration->getLockdownPeriodStart(); $lockedEnd = $this->configuration->getLockdownPeriodEnd(); $gracePeriod = $this->configuration->getLockdownGracePeriod(); if (!empty($gracePeriod)) { $gracePeriod = $gracePeriod . ' '; } try { $lockdownStart = new \DateTime($lockedStart, $timesheetStart->getTimezone()); $lockdownEnd = new \DateTime($lockedEnd, $timesheetStart->getTimezone()); $lockdownGrace = new \DateTime($gracePeriod . $lockdownEnd->format('Y-m-d'), $timesheetStart->getTimezone()); } catch (\Exception $ex) { // should not happen, but ... if parsing of datetimes fails: skip validation return; } // misconfiguration detected, skip validation if ($lockdownEnd < $lockdownStart) { return; } // validate only entries added before the end of lockdown period if ($timesheetStart > $lockdownEnd) { return; } // lockdown never takes effect for users with special permission if ($this->auth->isGranted('lockdown_override_timesheet')) { return; } if (!empty($constraint->now)) { if ($constraint->now instanceof \DateTime) { $now = $constraint->now; } elseif (\is_string($constraint->now)) { try { $now = new \DateTime($constraint->now, $timesheetStart->getTimezone()); } catch (\Exception $ex) { } } } if (empty($now)) { $now = new \DateTime('now', $timesheetStart->getTimezone()); } // further validate entries inside of the most recent lockdown if ($timesheetStart > $lockdownStart && $timesheetStart < $lockdownEnd) { // if grace period is still in effect, validation succeeds if ($now < $lockdownGrace) { return; } // if user has special role, validation succeeds if ($this->auth->isGranted('lockdown_grace_timesheet')) { return; } } // raise a violation for all entries before the start of lockdown period $this->context->buildViolation('This period is locked, please choose a later date.') ->atPath('begin') ->setTranslationDomain('validators') ->setCode(TimesheetLockdown::PERIOD_LOCKED) ->addViolation(); } }