Skip to content
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();
$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