/**
  * @param string|array $workspaceNames
  * @return boolean
  */
 public function isInWorkspace($workspaceNames)
 {
     if ($this->node === NULL) {
         return TRUE;
     }
     return in_array($this->node->getWorkspace()->getName(), $workspaceNames);
 }
 /**
  * Matches if the selected node belongs to one of the given $workspaceNames
  *
  * Example: isInWorkspace(['live', 'user-admin']) matches if the selected node is in one of the workspaces "user-admin" or "live"
  *
  * @param array $workspaceNames An array of workspace names, e.g. ["live", "user-admin"]
  * @return boolean TRUE if the selected node matches the $workspaceNames, otherwise FALSE
  */
 public function isInWorkspace($workspaceNames)
 {
     if ($this->node === null) {
         return true;
     }
     return in_array($this->node->getWorkspace()->getName(), $workspaceNames);
 }
 /**
  * Publishes the given node to the specified target workspace. If no workspace is specified, the base workspace
  * is assumed.
  *
  * If the given node is a Document or has ContentCollection child nodes, these nodes are published as well.
  *
  * @param NodeInterface $node
  * @param Workspace $targetWorkspace If not set the base workspace is assumed to be the publishing target
  * @return void
  * @api
  */
 public function publishNode(NodeInterface $node, Workspace $targetWorkspace = null)
 {
     if ($targetWorkspace === null) {
         $targetWorkspace = $node->getWorkspace()->getBaseWorkspace();
     }
     if (!$targetWorkspace instanceof Workspace) {
         return;
     }
     $nodes = array($node);
     $nodeType = $node->getNodeType();
     if ($nodeType->isOfType('TYPO3.Neos:Document') || $nodeType->hasConfiguration('childNodes')) {
         foreach ($node->getChildNodes('TYPO3.Neos:ContentCollection') as $contentCollectionNode) {
             array_push($nodes, $contentCollectionNode);
         }
     }
     $sourceWorkspace = $node->getWorkspace();
     $sourceWorkspace->publishNodes($nodes, $targetWorkspace);
     $this->emitNodePublished($node, $targetWorkspace);
 }
 /**
  * Publishes the given node to the specified targetWorkspace
  *
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node
  * @param string $targetWorkspaceName
  * @return void
  * @ExtDirect
  */
 public function publishNodeAction(\TYPO3\TYPO3CR\Domain\Model\NodeInterface $node, $targetWorkspaceName)
 {
     /**
      * TODO: The publishing pushes the same node twice, which causes the node to be published
      * already when it's processed the second time. This obviously leads to a problem for the
      * Workspace object which will (in the second time) try to publish a node in the live workspace
      * to the baseWorkspace of the live workspace (which does not exist).
      */
     if ($targetWorkspaceName === $node->getWorkspace()->getName()) {
         $this->view->assign('value', array('success' => TRUE));
         return;
     }
     $this->workspacesService->publishNode($node, $targetWorkspaceName);
     $this->view->assign('value', array('success' => TRUE));
 }
 /**
  * Publishes the given node to the target workspace.
  *
  * The specified workspace must be a base workspace of this workspace.
  *
  * @param NodeInterface $node The node to publish
  * @param Workspace $targetWorkspace The workspace to publish to
  * @return void
  * @api
  */
 public function publishNode(NodeInterface $node, Workspace $targetWorkspace)
 {
     if ($this->baseWorkspace === null) {
         return;
     }
     if ($node->getWorkspace() !== $this) {
         return;
     }
     $this->verifyPublishingTargetWorkspace($targetWorkspace);
     $this->emitBeforeNodePublishing($node, $targetWorkspace);
     if ($node->getPath() === '/') {
         return;
     }
     $targetNodeData = $this->findNodeDataInTargetWorkspace($node, $targetWorkspace);
     $matchingNodeVariantExistsInTargetWorkspace = $targetNodeData !== null && $targetNodeData->getDimensionValues() === $node->getDimensions();
     if ($matchingNodeVariantExistsInTargetWorkspace) {
         $this->replaceNodeData($node, $targetNodeData);
     } else {
         $this->moveNodeVariantToTargetWorkspace($node, $targetWorkspace);
     }
     $this->emitAfterNodePublishing($node, $targetWorkspace);
 }
    /**
     *
     *
     * @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'));
    }
 /**
  * Publishes the given node to the target workspace.
  *
  * The specified workspace must be a base workspace of this workspace.
  *
  * @param NodeInterface $node The node to publish
  * @param Workspace $targetWorkspace The workspace to publish to
  * @return void
  * @api
  */
 public function publishNode(NodeInterface $node, Workspace $targetWorkspace)
 {
     if ($this->baseWorkspace === null) {
         return;
     }
     if ($node->getWorkspace() !== $this) {
         return;
     }
     // Might happen if a node which has been published during an earlier call of publishNode() is attempted to
     // be published again:
     if ($node->getWorkspace() === $targetWorkspace) {
         return;
     }
     $this->verifyPublishingTargetWorkspace($targetWorkspace);
     $this->emitBeforeNodePublishing($node, $targetWorkspace);
     if ($node->getPath() === '/') {
         return;
     }
     $targetNodeData = $this->findNodeDataInTargetWorkspace($node, $targetWorkspace);
     $matchingNodeVariantExistsInTargetWorkspace = $targetNodeData !== null && $targetNodeData->getDimensionValues() === $node->getDimensions();
     if ($matchingNodeVariantExistsInTargetWorkspace) {
         $this->replaceNodeData($node, $targetNodeData);
     } else {
         $this->moveNodeVariantToTargetWorkspace($node, $targetWorkspace);
     }
     $this->emitAfterNodePublishing($node, $targetWorkspace);
 }
 /**
  * Collects metadata attributes used to allow editing of the node in the Neos backend.
  *
  * @param array $attributes
  * @param NodeInterface $node
  * @return array
  */
 protected function addGenericEditingMetadata(array $attributes, NodeInterface $node)
 {
     $attributes['typeof'] = 'typo3:' . $node->getNodeType()->getName();
     $attributes['about'] = $node->getContextPath();
     $attributes['data-node-_identifier'] = $node->getIdentifier();
     $attributes['data-node-__workspace-name'] = $node->getWorkspace()->getName();
     $attributes['data-node-__label'] = $node->getLabel();
     if ($node->getNodeType()->isOfType('TYPO3.Neos:ContentCollection')) {
         $attributes['rel'] = 'typo3:content-collection';
     }
     // these properties are needed together with the current NodeType to evaluate Node Type Constraints
     // TODO: this can probably be greatly cleaned up once we do not use CreateJS or VIE anymore.
     if ($node->getParent()) {
         $attributes['data-node-__parent-node-type'] = $node->getParent()->getNodeType()->getName();
     }
     if ($node->isAutoCreated()) {
         $attributes['data-node-_name'] = $node->getName();
         $attributes['data-node-_is-autocreated'] = 'true';
     }
     if ($node->getParent() && $node->getParent()->isAutoCreated()) {
         $attributes['data-node-_parent-is-autocreated'] = 'true';
         // we shall only add these properties if the parent is actually auto-created; as the Node-Type-Switcher in the UI relies on that.
         $attributes['data-node-__parent-node-name'] = $node->getParent()->getName();
         $attributes['data-node-__grandparent-node-type'] = $node->getParent()->getParent()->getNodeType()->getName();
     }
     return $attributes;
 }
 /**
  * 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);
     }
 }
示例#10
0
 /**
  * Updates the specified node. Returns the following data:
  * - the (possibly changed) workspace name of the node
  * - the URI of the closest folder node. If $node is a folder node (f.e. a Page), the own URI is returned.
  *   This is important to handle renamings of nodes correctly.
  *
  * Note: We do not call $nodeRepository->update() here, as TYPO3CR has a stateful API for now.
  *
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node
  * @return void
  * @ExtDirect
  */
 public function updateAction(\TYPO3\TYPO3CR\Domain\Model\NodeInterface $node)
 {
     $closestFolderNode = $node;
     while (!$closestFolderNode->getContentType()->isOfType('TYPO3.TYPO3CR:Folder')) {
         $closestFolderNode = $closestFolderNode->getParent();
     }
     $nextUri = $this->uriBuilder->reset()->setFormat('html')->setCreateAbsoluteUri(TRUE)->uriFor('show', array('node' => $closestFolderNode), 'Frontend\\Node', 'TYPO3.TYPO3', '');
     $this->view->assign('value', array('data' => array('workspaceNameOfNode' => $node->getWorkspace()->getName(), 'nextUri' => $nextUri), 'success' => TRUE));
 }
 /**
  * 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);
 }
 /**
  * Checks if the given node path can be used for the given node.
  *
  * @param string $nodePath
  * @param NodeInterface $node
  * @return boolean
  */
 public function nodePathAvailableForNode($nodePath, NodeInterface $node)
 {
     /** @var NodeData $existingNodeData */
     $existingNodeDataObjects = $this->nodeDataRepository->findByPathWithoutReduce($nodePath, $node->getWorkspace(), true);
     foreach ($existingNodeDataObjects as $existingNodeData) {
         if ($existingNodeData->getMovedTo() !== null && $existingNodeData->getMovedTo() === $node->getNodeData()) {
             return true;
         }
     }
     return !$this->nodePathExistsInAnyContext($nodePath);
 }
 /**
  * Retrieves the given node's corresponding node in the base workspace (that is, which would be overwritten if the
  * given node would be published)
  *
  * @param NodeInterface $modifiedNode
  * @return NodeInterface
  */
 protected function getOriginalNode(NodeInterface $modifiedNode)
 {
     $baseWorkspaceName = $modifiedNode->getWorkspace()->getBaseWorkspace()->getName();
     $contextProperties = $modifiedNode->getContext()->getProperties();
     $contextProperties['workspaceName'] = $baseWorkspaceName;
     $contentContext = $this->contextFactory->create($contextProperties);
     return $contentContext->getNodeByIdentifier($modifiedNode->getIdentifier());
 }
示例#14
0
 /**
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node
  * @param $targetWorkspaceName
  * @return void
  */
 public function publishNode(\TYPO3\TYPO3CR\Domain\Model\NodeInterface $node, $targetWorkspaceName = 'live')
 {
     $nodes = array($node);
     $contentType = $node->getContentType();
     if ($contentType->isOfType('TYPO3.Phoenix.ContentTypes:Page') || $contentType->hasStructure()) {
         foreach ($node->getChildNodes('TYPO3.Phoenix.ContentTypes:Section') as $sectionNode) {
             array_push($nodes, $sectionNode);
         }
     }
     $sourceWorkspace = $node->getWorkspace();
     $sourceWorkspace->publishNodes($nodes, $targetWorkspaceName);
 }
 /**
  * Wrap the $content identified by $node with the needed markup for
  * the backend.
  * $parameters can be used to further pass parameters to the content element.
  *
  * @param \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node
  * @param string $typoscriptPath
  * @param string $content
  * @param boolean $isPage
  * @return string
  */
 public function wrapContentObject(\TYPO3\TYPO3CR\Domain\Model\NodeInterface $node, $typoscriptPath, $content, $isPage = FALSE)
 {
     $contentType = $node->getContentType();
     $tagBuilder = new \TYPO3\Fluid\Core\ViewHelper\TagBuilder('div');
     $tagBuilder->forceClosingTag(TRUE);
     if (!$node->isRemoved()) {
         $tagBuilder->setContent($content);
     }
     if (!$isPage) {
         $cssClasses = array('t3-contentelement');
         $cssClasses[] = str_replace(array(':', '.'), '-', strtolower($contentType->getName()));
         if ($node->isHidden()) {
             $cssClasses[] = 't3-contentelement-hidden';
         }
         if ($node->isRemoved()) {
             $cssClasses[] = 't3-contentelement-removed';
         }
         $tagBuilder->addAttribute('class', implode(' ', $cssClasses));
         $tagBuilder->addAttribute('id', 'c' . $node->getIdentifier());
     }
     try {
         $this->accessDecisionManager->decideOnResource('TYPO3_TYPO3_Backend_BackendController');
     } catch (\TYPO3\FLOW3\Security\Exception\AccessDeniedException $e) {
         return $tagBuilder->render();
     }
     $tagBuilder->addAttribute('typeof', 'typo3:' . $contentType->getName());
     $tagBuilder->addAttribute('about', $node->getContextPath());
     $this->addScriptTag($tagBuilder, '__workspacename', $node->getWorkspace()->getName());
     $this->addScriptTag($tagBuilder, '_removed', $node->isRemoved() ? 'true' : 'false', 'boolean');
     $this->addScriptTag($tagBuilder, '_typoscriptPath', $typoscriptPath);
     foreach ($contentType->getProperties() as $propertyName => $propertyConfiguration) {
         $dataType = isset($propertyConfiguration['type']) ? $propertyConfiguration['type'] : 'string';
         if ($propertyName[0] === '_') {
             $propertyValue = \TYPO3\FLOW3\Reflection\ObjectAccess::getProperty($node, substr($propertyName, 1));
         } else {
             $propertyValue = $node->getProperty($propertyName);
         }
         // Serialize boolean values to String
         if (isset($propertyConfiguration['type']) && $propertyConfiguration['type'] === 'boolean') {
             $propertyValue = $propertyValue ? 'true' : 'false';
         }
         // Serialize date values to String
         if ($propertyValue !== NULL && isset($propertyConfiguration['type']) && $propertyConfiguration['type'] === 'date') {
             $propertyValue = $propertyValue->format('Y-m-d');
         }
         // Serialize objects to JSON strings
         if (is_object($propertyValue) && $propertyValue !== NULL && isset($propertyConfiguration['type']) && $this->objectManager->isRegistered($propertyConfiguration['type'])) {
             $gettableProperties = \TYPO3\FLOW3\Reflection\ObjectAccess::getGettableProperties($propertyValue);
             $convertedProperties = array();
             foreach ($gettableProperties as $key => $value) {
                 if (is_object($value)) {
                     $entityIdentifier = $this->persistenceManager->getIdentifierByObject($value);
                     if ($entityIdentifier !== NULL) {
                         $value = $entityIdentifier;
                     }
                 }
                 $convertedProperties[$key] = $value;
             }
             $propertyValue = json_encode($convertedProperties);
             $dataType = 'jsonEncoded';
         }
         $this->addScriptTag($tagBuilder, $propertyName, $propertyValue, $dataType);
     }
     if (!$isPage) {
         // add CSS classes
         $this->addScriptTag($tagBuilder, '__contenttype', $contentType->getName());
     } else {
         $tagBuilder->addAttribute('id', 't3-page-metainformation');
         $tagBuilder->addAttribute('data-__sitename', $this->nodeRepository->getContext()->getCurrentSite()->getName());
         $tagBuilder->addAttribute('data-__siteroot', sprintf('/sites/%s@%s', $this->nodeRepository->getContext()->getCurrentSite()->getNodeName(), $this->nodeRepository->getContext()->getWorkspace()->getName()));
     }
     return $tagBuilder->render();
 }