Skip to content

Commit

Permalink
Merge pull request #68 from systopia/custom-types
Browse files Browse the repository at this point in the history
Allow custom JSONForms types
  • Loading branch information
dontub authored Aug 2, 2024
2 parents 9009627 + 7a520d4 commit 9512d12
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/Form/Util/JsonConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static function toStdClass(array $data): \stdClass {
return new \stdClass();
}

$result = \json_decode(\json_encode($data, JSON_THROW_ON_ERROR));
$result = \json_decode(\json_encode($data, JSON_THROW_ON_ERROR), FALSE, 512, JSON_THROW_ON_ERROR);
Assertion::isInstanceOf($result, \stdClass::class);

return $result;
Expand Down
10 changes: 10 additions & 0 deletions src/JsonForms/Definition/Control/ControlDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ public function getEnum(): ?array {
return $this->propertySchema->enum ?? NULL;
}

/**
* {@inheritDoc}
*/
public function getKeywordValue(string $keyword, $default = NULL) {
return $this->uiSchema->{$keyword} ?? $default;
}

public function getLabel(): string {
return $this->controlSchema->label ?? $this->propertySchema->title ?? ucfirst($this->getPropertyName());
}
Expand Down Expand Up @@ -319,6 +326,9 @@ public function isRequired(): bool {
return in_array($this->getPropertyName(), $this->objectSchema->required ?? [], TRUE);
}

/**
* {@inheritDoc}
*/
public function withScopePrefix(string $scopePrefix): DefinitionInterface {
if (NULL !== $this->getScopePrefix()) {
$scopePrefix = $this->getScopePrefix() . ltrim($scopePrefix, '#');
Expand Down
78 changes: 78 additions & 0 deletions src/JsonForms/Definition/Custom/CustomDefinition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

/*
* Copyright (C) 2024 SYSTOPIA GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation in version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

declare(strict_types=1);

namespace Drupal\json_forms\JsonForms\Definition\Custom;

use Drupal\json_forms\JsonForms\Definition\DefinitionInterface;

/**
* Used for unknown UI schema types.
*
* @codeCoverageIgnore
*/
final class CustomDefinition implements DefinitionInterface {

private \stdClass $uiSchema;

private \stdClass $jsonSchema;

private bool $parentReadonly;

public function __construct(\stdClass $uiSchema, \stdClass $jsonSchema, bool $parentReadonly) {
$this->uiSchema = $uiSchema;
$this->jsonSchema = $jsonSchema;
$this->parentReadonly = $parentReadonly;
}

/**
* {@inheritDoc}
*/
public function getKeywordValue(string $keyword, $default = NULL) {
return $this->uiSchema->{$keyword} ?? $default;
}

public function getJsonSchema(): \stdClass {
return $this->jsonSchema;
}

public function getUiSchema(): \stdClass {
return $this->uiSchema;
}

public function getRule(): ?\stdClass {
return $this->uiSchema->rule ?? NULL;
}

public function getType(): string {
return $this->uiSchema->type;
}

public function isParentReadonly(): bool {
return $this->parentReadonly;
}

/**
* {@inheritDoc}
*/
public function withScopePrefix(string $scopePrefix): DefinitionInterface {
return new static($this->uiSchema, $this->jsonSchema, $this->parentReadonly);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ public function getContentMediaType(): string {
}

/**
* @param string $keyword
* @param mixed $default
*
* @return mixed
* {@inheritDoc}
*/
public function getKeywordValue(string $keyword, $default = NULL) {
return $this->markupSchema->{$keyword} ?? $default;
Expand All @@ -75,6 +72,9 @@ public function getType(): string {
return $this->markupSchema->type;
}

/**
* {@inheritDoc}
*/
public function withScopePrefix(string $scopePrefix): DefinitionInterface {
return new static($this->markupSchema);
}
Expand Down
6 changes: 4 additions & 2 deletions src/JsonForms/Definition/DefinitionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
namespace Drupal\json_forms\JsonForms\Definition;

use Drupal\json_forms\JsonForms\Definition\Control\ControlDefinition;
use Drupal\json_forms\JsonForms\Definition\Custom\CustomDefinition;
use Drupal\json_forms\JsonForms\Definition\Layout\LayoutDefinition;
use Drupal\json_forms\JsonForms\Definition\Markup\MarkupDefinition;

Expand All @@ -38,15 +39,16 @@ public static function createDefinition(
if ('Control' === $uiSchema->type) {
return ControlDefinition::fromJsonSchema($uiSchema, $jsonSchema, $parentUiReadonly);
}
elseif ('Markup' === $uiSchema->type) {

if ('Markup' === $uiSchema->type) {
return new MarkupDefinition($uiSchema);
}

if (property_exists($uiSchema, 'elements')) {
return new LayoutDefinition($uiSchema, $jsonSchema, $parentUiReadonly);
}

throw new \InvalidArgumentException(sprintf('Invalid type "%s"', $uiSchema->type));
return new CustomDefinition($uiSchema, $jsonSchema, $parentUiReadonly);
}

}
14 changes: 12 additions & 2 deletions src/JsonForms/Definition/DefinitionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,22 @@

interface DefinitionInterface {

/**
* @param mixed $default
*
* @return mixed
* The value for the given keyword in the UI schema or $default if not set.
*/
public function getKeywordValue(string $keyword, $default = NULL);

public function getRule(): ?\stdClass;

public function getType(): string;

/**
* @param string $scopePrefix
*
* @return static
* A new definition where the given scope prefix is prepended to the scopes
* of all Controls.
*/
public function withScopePrefix(string $scopePrefix): self;

Expand Down
8 changes: 4 additions & 4 deletions src/JsonForms/Definition/Layout/LayoutDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ public function getLayoutSchema(): \stdClass {
}

/**
* @param string $keyword
* @param mixed $default
*
* @return mixed
* {@inheritDoc}
*/
public function getKeywordValue(string $keyword, $default = NULL) {
return $this->layoutSchema->{$keyword} ?? $default;
Expand Down Expand Up @@ -93,6 +90,9 @@ public function getOptionsValue(string $key, $default = NULL) {
return $this->layoutSchema->options->{$key} ?? $default;
}

/**
* {@inheritDoc}
*/
public function withScopePrefix(string $scopePrefix): DefinitionInterface {
$definition = (new \ReflectionClass($this))->newInstanceWithoutConstructor();
$definition->layoutSchema = $this->layoutSchema;
Expand Down

0 comments on commit 9512d12

Please sign in to comment.