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

FEATURE: check if properties of node are valid #47

Closed
wants to merge 1 commit into from
Closed
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
68 changes: 68 additions & 0 deletions Classes/Template.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use Neos\ContentRepository\Utility as NodeUtility;
use Neos\Flow\Persistence\Doctrine\PersistenceManager;
use Neos\Neos\Service\NodeOperations;
use Neos\Neos\Ui\Domain\Model\Feedback\Messages\Error;
use Neos\Neos\Ui\Domain\Model\FeedbackCollection;
use Neos\Utility\ObjectAccess;

class Template
Expand Down Expand Up @@ -72,6 +74,12 @@ class Template
*/
protected $persistenceManager;

/**
* @var FeedbackCollection
* @Flow\Inject
*/
protected $feedbackCollection;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is hacky as hell i know ^^


/**
* Template constructor
*
Expand Down Expand Up @@ -131,6 +139,16 @@ private function applyTemplateOnNode(NodeInterface $node, array $context): void
$childNodeTemplate->createOrFetchAndApply($node, $context);
}

$messages = [];
$this->checkIfPropertiesOfNodeAreValid($node, $messages);
foreach ($messages as $message) {
$info = new Error();
mhsdesign marked this conversation as resolved.
Show resolved Hide resolved
$info->setMessage('[NodeTemplate] ' . $message);
$this->feedbackCollection->add(
$info
);
}

$this->emitNodeTemplateApplied($node, $context, $this->options);
}

Expand Down Expand Up @@ -265,6 +283,56 @@ private function mergeContextAndWithContext(array $context): array
return array_merge($context, $withContext);
}

/**
* A few checks are run against the properties of the node
*
* 1. It is checked, that a node only has properties set, that were declared in the NodeType
*
* 2. In case the property is a select-box, it is checked, that the current value is a valid option of the select-box
*
* 3. It is made sure is that a property value is never null for the reason:
* In case that due to a condition in the nodeTemplate `null` is assigned to a node property, it will override the defaultValue.
* This is a problem, as setting `null` might not be possible via the Neos UI and the Fusion rendering is most likely not going to handle this edge case.
* So we assume this must have been a mistake. A cleaner, but also more difficult way would be to actually assert that the type matches
*
* @param array<int, string> $messages by reference in case one of the above constraints is not met.
*/
private function checkIfPropertiesOfNodeAreValid(NodeInterface $node, array &$messages = []): void
{
$nodeType = $node->getNodeType();
$defaultValues = $nodeType->getDefaultValuesForProperties();
foreach ($node->getProperties() as $propertyName => $propertyValue) {
if (!isset($nodeType->getProperties()[$propertyName])) {
$value = json_encode($propertyValue);
$messages[] = "Property '$propertyName' is not declared in NodeType {$nodeType->getName()} but was set to: " . $value;
continue;
}
if (array_key_exists($propertyName, $defaultValues) && $propertyValue === null) {
$defaultValue = json_encode($defaultValues[$propertyName]);
$messages[] = "Property '$propertyName' of node {$nodeType->getName()} is not supposed to be null. The default value would be: $defaultValue.";
continue;
}
if ($propertyValue === null) {
// in case the nodeIdentifier of a reference property cannot be resolved, null will be written to the property, and we guard against this
// also we want to enforce the actual type of the property which is likely not null
$messages[] = "Property '$propertyName' of node {$nodeType->getName()} was set to null. Type is {$nodeType->getPropertyType($propertyName)}";
continue;
}
$propertyConfiguration = $nodeType->getProperties()[$propertyName];
$editor = $propertyConfiguration["ui"]["inspector"]["editor"] ?? null;
$type = $propertyConfiguration["type"] ?? null;
$selectBoxValues = $propertyConfiguration["ui"]["inspector"]["editorOptions"]["values"] ?? null;
if ($editor === 'Neos.Neos/Inspector/Editors/SelectBoxEditor' && $selectBoxValues && in_array($type, ["string", "array"], true)) {
$selectedValue = $type === "string" ? [$propertyValue] : $propertyValue;
$difference = array_diff($selectedValue, array_keys($selectBoxValues));
if (\count($difference) !== 0) {
$messages[] = "Property '$propertyName' of node {$nodeType->getName()} has illegal select-box value(s): (" . join(", ", $difference) . ')';
continue;
}
}
}
}

/**
* Signals that a node template has been applied to the given node.
*
Expand Down