Skip to content

Commit

Permalink
(feature) Add support for setting minimum and maximum count of select…
Browse files Browse the repository at this point in the history
…ed `ChoiceField` options.
  • Loading branch information
keichinger committed Oct 26, 2023
1 parent c171463 commit 289bda0
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
3.3.0
=====

* (feature) Add support for setting minimum and maximum count of selected `ChoiceField` options.


3.2.2
=====

Expand Down
57 changes: 48 additions & 9 deletions src/Field/Definition/ChoiceField.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\AtLeastOneOf;
use Symfony\Component\Validator\Constraints\Count;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Type;
use Torr\Storyblok\Context\ComponentContext;
use Torr\Storyblok\Exception\InvalidFieldConfigurationException;
use Torr\Storyblok\Field\Choices\ChoicesInterface;
use Torr\Storyblok\Field\FieldType;
use Torr\Storyblok\Visitor\DataVisitorInterface;
Expand All @@ -20,9 +22,29 @@ public function __construct (
private readonly ChoicesInterface $choices,
private readonly bool $allowMultiselect = false,
private readonly int|string|\BackedEnum|null $defaultValue = null,
private readonly ?int $minimumNumberOfOptions = null,
private readonly ?int $maximumNumberOfOptions = null,
)
{
parent::__construct($label, $this->defaultValue);

if (!$this->allowMultiselect && (null !== $this->minimumNumberOfOptions || null !== $this->maximumNumberOfOptions))
{
throw new InvalidFieldConfigurationException(\sprintf(
"Can't configure minimum or maximum amount of options for single-select choice.",
));
}

if (
null !== $this->minimumNumberOfOptions
&& null !== $this->maximumNumberOfOptions
&& $this->minimumNumberOfOptions > $this->maximumNumberOfOptions
)
{
throw new InvalidFieldConfigurationException(\sprintf(
"The minimum number of options value can't be higher than the maximum",
));
}
}


Expand All @@ -48,6 +70,8 @@ protected function toManagementApiData () : array
"default_value" => $this->defaultValue instanceof \BackedEnum
? $this->defaultValue->value
: $this->defaultValue,
"min_options" => $this->minimumNumberOfOptions,
"max_options" => $this->maximumNumberOfOptions,
],
);
}
Expand All @@ -57,20 +81,35 @@ protected function toManagementApiData () : array
*/
public function validateData (ComponentContext $context, array $contentPath, mixed $data, array $fullData) : void
{
$allowedValueTypeConstraints = new AtLeastOneOf([
new Type("string"),
new Type("int"),
]);
$valueConstraints = [
new AtLeastOneOf([
new Type("string"),
new Type("int"),
]),
];

if ($this->allowMultiselect)
{
$valueConstraints[] = new NotNull();

if (null !== $this->minimumNumberOfOptions || null !== $this->maximumNumberOfOptions)
{
$valueConstraints[] = new Count(
min: $this->minimumNumberOfOptions,
max: $this->maximumNumberOfOptions,
minMessage: "At least {{ limit }} option(s) must be selected.",
maxMessage: "You cannot specify more than {{ limit }} options.",
);
}
}

$context->ensureDataIsValid(
$contentPath,
$this,
$data,
[
$this->allowMultiselect
? new All([new NotNull(), $allowedValueTypeConstraints])
: $allowedValueTypeConstraints,
],
$this->allowMultiselect
? [new All($valueConstraints)]
: $valueConstraints,
);

\assert(null === $data || \is_array($data) || \is_int($data) || \is_string($data));
Expand Down

0 comments on commit 289bda0

Please sign in to comment.