/** * Change the property on the given node. * * @param NodeData $node * @return void */ public function execute(NodeData $node) { foreach ($node->getNodeType()->getProperties() as $propertyName => $propertyConfiguration) { if (isset($propertyConfiguration['type']) && in_array(trim($propertyConfiguration['type']), $this->getHandledObjectTypes())) { if (!isset($nodeProperties)) { $nodeRecordQuery = $this->entityManager->getConnection()->prepare('SELECT properties FROM typo3_typo3cr_domain_model_nodedata WHERE persistence_object_identifier=?'); $nodeRecordQuery->execute([$this->persistenceManager->getIdentifierByObject($node)]); $nodeRecord = $nodeRecordQuery->fetch(\PDO::FETCH_ASSOC); $nodeProperties = unserialize($nodeRecord['properties']); } if (!isset($nodeProperties[$propertyName]) || !is_object($nodeProperties[$propertyName])) { continue; } /** @var Asset $assetObject */ $assetObject = $nodeProperties[$propertyName]; $nodeProperties[$propertyName] = null; $stream = $assetObject->getResource()->getStream(); if ($stream === false) { continue; } fclose($stream); $objectType = TypeHandling::getTypeForValue($assetObject); $objectIdentifier = ObjectAccess::getProperty($assetObject, 'Persistence_Object_Identifier', true); $nodeProperties[$propertyName] = array('__flow_object_type' => $objectType, '__identifier' => $objectIdentifier); } } if (isset($nodeProperties)) { $nodeUpdateQuery = $this->entityManager->getConnection()->prepare('UPDATE typo3_typo3cr_domain_model_nodedata SET properties=? WHERE persistence_object_identifier=?'); $nodeUpdateQuery->execute([serialize($nodeProperties), $this->persistenceManager->getIdentifierByObject($node)]); } }
/** * Add dimensions to the node. * * @param NodeData $node * @return void */ public function execute(NodeData $node) { $dimensionValuesToBeAdded = $node->getDimensionValues(); foreach ($this->dimensionValues as $dimensionName => $dimensionValues) { if (!isset($dimensionValuesToBeAdded[$dimensionName])) { if (is_array($dimensionValues)) { $dimensionValuesToBeAdded[$dimensionName] = $dimensionValues; } else { $dimensionValuesToBeAdded[$dimensionName] = array($dimensionValues); } } } if ($this->addDefaultDimensionValues === true) { $configuredDimensions = $this->contentDimensionRepository->findAll(); foreach ($configuredDimensions as $configuredDimension) { if (!isset($dimensionValuesToBeAdded[$configuredDimension->getIdentifier()])) { $dimensionValuesToBeAdded[$configuredDimension->getIdentifier()] = array($configuredDimension->getDefault()); } } } $dimensionsToBeSet = array(); foreach ($dimensionValuesToBeAdded as $dimensionName => $dimensionValues) { foreach ($dimensionValues as $dimensionValue) { $dimensionsToBeSet[] = new NodeDimension($node, $dimensionName, $dimensionValue); } } $node->setDimensions($dimensionsToBeSet); }
/** * Returns TRUE if the given node has the property and the value is not empty. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return boolean */ public function matches(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { if ($node->hasProperty($this->propertyName)) { $propertyValue = $node->getProperty($this->propertyName); return !empty($propertyValue); } return FALSE; }
/** * Returns TRUE if the given node has the property and the value is not empty. * * @param NodeData $node * @return boolean */ public function matches(NodeData $node) { if ($node->hasProperty($this->propertyName)) { $propertyValue = $node->getProperty($this->propertyName); return !empty($propertyValue); } return false; }
/** * Creates a node from the given NodeData container. * * If this factory has previously created a Node for the given $node and $context, * it will return the same Node again. * * @param NodeData $nodeData * @param Context $context * @return \TYPO3\TYPO3CR\Domain\Model\Node */ public function createFromNodeData(NodeData $nodeData, Context $context) { $internalNodeIdentifier = $nodeData->getIdentifier() . spl_object_hash($context); if (!isset($this->nodes[$internalNodeIdentifier])) { $this->nodes[$internalNodeIdentifier] = new Node($nodeData, $context); } $node = $this->nodes[$internalNodeIdentifier]; return $this->filterNodeByContext($node, $context); }
/** * Extract comments and deserialize them * * @param NodeInterface|NodeData $nodeOrNodeData * @return array */ protected function extractComments($nodeOrNodeData) { if ($nodeOrNodeData->hasProperty('comments')) { $comments = $nodeOrNodeData->getProperty('comments'); if (is_string($comments) && strlen($comments) > 0) { return json_decode($comments, TRUE); } } return array(); }
/** * Returns TRUE if the given node has the default dimension values. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return boolean */ public function matches(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { if ($this->filterForDefaultDimensionValues === true) { $configuredDimensions = $this->contentDimensionRepository->findAll(); foreach ($configuredDimensions as $dimension) { $this->dimensionValues[$dimension->getIdentifier()] = array($dimension->getDefault()); } } return $node->getDimensionValues() === $this->dimensionValues; }
/** * Generates a Context that exactly fits the given NodeData Workspace, Dimensions & Site. * * @param NodeData $nodeData * @return ContentContext */ protected function createContextMatchingNodeData(NodeData $nodeData) { $nodePath = NodePaths::getRelativePathBetween(SiteService::SITES_ROOT_PATH, $nodeData->getPath()); list($siteNodeName) = explode('/', $nodePath); $site = $this->siteRepository->findOneByNodeName($siteNodeName); $contextProperties = ['workspaceName' => $nodeData->getWorkspace()->getName(), 'invisibleContentShown' => true, 'inaccessibleContentShown' => true, 'removedContentShown' => true, 'dimensions' => $nodeData->getDimensionValues(), 'currentSite' => $site]; if ($domain = $site->getFirstActiveDomain()) { $contextProperties['currentDomain'] = $domain; } return $this->_contextFactory->create($contextProperties); }
/** * Returns TRUE if the given node is of the node type this filter expects. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return boolean */ public function matches(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { if ($this->withSubTypes === true) { $nodeIsMatchingNodeType = $node->getNodeType()->isOfType($this->nodeTypeName); } else { // This is needed to get the raw string NodeType to prevent errors for NodeTypes that no longer exist. $nodeType = \TYPO3\Flow\Reflection\ObjectAccess::getProperty($node, 'nodeType', true); $nodeIsMatchingNodeType = $nodeType === $this->nodeTypeName; } if ($this->exclude === true) { return !$nodeIsMatchingNodeType; } return $nodeIsMatchingNodeType; }
/** * If AssetList contains only 1 file, and it's of type Audio, turn it into targetNodeType * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return void */ public function execute(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { $assets = $node->getProperty($this->sourcePropertyName); if (count($assets) === 1) { $asset = $assets[0]; if ($asset instanceof $this->assetType) { $nodeType = $this->nodeTypeManager->getNodeType($this->targetNodeType); $node->setNodeType($nodeType); $node->setProperty($this->targetPropertyName, $asset); $node->removeProperty($this->sourcePropertyName); echo "Converted AssetList with asset of type" . $this->assetType . " to node of type " . $this->targetNodeType . "\n"; } } }
/** * Given a context a new node is returned that is like this node, but * lives in the new context. * * @param Context $context * @return NodeInterface */ public function createVariantForContext($context) { $autoCreatedChildNodes = []; $nodeType = $this->getNodeType(); foreach ($nodeType->getAutoCreatedChildNodes() as $childNodeName => $childNodeConfiguration) { $childNode = $this->getNode($childNodeName); if ($childNode !== null) { $autoCreatedChildNodes[$childNodeName] = $childNode; } } $nodeData = new NodeData($this->nodeData->getPath(), $context->getWorkspace(), $this->nodeData->getIdentifier(), $context->getTargetDimensionValues()); $nodeData->similarize($this->nodeData); if ($this->context !== $context) { $node = $this->nodeFactory->createFromNodeData($nodeData, $context); } else { $this->setNodeData($nodeData); $node = $this; } $this->context->getFirstLevelNodeCache()->flush(); $this->emitNodeAdded($node); /** * @var $autoCreatedChildNode NodeInterface */ foreach ($autoCreatedChildNodes as $autoCreatedChildNode) { $autoCreatedChildNode->createVariantForContext($context); } return $node; }
/** * @test */ public function matchesWorkspaceAndDimensionsWithMatchingWorkspaceAndDimensionsReturnsTrue() { $this->nodeData = new NodeData('/foo/bar', $this->mockWorkspace, NULL, array('locales' => array('mul_ZZ'))); $this->mockWorkspace->expects($this->any())->method('getName')->will($this->returnValue('live')); $result = $this->nodeData->matchesWorkspaceAndDimensions($this->mockWorkspace, array('locales' => array('de_DE', 'mul_ZZ'))); $this->assertTrue($result); }
/** * Change the property on the given node. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $nodeData * @return void */ public function execute(NodeData $nodeData) { $dimensions = $nodeData->getDimensions(); if ($dimensions !== array()) { $hasChanges = false; $newDimensions = array(); foreach ($dimensions as $dimension) { /** @var NodeDimension $dimension */ if ($dimension->getName() === $this->oldDimensionName) { $dimension = new NodeDimension($dimension->getNodeData(), $this->newDimensionName, $dimension->getValue()); $hasChanges = true; } else { $dimension = new NodeDimension($dimension->getNodeData(), $dimension->getName(), $dimension->getValue()); } $newDimensions[] = $dimension; } if ($hasChanges) { $nodeData->setDimensions($newDimensions); } } }
/** * Change the property on the given node. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return void */ public function execute(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { $dimensions = array(); foreach ($this->dimensionValues as $dimensionName => $dimensionConfiguration) { foreach ($dimensionConfiguration as $dimensionValues) { if (is_array($dimensionValues)) { foreach ($dimensionValues as $dimensionValue) { $dimensions[] = new NodeDimension($node, $dimensionName, $dimensionValue); } } else { $dimensions[] = new NodeDimension($node, $dimensionName, $dimensionValues); } } } if ($this->addDefaultDimensionValues === TRUE) { $configuredDimensions = $this->contentDimensionRepository->findAll(); foreach ($configuredDimensions as $configuredDimension) { if (!isset($this->dimensionValues[$configuredDimension->getIdentifier()])) { $dimensions[] = new NodeDimension($node, $configuredDimension->getIdentifier(), $configuredDimension->getDefault()); } } } $node->setDimensions($dimensions); }
/** * Change the property on the given node. * * @param NodeData $node * @return NodeData */ public function execute(NodeData $node) { $reference = (string) $node->getProperty('plugin'); $workspace = $node->getWorkspace(); do { if ($this->reverse === false && preg_match(NodeInterface::MATCH_PATTERN_PATH, $reference)) { $pluginNode = $this->nodeDataRepository->findOneByPath($reference, $node->getWorkspace()); } else { $pluginNode = $this->nodeDataRepository->findOneByIdentifier($reference, $node->getWorkspace()); } if (isset($pluginNode)) { break; } $workspace = $workspace->getBaseWorkspace(); } while ($workspace && $workspace->getName() !== 'live'); if (isset($pluginNode)) { $node->setProperty('plugin', $this->reverse === false ? $pluginNode->getIdentifier() : $pluginNode->getPath()); } return $node; }
/** * Generates cache tags to be flushed for a node which is flushed on shutdown. * * Code duplicated from Neos' ContentCacheFlusher class * * @param NodeInterface|NodeData $node The node which has changed in some way * @return void */ protected function generateCacheTags($node) { $this->tagsToFlush[ContentCache::TAG_EVERYTHING] = 'which were tagged with "Everything".'; $nodeTypesToFlush = $this->getAllImplementedNodeTypes($node->getNodeType()); foreach ($nodeTypesToFlush as $nodeType) { /** @var NodeType $nodeType */ $nodeTypeName = $nodeType->getName(); $this->tagsToFlush['NodeType_' . $nodeTypeName] = sprintf('which were tagged with "NodeType_%s" because node "%s" has changed and was of type "%s".', $nodeTypeName, $node->getPath(), $node->getNodeType()->getName()); } $this->tagsToFlush['Node_' . $node->getIdentifier()] = sprintf('which were tagged with "Node_%s" because node "%s" has changed.', $node->getIdentifier(), $node->getPath()); while ($node->getDepth() > 1) { $node = $node->getParent(); if ($node === NULL) { break; } $this->tagsToFlush['DescendantOf_' . $node->getIdentifier()] = sprintf('which were tagged with "DescendantOf_%s" because node "%s" has changed.', $node->getIdentifier(), $node->getPath()); } if ($node instanceof NodeInterface && $node->getContext() instanceof ContentContext) { $firstActiveDomain = $node->getContext()->getCurrentSite()->getFirstActiveDomain(); if ($firstActiveDomain) { $this->domainsToFlush[] = $firstActiveDomain->getHostPattern(); } } }
/** * Remove the property from the given node. * * @param NodeData $node * @return void */ public function execute(NodeData $node) { $node->removeProperty($this->propertyName); }
/** * Remove the given node * * @param NodeData $node * @return void */ public function execute(NodeData $node) { $node->setRemoved(true); }
/** * Change the Node Type on the given node. * * @param NodeData $node * @return void */ public function execute(NodeData $node) { $nodeType = $this->nodeTypeManager->getNodeType($this->newType); $node->setNodeType($nodeType); }
/** * Strips tags on the value of the property to work on. * * @param NodeData $node * @return void */ public function execute(NodeData $node) { $node->setProperty($this->propertyName, strip_tags($node->getProperty($this->propertyName))); }
/** * Returns TRUE if the given node is in the workspace this filter expects. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return boolean */ public function matches(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { return $node->getWorkspace() !== NULL && $node->getWorkspace()->getName() === $this->workspaceName; }
/** * Returns TRUE if the given node is removed * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return boolean */ public function matches(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { return $node->isRemoved(); }
/** * Create a node for the given NodeData, given that it is a variant of the current node * * @param NodeData $nodeData * @return Node */ protected function createNodeForVariant($nodeData) { $contextProperties = $this->context->getProperties(); $contextProperties['dimensions'] = $nodeData->getDimensionValues(); unset($contextProperties['targetDimensions']); $adjustedContext = $this->contextFactory->create($contextProperties); return $this->nodeFactory->createFromNodeData($nodeData, $adjustedContext); }
/** * Assigns an index to the given node which reflects the specified position. * If the position is "before" or "after", an index will be chosen which makes * the given node the previous or next node of the given reference node. * If the position "last" is specified, an index higher than any existing index * will be chosen. * * If no free index is available between two nodes (for "before" and "after"), * the whole index of the current node level will be renumbered. * * @param NodeData $node The node to set the new index for * @param integer $position The position the new index should reflect, must be one of the POSITION_* constants * @param NodeInterface $referenceNode The reference node. Mandatory for POSITION_BEFORE and POSITION_AFTER * @return void * @throws \InvalidArgumentException */ public function setNewIndex(NodeData $node, $position, NodeInterface $referenceNode = null) { $parentPath = $node->getParentPath(); switch ($position) { case self::POSITION_BEFORE: if ($referenceNode === null) { throw new \InvalidArgumentException('The reference node must be specified for POSITION_BEFORE.', 1317198857); } $referenceIndex = $referenceNode->getIndex(); $nextLowerIndex = $this->findNextLowerIndex($parentPath, $referenceIndex); if ($nextLowerIndex === null) { // FIXME: $nextLowerIndex returns 0 and not NULL in case no lower index is found. So this case seems to be // never executed. We need to check that again! $newIndex = (int) round($referenceIndex / 2); } elseif ($nextLowerIndex < $referenceIndex - 1) { // there is free space left between $referenceNode and preceding sibling. $newIndex = (int) round($nextLowerIndex + ($referenceIndex - $nextLowerIndex) / 2); } else { // there is no free space left between $referenceNode and following sibling -> we need to re-number! $this->renumberIndexesInLevel($parentPath); $referenceIndex = $referenceNode->getIndex(); $nextLowerIndex = $this->findNextLowerIndex($parentPath, $referenceIndex); if ($nextLowerIndex === null) { $newIndex = (int) round($referenceIndex / 2); } else { $newIndex = (int) round($nextLowerIndex + ($referenceIndex - $nextLowerIndex) / 2); } } break; case self::POSITION_AFTER: if ($referenceNode === null) { throw new \InvalidArgumentException('The reference node must be specified for POSITION_AFTER.', 1317198858); } $referenceIndex = $referenceNode->getIndex(); $nextHigherIndex = $this->findNextHigherIndex($parentPath, $referenceIndex); if ($nextHigherIndex === null) { // $referenceNode is last node, so we can safely add an index at the end by incrementing the reference index. $newIndex = $referenceIndex + 100; $this->setHighestIndexInParentPath($parentPath, $newIndex); } elseif ($nextHigherIndex > $referenceIndex + 1) { // $referenceNode is not last node, but there is free space left between $referenceNode and following sibling. $newIndex = (int) round($referenceIndex + ($nextHigherIndex - $referenceIndex) / 2); } else { // $referenceNode is not last node, and no free space is left -> we need to re-number! $this->renumberIndexesInLevel($parentPath); $referenceIndex = $referenceNode->getIndex(); $nextHigherIndex = $this->findNextHigherIndex($parentPath, $referenceIndex); if ($nextHigherIndex === null) { $newIndex = $referenceIndex + 100; $this->setHighestIndexInParentPath($parentPath, $newIndex); } else { $newIndex = (int) round($referenceIndex + ($nextHigherIndex - $referenceIndex) / 2); } } break; case self::POSITION_LAST: $nextFreeIndex = $this->findNextFreeIndexInParentPath($parentPath); $newIndex = $nextFreeIndex; break; default: throw new \InvalidArgumentException('Invalid position for new node index given.', 1329729088); } $node->setIndex($newIndex); }
/** * Remove the given node * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return void */ public function execute(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { $node->setRemoved(true); }
/** * Renames the configured property to the new name. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return void */ public function execute(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { $node->setProperty($this->newPropertyName, $node->getProperty($this->oldPropertyName)); $node->removeProperty($this->oldPropertyName); }
/** * Create a shadow NodeData at the given path with the same workspace and dimensions as this * * Note: The constructor will already add the new object to the repository * * @param string $path The (original) path for the node data * @return NodeData */ public function createShadow($path) { $shadowNode = new NodeData($path, $this->workspace, $this->identifier, $this->dimensionValues); $shadowNode->similarize($this); $shadowNode->setAsShadowOf($this); return $shadowNode; }
/** * Strips tags on the value of the property to work on. * * @param \TYPO3\TYPO3CR\Domain\Model\NodeData $node * @return void */ public function execute(\TYPO3\TYPO3CR\Domain\Model\NodeData $node) { $node->setProperty($this->propertyName, strip_tags($node->getProperty($this->propertyName))); }
/** * Return the assigned content dimensions of the node. * * @return array */ public function getDimensions() { return $this->nodeData->getDimensionValues(); }
/** * Adjusts the path of $shadowNodeData to $path, if needed/possible. * * If the $path is occupied in $targetWorkspace, the shadow is removed. * * @param NodeData $shadowNodeData * @param $path * @param Workspace $targetWorkspace * @param array $dimensionValues * @return void */ protected function adjustShadowNodePath(NodeData $shadowNodeData, $path, Workspace $targetWorkspace, array $dimensionValues) { $nodeOnSamePathInTargetWorkspace = $this->nodeDataRepository->findOneByPath($path, $targetWorkspace, $dimensionValues); if ($nodeOnSamePathInTargetWorkspace === null || $nodeOnSamePathInTargetWorkspace->getWorkspace() !== $targetWorkspace) { $shadowNodeData->setPath($path, false); return; } // A node exists in that path, so no shadow node is needed/possible. $this->nodeDataRepository->remove($shadowNodeData); }