From e01a2a7c53ac0803b28e6bcfb023f10fc6df2a83 Mon Sep 17 00:00:00 2001 From: Nic Horstmeier Date: Wed, 13 Nov 2019 23:14:29 -0600 Subject: [PATCH 1/3] ENHANCEMENT Custom Option schema validator --- src/Page/EventPage.php | 21 ++++++--- src/RRule/CustomSchemaHelper.php | 49 +++++++++++++++++++ src/RRule/SchemaHelper.php | 65 ++++++++++++++++++++++++++ src/RRule/Traits/SchemaValidator.php | 34 ++++++++++++++ tests/RRule/CustomSchemaHelperTest.php | 34 ++++++++++++++ tests/RRule/SchemaHelperTest.php | 27 +++++++++++ 6 files changed, 224 insertions(+), 6 deletions(-) create mode 100644 src/RRule/CustomSchemaHelper.php create mode 100644 src/RRule/SchemaHelper.php create mode 100644 src/RRule/Traits/SchemaValidator.php create mode 100644 tests/RRule/CustomSchemaHelperTest.php create mode 100644 tests/RRule/SchemaHelperTest.php diff --git a/src/Page/EventPage.php b/src/Page/EventPage.php index 5187ff7..7f6582c 100644 --- a/src/Page/EventPage.php +++ b/src/Page/EventPage.php @@ -6,6 +6,7 @@ use Dynamic\Calendar\Factory\RecursiveEventFactory; use Dynamic\Calendar\Form\CalendarTimeField; use Dynamic\Calendar\Model\Category; +use Dynamic\Calendar\RRule\CustomSchemaHelper; use RRule\RRule; use SilverStripe\Forms\DateField; use SilverStripe\Forms\DropdownField; @@ -425,16 +426,24 @@ protected function cleanRecursions() */ protected function getRecursionSet() { - if (!$this->eventRecurs()) { - return []; - } - - return new RRule([ + $pattern = [ 'FREQ' => $this->Recursion, 'INTERVAL' => $this->Interval, 'DTSTART' => $this->StartDate, 'UNTIL' => $this->RecursionEndDate, - ]); + ]; + + if (!$this->eventRecurs()) { + return []; + } + + $validator = CustomSchemaHelper::create($pattern); + + if (!$validator->isValidPattern()) { + return []; + } + + return new RRule($pattern); } /** diff --git a/src/RRule/CustomSchemaHelper.php b/src/RRule/CustomSchemaHelper.php new file mode 100644 index 0000000..d4e9b4a --- /dev/null +++ b/src/RRule/CustomSchemaHelper.php @@ -0,0 +1,49 @@ +config()->get('match_one') as $key) { + if (!$match && array_key_exists($key, $this->getPattern())) { + $match = true; + } + } + + $valid = $match; + } + + return $valid; + } +} diff --git a/src/RRule/SchemaHelper.php b/src/RRule/SchemaHelper.php new file mode 100644 index 0000000..1136456 --- /dev/null +++ b/src/RRule/SchemaHelper.php @@ -0,0 +1,65 @@ +setPattern($pattern); + } + + /** + * @return bool + */ + public function isValidPattern() + { + $valid = is_array($this->getPattern()); + + if ($valid) { + $valid = $this->validateKeys(); + } + + return $valid; + } + + /** + * @return bool + */ + protected function validateKeys() + { + $keys = static::config()->get('valid_keys', Config::UNINHERITED); + + foreach ($keys as $key) { + if (!array_key_exists($key, $this->getPattern())) { + return false; + } + } + + return true; + } +} diff --git a/src/RRule/Traits/SchemaValidator.php b/src/RRule/Traits/SchemaValidator.php new file mode 100644 index 0000000..e6f37de --- /dev/null +++ b/src/RRule/Traits/SchemaValidator.php @@ -0,0 +1,34 @@ +pattern = $pattern; + + return $this; + } + + /** + * @return array + */ + public function getPattern() + { + return $this->pattern; + } +} diff --git a/tests/RRule/CustomSchemaHelperTest.php b/tests/RRule/CustomSchemaHelperTest.php new file mode 100644 index 0000000..dbeda0b --- /dev/null +++ b/tests/RRule/CustomSchemaHelperTest.php @@ -0,0 +1,34 @@ + 'foo', + 'INTERVAL' => 'bar', + 'DTSTART' => 'baz', + 'UNTIL' => 'bing', + 'COUNT' => 'bang', + ]; + + $fail = [ + 'FREQ' => 'foo', + ]; + + $this->assertTrue(CustomSchemaHelper::create($pass)->isValidPattern()); + $this->assertFalse(CustomSchemaHelper::create($fail)->isValidPattern()); + } +} diff --git a/tests/RRule/SchemaHelperTest.php b/tests/RRule/SchemaHelperTest.php new file mode 100644 index 0000000..0396818 --- /dev/null +++ b/tests/RRule/SchemaHelperTest.php @@ -0,0 +1,27 @@ +assertTrue(SchemaHelper::create($pattern)->isValidPattern()); + } +} From d73c5593a76070d217f9ded12927fd1e0681c5e6 Mon Sep 17 00:00:00 2001 From: Nic Horstmeier Date: Wed, 13 Nov 2019 23:39:21 -0600 Subject: [PATCH 2/3] UPDATE cms interface for custom recursion UX --- src/Page/EventPage.php | 49 +++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Page/EventPage.php b/src/Page/EventPage.php index 7f6582c..86f3fce 100644 --- a/src/Page/EventPage.php +++ b/src/Page/EventPage.php @@ -38,6 +38,7 @@ * @property int $Interval * @property string $EventType * @property DBDate $RecursionEndDate + * @property string $RecursionString * @method ManyManyList Categories() */ class EventPage extends \Page @@ -103,8 +104,11 @@ class EventPage extends \Page 'EndTime' => 'Time', 'AllDay' => 'Boolean', 'Recursion' => 'Enum(array("NONE","DAILY","WEEKLY","MONTHLY","YEARLY"), "NONE")', + 'RecursionString' => 'Varchar(255)', + 'EndType' => 'Enum(array("UNTIL","COUNT"))', 'Interval' => 'Int', 'RecursionEndDate' => 'Date', + 'RecursionInstances' => 'Int', 'EventType' => 'Varchar(255)', ]; @@ -293,20 +297,39 @@ public function getCMSFields() $startTime->hideIf('AllDay')->isEqualTo(true)->end(); $endTime->hideIf('AllDay')->isEqualTo(true)->end(); - if ($this->config()->get('recursion') && !$this->isCopy()) { + if ($this->config()->get('recursion') && !$this->isCopy() && $this->exists()) { $fields->addFieldsToTab( 'Root.Recursion', [ + DropdownField::create('RecursionString') + ->setSource($this->getRecursionStringSource()) + ->setTitle('Repeat'), FieldGroup::create( $interval = NumericField::create('Interval') - ->setTitle(''), + ->setTitle('Repeat every'), $recursion = DropdownField::create('Recursion') - ->setSource($this->getPatternSource()), + ->setSource(self::RRULE) + ->setTitle('') + ), + FieldGroup::create( + $endType = DropdownField::create('EndType') + ->setTitle('Ends') + ->setSource(['UNTIL' => 'On', 'COUNT' => 'After']), $recursionEndDate = DateField::create('RecursionEndDate') - ->setTitle('Ending On') - )->setTitle('Repeat every'), + ->setTitle(''), + $recursionInstances = NumericField::create('RecursionInstances') + ->setTitle('') + ->setRightTitle('Occurrences') + ) ] ); + + $interval->hideUnless('RecursionString')->isEqualTo('CUSTOM')->end(); + $recursion->hideUnless('RecursionString')->isEqualTo('CUSTOM')->end(); + $endType->hideUnless('RecursionString')->isEqualTo('CUSTOM')->end(); + $recursionEndDate->hideUnless('RecursionString')->isEqualTo('CUSTOM')->end(); + $recursionEndDate->hideUnless('RecursionString')->isEqualTo('CUSTOM')->andIf('EndType')->isEqualTo('UNTIL')->end(); + $recursionInstances->hideUnless('RecursionString')->isEqualTo('CUSTOM')->andIf('EndType')->isEqualTo('COUNT')->end(); } }); @@ -332,6 +355,14 @@ public function getCMSFields() return $fields; } + /** + * @return array + */ + protected function getRecursionStringSource() + { + return ['CUSTOM' => 'Custom']; + } + /** * */ @@ -546,14 +577,6 @@ public function isCopy() return $this->ParentID > 0 && $this->ClassName == RecursiveEvent::class; } - /** - * @return mixed - */ - public function getPatternSource() - { - return array_merge(['NONE' => 'Does not repeat'], self::RRULE); - } - /** * @param $list * @return \Generator From 436448b3b3983eba7a4a921efc21d86e64b3de1b Mon Sep 17 00:00:00 2001 From: Nic Horstmeier Date: Wed, 13 Nov 2019 23:44:26 -0600 Subject: [PATCH 3/3] UPDATE phpcs --- src/Page/EventPage.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Page/EventPage.php b/src/Page/EventPage.php index 86f3fce..29eff86 100644 --- a/src/Page/EventPage.php +++ b/src/Page/EventPage.php @@ -328,8 +328,10 @@ public function getCMSFields() $recursion->hideUnless('RecursionString')->isEqualTo('CUSTOM')->end(); $endType->hideUnless('RecursionString')->isEqualTo('CUSTOM')->end(); $recursionEndDate->hideUnless('RecursionString')->isEqualTo('CUSTOM')->end(); - $recursionEndDate->hideUnless('RecursionString')->isEqualTo('CUSTOM')->andIf('EndType')->isEqualTo('UNTIL')->end(); - $recursionInstances->hideUnless('RecursionString')->isEqualTo('CUSTOM')->andIf('EndType')->isEqualTo('COUNT')->end(); + $recursionEndDate->hideUnless('RecursionString')->isEqualTo('CUSTOM') + ->andIf('EndType')->isEqualTo('UNTIL')->end(); + $recursionInstances->hideUnless('RecursionString')->isEqualTo('CUSTOM') + ->andIf('EndType')->isEqualTo('COUNT')->end(); } });