/**
  * Shows details of the given workspace
  *
  * @param string $workspaceName
  * @param Workspace $baseWorkspace
  * @return string
  */
 public function createAction($workspaceName, Workspace $baseWorkspace)
 {
     $existingWorkspace = $this->workspaceRepository->findByIdentifier($workspaceName);
     if ($existingWorkspace !== NULL) {
         $this->throwStatus(409, 'Workspace already exists', '');
     }
     $workspace = new Workspace($workspaceName, $baseWorkspace);
     $this->workspaceRepository->add($workspace);
     $this->throwStatus(201, 'Workspace created', '');
 }
 /**
  * Remove dimensions on nodes "/" and "/sites"
  *
  * This empties the content dimensions on those nodes, so when traversing via the Node API from the root node,
  * the nodes below "/sites" are always reachable.
  *
  * @param string $workspaceName
  * @param boolean $dryRun
  * @return void
  */
 public function removeContentDimensionsFromRootAndSitesNode($workspaceName, $dryRun)
 {
     $workspace = $this->workspaceRepository->findByIdentifier($workspaceName);
     $rootNodes = $this->nodeDataRepository->findByPath('/', $workspace);
     $sitesNodes = $this->nodeDataRepository->findByPath('/sites', $workspace);
     $this->output->outputLine('Checking for root and site nodes with content dimensions set ...');
     /** @var \TYPO3\TYPO3CR\Domain\Model\NodeData $rootNode */
     foreach ($rootNodes as $rootNode) {
         if ($rootNode->getDimensionValues() !== []) {
             if ($dryRun === false) {
                 $rootNode->setDimensions([]);
                 $this->nodeDataRepository->update($rootNode);
                 $this->output->outputLine('Removed content dimensions from root node');
             } else {
                 $this->output->outputLine('Found root node with content dimensions set.');
             }
         }
     }
     /** @var \TYPO3\TYPO3CR\Domain\Model\NodeData $sitesNode */
     foreach ($sitesNodes as $sitesNode) {
         if ($sitesNode->getDimensionValues() !== []) {
             if ($dryRun === false) {
                 $sitesNode->setDimensions([]);
                 $this->nodeDataRepository->update($sitesNode);
                 $this->output->outputLine('Removed content dimensions from node "/sites"');
             } else {
                 $this->output->outputLine('Found node "/sites"');
             }
         }
     }
 }
 /**
  * Removes all personal workspaces of the given user's account if these workspaces exist. Also removes
  * all possibly existing content of these workspaces.
  *
  * @param string $accountIdentifier Identifier of the user's account
  * @return void
  */
 protected function deletePersonalWorkspace($accountIdentifier)
 {
     $userWorkspace = $this->workspaceRepository->findByIdentifier(UserUtility::getPersonalWorkspaceNameForUsername($accountIdentifier));
     if ($userWorkspace instanceof Workspace) {
         $this->publishingService->discardAllNodes($userWorkspace);
         $this->workspaceRepository->remove($userWorkspace);
     }
 }
 /**
  * Removes all personal workspaces of the given user's account if these workspaces exist. Also removes
  * all possibly existing content of these workspaces.
  *
  * @param string $accountIdentifier Identifier of the user's account
  * @return void
  */
 protected function deleteUserWorkspaces($accountIdentifier)
 {
     $userWorkspace = $this->workspaceRepository->findByIdentifier('user-' . $accountIdentifier);
     if ($userWorkspace instanceof Workspace) {
         $this->publishingService->discardAllNodes($userWorkspace);
         $this->workspaceRepository->remove($userWorkspace);
     }
 }
 /**
  * Performs checks for orphan nodes removes them if found.
  *
  * @param NodeType $nodeType Only for this node type, if specified
  * @param string $workspaceName
  * @param boolean $dryRun Simulate?
  * @return void
  */
 public function removeUndefinedProperties(NodeType $nodeType = NULL, $workspaceName, $dryRun)
 {
     $this->output->outputLine('Checking for undefined properties ...');
     /** @var \TYPO3\TYPO3CR\Domain\Model\Workspace $workspace */
     $workspace = $this->workspaceRepository->findByIdentifier($workspaceName);
     $nodesWithUndefinedPropertiesNodes = array();
     $undefinedPropertiesCount = 0;
     $nodes = $nodeType !== NULL ? $this->getNodeDataByNodeTypeAndWorkspace($nodeType, $workspaceName) : $this->nodeDataRepository->findByWorkspace($workspace);
     foreach ($nodes as $nodeData) {
         try {
             /** @var NodeData $nodeData */
             if ($nodeData->getNodeType()->getName() === 'unstructured') {
                 continue;
             }
             $context = $this->nodeFactory->createContextMatchingNodeData($nodeData);
             $node = $this->nodeFactory->createFromNodeData($nodeData, $context);
             if (!$node instanceof NodeInterface) {
                 continue;
             }
             $nodeType = $node->getNodeType();
             $undefinedProperties = array_diff(array_keys($node->getProperties()), array_keys($nodeType->getProperties()));
             if ($undefinedProperties !== array()) {
                 $nodesWithUndefinedPropertiesNodes[$node->getIdentifier()] = array('node' => $node, 'undefinedProperties' => $undefinedProperties);
                 foreach ($undefinedProperties as $undefinedProperty) {
                     $undefinedPropertiesCount++;
                     $this->output->outputLine('Found undefined property named "%s" in "%s" (%s)', array($undefinedProperty, $node->getPath(), $node->getNodeType()->getName()));
                 }
             }
         } catch (NodeTypeNotFoundException $exception) {
             $this->output->outputLine('Skipped undefined node type in "%s"', array($nodeData->getPath()));
         }
     }
     if ($undefinedPropertiesCount > 0) {
         $this->output->outputLine();
         if (!$dryRun) {
             $self = $this;
             $this->askBeforeExecutingTask('Do you want to remove undefined node properties?', function () use($self, $nodesWithUndefinedPropertiesNodes, $undefinedPropertiesCount, $workspaceName, $dryRun) {
                 foreach ($nodesWithUndefinedPropertiesNodes as $nodesWithUndefinedPropertiesNode) {
                     /** @var NodeInterface $node */
                     $node = $nodesWithUndefinedPropertiesNode['node'];
                     foreach ($nodesWithUndefinedPropertiesNode['undefinedProperties'] as $undefinedProperty) {
                         if ($node->hasProperty($undefinedProperty)) {
                             $node->removeProperty($undefinedProperty);
                         }
                     }
                 }
                 $self->output->outputLine('Removed %s undefined propert%s.', array($undefinedPropertiesCount, $undefinedPropertiesCount > 1 ? 'ies' : 'y'));
             });
         } else {
             $this->output->outputLine('Found %s undefined propert%s to be removed.', array($undefinedPropertiesCount, $undefinedPropertiesCount > 1 ? 'ies' : 'y'));
         }
         $this->output->outputLine();
     }
 }
 /**
  * Repair nodes whose shadow nodes are missing
  *
  * This check searches for nodes which have a corresponding node in one of the base workspaces,
  * have different node paths, but don't have a corresponding shadow node with a "movedto" value.
  *
  * @param string $workspaceName Currently ignored
  * @param boolean $dryRun Simulate?
  * @param NodeType $nodeType This argument will be ignored
  * @return void
  */
 protected function repairShadowNodes($workspaceName, $dryRun, NodeType $nodeType = null)
 {
     /** @var Workspace $workspace */
     $workspace = $this->workspaceRepository->findByIdentifier($workspaceName);
     if ($workspace->getBaseWorkspace() === null) {
         $this->output->outputLine('Repairing base workspace "%s", therefore skipping check for shadow nodes.', [$workspaceName]);
         $this->output->outputLine();
         return;
     }
     $this->output->outputLine('Checking for nodes with missing shadow nodes ...');
     $fixedShadowNodes = $this->fixShadowNodesInWorkspace($workspace, $nodeType);
     $this->output->outputLine('%s %s node%s with missing shadow nodes.', [$dryRun ? 'Would repair' : 'Repaired', $fixedShadowNodes, $fixedShadowNodes !== 1 ? 's' : '']);
     $this->output->outputLine();
 }
 /**
  * Returns the current workspace.
  *
  * @param boolean $createWorkspaceIfNecessary DEPRECATED: If enabled, creates a workspace with the configured name if it doesn't exist already. This option is DEPRECATED, create workspace explicitly instead.
  * @return Workspace The workspace or NULL
  * @api
  */
 public function getWorkspace($createWorkspaceIfNecessary = TRUE)
 {
     if ($this->workspace !== NULL) {
         return $this->workspace;
     }
     $this->workspace = $this->workspaceRepository->findByIdentifier($this->workspaceName);
     if ($this->workspace !== NULL) {
         return $this->workspace;
     }
     if ($createWorkspaceIfNecessary) {
         $liveWorkspace = $this->workspaceRepository->findByIdentifier('live');
         $this->workspace = new Workspace($this->workspaceName, $liveWorkspace);
         $this->workspaceRepository->add($this->workspace);
         $this->systemLogger->log(sprintf('Notice: %s::getWorkspace() implicitly created the new workspace "%s". This behaviour is discouraged and will be removed in future versions. Make sure to create workspaces explicitly by adding a new workspace to the Workspace Repository.', __CLASS__, $this->workspaceName), LOG_NOTICE);
     }
 }
 /**
  * Create a workspace
  *
  * @param string $workspaceName
  * @param Workspace $baseWorkspace
  * @param string $ownerAccountIdentifier
  * @return string
  */
 public function createAction($workspaceName, Workspace $baseWorkspace, $ownerAccountIdentifier = null)
 {
     $existingWorkspace = $this->workspaceRepository->findByIdentifier($workspaceName);
     if ($existingWorkspace !== null) {
         $this->throwStatus(409, 'Workspace already exists', '');
     }
     if ($ownerAccountIdentifier !== null) {
         $owner = $this->userService->getUser($ownerAccountIdentifier);
         if ($owner === null) {
             $this->throwStatus(422, 'Requested owner account does not exist', '');
         }
     } else {
         $owner = null;
     }
     $workspace = new Workspace($workspaceName, $baseWorkspace, $owner);
     $this->workspaceRepository->add($workspace);
     $this->throwStatus(201, 'Workspace created', '');
 }
 /**
  * Remove broken entity references
  *
  * This removes references from nodes to entities which don't exist anymore.
  *
  * @param string $workspaceName
  * @param boolean $dryRun
  * @return void
  */
 public function removeBrokenEntityReferences($workspaceName, $dryRun)
 {
     $this->output->outputLine('Checking for broken entity references ...');
     /** @var \TYPO3\TYPO3CR\Domain\Model\Workspace $workspace */
     $workspace = $this->workspaceRepository->findByIdentifier($workspaceName);
     $nodeTypesWithEntityReferences = array();
     foreach ($this->nodeTypeManager->getNodeTypes() as $nodeType) {
         /** @var NodeType $nodeType */
         foreach (array_keys($nodeType->getProperties()) as $propertyName) {
             $propertyType = $nodeType->getPropertyType($propertyName);
             if (strpos($propertyType, '\\') !== false) {
                 if (!isset($nodeTypesWithEntityReferences[$nodeType->getName()])) {
                     $nodeTypesWithEntityReferences[$nodeType->getName()] = array();
                 }
                 $nodeTypesWithEntityReferences[$nodeType->getName()][$propertyName] = $propertyType;
             }
         }
     }
     $nodesWithBrokenEntityReferences = array();
     $brokenReferencesCount = 0;
     foreach ($nodeTypesWithEntityReferences as $nodeTypeName => $properties) {
         $nodeDatas = $this->nodeDataRepository->findByParentAndNodeTypeRecursively('/', $nodeTypeName, $workspace);
         foreach ($nodeDatas as $nodeData) {
             /** @var NodeData $nodeData */
             foreach ($properties as $propertyName => $propertyType) {
                 $propertyValue = $nodeData->getProperty($propertyName);
                 $convertedProperty = null;
                 if (is_object($propertyValue)) {
                     $convertedProperty = $propertyValue;
                 }
                 if (is_string($propertyValue) && strlen($propertyValue) === 36) {
                     $convertedProperty = $this->propertyMapper->convert($propertyValue, $propertyType);
                     if ($convertedProperty === null) {
                         $nodesWithBrokenEntityReferences[$nodeData->getIdentifier()][$propertyName] = $nodeData;
                         $this->output->outputLine('Broken reference in "%s", property "%s" (%s) referring to %s.', array($nodeData->getPath(), $nodeData->getIdentifier(), $propertyName, $propertyType, $propertyValue));
                         $brokenReferencesCount++;
                     }
                 }
                 if ($convertedProperty instanceof \Doctrine\ORM\Proxy\Proxy) {
                     try {
                         $convertedProperty->__load();
                     } catch (EntityNotFoundException $e) {
                         $nodesWithBrokenEntityReferences[$nodeData->getIdentifier()][$propertyName] = $nodeData;
                         $this->output->outputLine('Broken reference in "%s", property "%s" (%s) referring to %s.', array($nodeData->getPath(), $nodeData->getIdentifier(), $propertyName, $propertyType, $propertyValue));
                         $brokenReferencesCount++;
                     }
                 }
             }
         }
     }
     if ($brokenReferencesCount > 0) {
         $this->output->outputLine();
         if (!$dryRun) {
             $self = $this;
             $this->askBeforeExecutingTask('Do you want to remove the broken entity references?', function () use($self, $nodesWithBrokenEntityReferences, $brokenReferencesCount, $workspaceName, $dryRun) {
                 foreach ($nodesWithBrokenEntityReferences as $nodeIdentifier => $properties) {
                     foreach ($properties as $propertyName => $nodeData) {
                         /** @var NodeData $nodeData */
                         $nodeData->setProperty($propertyName, null);
                     }
                 }
                 $self->output->outputLine('Removed %s broken entity reference%s.', array($brokenReferencesCount, $brokenReferencesCount > 1 ? 's' : ''));
             });
         } else {
             $this->output->outputLine('Found %s broken entity reference%s to be removed.', array($brokenReferencesCount, $brokenReferencesCount > 1 ? 's' : ''));
         }
         $this->output->outputLine();
     }
 }