Skip to content

Commit

Permalink
Rules: Allow keyword contains
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominic Tubach committed Jul 9, 2024
1 parent 2e92c7b commit 1c7382a
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 11 deletions.
20 changes: 15 additions & 5 deletions src/Form/Control/Rule/StatesArrayFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,35 @@ private function getFieldName(string $scope): string {
return FormPropertyUtil::getFormNameForPropertyPath(ScopePointer::new($scope)->getPropertyPath());
}

private function addStates(string $effect, string $fieldName, \stdClass $schema, bool $negate = FALSE): void {
private function addStates(
string $effect,
string $fieldName,
\stdClass $schema,
bool $negate = FALSE,
bool $isContains = FALSE
): void {
if (property_exists($schema, 'not')) {
$this->addStates($effect, $fieldName, $schema->not, !$negate);
$this->addStates($effect, $fieldName, $schema->not, !$negate, $isContains);
}

if (property_exists($schema, 'const')) {
$this->statesBuilder->add($effect, $fieldName, $schema->const, $negate);
$this->statesBuilder->add($effect, $fieldName, $schema->const, $negate, $isContains);
}

if (property_exists($schema, 'enum')) {
$this->statesBuilder->add($effect, $fieldName, $schema->enum, $negate);
$this->statesBuilder->add($effect, $fieldName, $schema->enum, $negate, $isContains);
}

if (property_exists($schema, 'properties')) {
foreach ($schema->properties as $property => $propertySchema) {
$propertyFieldName = $fieldName . '[' . $property . ']';
$this->addStates($effect, $propertyFieldName, $propertySchema, $negate);
$this->addStates($effect, $propertyFieldName, $propertySchema, $negate, $isContains);
}
}

if (property_exists($schema, 'contains')) {
$this->addStates($effect, $fieldName, $schema->contains, $negate, TRUE);
}
}

}
46 changes: 40 additions & 6 deletions src/Form/Control/Rule/StatesBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
namespace Drupal\json_forms\Form\Control\Rule;

/**
* @phpstan-type statesT array<string, array<string, array<array<string, mixed>|'and'|'or'|'xor'>>>
* @phpstan-type statesT array<string, array<string|int, array<array<string, mixed>|'and'|'or'|'xor'>>>
* @phpstan-type conditionT array{checked: bool}|array{empty: bool}|array{value: scalar}
*/
final class StatesBuilder {
Expand All @@ -39,15 +39,21 @@ public function add(
string $effect,
string $fieldName,
$value,
bool $negate
bool $negate,
bool $isContains
): self {
foreach ($this->getStates($effect, $negate) as $state) {
$selector = '[name="' . $fieldName . '"]';
if (isset($this->states[$state][$selector])) {
$this->states[$state][$selector][] = 'and';
if ($isContains) {
$this->states[$state][] = $this->buildContainsCondition($fieldName, $value);
}
else {
$selector = '[name="' . $fieldName . '"]';
if (isset($this->states[$state][$selector])) {
$this->states[$state][$selector][] = 'and';
}

$this->states[$state][$selector][] = $this->buildCondition($value);
$this->states[$state][$selector][] = $this->buildCondition($value);
}
}

return $this;
Expand Down Expand Up @@ -118,6 +124,34 @@ private function buildCondition($value): array {
return $condition;
}

/**
* @phpstan-param scalar|array<scalar>|null $value
*
* @phpstan-return array<string|int, conditionT|'or'>>
*/
private function buildContainsCondition(string $fieldName, $value): array {
if (!is_array($value)) {
$selector = '[name="' . $fieldName . '[' . $value . ']"]';
return [
$selector => ['checked' => TRUE],
];
}

$condition = [];
$value = array_unique($value);
foreach ($value as $v) {
if (!is_array($v)) {
/** @phpstan-var array<string, conditionT> $subCondition */
$subCondition = $this->buildContainsCondition($fieldName, $v);
$condition += $subCondition;
$condition[] = 'or';
}
}
array_pop($condition);

return $condition;
}

/**
* @phpstan-return statesT
*/
Expand Down
56 changes: 56 additions & 0 deletions tests/src/Unit/Form/Rule/StatesArrayFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,60 @@ public function testHideWithInteger(): void {
);
}

public function testContains(): void {
$rule = (object) [
'effect' => 'SHOW',
'condition' => (object) [
'scope' => '#/properties/foo/properties/bar',
'schema' => (object) ['contains' => (object) ['const' => 'baz']],
],
];

static::assertSame(
[
'visible' => [
[
'[name="foo[bar][baz]"]' => [
'checked' => TRUE,
],
],
],
],
$this->factory->createStatesArray($rule)
);
}

public function testContainsEnum(): void {
$rule = (object) [
'effect' => 'SHOW',
'condition' => (object) [
'scope' => '#/properties/foo/properties/bar',
'schema' => (object) [
'contains' => (object) [
'enum' => ['baz1', 'baz2'],
],
],
],
];

// phpcs:disable Squiz.Arrays.ArrayDeclaration.NoKeySpecified
static::assertSame(
[
'visible' => [
[
'[name="foo[bar][baz1]"]' => [
'checked' => TRUE,
],
'or',
'[name="foo[bar][baz2]"]' => [
'checked' => TRUE,
],
],
],
],
$this->factory->createStatesArray($rule)
);
// phpcs:enable
}

}

0 comments on commit 1c7382a

Please sign in to comment.