/**
  * Index all nodes.
  *
  * This command (re-)indexes all nodes contained in the content repository and sets the schema beforehand.
  *
  *
  * @param string $workspace
  * @return void
  */
 public function buildCommand($workspace = NULL)
 {
     $this->indexedNodes = 0;
     if ($workspace === NULL) {
         foreach ($this->workspaceRepository->findAll() as $workspace) {
             $this->indexWorkspace($workspace->getName());
         }
     } else {
         $this->indexWorkspace($workspace);
     }
     $this->outputLine('Finished indexing.');
 }
 /**
  * Shows a list of existing workspaces
  *
  * @return string
  */
 public function indexAction()
 {
     $user = $this->userService->getCurrentUser();
     $workspacesArray = [];
     /** @var Workspace $workspace */
     foreach ($this->workspaceRepository->findAll() as $workspace) {
         // FIXME: This check should be implemented through a specialized Workspace Privilege or something similar
         if ($workspace->getOwner() !== null && $workspace->getOwner() !== $user) {
             continue;
         }
         $workspaceArray = ['name' => $workspace->getName(), 'title' => $workspace->getTitle(), 'description' => $workspace->getDescription(), 'baseWorkspace' => $workspace->getBaseWorkspace()];
         if ($user !== null) {
             $workspaceArray['readonly'] = !$this->userService->currentUserCanPublishToWorkspace($workspace);
         }
         $workspacesArray[] = $workspaceArray;
     }
     $this->view->assign('workspaces', $workspacesArray);
 }
 /**
  * Creates an array of workspace names and their respective titles which are possible base workspaces for other
  * workspaces.
  *
  * @param Workspace $excludedWorkspace If set, this workspace will be excluded from the list of returned workspaces
  * @return array
  */
 protected function prepareBaseWorkspaceOptions(Workspace $excludedWorkspace = null)
 {
     $baseWorkspaceOptions = [];
     foreach ($this->workspaceRepository->findAll() as $workspace) {
         /** @var Workspace $workspace */
         if (!$workspace->isPersonalWorkspace() && $workspace !== $excludedWorkspace && ($workspace->isPublicWorkspace() || $workspace->isInternalWorkspace() || $this->userService->currentUserCanManageWorkspace($workspace))) {
             $baseWorkspaceOptions[$workspace->getName()] = $workspace->getTitle();
         }
     }
     return $baseWorkspaceOptions;
 }
 /**
  * @param NodeInterface $node
  * @return void
  */
 protected function indexAllNodeVariants(NodeInterface $node)
 {
     $nodeIdentifier = $node->getIdentifier();
     $allIndexedVariants = $this->indexClient->query('SELECT __identifier__ FROM objects WHERE __identifier = "' . $nodeIdentifier . '"');
     foreach ($allIndexedVariants as $nodeVariant) {
         $this->indexClient->removeData($nodeVariant['__identifier__']);
     }
     foreach ($this->workspaceRepository->findAll() as $workspace) {
         $this->indexNodeInWorkspace($nodeIdentifier, $workspace->getName());
     }
 }
 /**
  * Detect and fix nodes in non-live workspaces whose identifier does not match their corresponding node in the
  * live workspace.
  *
  * @param string $workspaceName This argument will be ignored
  * @param boolean $dryRun Simulate?
  * @return void
  */
 public function fixNodesWithInconsistentIdentifier($workspaceName, $dryRun)
 {
     $this->output->outputLine('Checking for nodes with inconsistent identifier ...');
     $nodesArray = [];
     $liveWorkspaceNames = [];
     $nonLiveWorkspaceNames = [];
     foreach ($this->workspaceRepository->findAll() as $workspace) {
         /** @var Workspace $workspace */
         if ($workspace->getBaseWorkspace() !== null) {
             $nonLiveWorkspaceNames[] = $workspace->getName();
         } else {
             $liveWorkspaceNames[] = $workspace->getName();
         }
     }
     foreach ($nonLiveWorkspaceNames as $workspaceName) {
         /** @var QueryBuilder $queryBuilder */
         $queryBuilder = $this->entityManager->createQueryBuilder();
         $queryBuilder->select('nonlive.Persistence_Object_Identifier, nonlive.identifier, nonlive.path, live.identifier AS liveIdentifier')->from(NodeData::class, 'nonlive')->join(NodeData::class, 'live', 'WITH', 'live.path = nonlive.path AND live.dimensionsHash = nonlive.dimensionsHash AND live.identifier != nonlive.identifier')->where('nonlive.workspace = ?1')->andWhere($queryBuilder->expr()->in('live.workspace', $liveWorkspaceNames))->andWhere('nonlive.path != \'/\'')->setParameter(1, $workspaceName);
         foreach ($queryBuilder->getQuery()->getArrayResult() as $nodeDataArray) {
             $this->output->outputLine('Node %s in workspace %s has identifier %s but live node has identifier %s.', [$nodeDataArray['path'], $workspaceName, $nodeDataArray['identifier'], $nodeDataArray['liveIdentifier']]);
             $nodesArray[] = $nodeDataArray;
         }
     }
     if ($nodesArray === []) {
         return;
     }
     if (!$dryRun) {
         $self = $this;
         $this->output->outputLine();
         $this->output->outputLine('Nodes with inconsistent identifiers found.');
         $this->askBeforeExecutingTask(sprintf('Do you want to fix the identifiers of %s node%s now?', count($nodesArray), count($nodesArray) > 1 ? 's' : ''), function () use($self, $nodesArray) {
             foreach ($nodesArray as $nodeArray) {
                 /** @var QueryBuilder $queryBuilder */
                 $queryBuilder = $this->entityManager->createQueryBuilder();
                 $queryBuilder->update(NodeData::class, 'nonlive')->set('nonlive.identifier', $queryBuilder->expr()->literal($nodeArray['liveIdentifier']))->where('nonlive.Persistence_Object_Identifier = ?1')->setParameter(1, $nodeArray['Persistence_Object_Identifier']);
                 $result = $queryBuilder->getQuery()->getResult();
                 if ($result !== 1) {
                     $self->output->outputLine('<error>Error:</error> The update query returned an unexpected result!');
                     $self->output->outputLine('<b>Query:</b> ' . $queryBuilder->getQuery()->getSQL());
                     $self->output->outputLine('<b>Result:</b> %s', [var_export($result, true)]);
                     exit(1);
                 }
             }
             $self->output->outputLine('Fixed inconsistent identifiers.');
         });
     } else {
         $this->output->outputLine('Found %s node%s with inconsistent identifiers which need to be fixed.', array(count($nodesArray), count($nodesArray) > 1 ? 's' : ''));
     }
     $this->output->outputLine();
 }
 /**
  * Display a list of existing workspaces
  *
  * @return void
  */
 public function listCommand()
 {
     $workspaces = $this->workspaceRepository->findAll();
     if ($workspaces->count() === 0) {
         $this->outputLine('No workspaces found.');
         $this->quit(0);
     }
     $tableRows = array();
     $headerRow = array('Name', 'Base Workspace', 'Title', 'Description');
     foreach ($workspaces as $workspace) {
         $tableRows[] = array($workspace->getName(), $workspace->getBaseWorkspace() ? $workspace->getBaseWorkspace()->getName() : '', $workspace->getTitle(), $workspace->getDescription());
     }
     $this->output->outputTable($tableRows, $headerRow);
 }
 /**
  * Collects all nodes of the given node type which refer to an invalid workspace
  * configuration.
  *
  * Note: due to the foreign key constraints in the database, there actually never should
  *       be any node with n.workspace of a non-existing workspace because if that workspace
  *       does not exist anymore, the value would turn NULL. But the query covers this nevertheless.
  *       Better safe than sorry.
  *
  * @return array
  */
 protected function collectNodesWithInvalidWorkspace()
 {
     $nodes = [];
     $workspaceNames = [];
     foreach ($this->workspaceRepository->findAll() as $workspace) {
         $workspaceNames[] = $workspace->getName();
     }
     /** @var QueryBuilder $queryBuilder */
     $queryBuilder = $this->entityManager->createQueryBuilder();
     $queryBuilder->select('n')->from('TYPO3\\TYPO3CR\\Domain\\Model\\NodeData', 'n')->add('where', $queryBuilder->expr()->orX($queryBuilder->expr()->notIn('n.workspace', $workspaceNames), $queryBuilder->expr()->isNull('n.workspace')));
     foreach ($queryBuilder->getQuery()->getArrayResult() as $nodeDataArray) {
         $this->output->outputLine('Node %s (identifier: %s) refers to an invalid workspace: %s', [$nodeDataArray['path'], $nodeDataArray['identifier'], isset($nodeDataArray['workspace']) ? $nodeDataArray['workspace'] : 'null']);
         $nodes[] = $nodeDataArray;
     }
     return $nodes;
 }
 /**
  * Index all nodes by creating a new index and when everything was completed, switch the index alias.
  *
  * This command (re-)indexes all nodes contained in the content repository and sets the schema beforehand.
  *
  * @param integer $limit Amount of nodes to index at maximum
  * @param boolean $update if TRUE, do not throw away the index at the start. Should *only be used for development*.
  * @param string $workspace name of the workspace which should be indexed
  * @param string $postfix Index postfix, index with the same postifix will be deleted if exist
  * @return void
  */
 public function buildCommand($limit = null, $update = false, $workspace = null, $postfix = null)
 {
     if ($update === true) {
         $this->logger->log('!!! Update Mode (Development) active!', LOG_INFO);
     } else {
         $this->nodeIndexer->setIndexNamePostfix($postfix ?: time());
         if ($this->nodeIndexer->getIndex()->exists() === true) {
             $this->logger->log(sprintf('Deleted index with the same postfix (%s)!', $postfix), LOG_WARNING);
             $this->nodeIndexer->getIndex()->delete();
         }
         $this->nodeIndexer->getIndex()->create();
         $this->logger->log('Created index ' . $this->nodeIndexer->getIndexName(), LOG_INFO);
         $nodeTypeMappingCollection = $this->nodeTypeMappingBuilder->buildMappingInformation($this->nodeIndexer->getIndex());
         foreach ($nodeTypeMappingCollection as $mapping) {
             /** @var \Flowpack\ElasticSearch\Domain\Model\Mapping $mapping */
             $mapping->apply();
         }
         $this->logger->log('Updated Mapping.', LOG_INFO);
     }
     $this->logger->log(sprintf('Indexing %snodes ... ', $limit !== null ? 'the first ' . $limit . ' ' : ''), LOG_INFO);
     $count = 0;
     if ($workspace === null && $this->settings['indexAllWorkspaces'] === false) {
         $workspace = 'live';
     }
     $callback = function ($workspaceName, $indexedNodes, $dimensions) {
         if ($dimensions === []) {
             $this->outputLine('Workspace "' . $workspaceName . '" without dimensions done. (Indexed ' . $indexedNodes . ' nodes)');
         } else {
             $this->outputLine('Workspace "' . $workspaceName . '" and dimensions "' . json_encode($dimensions) . '" done. (Indexed ' . $indexedNodes . ' nodes)');
         }
     };
     if ($workspace === null) {
         foreach ($this->workspaceRepository->findAll() as $workspace) {
             $count += $this->indexWorkspace($workspace->getName(), $limit, $callback);
         }
     } else {
         $count += $this->indexWorkspace($workspace, $limit, $callback);
     }
     $this->nodeIndexingManager->flushQueues();
     $this->logger->log('Done. (indexed ' . $count . ' nodes)', LOG_INFO);
     $this->nodeIndexer->getIndex()->refresh();
     // TODO: smoke tests
     if ($update === false) {
         $this->nodeIndexer->updateIndexAlias();
     }
 }
 /**
  * Display a list of unpublished content
  *
  * @param Workspace $workspace
  * @return void
  * @todo Pagination
  * @todo Tree filtering + level limit
  * @todo Search field
  * @todo Difference mechanism
  */
 public function indexAction(Workspace $workspace = NULL)
 {
     if ($workspace === NULL) {
         $workspace = $this->userService->getUserWorkspace();
     }
     $sites = array();
     foreach ($this->publishingService->getUnpublishedNodes($workspace) as $node) {
         $pathParts = explode('/', $node->getPath());
         if (count($pathParts) > 2) {
             $siteNodeName = $pathParts[2];
             $q = new FlowQuery(array($node));
             $document = $q->closest('[instanceof TYPO3.Neos:Document]')->get(0);
             // FIXME: $document will be NULL if we have a broken rootline for this node. This actually should never happen, but currently can in some scenarios.
             if ($document !== NULL) {
                 $documentPath = implode('/', array_slice(explode('/', $document->getPath()), 3));
                 $relativePath = str_replace(sprintf('/sites/%s/%s', $siteNodeName, $documentPath), '', $node->getPath());
                 if (!isset($sites[$siteNodeName]['siteNode'])) {
                     $sites[$siteNodeName]['siteNode'] = $this->siteRepository->findOneByNodeName($siteNodeName);
                 }
                 $sites[$siteNodeName]['documents'][$documentPath]['documentNode'] = $document;
                 $change = array('node' => $node);
                 if ($node->getNodeType()->isOfType('TYPO3.Neos:Node')) {
                     $change['configuration'] = $node->getNodeType()->getFullConfiguration();
                 }
                 $sites[$siteNodeName]['documents'][$documentPath]['changes'][$relativePath] = $change;
             }
         }
     }
     $liveContext = $this->contextFactory->create(array('workspaceName' => 'live'));
     ksort($sites);
     foreach ($sites as $siteKey => $site) {
         foreach ($site['documents'] as $documentKey => $document) {
             foreach ($document['changes'] as $changeKey => $change) {
                 $liveNode = $liveContext->getNodeByIdentifier($change['node']->getIdentifier());
                 $sites[$siteKey]['documents'][$documentKey]['changes'][$changeKey]['isNew'] = is_null($liveNode);
                 $sites[$siteKey]['documents'][$documentKey]['changes'][$changeKey]['isMoved'] = $liveNode && $change['node']->getPath() !== $liveNode->getPath();
             }
         }
         ksort($sites[$siteKey]['documents']);
     }
     $workspaces = array();
     foreach ($this->workspaceRepository->findAll() as $workspaceInstance) {
         array_push($workspaces, array('workspaceNode' => $workspaceInstance, 'unpublishedNodesCount' => $this->publishingService->getUnpublishedNodesCount($workspaceInstance)));
     }
     $this->view->assignMultiple(array('workspace' => $workspace, 'workspaces' => $workspaces, 'sites' => $sites));
 }
 /**
  * Update a site
  *
  * @param Site $site A site to update
  * @param string $newSiteNodeName A new site node name
  * @return void
  * @Flow\Validate(argumentName="$site", type="UniqueEntity")
  * @Flow\Validate(argumentName="$newSiteNodeName", type="NotEmpty")
  * @Flow\Validate(argumentName="$newSiteNodeName", type="StringLength", options={ "minimum"=1, "maximum"=250 })
  * @Flow\Validate(argumentName="$newSiteNodeName", type="TYPO3.Neos:NodeName")
  */
 public function updateSiteAction(Site $site, $newSiteNodeName)
 {
     if ($site->getNodeName() !== $newSiteNodeName) {
         $oldSiteNodePath = NodePaths::addNodePathSegment(SiteService::SITES_ROOT_PATH, $site->getNodeName());
         $newSiteNodePath = NodePaths::addNodePathSegment(SiteService::SITES_ROOT_PATH, $newSiteNodeName);
         /** @var $workspace Workspace */
         foreach ($this->workspaceRepository->findAll() as $workspace) {
             $siteNode = $this->nodeDataRepository->findOneByPath($oldSiteNodePath, $workspace);
             if ($siteNode !== null) {
                 $siteNode->setPath($newSiteNodePath);
             }
         }
         $site->setNodeName($newSiteNodeName);
         $this->nodeDataRepository->persistEntities();
     }
     $this->siteRepository->update($site);
     $this->addFlashMessage('The site "%s" has been updated.', 'Update', null, array(htmlspecialchars($site->getName())), 1412371798);
     $this->unsetLastVisitedNodeAndRedirect('index');
 }
 /**
  * Update a site
  *
  * @param Site $site A site to update
  * @param string $newSiteNodeName A new site node name
  * @return void
  * @Flow\Validate(argumentName="$site", type="UniqueEntity")
  * @Flow\Validate(argumentName="$newSiteNodeName", type="NotEmpty")
  * @Flow\Validate(argumentName="$newSiteNodeName", type="StringLength", options={ "minimum"=1, "maximum"=250 })
  * @Flow\Validate(argumentName="$newSiteNodeName", type="TYPO3.Neos:NodeName")
  */
 public function updateSiteAction(Site $site, $newSiteNodeName)
 {
     if ($site->getNodeName() !== $newSiteNodeName) {
         $oldSiteNodePath = '/sites/' . $site->getNodeName();
         $newSiteNodePath = '/sites/' . $newSiteNodeName;
         /** @var $workspace Workspace */
         foreach ($this->workspaceRepository->findAll() as $workspace) {
             $siteNode = $this->nodeDataRepository->findOneByPath($oldSiteNodePath, $workspace);
             if ($siteNode !== NULL) {
                 $siteNode->setPath($newSiteNodePath);
             }
         }
         $site->setNodeName($newSiteNodeName);
         $this->nodeDataRepository->persistEntities();
     }
     $this->siteRepository->update($site);
     $this->addFlashMessage('The site "%s" has been updated.', 'Update', NULL, array($site->getName()), 1412371798);
     $this->unsetLastVisitedNodeAndRedirect('index');
 }
 /**
  * Index all nodes by creating a new index and when everything was completed, switch the index alias.
  *
  * This command (re-)indexes all nodes contained in the content repository and sets the schema beforehand.
  *
  * @param integer $limit Amount of nodes to index at maximum
  * @param boolean $update if TRUE, do not throw away the index at the start. Should *only be used for development*.
  * @param string $workspace name of the workspace which should be indexed
  * @return void
  */
 public function buildCommand($limit = NULL, $update = FALSE, $workspace = NULL)
 {
     if ($update === TRUE) {
         $this->logger->log('!!! Update Mode (Development) active!', LOG_INFO);
     } else {
         $this->nodeIndexer->setIndexNamePostfix(time());
         $this->nodeIndexer->getIndex()->create();
         $this->logger->log('Created index ' . $this->nodeIndexer->getIndexName(), LOG_INFO);
         $nodeTypeMappingCollection = $this->nodeTypeMappingBuilder->buildMappingInformation($this->nodeIndexer->getIndex());
         foreach ($nodeTypeMappingCollection as $mapping) {
             /** @var \Flowpack\ElasticSearch\Domain\Model\Mapping $mapping */
             $mapping->apply();
         }
         $this->logger->log('Updated Mapping.', LOG_INFO);
     }
     $this->logger->log(sprintf('Indexing %snodes ... ', $limit !== NULL ? 'the first ' . $limit . ' ' : ''), LOG_INFO);
     $count = 0;
     $this->limit = $limit;
     $this->indexedNodes = 0;
     $this->countedIndexedNodes = 0;
     if ($workspace === NULL && $this->settings['indexAllWorkspaces'] === FALSE) {
         $workspace = 'live';
     }
     if ($workspace === NULL) {
         foreach ($this->workspaceRepository->findAll() as $workspace) {
             $this->indexWorkspace($workspace->getName());
             $count = $count + $this->countedIndexedNodes;
         }
     } else {
         $this->indexWorkspace($workspace);
         $count = $count + $this->countedIndexedNodes;
     }
     $this->nodeIndexingManager->flushQueues();
     $this->logger->log('Done. (indexed ' . $count . ' nodes)', LOG_INFO);
     $this->nodeIndexer->getIndex()->refresh();
     // TODO: smoke tests
     if ($update === FALSE) {
         $this->nodeIndexer->updateIndexAlias();
     }
 }
示例#13
0
 /**
  * @return \TYPO3\FLOW3\Persistence\QueryResultInterface
  */
 public function getWorkspaces()
 {
     return $this->workspaceRepository->findAll();
 }
 /**
  * Shows a list of existing workspaces
  *
  * @return string
  */
 public function indexAction()
 {
     $this->view->assign('workspaces', $this->workspaceRepository->findAll());
 }