/** * Find a single node by exact path. * * @param string $path Absolute path of the node * @param Workspace $workspace The containing workspace * @param array $dimensions An array of dimensions with array of ordered values to use for fallback matching * @return NodeData The matching node if found, otherwise NULL * @throws \InvalidArgumentException */ public function findOneByPath($path, Workspace $workspace, array $dimensions = NULL) { if (strlen($path) === 0 || $path !== '/' && ($path[0] !== '/' || substr($path, -1, 1) === '/')) { throw new \InvalidArgumentException('"' . $path . '" is not a valid path: must start but not end with a slash.', 1284985489); } if ($path === '/') { return $workspace->getRootNodeData(); } $originalWorkspace = $workspace; while ($workspace !== NULL) { /** @var $node NodeData */ foreach ($this->addedNodes as $node) { if ($node->getPath() === $path && $node->matchesWorkspaceAndDimensions($workspace, $dimensions)) { return $node; } } foreach ($this->removedNodes as $node) { if ($node->getPath() === $path && $node->matchesWorkspaceAndDimensions($workspace, $dimensions)) { return NULL; } } $queryBuilder = $this->createQueryBuilderForPathWorkspaceAndDimensions($path, $workspace, $dimensions); $query = $queryBuilder->getQuery(); $nodes = $query->getResult(); if ($nodes !== array()) { $foundNodes = $this->reduceNodeVariantsByDimensions($nodes, $dimensions); $foundNodes = $this->filterNodesOverlaidInBaseWorkspace($foundNodes, $originalWorkspace, $dimensions); if ($foundNodes !== array()) { return reset($foundNodes); } } $workspace = $workspace->getBaseWorkspace(); } return NULL; }
/** * Find a single node by exact path. * * @param string $path Absolute path of the node * @param Workspace $workspace The containing workspace * @param array $dimensions An array of dimensions with array of ordered values to use for fallback matching * @param boolean|NULL $removedNodes Include removed nodes, NULL (all), FALSE (no removed nodes) or TRUE (only removed nodes) * @throws \InvalidArgumentException * @return NodeData The matching node if found, otherwise NULL */ public function findOneByPath($path, Workspace $workspace, array $dimensions = null, $removedNodes = false) { $path = strtolower($path); if ($path === '' || $path !== '/' && ($path[0] !== '/' || substr($path, -1, 1) === '/')) { throw new \InvalidArgumentException('"' . $path . '" is not a valid path: must start but not end with a slash.', 1284985489); } if ($path === '/') { return $workspace->getRootNodeData(); } $workspaces = array(); while ($workspace !== null) { /** @var $node NodeData */ foreach ($this->addedNodes as $node) { if ($node->getPath() === $path && $node->matchesWorkspaceAndDimensions($workspace, $dimensions)) { return $node; } } foreach ($this->removedNodes as $node) { if ($node->getPath() === $path && $node->matchesWorkspaceAndDimensions($workspace, $dimensions)) { return null; } } $workspaces[] = $workspace; $workspace = $workspace->getBaseWorkspace(); } $queryBuilder = $this->createQueryBuilder($workspaces); if ($dimensions !== null) { $this->addDimensionJoinConstraintsToQueryBuilder($queryBuilder, $dimensions); } else { $dimensions = array(); } $this->addPathConstraintToQueryBuilder($queryBuilder, $path); $query = $queryBuilder->getQuery(); $nodes = $query->getResult(); $foundNodes = $this->reduceNodeVariantsByWorkspacesAndDimensions($nodes, $workspaces, $dimensions); $foundNodes = $this->filterRemovedNodes($foundNodes, $removedNodes); if ($foundNodes !== array()) { return reset($foundNodes); } return null; }
/** * This finds nodes by path and delivers a raw, unfiltered result. * * To get a "usable" set of nodes, filtering by workspaces, dimensions and * removed nodes must be done on the result. * * @param string $path * @param Workspace $workspace * @param array|null $dimensions * @param boolean $onlyShadowNodes * @return array * @throws \InvalidArgumentException */ protected function findRawNodesByPath($path, Workspace $workspace, array $dimensions = null, $onlyShadowNodes = false) { $path = strtolower($path); if ($path === '' || $path !== '/' && ($path[0] !== '/' || substr($path, -1, 1) === '/')) { throw new \InvalidArgumentException('"' . $path . '" is not a valid path: must start but not end with a slash.', 1284985489); } if ($path === '/') { return [$workspace->getRootNodeData()]; } $addedNodes = []; $workspaces = []; while ($workspace !== null) { /** @var $node NodeData */ foreach ($this->addedNodes as $node) { if ($node->getPath() === $path && $node->matchesWorkspaceAndDimensions($workspace, $dimensions) && ($onlyShadowNodes === false || $node->isInternal())) { $addedNodes[] = $node; // removed nodes don't matter here because due to the identity map the right object will be returned from the query and will have "removed" set. } } $workspaces[] = $workspace; $workspace = $workspace->getBaseWorkspace(); } $queryBuilder = $this->createQueryBuilder($workspaces); if ($dimensions !== null) { $this->addDimensionJoinConstraintsToQueryBuilder($queryBuilder, $dimensions); } $this->addPathConstraintToQueryBuilder($queryBuilder, $path); if ($onlyShadowNodes) { $queryBuilder->andWhere('n.movedTo IS NOT NULL AND n.removed = TRUE'); } $query = $queryBuilder->getQuery(); $nodes = $query->getResult(); return array_merge($nodes, $addedNodes); }