/**
  * Publish changes of a workspace
  *
  * This command publishes all modified, created or deleted nodes in the specified workspace to its base workspace.
  * If a target workspace is specified, the content is published to that workspace instead.
  *
  * @param string $workspace Name of the workspace containing the changes to publish, for example "user-john"
  * @param string $targetWorkspace If specified, the content will be published to this workspace instead of the base workspace
  * @param boolean $verbose If enabled, some information about individual nodes will be displayed
  * @param boolean $dryRun If set, only displays which nodes would be published, no real changes are committed
  * @return void
  */
 public function publishCommand($workspace, $targetWorkspace = NULL, $verbose = FALSE, $dryRun = FALSE)
 {
     $workspaceName = $workspace;
     $workspace = $this->workspaceRepository->findOneByName($workspaceName);
     if (!$workspace instanceof Workspace) {
         $this->outputLine('Workspace "%s" does not exist', array($workspaceName));
         $this->quit(1);
     }
     if ($targetWorkspace === NULL) {
         $targetWorkspace = $workspace->getBaseWorkspace();
         $targetWorkspaceName = $targetWorkspace->getName();
     } else {
         $targetWorkspaceName = $targetWorkspace;
         $targetWorkspace = $this->workspaceRepository->findOneByName($targetWorkspaceName);
         if (!$targetWorkspace instanceof Workspace) {
             $this->outputLine('Target workspace "%s" does not exist', array($targetWorkspaceName));
             $this->quit(2);
         }
         $possibleTargetWorkspaceNames = array();
         $baseWorkspace = $workspace->getBaseWorkspace();
         while ($targetWorkspace !== $baseWorkspace) {
             if ($baseWorkspace === NULL) {
                 $this->outputLine('The target workspace must be a base workspace of "%s".', array($targetWorkspaceName));
                 if (count($possibleTargetWorkspaceNames) > 1) {
                     $this->outputLine('For "%s" possible target workspaces currently are: %s', array($workspaceName, implode(', ', $possibleTargetWorkspaceNames)));
                 } else {
                     $this->outputLine('For "%s" the only possible target workspace currently is "%s".', array($workspaceName, reset($possibleTargetWorkspaceNames)));
                 }
                 $this->quit(3);
             }
             $possibleTargetWorkspaceNames[] = $baseWorkspace->getName();
             $baseWorkspace = $baseWorkspace->getBaseWorkspace();
         }
     }
     try {
         $nodes = $this->publishingService->getUnpublishedNodes($workspace);
     } catch (\Exception $exception) {
         $this->outputLine('An error occurred while fetching unpublished nodes from workspace %s, publish aborted.', array($workspaceName));
         $this->quit(1);
     }
     $this->outputLine('The workspace %s contains %u unpublished nodes.', array($workspaceName, count($nodes)));
     foreach ($nodes as $node) {
         /** @var \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node */
         if ($verbose) {
             $this->outputLine('    ' . $node->getPath());
         }
         if (!$dryRun) {
             $this->publishingService->publishNode($node, $targetWorkspace);
         }
     }
     if (!$dryRun) {
         $this->outputLine('Published all nodes in workspace %s to workspace %s', array($workspaceName, $targetWorkspaceName));
     }
 }
 /**
  * @test
  */
 public function publishNodePublishesTheNodeAndItsChildNodeCollectionsIfTheNodeTypeHasChildNodes()
 {
     $mockNode = $this->getMockBuilder('TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface')->getMock();
     $mockChildNode = $this->getMockBuilder('TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface')->getMock();
     $mockNodeType = $this->getMockBuilder('TYPO3\\TYPO3CR\\Domain\\Model\\NodeType')->disableOriginalConstructor()->setMethods(array('hasConfiguration', 'isOfType'))->getMock();
     $mockNodeType->expects($this->atLeastOnce())->method('hasConfiguration')->with('childNodes')->will($this->returnValue(true));
     $mockNode->expects($this->atLeastOnce())->method('getNodeType')->will($this->returnValue($mockNodeType));
     $mockNode->expects($this->atLeastOnce())->method('getWorkspace')->will($this->returnValue($this->mockWorkspace));
     $mockNode->expects($this->atLeastOnce())->method('getChildNodes')->with('TYPO3.Neos:ContentCollection')->will($this->returnValue(array($mockChildNode)));
     $mockTargetWorkspace = $this->getMockBuilder('TYPO3\\TYPO3CR\\Domain\\Model\\Workspace')->disableOriginalConstructor()->getMock();
     $this->mockWorkspace->expects($this->atLeastOnce())->method('publishNodes')->with(array($mockNode, $mockChildNode), $mockTargetWorkspace);
     $this->publishingService->publishNode($mockNode, $mockTargetWorkspace);
 }
 /**
  * Publish nodes
  *
  * @param array $nodeContextPaths
  * @param string $targetWorkspaceName
  * @return void
  */
 public function publishAction(array $nodeContextPaths, $targetWorkspaceName)
 {
     try {
         $targetWorkspace = $this->workspaceRepository->findOneByName($targetWorkspaceName);
         foreach ($nodeContextPaths as $contextPath) {
             $node = $this->nodeService->getNodeFromContextPath($contextPath);
             $this->publishingService->publishNode($node, $targetWorkspace);
         }
         $success = new Success();
         $success->setMessage(sprintf('Published %d change(s) to %s.', count($nodeContextPaths), $targetWorkspaceName));
         $this->updateWorkspaceInfo($nodeContextPaths[0]);
         $this->feedbackCollection->add($success);
         $this->persistenceManager->persistAll();
     } catch (\Exception $e) {
         $error = new Error();
         $error->setMessage($e->getMessage());
         $this->feedbackCollection->add($error);
     }
     $this->view->assign('value', $this->feedbackCollection);
 }
 /**
  * Publishes or discards the given nodes
  *
  * @param array $nodes <\TYPO3\TYPO3CR\Domain\Model\NodeInterface> $nodes
  * @param string $action
  * @param Workspace $selectedWorkspace
  * @throws \Exception
  * @throws \TYPO3\Flow\Property\Exception
  * @throws \TYPO3\Flow\Security\Exception
  */
 public function publishOrDiscardNodesAction(array $nodes, $action, Workspace $selectedWorkspace = null)
 {
     $propertyMappingConfiguration = $this->propertyMappingConfigurationBuilder->build();
     $propertyMappingConfiguration->setTypeConverterOption('TYPO3\\TYPO3CR\\TypeConverter\\NodeConverter', \TYPO3\TYPO3CR\TypeConverter\NodeConverter::REMOVED_CONTENT_SHOWN, true);
     foreach ($nodes as $key => $node) {
         $nodes[$key] = $this->propertyMapper->convert($node, 'TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface', $propertyMappingConfiguration);
     }
     switch ($action) {
         case 'publish':
             foreach ($nodes as $node) {
                 $this->publishingService->publishNode($node);
             }
             $this->addFlashMessage($this->translator->translateById('workspaces.selectedChangesHaveBeenPublished', [], null, null, 'Modules', 'TYPO3.Neos'));
             break;
         case 'discard':
             $this->publishingService->discardNodes($nodes);
             $this->addFlashMessage($this->translator->translateById('workspaces.selectedChangesHaveBeenDiscarded', [], null, null, 'Modules', 'TYPO3.Neos'));
             break;
         default:
             throw new \RuntimeException('Invalid action "' . htmlspecialchars($action) . '" given.', 1346167441);
     }
     $this->redirect('show', null, null, ['workspace' => $selectedWorkspace]);
 }
 /**
  * Publishes or discards the given nodes
  *
  * @param array<\TYPO3\TYPO3CR\Domain\Model\NodeInterface> $nodes
  * @param string $action
  * @return void
  * @throws \RuntimeException
  */
 public function publishOrDiscardNodesAction(array $nodes, $action)
 {
     $propertyMappingConfiguration = $this->propertyMappingConfigurationBuilder->build();
     $propertyMappingConfiguration->setTypeConverterOption('TYPO3\\TYPO3CR\\TypeConverter\\NodeConverter', \TYPO3\TYPO3CR\TypeConverter\NodeConverter::REMOVED_CONTENT_SHOWN, TRUE);
     foreach ($nodes as $key => $node) {
         $nodes[$key] = $this->propertyMapper->convert($node, 'TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface', $propertyMappingConfiguration);
     }
     switch ($action) {
         case 'publish':
             foreach ($nodes as $node) {
                 $this->publishingService->publishNode($node);
             }
             $this->addFlashMessage('Selected changes have been published', NULL, NULL, array(), 412420736);
             break;
         case 'discard':
             $this->publishingService->discardNodes($nodes);
             $this->addFlashMessage('Selected changes have been discarded', NULL, NULL, array(), 412420851);
             break;
         default:
             throw new \RuntimeException('Invalid action "' . $action . '" given.', 1346167441);
     }
     $this->redirect('index');
 }
 /**
  * Publishes the given node to the specified targetWorkspace
  *
  * @param NodeInterface $node
  * @param string $targetWorkspaceName
  * @return void
  */
 public function publishNodeAction(NodeInterface $node, $targetWorkspaceName = null)
 {
     $targetWorkspace = $targetWorkspaceName !== null ? $this->workspaceRepository->findOneByName($targetWorkspaceName) : null;
     $this->publishingService->publishNode($node, $targetWorkspace);
     $this->throwStatus(204, 'Node published', '');
 }