/** * Creates a node from the given NodeData container. * * If this factory has previously created a Node for the given $node and it's dimensions, * it will return the same node again. * * @param NodeData $nodeData * @param Context $context * @return NodeInterface * @throws NodeConfigurationException if a configured 'class' for a Node does not exist or does not inherit NodeInterface */ public function createFromNodeData(NodeData $nodeData, Context $context) { if ($nodeData->isInternal()) { return null; } $internalNodeIdentifier = $nodeData->getIdentifier() . spl_object_hash($context); // In case there is a Node with an internal NodeData (because the NodeData was changed in the meantime) we need to flush it. if (isset($this->nodes[$internalNodeIdentifier]) && $this->nodes[$internalNodeIdentifier]->getNodeData()->isInternal()) { unset($this->nodes[$internalNodeIdentifier]); } if (!isset($this->nodes[$internalNodeIdentifier])) { // Warning: Alternative node implementations are considered internal for now, feature can change or be removed anytime. We want to be sure it works well and makes sense before declaring it public. $class = $nodeData->getNodeType()->getConfiguration('class') ?: $this->objectManager->getClassNameByObjectName(NodeInterface::class); if (!in_array($class, static::getNodeInterfaceImplementations($this->objectManager))) { throw new NodeConfigurationException('The configured implementation class name "' . $class . '" for NodeType "' . $nodeData->getNodeType() . '" does not inherit from ' . NodeInterface::class . '.', 1406884014); } $this->nodes[$internalNodeIdentifier] = new $class($nodeData, $context); } $node = $this->nodes[$internalNodeIdentifier]; return $this->filterNodeByContext($node, $context); }