diff options
Diffstat (limited to 'vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php')
-rw-r--r-- | vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php b/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php new file mode 100644 index 0000000..26329fc --- /dev/null +++ b/vendor/ipl/web/src/FormElement/ScheduleElement/MonthlyFields.php @@ -0,0 +1,191 @@ +<?php + +namespace ipl\Web\FormElement\ScheduleElement; + +use ipl\Html\Attributes; +use ipl\Html\FormElement\FieldsetElement; +use ipl\Html\HtmlElement; +use ipl\Validator\CallbackValidator; +use ipl\Validator\InArrayValidator; +use ipl\Validator\ValidatorChain; +use ipl\Web\FormElement\ScheduleElement\Common\FieldsProtector; +use ipl\Web\FormElement\ScheduleElement\Common\FieldsUtils; + +class MonthlyFields extends FieldsetElement +{ + use FieldsUtils; + use FieldsProtector; + + /** @var string Used as radio option to run each selected days/months */ + public const RUNS_EACH = 'each'; + + /** @var string Used as radio option to build complex job schedules */ + public const RUNS_ONTHE = 'onthe'; + + /** @var int Number of days in a week */ + public const WEEK_DAYS = 7; + + /** @var int Day of the month to preselect by default */ + protected $default = 1; + + /** @var int Number of fields to render */ + protected $availableFields; + + protected function init(): void + { + parent::init(); + $this->initUtils(); + + $this->availableFields = (int) date('t'); + } + + /** + * Set the available fields/days of the month to be rendered + * + * @param int $fields + * + * @return $this + */ + public function setAvailableFields(int $fields): self + { + $this->availableFields = $fields; + + return $this; + } + + /** + * Set the default field/day to be selected + * + * @param int $default + * + * @return $this + */ + public function setDefault(int $default): self + { + $this->default = $default; + + return $this; + } + + /** + * Get all the selected weekdays + * + * @return array + */ + public function getSelectedDays(): array + { + $selectedDays = []; + foreach (range(1, $this->availableFields) as $day) { + if ($this->getValue("day$day", 'n') === 'y') { + $selectedDays[] = $day; + } + } + + if (empty($selectedDays)) { + $selectedDays[] = $this->default; + } + + return $selectedDays; + } + + protected function assemble() + { + $this->getAttributes()->set('id', $this->protectId('monthly-fields')); + + $runsOn = $this->getPopulatedValue('runsOn', static::RUNS_EACH); + $this->addElement('radio', 'runsOn', [ + 'required' => true, + 'class' => 'autosubmit', + 'value' => $runsOn, + 'options' => [static::RUNS_EACH => $this->translate('Each')], + ]); + + $listItems = HtmlElement::create('ul', ['class' => ['schedule-element-fields', 'multiple-fields']]); + if ($runsOn === static::RUNS_ONTHE) { + $listItems->getAttributes()->add('class', 'disabled'); + } + + foreach (range(1, $this->availableFields) as $day) { + $checkbox = $this->createElement('checkbox', "day$day", [ + 'class' => ['autosubmit', 'sr-only'], + 'value' => $day === $this->default && $runsOn === static::RUNS_EACH + ]); + $this->registerElement($checkbox); + + $htmlId = $this->protectId("day$day"); + $checkbox->getAttributes()->set('id', $htmlId); + + $listItem = HtmlElement::create('li'); + $listItem->addHtml($checkbox, HtmlElement::create('label', ['for' => $htmlId], $day)); + $listItems->addHtml($listItem); + } + + $monthlyWrapper = HtmlElement::create('div', ['class' => 'monthly']); + $runsEach = $this->getElement('runsOn'); + $runsEach->prependWrapper($monthlyWrapper); + $monthlyWrapper->addHtml($runsEach, $listItems); + + $this->addElement('radio', 'runsOn', [ + 'required' => $runsOn !== static::RUNS_EACH, + 'class' => 'autosubmit', + 'options' => [static::RUNS_ONTHE => $this->translate('On the')], + 'validators' => [ + new InArrayValidator([ + 'strict' => true, + 'haystack' => [static::RUNS_EACH, static::RUNS_ONTHE] + ]) + ] + ]); + + $ordinalWrapper = HtmlElement::create('div', ['class' => 'ordinal']); + $runsOnThe = $this->getElement('runsOn'); + $runsOnThe->prependWrapper($ordinalWrapper); + $ordinalWrapper->addHtml($runsOnThe); + + $enumerations = $this->createOrdinalElement(); + $enumerations->getAttributes()->set('disabled', $runsOn === static::RUNS_EACH); + $this->registerElement($enumerations); + + $selectableDays = $this->createOrdinalSelectableDays(); + $selectableDays->getAttributes()->set('disabled', $runsOn === static::RUNS_EACH); + $this->registerElement($selectableDays); + + $ordinalWrapper->addHtml($enumerations, $selectableDays); + } + + protected function registerAttributeCallbacks(Attributes $attributes) + { + parent::registerAttributeCallbacks($attributes); + + $attributes + ->registerAttributeCallback('default', null, [$this, 'setDefault']) + ->registerAttributeCallback('availableFields', null, [$this, 'setAvailableFields']) + ->registerAttributeCallback('protector', null, [$this, 'setIdProtector']); + } + + protected function addDefaultValidators(ValidatorChain $chain): void + { + $chain->add( + new CallbackValidator(function ($_, CallbackValidator $validator): bool { + if ($this->getValue('runsOn', static::RUNS_EACH) !== static::RUNS_EACH) { + return true; + } + + $valid = false; + foreach (range(1, $this->availableFields) as $day) { + if ($this->getValue("day$day") === 'y') { + $valid = true; + + break; + } + } + + if (! $valid) { + $validator->addMessage($this->translate('You must select at least one of these days')); + } + + return $valid; + }) + ); + } +} |