/**
  * @param NodeInterface $contextNode
  * @return QueryBuilder
  */
 public function query(NodeInterface $contextNode)
 {
     $this->where[] = "(__parentPath LIKE '%#" . $contextNode->getPath() . "#%' OR __path LIKE '" . $contextNode->getPath() . "')";
     $this->where[] = "(__workspace LIKE '%#" . $contextNode->getContext()->getWorkspace()->getName() . "#%')";
     $this->where[] = "(__dimensionshash LIKE '%#" . md5(json_encode($contextNode->getContext()->getDimensions())) . "#%')";
     $this->contextNode = $contextNode;
     return $this;
 }
 /**
  * Matches if the selected node is a *descendant* of the given node specified by $nodePathOrIdentifier
  *
  * Example: isDescendantNodeOf('/sites/some/path') matches for the nodes "/sites/some/path", "/sites/some/path/subnode" but not for "/sites/some/other"
  *
  * @param string $nodePathOrIdentifier The identifier or absolute path of the node to match
  * @return boolean TRUE if the given node matches otherwise false
  */
 public function isDescendantNodeOf($nodePathOrIdentifier)
 {
     $nodePath = $this->resolveNodePath($nodePathOrIdentifier);
     if (is_bool($nodePath)) {
         return $nodePath;
     }
     return substr($this->node->getPath() . '/', 0, strlen($nodePath)) === $nodePath;
 }
 /**
  * @param string $nodePathOrIdentifier
  * @return boolean
  */
 public function isDescendantNodeOf($nodePathOrIdentifier)
 {
     if ($this->node === NULL) {
         return TRUE;
     }
     if (preg_match(UuidValidator::PATTERN_MATCH_UUID, $nodePathOrIdentifier) === 1) {
         if ($this->node->getIdentifier() === $nodePathOrIdentifier) {
             return TRUE;
         }
         $node = $this->getNodeByIdentifier($nodePathOrIdentifier);
         if ($node === NULL) {
             return FALSE;
         }
         $nodePath = $node->getPath() . '/';
     } else {
         $nodePath = rtrim($nodePathOrIdentifier, '/') . '/';
     }
     return substr($this->node->getPath() . '/', 0, strlen($nodePath)) === $nodePath;
 }
 /**
  * Register a node change for a later cache flush. This method is triggered by a signal sent via TYPO3CR's Node
  * model or the Neos Publishing Service.
  *
  * @param NodeInterface $node The node which has changed in some way
  * @return void
  */
 public function registerNodeChange(NodeInterface $node)
 {
     $this->tagsToFlush[ContentCache::TAG_EVERYTHING] = 'which were tagged with "Everything".';
     $nodeTypesToFlush = $this->getAllImplementedNodeTypes($node->getNodeType());
     foreach ($nodeTypesToFlush as $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());
     $originalNode = $node;
     while ($node->getDepth() > 1) {
         $node = $node->getParent();
         // Workaround for issue #56566 in TYPO3.TYPO3CR
         if ($node === null) {
             break;
         }
         $tagName = 'DescendantOf_' . $node->getIdentifier();
         $this->tagsToFlush[$tagName] = sprintf('which were tagged with "%s" because node "%s" has changed.', $tagName, $originalNode->getPath());
     }
 }
 /**
  * Get the rootline from the current node up to the site node.
  *
  * @return array
  */
 protected function getCurrentNodeRootline()
 {
     if ($this->currentNodeRootline === null) {
         $nodeRootline = $this->currentNode->getContext()->getNodesOnPath($this->currentNode->getContext()->getCurrentSiteNode()->getPath(), $this->currentNode->getPath());
         $this->currentNodeRootline = array();
         foreach ($nodeRootline as $rootlineElement) {
             $this->currentNodeRootline[$this->getNodeLevelInSite($rootlineElement)] = $rootlineElement;
         }
     }
     return $this->currentNodeRootline;
 }
 /**
  * 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();
         }
     }
 }
 /**
  * Search all properties for given $term
  *
  * TODO: Implement a better search when Flow offer the possibility
  *
  * @param string $term
  * @param array $searchNodeTypes
  * @param Context $context
  * @param NodeInterface $startingPoint
  * @return array <\TYPO3\TYPO3CR\Domain\Model\NodeInterface>
  */
 public function findByProperties($term, array $searchNodeTypes, Context $context, NodeInterface $startingPoint = null)
 {
     if (strlen($term) === 0) {
         throw new \InvalidArgumentException('"term" cannot be empty: provide a term to search for.', 1421329285);
     }
     $searchResult = array();
     $nodeTypeFilter = implode(',', $searchNodeTypes);
     $nodeDataRecords = $this->nodeDataRepository->findByProperties($term, $nodeTypeFilter, $context->getWorkspace(), $context->getDimensions(), $startingPoint ? $startingPoint->getPath() : null);
     foreach ($nodeDataRecords as $nodeData) {
         $node = $this->nodeFactory->createFromNodeData($nodeData, $context);
         if ($node !== null) {
             $searchResult[$node->getPath()] = $node;
         }
     }
     return $searchResult;
 }
 /**
  * Check if the given node is already a collection, find collection by nodePath otherwise, throw exception
  * if no content collection could be found
  *
  * @param NodeInterface $node
  * @param string $nodePath
  * @return NodeInterface
  * @throws Exception
  */
 public function nearestContentCollection(NodeInterface $node, $nodePath)
 {
     $contentCollectionType = 'TYPO3.Neos:ContentCollection';
     if ($node->getNodeType()->isOfType($contentCollectionType)) {
         return $node;
     } else {
         if ((string) $nodePath === '') {
             throw new Exception(sprintf('No content collection of type %s could be found in the current node and no node path was provided. You might want to configure the nodePath property with a relative path to the content collection.', $contentCollectionType), 1409300545);
         }
         $subNode = $node->getNode($nodePath);
         if ($subNode !== null && $subNode->getNodeType()->isOfType($contentCollectionType)) {
             return $subNode;
         } else {
             throw new Exception(sprintf('No content collection of type %s could be found in the current node (%s) or at the path "%s". You might want to adjust your node type configuration and create the missing child node through the "flow node:repair --node-type %s" command.', $contentCollectionType, $node->getPath(), $nodePath, (string) $node->getNodeType()), 1389352984);
         }
     }
 }
 /**
  * Creates missing child nodes for the given node.
  *
  * @param NodeInterface $node
  * @return void
  */
 public function createChildNodes(NodeInterface $node)
 {
     $nodeType = $node->getNodeType();
     foreach ($nodeType->getAutoCreatedChildNodes() as $childNodeName => $childNodeType) {
         try {
             $node->createNode($childNodeName, $childNodeType);
         } catch (NodeExistsException $exception) {
             // If you have a node that has been marked as removed, but is needed again
             // the old node is recovered
             $childNodePath = NodePaths::addNodePathSegment($node->getPath(), $childNodeName);
             $contextProperties = $node->getContext()->getProperties();
             $contextProperties['removedContentShown'] = true;
             $context = $this->contextFactory->create($contextProperties);
             $childNode = $context->getNode($childNodePath);
             if ($childNode->isRemoved()) {
                 $childNode->setRemoved(false);
             }
         }
     }
 }
예제 #10
0
 /**
  * Returns a merged TypoScript object tree in the context of the given nodes
  *
  * The start node and end node mark the starting point and end point of the
  * path to take while searching for TypoScript configuration. The path of the
  * start node must be the base path of the end node's path.
  *
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $startNode Node marking the starting point
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $endNode Node marking the end point
  * @return array The merged object tree as of the given node
  */
 public function getMergedTypoScriptObjectTree(\TYPO3\TYPO3CR\Domain\Model\NodeInterface $startNode, \TYPO3\TYPO3CR\Domain\Model\NodeInterface $endNode)
 {
     $contentContext = $this->nodeRepository->getContext();
     $parentNodes = $contentContext->getNodesOnPath($startNode->getPath(), $endNode->getPath());
     if (!is_array($parentNodes)) {
         return NULL;
     }
     $siteResourcesPackageKey = $contentContext->getCurrentSite()->getSiteResourcesPackageKey();
     $typoScriptsPath = sprintf($this->typoScriptsPathPattern, $siteResourcesPackageKey);
     $mergedTypoScriptCode = $this->readExternalTypoScriptFile('resource://TYPO3.TYPO3/Private/DefaultTypoScript/All.ts2');
     $mergedTypoScriptCode .= $this->readExternalTypoScriptFile($typoScriptsPath . '/Library/Root.ts2');
     $currentTypoScriptPath = $typoScriptsPath . '/Nodes';
     foreach ($parentNodes as $node) {
         $nodeName = $node->getName();
         $mergedTypoScriptCode .= Files::getFileContents($this->getMixedCasedPathAndFilename($currentTypoScriptPath . '/' . $nodeName . '.ts2')) . chr(10);
         $currentTypoScriptPath .= '/' . basename($this->getMixedCasedPathAndFilename($currentTypoScriptPath . '/' . $nodeName));
         $typoScriptNodes = $node->getChildNodes('TYPO3.TYPO3:TypoScript');
         foreach ($typoScriptNodes as $typoScriptNode) {
             $mergedTypoScriptCode .= $typoScriptNode->getProperty('sourceCode') . chr(10);
         }
     }
     return $this->typoScriptParser->parse($mergedTypoScriptCode, $typoScriptsPath);
 }
 /**
  * Returns an array with the data needed by for example the Hallo and Aloha
  * link plugins to represent the passed Node instance.
  *
  * @param NodeInterface $node
  * @return array
  */
 protected function processNodeForEditorPlugins(NodeInterface $node)
 {
     return array('id' => $node->getPath(), 'name' => $node->getLabel(), 'url' => $this->uriBuilder->uriFor('show', array('node' => $node), 'Frontend\\Node', 'TYPO3.Neos'), 'type' => 'neos/internal-link');
 }
 /**
  * Adds the given node to the cache for the given identifier. The node
  * will also be added with is's path.
  *
  * @param string $identifier
  * @param NodeInterface $node
  * @return void
  */
 public function setByIdentifier($identifier, NodeInterface $node = null)
 {
     $this->nodesByIdentifier[$identifier] = $node;
     if ($node !== null) {
         $this->nodesByPath[$node->getPath()] = $node;
     }
 }
 protected function getACLPropertiesForNode(NodeInterface $node)
 {
     $properties = ['nodeIdentifier' => $node->getIdentifier(), 'nodePath' => $node->getPath(), 'nodeLabel' => $node->getLabel(), 'nodeType' => $node->getNodeType()->getName(), 'nodeLevel' => $node->getDepth()];
     return $properties;
 }
예제 #14
0
 /**
  * Internal method to do the actual copying.
  *
  * For behavior of the $detachedCopy parameter, see method Node::createRecursiveCopy().
  *
  * @param NodeInterface $referenceNode
  * @param $nodeName
  * @param boolean $detachedCopy
  * @return NodeInterface
  * @throws NodeConstraintException
  * @throws NodeExistsException
  */
 protected function copyIntoInternal(NodeInterface $referenceNode, $nodeName, $detachedCopy)
 {
     if ($referenceNode->getNode($nodeName) !== null) {
         throw new NodeExistsException('Node with path "' . $referenceNode->getPath() . '/' . $nodeName . '" already exists.', 1292503467);
     }
     // On copy we basically re-recreate an existing node on a new location. As we skip the constraints check on
     // node creation we should do the same while writing the node on the new location.
     if (!$referenceNode->willChildNodeBeAutoCreated($nodeName) && !$referenceNode->isNodeTypeAllowedAsChildNode($this->getNodeType())) {
         throw new NodeConstraintException(sprintf('Cannot copy "%s" into "%s" due to node type constraints.', $this->__toString(), $referenceNode->__toString()), 1404648177);
     }
     $copiedNode = $this->createRecursiveCopy($referenceNode, $nodeName, $detachedCopy);
     $this->context->getFirstLevelNodeCache()->flush();
     $this->emitNodeAdded($copiedNode);
     return $copiedNode;
 }
    /**
     *
     *
     * @param NodeInterface $node
     * @param array $fulltextIndexOfNode
     * @param string $targetWorkspaceName
     * @return void
     */
    protected function updateFulltext(NodeInterface $node, array $fulltextIndexOfNode, $targetWorkspaceName = NULL)
    {
        if ($targetWorkspaceName !== NULL && $targetWorkspaceName !== 'live' || $node->getWorkspace()->getName() !== 'live' || count($fulltextIndexOfNode) === 0) {
            return;
        }
        $closestFulltextNode = $node;
        while (!$this->isFulltextRoot($closestFulltextNode)) {
            $closestFulltextNode = $closestFulltextNode->getParent();
            if ($closestFulltextNode === NULL) {
                // root of hierarchy, no fulltext root found anymore, abort silently...
                $this->logger->log('No fulltext root found for ' . $node->getPath(), LOG_WARNING);
                return;
            }
        }
        $closestFulltextNodeContextPath = str_replace($closestFulltextNode->getContext()->getWorkspace()->getName(), 'live', $closestFulltextNode->getContextPath());
        $closestFulltextNodeContextPathHash = sha1($closestFulltextNodeContextPath);
        $this->currentBulkRequest[] = array(array('update' => array('_type' => NodeTypeMappingBuilder::convertNodeTypeNameToMappingName($closestFulltextNode->getNodeType()->getName()), '_id' => $closestFulltextNodeContextPathHash)), array('script' => '
					if (!ctx._source.containsKey("__fulltextParts")) {
						ctx._source.__fulltextParts = new LinkedHashMap();
					}
					ctx._source.__fulltextParts[identifier] = fulltext;
					ctx._source.__fulltext = new LinkedHashMap();

					Iterator<LinkedHashMap.Entry<String, LinkedHashMap>> fulltextByNode = ctx._source.__fulltextParts.entrySet().iterator();
					for (fulltextByNode; fulltextByNode.hasNext();) {
						Iterator<LinkedHashMap.Entry<String, String>> elementIterator = fulltextByNode.next().getValue().entrySet().iterator();
						for (elementIterator; elementIterator.hasNext();) {
							Map.Entry<String, String> element = elementIterator.next();
							String value;

							if (ctx._source.__fulltext.containsKey(element.key)) {
								value = ctx._source.__fulltext[element.key] + " " + element.value.trim();
							} else {
								value = element.value.trim();
							}

							ctx._source.__fulltext[element.key] = value;
						}
					}
				', 'params' => array('identifier' => $node->getIdentifier(), 'fulltext' => $fulltextIndexOfNode), 'upsert' => array('__fulltext' => $fulltextIndexOfNode, '__fulltextParts' => array($node->getIdentifier() => $fulltextIndexOfNode)), 'lang' => 'groovy'));
    }
 /**
  * Replace the node data of a node instance with a given target node data
  *
  * The node data of the node that is published will be removed and the existing node data inside the target
  * workspace is updated to the changes and will be injected into the node instance. If the node was marked as
  * removed, both node data are removed.
  *
  * @param NodeInterface $node The node instance with node data to be published
  * @param NodeData $targetNodeData The existing node data in the target workspace
  * @return void
  */
 protected function replaceNodeData(NodeInterface $node, NodeData $targetNodeData)
 {
     $sourceNodeData = $node->getNodeData();
     $nodeWasMoved = $this->handleShadowNodeData($sourceNodeData, $targetNodeData->getWorkspace(), $targetNodeData);
     // Technically this shouldn't be needed but due to doctrines behavior we need it.
     if ($sourceNodeData->isRemoved() && $targetNodeData->getWorkspace()->getBaseWorkspace() === null) {
         $this->nodeDataRepository->remove($targetNodeData);
         $this->nodeDataRepository->remove($sourceNodeData);
         return;
     }
     $targetNodeData->similarize($sourceNodeData);
     $targetNodeData->setLastPublicationDateTime($this->now);
     if ($nodeWasMoved) {
         // TODO: This seems wrong and introduces a publish order between nodes. We should always set the path.
         $targetNodeData->setPath($node->getPath(), false);
     }
     $node->setNodeData($targetNodeData);
     $this->nodeService->cleanUpProperties($node);
     $targetNodeData->setRemoved($sourceNodeData->isRemoved());
     $this->nodeDataRepository->remove($sourceNodeData);
 }
 /**
  * Sets the starting point for this query. Search result should only contain nodes that
  * match the context of the given node and have it as parent node in their rootline.
  *
  * @param NodeInterface $contextNode
  * @return QueryBuilderInterface
  * @api
  */
 public function query(NodeInterface $contextNode)
 {
     // on indexing, the __parentPath is tokenized to contain ALL parent path parts,
     // e.g. /foo, /foo/bar/, /foo/bar/baz; to speed up matching.. That's why we use a simple "term" filter here.
     // http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-filter.html
     $this->queryFilter('term', ['__parentPath' => $contextNode->getPath()]);
     //
     // http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-terms-filter.html
     $this->queryFilter('terms', ['__workspace' => array_unique(['live', $contextNode->getContext()->getWorkspace()->getName()])]);
     // match exact dimension values for each dimension, this works because the indexing flattens the node variants for all dimension preset combinations
     $dimensionCombinations = $contextNode->getContext()->getDimensions();
     if (is_array($dimensionCombinations)) {
         $this->queryFilter('term', ['__dimensionCombinationHash' => md5(json_encode($dimensionCombinations))]);
     }
     $this->contextNode = $contextNode;
     return $this;
 }
 /**
  * Traverses through the tree starting at the given root node and sets the uriPathSegment property derived from
  * the node label.
  *
  * @param NodeInterface $node The node where the traversal starts
  * @param boolean $dryRun
  * @return void
  */
 protected function generateUriPathSegmentsForNode(NodeInterface $node, $dryRun)
 {
     if ((string) $node->getProperty('uriPathSegment') === '') {
         $name = $node->getLabel() ?: $node->getName();
         $uriPathSegment = Utility::renderValidNodeName($name);
         if ($dryRun === FALSE) {
             $node->setProperty('uriPathSegment', $uriPathSegment);
             $this->output->outputLine('Added missing URI path segment for "%s" (%s) => %s', array($node->getPath(), $name, $uriPathSegment));
         } else {
             $this->output->outputLine('Found missing URI path segment for "%s" (%s) => %s', array($node->getPath(), $name, $uriPathSegment));
         }
     }
     foreach ($node->getChildNodes('TYPO3.Neos:Document') as $childNode) {
         $this->generateUriPathSegmentsForNode($childNode, $dryRun);
     }
 }
 /**
  * @param array $parentNodes the parent nodes
  * @param NodeInterface $until
  * @return array
  */
 protected function getNodesUntil($parentNodes, NodeInterface $until)
 {
     $count = count($parentNodes) - 1;
     for ($i = $count; $i >= 0; $i--) {
         if ($parentNodes[$i]->getPath() === $until->getPath()) {
             unset($parentNodes[$i]);
             return array_values($parentNodes);
         } else {
             unset($parentNodes[$i]);
         }
     }
     return array_values($parentNodes);
 }
 /**
  * Method which does the actual work of discarding, includes a protection against endless recursions and
  * multiple discarding of the same node.
  *
  * @param NodeInterface $node The node to discard
  * @param array &$alreadyDiscardedNodeIdentifiers List of node identifiers which already have been discarded during one discardNode() run
  * @return void
  * @throws \TYPO3\TYPO3CR\Exception\WorkspaceException
  */
 protected function doDiscardNode(NodeInterface $node, array &$alreadyDiscardedNodeIdentifiers = [])
 {
     if ($node->getWorkspace()->getBaseWorkspace() === null) {
         throw new WorkspaceException('Nodes in a in a workspace without a base workspace cannot be discarded.', 1395841899);
     }
     if ($node->getPath() === '/') {
         return;
     }
     if (array_search($node->getIdentifier(), $alreadyDiscardedNodeIdentifiers) !== false) {
         return;
     }
     $alreadyDiscardedNodeIdentifiers[] = $node->getIdentifier();
     $possibleShadowNodeData = $this->nodeDataRepository->findOneByMovedTo($node->getNodeData());
     if ($possibleShadowNodeData instanceof NodeData) {
         if ($possibleShadowNodeData->getMovedTo() !== null) {
             $parentBasePath = $node->getPath();
             $affectedChildNodeDataInSameWorkspace = $this->nodeDataRepository->findByParentAndNodeType($parentBasePath, null, $node->getWorkspace(), null, false, true);
             foreach ($affectedChildNodeDataInSameWorkspace as $affectedChildNodeData) {
                 /** @var NodeData $affectedChildNodeData */
                 $affectedChildNode = $this->nodeFactory->createFromNodeData($affectedChildNodeData, $node->getContext());
                 $this->doDiscardNode($affectedChildNode, $alreadyDiscardedNodeIdentifiers);
             }
         }
         $this->nodeDataRepository->remove($possibleShadowNodeData);
     }
     $this->nodeDataRepository->remove($node);
     $this->emitNodeDiscarded($node);
 }
 /**
  * @param string $externalIdentifier
  * @param NodeInterface $node
  * @return ProcessedNodeDefinition
  */
 public static function createFromNode($externalIdentifier, NodeInterface $node)
 {
     return new ProcessedNodeDefinition($node->getIdentifier(), $node->getPath(), $externalIdentifier);
 }
예제 #22
0
 /**
  * Returns an array with the data needed by for example the Hallo and Aloha
  * link plugins to represent the passed NodeInterface instance.
  *
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node
  * @return array
  */
 protected function processNodeForEditorPlugins(\TYPO3\TYPO3CR\Domain\Model\NodeInterface $node)
 {
     return array('id' => $node->getPath(), 'name' => $node->getLabel(), 'url' => $this->uriBuilder->setLinkProtectionEnabled(FALSE)->uriFor('show', array('node' => $node), 'Frontend\\Node', 'TYPO3.TYPO3', ''), 'type' => 'phoenix/internal-link');
 }
 /**
  * Creates a new node beneath $parent
  *
  * @param  NodeInterface $parent
  * @return NodeInterface
  */
 protected function createNode(NodeInterface $parent)
 {
     $nodeType = $this->getNodeType();
     $initialProperties = $this->getInitialProperties();
     $name = $this->getName() ?: $this->nodeService->generateUniqueNodeName($parent->getPath());
     //
     // If we're about to create a document, check for the presence of the uriPathSegment property first
     // and create it, if it's missing
     //
     if ($nodeType->isOfType('TYPO3.Neos:Document') && !isset($initialProperties['uriPathSegment'])) {
         if (!isset($initialProperties['title'])) {
             throw new \IllegalArgumentException('You must either provide a title or a uriPathSegment in order to create a document.', 1452103891);
         }
         $initialProperties['uriPathSegment'] = NodeUtility::renderValidNodeName($initialProperties['title']);
     }
     $node = $parent->createNode($name, $nodeType);
     foreach ($initialProperties as $key => $value) {
         $node->setProperty($key, $value);
     }
     return $node;
 }
 /**
  * Rebase the current users personal workspace onto the given $targetWorkspace and then
  * redirects to the $targetNode in the content module.
  *
  * @param NodeInterface $targetNode
  * @param Workspace $targetWorkspace
  * @return void
  */
 public function rebaseAndRedirectAction(NodeInterface $targetNode, Workspace $targetWorkspace)
 {
     $currentAccount = $this->securityContext->getAccount();
     $personalWorkspace = $this->workspaceRepository->findOneByName('user-' . $currentAccount->getAccountIdentifier());
     /** @var Workspace $personalWorkspace */
     if ($this->publishingService->getUnpublishedNodesCount($personalWorkspace) > 0) {
         $message = $this->translator->translateById('workspaces.cantEditBecauseWorkspaceContainsChanges', [], null, null, 'Modules', 'TYPO3.Neos');
         $this->addFlashMessage($message, '', Message::SEVERITY_WARNING, [], 1437833387);
         $this->redirect('show', null, null, ['workspace' => $targetWorkspace]);
     }
     $personalWorkspace->setBaseWorkspace($targetWorkspace);
     $this->workspaceRepository->update($personalWorkspace);
     $contextProperties = $targetNode->getContext()->getProperties();
     $contextProperties['workspaceName'] = $personalWorkspace->getName();
     $context = $this->contextFactory->create($contextProperties);
     $mainRequest = $this->controllerContext->getRequest()->getMainRequest();
     /** @var ActionRequest $mainRequest */
     $this->uriBuilder->setRequest($mainRequest);
     $this->redirect('show', 'Frontend\\Node', 'TYPO3.Neos', ['node' => $context->getNode($targetNode->getPath())]);
 }
 /**
  * Renders a request path based on the "uriPathSegment" properties of the nodes leading to the given node.
  *
  * @param NodeInterface $siteNode Top level node, corresponds to the top level of the request path
  * @param NodeInterface $node The node where the generated path should lead to
  * @return string A relative request path
  * @throws Exception\MissingNodePropertyException if the given node doesn't have a "uriPathSegment" property set
  */
 protected function getRequestPathByNode(NodeInterface $siteNode, NodeInterface $node)
 {
     if ($siteNode === $node) {
         return '';
     }
     $requestPathSegments = array();
     while ($siteNode !== $node && $node instanceof NodeInterface) {
         if (!$node->hasProperty('uriPathSegment')) {
             throw new Exception\MissingNodePropertyException(sprintf('Missing "uriPathSegment" property for node "%s". Nodes can be migrated with the "flow node:repair" command.', $node->getPath()), 1415020326);
         }
         $pathSegment = $node->getProperty('uriPathSegment');
         $requestPathSegments[] = $pathSegment;
         $node = $node->getParent();
     }
     return implode('/', array_reverse($requestPathSegments));
 }
 /**
  * returns a specific view node of an master plugin
  * or NULL if it does not exist
  *
  * @param NodeInterface $node
  * @param string $viewName
  * @return NodeInterface
  */
 public function getPluginViewNodeByMasterPlugin(NodeInterface $node, $viewName)
 {
     /** @var $context ContentContext */
     $context = $node->getContext();
     foreach ($this->getNodes('TYPO3.Neos:PluginView', $context) as $pluginViewNode) {
         /** @var \TYPO3\TYPO3CR\Domain\Model\NodeInterface $pluginViewNode */
         if ($pluginViewNode->isRemoved()) {
             continue;
         }
         if ($pluginViewNode->getProperty('plugin') === $node->getPath() && $pluginViewNode->getProperty('view') === $viewName) {
             return $pluginViewNode;
         }
     }
     return null;
 }
예제 #27
0
 /**
  * Copies this node into the given node
  *
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $referenceNode
  * @param string $nodeName
  * @return \TYPO3\TYPO3CR\Domain\Model\NodeInterface
  * @throws NodeExistsException
  * @api
  */
 public function copyInto(NodeInterface $referenceNode, $nodeName)
 {
     if ($referenceNode->getNode($nodeName) !== NULL) {
         throw new NodeExistsException('Node with path "' . $referenceNode->getPath() . '/' . $nodeName . '" already exists.', 1292503467);
     }
     if (!$this->isNodeDataMatchingContext()) {
         $this->materializeNodeData();
     }
     $copiedNode = $this->createRecursiveCopy($referenceNode, $nodeName);
     $this->context->getFirstLevelNodeCache()->flush();
     $this->emitNodeAdded($copiedNode);
     return $copiedNode;
 }
예제 #28
0
 /**
  * Creates a new node beneath $parent
  *
  * @param  NodeInterface $parent
  * @return NodeInterface
  */
 protected function createNode(NodeInterface $parent)
 {
     $nodeType = $this->getNodeType();
     $name = $this->getName() ?: $this->nodeService->generateUniqueNodeName($parent->getPath());
     $node = $parent->createNode($name, $nodeType);
     $this->applyNodeCreationHandlers($node);
     $this->persistenceManager->persistAll();
     if ($nodeType->isOfType('TYPO3.Neos:Content') && ($this->getParentDomAddress() || $this->getSiblingDomAddress())) {
         if ($parent->getNodeType()->isOfType('TYPO3.Neos:ContentCollection')) {
             $renderContentOutOfBand = new RenderContentOutOfBand();
             $renderContentOutOfBand->setNode($node);
             $renderContentOutOfBand->setParentDomAddress($this->getParentDomAddress());
             $renderContentOutOfBand->setSiblingDomAddress($this->getSiblingDomAddress());
             $renderContentOutOfBand->setMode($this->getMode());
             $this->feedbackCollection->add($renderContentOutOfBand);
         } else {
             $flowQuery = new FlowQuery(array($node));
             $closestDocument = $flowQuery->closest('[instanceof TYPO3.Neos:Document]')->get(0);
             $reloadDocument = new ReloadDocument();
             $reloadDocument->setDocument($closestDocument);
             $this->feedbackCollection->add($reloadDocument);
         }
     }
     $updateNodeInfo = new UpdateNodeInfo();
     $updateNodeInfo->setNode($node);
     $this->feedbackCollection->add($updateNodeInfo);
     return $node;
 }
 /**
  * Replace the node data of a node instance with a given target node data
  *
  * The node data of the node that is published will be removed and the existing node data inside the target
  * workspace is updated to the changes and will be injected into the node instance. If the node was marked as
  * removed, both node data are removed.
  *
  * @param NodeInterface $node The node instance with node data to be published
  * @param NodeData $targetNodeData The existing node data in the target workspace
  * @return void
  */
 protected function replaceNodeData(NodeInterface $node, NodeData $targetNodeData)
 {
     $sourceNodeData = $node->getNodeData();
     $nodeWasMoved = false;
     $movedShadowNodeData = $this->nodeDataRepository->findOneByMovedTo($sourceNodeData);
     if ($movedShadowNodeData instanceof NodeData) {
         $nodeWasMoved = true;
         if ($movedShadowNodeData->isRemoved()) {
             $this->nodeDataRepository->remove($movedShadowNodeData);
         }
     }
     if ($node->isRemoved() === true) {
         $this->nodeDataRepository->remove($targetNodeData);
     } else {
         $targetNodeData->similarize($node->getNodeData());
         if ($nodeWasMoved) {
             $targetNodeData->setPath($node->getPath(), false);
         }
         $targetNodeData->setLastPublicationDateTime($this->now);
         $node->setNodeData($targetNodeData);
         $this->nodeService->cleanUpProperties($node);
     }
     $this->nodeDataRepository->remove($sourceNodeData);
 }
 /**
  * Discards the given node.
  *
  * @param NodeInterface $node
  * @return void
  * @throws \TYPO3\TYPO3CR\Exception\WorkspaceException
  * @api
  */
 public function discardNode(NodeInterface $node)
 {
     if ($node->getWorkspace()->getBaseWorkspace() === NULL) {
         throw new WorkspaceException('Nodes in a in a workspace without a base workspace cannot be discarded.', 1395841899);
     }
     $possibleShadowNodeData = $this->nodeDataRepository->findOneByMovedTo($node->getNodeData());
     if ($possibleShadowNodeData !== NULL) {
         $this->nodeDataRepository->remove($possibleShadowNodeData);
     }
     if ($node->getPath() !== '/') {
         $this->nodeDataRepository->remove($node);
         $this->emitNodeDiscarded($node);
     }
 }