Return the context of the node
public getContext ( ) : |
||
Результат |
/** * Shows the specified node and takes visibility and access restrictions into * account. * * @param NodeInterface $node * @return string View output for the specified node * @Flow\SkipCsrfProtection We need to skip CSRF protection here because this action could be called with unsafe requests from widgets or plugins that are rendered on the node - For those the CSRF token is validated on the sub-request, so it is safe to be skipped here * @Flow\IgnoreValidation("node") * @throws NodeNotFoundException */ public function showAction(NodeInterface $node = null) { if ($node === null) { throw new NodeNotFoundException('The requested node does not exist or isn\'t accessible to the current user', 1430218623); } $inBackend = $node->getContext()->isInBackend(); if ($node->getNodeType()->isOfType('Neos.Neos:Shortcut') && !$inBackend) { $this->handleShortcutNode($node); } $this->view->assign('value', $node); if ($inBackend) { $this->overrideViewVariablesFromInternalArguments(); /** @var UserInterfaceMode $renderingMode */ $renderingMode = $node->getContext()->getCurrentRenderingMode(); $this->response->setHeader('Cache-Control', 'no-cache'); if ($renderingMode !== null) { // Deprecated TypoScript context variable from version 2.0. $this->view->assign('editPreviewMode', $renderingMode->getTypoScriptPath()); } if (!$this->view->canRenderWithNodeAndPath()) { $this->view->setTypoScriptPath('rawContent'); } } if ($this->session->isStarted() && $inBackend) { $this->session->putData('lastVisitedNode', $node->getContextPath()); } }
/** * Generates a URI path segment for a given node taking it's language dimension into account * * @param NodeInterface $node Optional node to determine language dimension * @param string $text Optional text * @return string */ public function generateUriPathSegment(NodeInterface $node = null, $text = null) { if ($node) { $text = $text ?: $node->getLabel() ?: $node->getName(); $dimensions = $node->getContext()->getDimensions(); if (array_key_exists('language', $dimensions) && $dimensions['language'] !== array()) { $locale = new Locale($dimensions['language'][0]); $language = $locale->getLanguage(); } } elseif (strlen($text) === 0) { throw new Exception('Given text was empty.', 1457591815); } $text = $this->transliterationService->transliterate($text, isset($language) ? $language : null); return Transliterator::urlize($text); }
/** * Wrap the $content identified by $node with the needed markup for the backend. * * @param NodeInterface $node * @param string $property * @param string $content * @return string */ public function wrapContentProperty(NodeInterface $node, $property, $content) { /** @var $contentContext ContentContext */ $contentContext = $node->getContext(); if ($contentContext->getWorkspaceName() === 'live' || !$this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess')) { return $content; } if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) { return $content; } $attributes = array(); $attributes['class'] = 'neos-inline-editable'; $attributes['property'] = 'typo3:' . $property; $attributes['data-neos-node-type'] = $node->getNodeType()->getName(); return $this->htmlAugmenter->addAttributes($content, $attributes, 'span'); }
/** * Matches if the currently-selected preset in the passed $dimensionName is one of $presets. * * Example: isInDimensionPreset('language', 'de') checks whether the currently-selected language * preset (in the Neos backend) is "de". * * Implementation Note: We deliberately work on the Dimension Preset Name, and not on the * dimension values itself; as the preset is user-visible and the actual dimension-values * for a preset are just implementation details. * * @param string $dimensionName * @param string|array $presets * @return boolean */ public function isInDimensionPreset($dimensionName, $presets) { if ($this->node === null) { return true; } $dimensionValues = $this->node->getContext()->getDimensions(); if (!isset($dimensionValues[$dimensionName])) { return false; } $preset = $this->contentDimensionPresetSource->findPresetByDimensionValues($dimensionName, $dimensionValues[$dimensionName]); if ($preset === null) { return false; } $presetIdentifier = $preset['identifier']; if (!is_array($presets)) { $presets = array($presets); } return in_array($presetIdentifier, $presets); }
/** * Returns the rendered content of this plugin * * @return string The rendered content as a string * @throws StopActionException */ public function evaluate() { $currentContext = $this->tsRuntime->getCurrentContext(); $this->pluginViewNode = $currentContext['node']; /** @var $parentResponse Response */ $parentResponse = $this->tsRuntime->getControllerContext()->getResponse(); $pluginResponse = new Response($parentResponse); $pluginRequest = $this->buildPluginRequest(); if ($pluginRequest->getControllerObjectName() === '') { $message = 'Master View not selected'; if ($this->pluginViewNode->getProperty('plugin')) { $message = 'Plugin View not selected'; } if ($this->pluginViewNode->getProperty('view')) { $message = 'Master View or Plugin View not found'; } return $this->pluginViewNode->getContext()->getWorkspaceName() !== 'live' || $this->objectManager->getContext()->isDevelopment() ? '<p>' . $message . '</p>' : '<!-- ' . $message . '-->'; } $this->dispatcher->dispatch($pluginRequest, $pluginResponse); return $pluginResponse->getContent(); }
/** * Renders the URI to a given node instance or -path. * * @param ControllerContext $controllerContext * @param mixed $node A node object or a string node path, if a relative path is provided the baseNode argument is required * @param NodeInterface $baseNode * @param string $format Format to use for the URL, for example "html" or "json" * @param boolean $absolute If set, an absolute URI is rendered * @param array $arguments Additional arguments to be passed to the UriBuilder (for example pagination parameters) * @param string $section * @param boolean $addQueryString If set, the current query parameters will be kept in the URI * @param array $argumentsToBeExcludedFromQueryString arguments to be removed from the URI. Only active if $addQueryString = TRUE * @param boolean $resolveShortcuts INTERNAL Parameter - if FALSE, shortcuts are not redirected to their target. Only needed on rare backend occasions when we want to link to the shortcut itself. * @return string The rendered URI * @throws \InvalidArgumentException if the given node/baseNode is not valid * @throws NeosException if no URI could be resolved for the given node */ public function createNodeUri(ControllerContext $controllerContext, $node = null, NodeInterface $baseNode = null, $format = null, $absolute = false, array $arguments = array(), $section = '', $addQueryString = false, array $argumentsToBeExcludedFromQueryString = array(), $resolveShortcuts = true) { $this->lastLinkedNode = null; if (!($node instanceof NodeInterface || is_string($node) || $baseNode instanceof NodeInterface)) { throw new \InvalidArgumentException('Expected an instance of NodeInterface or a string for the node argument, or alternatively a baseNode argument.', 1373101025); } if (is_string($node)) { $nodeString = $node; if ($nodeString === '') { throw new NeosException(sprintf('Empty strings can not be resolved to nodes.', $nodeString), 1415709942); } preg_match(NodeInterface::MATCH_PATTERN_CONTEXTPATH, $nodeString, $matches); if (isset($matches['WorkspaceName']) && $matches['WorkspaceName'] !== '') { $node = $this->propertyMapper->convert($nodeString, NodeInterface::class); } else { if ($baseNode === null) { throw new NeosException('The baseNode argument is required for linking to nodes with a relative path.', 1407879905); } /** @var ContentContext $contentContext */ $contentContext = $baseNode->getContext(); $normalizedPath = $this->nodeService->normalizePath($nodeString, $baseNode->getPath(), $contentContext->getCurrentSiteNode()->getPath()); $node = $contentContext->getNode($normalizedPath); } if (!$node instanceof NodeInterface) { throw new NeosException(sprintf('The string "%s" could not be resolved to an existing node.', $nodeString), 1415709674); } } elseif (!$node instanceof NodeInterface) { $node = $baseNode; } if (!$node instanceof NodeInterface) { throw new NeosException(sprintf('Node must be an instance of NodeInterface or string, given "%s".', gettype($node)), 1414772029); } $this->lastLinkedNode = $node; if ($resolveShortcuts === true) { $resolvedNode = $this->nodeShortcutResolver->resolveShortcutTarget($node); } else { // this case is only relevant in extremely rare occasions in the Neos Backend, when we want to generate // a link towards the *shortcut itself*, and not to its target. $resolvedNode = $node; } if (is_string($resolvedNode)) { return $resolvedNode; } if (!$resolvedNode instanceof NodeInterface) { throw new NeosException(sprintf('Could not resolve shortcut target for node "%s"', $node->getPath()), 1414771137); } /** @var ActionRequest $request */ $request = $controllerContext->getRequest()->getMainRequest(); $uriBuilder = clone $controllerContext->getUriBuilder(); $uriBuilder->setRequest($request); $uri = $uriBuilder->reset()->setSection($section)->setArguments($arguments)->setAddQueryString($addQueryString)->setArgumentsToBeExcludedFromQueryString($argumentsToBeExcludedFromQueryString)->setFormat($format ?: $request->getFormat())->uriFor('show', array('node' => $resolvedNode), 'Frontend\\Node', 'Neos.Neos'); $siteNode = $resolvedNode->getContext()->getCurrentSiteNode(); if (NodePaths::isSubPathOf($siteNode->getPath(), $resolvedNode->getPath())) { /** @var Site $site */ $site = $resolvedNode->getContext()->getCurrentSite(); } else { $nodePath = NodePaths::getRelativePathBetween(SiteService::SITES_ROOT_PATH, $resolvedNode->getPath()); list($siteNodeName) = explode('/', $nodePath); $site = $this->siteRepository->findOneByNodeName($siteNodeName); } if ($site->hasActiveDomains()) { $requestUriHost = $request->getHttpRequest()->getBaseUri()->getHost(); $activeHostPatterns = $site->getActiveDomains()->map(function ($domain) { return $domain->getHostPattern(); })->toArray(); if (!in_array($requestUriHost, $activeHostPatterns, true)) { $uri = $this->createSiteUri($controllerContext, $site) . '/' . ltrim($uri, '/'); } elseif ($absolute === true) { $uri = $request->getHttpRequest()->getBaseUri() . ltrim($uri, '/'); } } elseif ($absolute === true) { $uri = $request->getHttpRequest()->getBaseUri() . ltrim($uri, '/'); } return $uri; }
/** * Node Level relative to site root node. * 0 = Site root node * * @param NodeInterface $node * @return integer */ protected function getNodeLevelInSite(NodeInterface $node) { $siteNode = $this->currentNode->getContext()->getCurrentSiteNode(); return $node->getDepth() - $siteNode->getDepth(); }
/** * 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(['Neos.Neos:PluginView'], $context) as $pluginViewNode) { /** @var NodeInterface $pluginViewNode */ if ($pluginViewNode->isRemoved()) { continue; } if ($pluginViewNode->getProperty('plugin') === $node->getIdentifier() && $pluginViewNode->getProperty('view') === $viewName) { return $pluginViewNode; } } return null; }
/** * Returns a merged TypoScript object tree in the context of the given nodes * * @param \Neos\ContentRepository\Domain\Model\NodeInterface $startNode Node marking the starting point * @return array The merged object tree as of the given node * @throws \Neos\Neos\Domain\Exception */ public function getMergedTypoScriptObjectTree(NodeInterface $startNode) { $contentContext = $startNode->getContext(); $siteResourcesPackageKey = $contentContext->getCurrentSite()->getSiteResourcesPackageKey(); $siteRootTypoScriptPathAndFilename = sprintf($this->siteRootTypoScriptPattern, $siteResourcesPackageKey); $siteRootTypoScriptCode = $this->readExternalTypoScriptFile($siteRootTypoScriptPathAndFilename); if ($siteRootTypoScriptCode === '') { $siteRootTypoScriptPathAndFilename = sprintf($this->legacySiteRootTypoScriptPattern, $siteResourcesPackageKey); $siteRootTypoScriptCode = $this->readExternalTypoScriptFile($siteRootTypoScriptPathAndFilename); } $mergedTypoScriptCode = ''; $mergedTypoScriptCode .= $this->generateNodeTypeDefinitions(); $mergedTypoScriptCode .= $this->getTypoScriptIncludes($this->prepareAutoIncludeTypoScript()); $mergedTypoScriptCode .= $this->getTypoScriptIncludes($this->prependTypoScriptIncludes); $mergedTypoScriptCode .= $siteRootTypoScriptCode; $mergedTypoScriptCode .= $this->getTypoScriptIncludes($this->appendTypoScriptIncludes); return $this->typoScriptParser->parse($mergedTypoScriptCode, $siteRootTypoScriptPathAndFilename); }
/** * Adopts a node from a (possibly) different context to this context * * Checks if a node variant matching the exact dimensions already exists for this context and * return it if found. Otherwise a new node variant for this context is created. * * In case the node already exists in the context but does not match the target dimensions a * new, more specific node is created and returned. * * @param NodeInterface $node The node with a different context. If the context of the given node is the same as this context the operation will have no effect. * @param boolean $recursive If TRUE also adopt all descendant nodes which are non-aggregate * @return NodeInterface A new or existing node that matches this context */ public function adoptNode(NodeInterface $node, $recursive = false) { if ($node->getContext() === $this && $node->dimensionsAreMatchingTargetDimensionValues()) { return $node; } $this->emitBeforeAdoptNode($node, $this, $recursive); $existingNode = $this->getNodeByIdentifier($node->getIdentifier()); if ($existingNode !== null) { if ($existingNode->dimensionsAreMatchingTargetDimensionValues()) { $adoptedNode = $existingNode; } else { $adoptedNode = $existingNode->createVariantForContext($this); } } else { $adoptedNode = $node->createVariantForContext($this); } $this->firstLevelNodeCache->setByIdentifier($adoptedNode->getIdentifier(), $adoptedNode); if ($recursive) { $childNodes = $node->getChildNodes(); /** @var NodeInterface $childNode */ foreach ($childNodes as $childNode) { if (!$childNode->getNodeType()->isAggregate()) { $this->adoptNode($childNode, true); } } } $this->emitAfterAdoptNode($node, $this, $recursive); return $adoptedNode; }
/** * @param NodeInterface $node * @param boolean $renderCurrentDocumentMetadata * @return boolean */ protected function needsMetadata(NodeInterface $node, $renderCurrentDocumentMetadata) { /** @var $contentContext ContentContext */ $contentContext = $node->getContext(); return $contentContext->isInBackend() === true && ($renderCurrentDocumentMetadata === true || $this->nodeAuthorizationService->isGrantedToEditNode($node) === true); }
/** * {@inheritdoc} */ public function createRedirectsForPublishedNode(NodeInterface $node, Workspace $targetWorkspace) { $nodeType = $node->getNodeType(); if ($targetWorkspace->getName() !== 'live' || !$nodeType->isOfType('Neos.Neos:Document')) { return; } $context = $this->contextFactory->create(['workspaceName' => 'live', 'invisibleContentShown' => true, 'dimensions' => $node->getContext()->getDimensions()]); $targetNode = $context->getNodeByIdentifier($node->getIdentifier()); if ($targetNode === null) { // The page has been added return; } $targetNodeUriPath = $this->buildUriPathForNodeContextPath($targetNode->getContextPath()); if ($targetNodeUriPath === null) { throw new Exception('The target URI path of the node could not be resolved', 1451945358); } $hosts = $this->getHostnames($node->getContext()); // The page has been removed if ($node->isRemoved()) { $this->flushRoutingCacheForNode($targetNode); $statusCode = (int) $this->defaultStatusCode['gone']; $this->redirectStorage->addRedirect($targetNodeUriPath, '', $statusCode, $hosts); return; } // compare the "old" node URI to the new one $nodeUriPath = $this->buildUriPathForNodeContextPath($node->getContextPath()); // use the same regexp than the ContentContextBar Ember View $nodeUriPath = preg_replace('/@[A-Za-z0-9;&,\\-_=]+/', '', $nodeUriPath); if ($nodeUriPath === null || $nodeUriPath === $targetNodeUriPath) { // The page node path has not been changed return; } $this->flushRoutingCacheForNode($targetNode); $statusCode = (int) $this->defaultStatusCode['redirect']; $this->redirectStorage->addRedirect($targetNodeUriPath, $nodeUriPath, $statusCode, $hosts); $q = new FlowQuery([$node]); foreach ($q->children('[instanceof Neos.Neos:Document]') as $childrenNode) { $this->createRedirectsForPublishedNode($childrenNode, $targetWorkspace); } }
/** * Create a recursive copy of this node below $referenceNode with $nodeName. * * $detachedCopy only has an influence if we are copying from one dimension to the other, possibly creating a new * node variant: * * - If $detachedCopy is TRUE, the whole (recursive) copy is done without connecting original and copied node, * so NOT CREATING a new node variant. * - If $detachedCopy is FALSE, and the node does not yet have a variant in the target dimension, we are CREATING * a new node variant. * * As a caller of this method, $detachedCopy should be TRUE if $this->getNodeType()->isAggregate() is TRUE, and FALSE * otherwise. * * @param NodeInterface $referenceNode * @param boolean $detachedCopy * @param string $nodeName * @return NodeInterface */ protected function createRecursiveCopy(NodeInterface $referenceNode, $nodeName, $detachedCopy) { $identifier = null; $referenceNodeDimensions = $referenceNode->getDimensions(); $referenceNodeDimensionsHash = Utility::sortDimensionValueArrayAndReturnDimensionsHash($referenceNodeDimensions); $thisDimensions = $this->getDimensions(); $thisNodeDimensionsHash = Utility::sortDimensionValueArrayAndReturnDimensionsHash($thisDimensions); if ($detachedCopy === false && $referenceNodeDimensionsHash !== $thisNodeDimensionsHash && $referenceNode->getContext()->getNodeByIdentifier($this->getIdentifier()) === null) { // If the target dimensions are different than this one, and there is no node shadowing this one in the target dimension yet, we use the same // node identifier, effectively creating a new node variant. $identifier = $this->getIdentifier(); } $copiedNode = $referenceNode->createSingleNode($nodeName, null, $identifier); $copiedNode->similarize($this, true); /** @var $childNode Node */ foreach ($this->getChildNodes() as $childNode) { // Prevent recursive copy when copying into itself if ($childNode->getIdentifier() !== $copiedNode->getIdentifier()) { $childNode->copyIntoInternal($copiedNode, $childNode->getName(), $detachedCopy); } } return $copiedNode; }
/** * Resolves the request path, also known as route path, identifying the given node. * * A path is built, based on the uri path segment properties of the parents of and the given node itself. * If content dimensions are configured, the first path segment will the identifiers of the dimension * values according to the current context. * * @param NodeInterface $node The node where the generated path should lead to * @return string The relative route path, possibly prefixed with a segment for identifying the current content dimension values */ protected function resolveRoutePathForNode(NodeInterface $node) { $workspaceName = $node->getContext()->getWorkspaceName(); $nodeContextPath = $node->getContextPath(); $nodeContextPathSuffix = $workspaceName !== 'live' ? substr($nodeContextPath, strpos($nodeContextPath, '@')) : ''; $currentNodeIsSiteNode = $node->getParentPath() === SiteService::SITES_ROOT_PATH; $dimensionsUriSegment = $this->getUriSegmentForDimensions($node->getContext()->getDimensions(), $currentNodeIsSiteNode); $requestPath = $this->getRequestPathByNode($node); return trim($dimensionsUriSegment . $requestPath, '/') . $nodeContextPathSuffix; }
/** * 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 \Neos\ContentRepository\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); }
/** * Set the "context node" this operation was working on. * * @param NodeInterface $node * @return void */ public function setNode(NodeInterface $node) { $this->nodeIdentifier = $node->getIdentifier(); $this->workspaceName = $node->getContext()->getWorkspaceName(); $this->dimension = $node->getContext()->getDimensions(); $context = $node->getContext(); if ($context instanceof ContentContext && $context->getCurrentSite() !== null) { $siteIdentifier = $this->persistenceManager->getIdentifierByObject($context->getCurrentSite()); } else { $siteIdentifier = null; } $this->data = Arrays::arrayMergeRecursiveOverrule($this->data, array('nodeContextPath' => $node->getContextPath(), 'nodeLabel' => $node->getLabel(), 'nodeType' => $node->getNodeType()->getName(), 'site' => $siteIdentifier)); $node = self::getClosestAggregateNode($node); if ($node !== null) { $this->documentNodeIdentifier = $node->getIdentifier(); $this->data = Arrays::arrayMergeRecursiveOverrule($this->data, array('documentNodeContextPath' => $node->getContextPath(), 'documentNodeLabel' => $node->getLabel(), 'documentNodeType' => $node->getNodeType()->getName())); } }
/** * 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()); }