Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENHANCEMENT Custom Option schema validator #30

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 53 additions & 19 deletions src/Page/EventPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -37,6 +38,7 @@
* @property int $Interval
* @property string $EventType
* @property DBDate $RecursionEndDate
* @property string $RecursionString
* @method ManyManyList Categories()
*/
class EventPage extends \Page
Expand Down Expand Up @@ -102,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)',
];

Expand Down Expand Up @@ -292,20 +297,41 @@ 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();
}
});

Expand All @@ -331,6 +357,14 @@ public function getCMSFields()
return $fields;
}

/**
* @return array
*/
protected function getRecursionStringSource()
{
return ['CUSTOM' => 'Custom'];
}

/**
*
*/
Expand Down Expand Up @@ -425,16 +459,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);
}

/**
Expand Down Expand Up @@ -537,14 +579,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
Expand Down
49 changes: 49 additions & 0 deletions src/RRule/CustomSchemaHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Dynamic\Calendar\RRule;

/**
* Class CustomSchemaHelper
* @package Dynamic\Calendar\RRule
*/
class CustomSchemaHelper extends SchemaHelper
{
/**
* @var array
*/
private static $valid_keys = [
'FREQ',
'INTERVAL',
'DTSTART',
];

/**
* @var array
*/
private static $match_one = [
'UNTIL',
'COUNT',
];

/**
* @return bool
*/
public function isValidPattern()
{
$valid = parent::isValidPattern();

if ($valid) {
$match = false;

foreach ($this->config()->get('match_one') as $key) {
if (!$match && array_key_exists($key, $this->getPattern())) {
$match = true;
}
}

$valid = $match;
}

return $valid;
}
}
65 changes: 65 additions & 0 deletions src/RRule/SchemaHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Dynamic\Calendar\RRule;

use Dynamic\Calendar\RRule\Traits\SchemaValidator;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;

/**
* Class SchemaHelper
* @package Dynamic\Calendar\RRule
*/
class SchemaHelper
{
use Configurable;
use Extensible;
use Injectable;
use SchemaValidator;

/**
* @var array
*/
private static $valid_keys = [];

/**
* SchemaHelper constructor.
* @param array $pattern
*/
public function __construct(array $pattern)
{
$this->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;
}
}
34 changes: 34 additions & 0 deletions src/RRule/Traits/SchemaValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Dynamic\Calendar\RRule\Traits;

/**
* Trait KeyValidator
* @package Dynamic\Calendar\RRule\Traits
*/
trait SchemaValidator
{
/**
* @var array
*/
private $pattern = [];

/**
* @param array $pattern
* @return $this
*/
public function setPattern(array $pattern): self
{
$this->pattern = $pattern;

return $this;
}

/**
* @return array
*/
public function getPattern()
{
return $this->pattern;
}
}
34 changes: 34 additions & 0 deletions tests/RRule/CustomSchemaHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Dynamic\Calendar\Tests\RRule;

use Dynamic\Calendar\RRule\CustomSchemaHelper;
use SilverStripe\Dev\SapphireTest;

/**
* Class CustomSchemaHelperTest
* @package Dynamic\Calendar\Tests\RRule
*/
class CustomSchemaHelperTest extends SapphireTest
{
/**
*
*/
public function testIsValidPattern()
{
$pass = [
'FREQ' => 'foo',
'INTERVAL' => 'bar',
'DTSTART' => 'baz',
'UNTIL' => 'bing',
'COUNT' => 'bang',
];

$fail = [
'FREQ' => 'foo',
];

$this->assertTrue(CustomSchemaHelper::create($pass)->isValidPattern());
$this->assertFalse(CustomSchemaHelper::create($fail)->isValidPattern());
}
}
27 changes: 27 additions & 0 deletions tests/RRule/SchemaHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Dynamic\Calendar\Tests\RRule;

use Dynamic\Calendar\RRule\SchemaHelper;
use SilverStripe\Dev\SapphireTest;

/**
* Class SchemaHelperTest
* @package Dynamic\Calendar\Tests\RRule
*/
class SchemaHelperTest extends SapphireTest
{
/**
*
*/
public function testIsValidPattern()
{
$pattern = [
'foo',
'bar',
'baz',
];

$this->assertTrue(SchemaHelper::create($pattern)->isValidPattern());
}
}