/**
  * Render user initials or an abbreviated name for a given username. If the account was deleted, use the username as fallback.
  *
  * @param string $format Supported are "fullFirstName" and "initials"
  * @return string
  */
 public function render($format = 'initials')
 {
     if (!in_array($format, array('fullFirstName', 'initials', 'fullName'))) {
         throw new \InvalidArgumentException(sprintf('Format "%s" given to history:userInitials(), only supporting "fullFirstName", "initials" and "fullName".', $format), 1415705861);
     }
     $username = $this->renderChildren();
     /* @var $requestedUser Person */
     $requestedUser = $this->domainUserService->getUser($username);
     if ($requestedUser === null || $requestedUser->getName() === null) {
         return $username;
     }
     $currentUser = $this->userService->getBackendUser();
     if ($currentUser) {
         if ($currentUser === $requestedUser) {
             $translationHelper = new TranslationHelper();
             $you = $translationHelper->translate('you', null, [], 'Main', 'TYPO3.Neos');
         }
     }
     switch ($format) {
         case 'initials':
             return mb_substr($requestedUser->getName()->getFirstName(), 0, 1) . mb_substr($requestedUser->getName()->getLastName(), 0, 1);
         case 'fullFirstName':
             return isset($you) ? $you : $requestedUser->getName()->getFirstName() . ' ' . mb_substr($requestedUser->getName()->getLastName(), 0, 1) . '.';
         case 'fullName':
             return isset($you) ? $you : $requestedUser->getName()->getFullName();
     }
 }
 public function initializeWorkspacesByName()
 {
     $workspaces = [];
     $personalWorkspace = $this->userService->getPersonalWorkspace();
     $workspaces[$personalWorkspace->getName()] = ['name' => $personalWorkspace->getName(), 'publishableNodes' => $this->getPublishableNodeInfo($personalWorkspace)];
     return $workspaces;
 }
 /**
  * Returns an array of usage reference objects.
  *
  * @param AssetInterface $asset
  * @return array<\TYPO3\Neos\Domain\Model\Dto\AssetUsageInNodeProperties>
  * @throws \TYPO3\TYPO3CR\Exception\NodeConfigurationException
  */
 public function getUsageReferences(AssetInterface $asset)
 {
     $assetIdentifier = $this->persistenceManager->getIdentifierByObject($asset);
     if (isset($this->firstlevelCache[$assetIdentifier])) {
         return $this->firstlevelCache[$assetIdentifier];
     }
     $userWorkspace = $this->userService->getPersonalWorkspace();
     $relatedNodes = [];
     foreach ($this->getRelatedNodes($asset) as $relatedNodeData) {
         $accessible = $this->domainUserService->currentUserCanReadWorkspace($relatedNodeData->getWorkspace());
         if ($accessible) {
             $context = $this->createContextMatchingNodeData($relatedNodeData);
         } else {
             $context = $this->createContentContext($userWorkspace->getName());
         }
         $site = $context->getCurrentSite();
         $node = $this->nodeFactory->createFromNodeData($relatedNodeData, $context);
         $flowQuery = new FlowQuery([$node]);
         /** @var \TYPO3\TYPO3CR\Domain\Model\NodeInterface $documentNode */
         $documentNode = $flowQuery->closest('[instanceof TYPO3.Neos:Document]')->get(0);
         $relatedNodes[] = new AssetUsageInNodeProperties($asset, $site, $documentNode, $node, $accessible);
     }
     $this->firstlevelCache[$assetIdentifier] = $relatedNodes;
     return $this->firstlevelCache[$assetIdentifier];
 }
 /**
  * Render user initials or an abbreviated name for a given username. If the account was deleted, use the username as fallback.
  *
  * @param string $format Supported are "fullFirstName" and "initials"
  * @return string
  */
 public function render($format = 'initials')
 {
     if (!in_array($format, array('fullFirstName', 'initials', 'fullName'))) {
         throw new \InvalidArgumentException(sprintf('Format "%s" given to history:userInitials(), only supporting "fullFirstName", "initials" and "fullName".', $format), 1415705861);
     }
     $accountIdentifier = $this->renderChildren();
     // TODO: search by credential source is still needed
     /* @var $account \TYPO3\Flow\Security\Account */
     $account = $this->accountRepository->findOneByAccountIdentifier($accountIdentifier);
     if ($account === null) {
         return $accountIdentifier;
     }
     /* @var $requestedUser Person */
     $requestedUser = $account->getParty();
     if ($requestedUser === null || $requestedUser->getName() === null) {
         return $accountIdentifier;
     }
     $currentUser = $this->userService->getBackendUser();
     if ($currentUser) {
         if ($currentUser === $requestedUser) {
             $translationHelper = new TranslationHelper();
             $you = $translationHelper->translateById('you', 'TYPO3.Neos');
         }
     }
     switch ($format) {
         case 'initials':
             return mb_substr($requestedUser->getName()->getFirstName(), 0, 1) . mb_substr($requestedUser->getName()->getLastName(), 0, 1);
         case 'fullFirstName':
             return isset($you) ? $you : $requestedUser->getName()->getFirstName() . ' ' . mb_substr($requestedUser->getName()->getLastName(), 0, 1) . '.';
         case 'fullName':
             return isset($you) ? $you : $requestedUser->getName()->getFullName();
     }
 }
 /**
  * Get the current rendering mode (editPreviewMode).
  * Will return a live mode when not in backend.
  *
  * @return UserInterfaceMode
  */
 public function findModeByCurrentUser()
 {
     if ($this->userService->getBackendUser() === NULL || !$this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess')) {
         return $this->findModeByName('live');
     }
     /** @var \TYPO3\Neos\Domain\Model\User $user */
     $editPreviewMode = $this->userService->getUserPreference('contentEditing.editPreviewMode');
     if ($editPreviewMode === NULL) {
         $editPreviewMode = $this->defaultEditPreviewMode;
     }
     $mode = $this->findModeByName($editPreviewMode);
     return $mode;
 }
 /**
  * @test
  */
 public function getUserWorkspaceNameReturnsTheUsersWorkspaceNameIfAUserIsLoggedIn()
 {
     $mockAccount = $this->getMockBuilder('TYPO3\\Flow\\Security\\Account')->disableOriginalConstructor()->getMock();
     $mockAccount->expects($this->atLeastOnce())->method('getAccountIdentifier')->will($this->returnValue('The UserName'));
     $this->mockSecurityContext->expects($this->atLeastOnce())->method('getAccount')->will($this->returnValue($mockAccount));
     $this->assertSame('user-TheUserName', $this->userService->getUserWorkspaceName());
 }
 /**
  * @test
  */
 public function getPersonalWorkspaceNameReturnsTheUsersWorkspaceNameIfAUserIsLoggedIn()
 {
     $mockUser = $this->getMockBuilder('TYPO3\\Neos\\Domain\\Model\\User')->disableOriginalConstructor()->getMock();
     $this->mockUserDomainService->expects($this->atLeastOnce())->method('getCurrentUser')->will($this->returnValue($mockUser));
     $this->mockUserDomainService->expects($this->atLeastOnce())->method('getUserName')->with($mockUser)->will($this->returnValue('TheUserName'));
     $this->assertSame('user-TheUserName', $this->userService->getPersonalWorkspaceName());
 }
 /**
  * Returns the node this even refers to, if it can be resolved.
  *
  * It might happen that, if this event refers to a node contained in a site which is not available anymore,
  * Doctrine's proxy class of the Site domain model will fail with an EntityNotFoundException. We catch this
  * case and return NULL.
  *
  * @return NodeInterface
  */
 public function getNode()
 {
     try {
         $context = $this->contextFactory->create(array('workspaceName' => $this->userService->getUserWorkspace()->getName(), 'dimensions' => $this->dimension, 'currentSite' => $this->getCurrentSite(), 'invisibleContentShown' => true));
         return $context->getNodeByIdentifier($this->nodeIdentifier);
     } catch (EntityNotFoundException $e) {
         return null;
     }
 }
 /**
  * If the specified workspace or its root node does not exist yet, the workspace and root node will be created.
  *
  * This method is basically a safeguard for legacy and potentially broken websites where users might not have
  * their own workspace yet. In a normal setup, the Domain User Service is responsible for creating and deleting
  * user workspaces.
  *
  * @param string $workspaceName Name of the workspace
  * @return void
  */
 protected function createWorkspaceAndRootNodeIfNecessary($workspaceName)
 {
     $workspace = $this->workspaceRepository->findOneByName($workspaceName);
     if ($workspace === null) {
         $liveWorkspace = $this->workspaceRepository->findOneByName('live');
         $owner = $this->userService->getBackendUser();
         $workspace = new Workspace($workspaceName, $liveWorkspace, $owner);
         $this->workspaceRepository->add($workspace);
         $this->persistenceManager->whitelistObject($workspace);
     }
     $contentContext = $this->createContext($workspaceName);
     $rootNode = $contentContext->getRootNode();
     $this->persistenceManager->whitelistObject($rootNode);
     $this->persistenceManager->whitelistObject($rootNode->getNodeData());
     $this->persistenceManager->persistAll(true);
 }
 /**
  * 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));
 }
 /**
  * Returns a specific URI string to redirect to after the login; or NULL if there is none.
  *
  * @param ActionRequest $actionRequest
  * @return string
  */
 public function getAfterLoginRedirectionUri(ActionRequest $actionRequest)
 {
     $user = $this->userService->getBackendUser();
     if ($user === NULL) {
         return NULL;
     }
     $workspaceName = $this->userService->getUserWorkspaceName();
     $this->createWorkspaceAndRootNodeIfNecessary($workspaceName);
     $uriBuilder = new UriBuilder();
     $uriBuilder->setRequest($actionRequest);
     $uriBuilder->setFormat('html');
     $uriBuilder->setCreateAbsoluteUri(TRUE);
     $contentContext = $this->createContext($workspaceName);
     $lastVisitedNode = $this->getLastVisitedNode($workspaceName);
     if ($lastVisitedNode !== NULL) {
         return $uriBuilder->uriFor('show', array('node' => $lastVisitedNode), 'Frontend\\Node', 'TYPO3.Neos');
     }
     return $uriBuilder->uriFor('show', array('node' => $contentContext->getCurrentSiteNode()), 'Frontend\\Node', 'TYPO3.Neos');
 }
 /**
  * Renders the translated label.
  *
  * Replaces all placeholders with corresponding values if they exist in the
  * translated label.
  *
  * @param string $id Id to use for finding translation (trans-unit id in XLIFF)
  * @param string $value If $key is not specified or could not be resolved, this value is used. If this argument is not set, child nodes will be used to render the default
  * @param array $arguments Numerically indexed array of values to be inserted into placeholders
  * @param string $source Name of file with translations
  * @param string $package Target package key. If not set, the current package key will be used
  * @param mixed $quantity A number to find plural form for (float or int), NULL to not use plural forms
  * @param string $languageIdentifier An identifier of a language to use (NULL for using the default language)
  * @return string Translated label or source label / ID key
  * @throws ViewHelper\Exception
  */
 public function render($id = null, $value = null, array $arguments = array(), $source = 'Main', $package = null, $quantity = null, $languageIdentifier = null)
 {
     if (preg_match(TranslationHelper::I18N_LABEL_ID_PATTERN, $id) === 1) {
         // In the longer run, this "extended ID" format should directly be resolved in the localization service
         list($package, $source, $id) = explode(':', $id, 3);
         $source = str_replace('.', '/', $source);
     }
     if ($languageIdentifier === null) {
         $languageIdentifier = $this->userService->getInterfaceLanguage();
     }
     // Catch exception in case the translation file doesn't exist, should be fixed in Flow 3.1
     try {
         $translation = parent::render($id, $value, $arguments, $source, $package, $quantity, $languageIdentifier);
         // Fallback to english label if label was not available in specific language
         if ($translation === $id && $languageIdentifier !== 'en') {
             $translation = parent::render($id, $value, $arguments, $source, $package, $quantity, 'en');
         }
         return $translation;
     } catch (Exception $exception) {
         return $value ?: $id;
     }
 }
 /**
  * Displays the backend interface
  *
  * @param NodeInterface $node The node that will be displayed on the first tab
  * @return void
  */
 public function indexAction(NodeInterface $node = null)
 {
     $this->contentCache->flush();
     $this->session->start();
     $this->session->putData('__cheEnabled__', true);
     if ($user = $this->userService->getBackendUser()) {
         $workspaceName = $this->userService->getPersonalWorkspaceName();
         $contentContext = $this->createContext($workspaceName);
         $contentContext->getWorkspace();
         $this->persistenceManager->persistAll();
         $siteNode = $contentContext->getCurrentSiteNode();
         if ($node === null) {
             $node = $siteNode;
         }
         $this->view->assign('user', $user);
         $this->view->assign('documentNode', $node);
         $this->view->assign('site', $node);
         $this->view->assign('translations', $this->xliffService->getCachedJson(new Locale($this->userService->getInterfaceLanguage())));
         return;
     }
     $this->redirectToUri($this->uriBuilder->uriFor('index', array(), 'Login', 'TYPO3.Neos'));
 }
 /**
  * Get Related Nodes for an asset
  *
  * @param Asset $asset
  * @return void
  */
 public function relatedNodesAction(Asset $asset)
 {
     $userWorkspace = $this->userService->getPersonalWorkspace();
     $relatedNodes = [];
     foreach ($this->getRelatedNodes($asset) as $relatedNodeData) {
         $accessible = $this->domainUserService->currentUserCanReadWorkspace($relatedNodeData->getWorkspace());
         if ($accessible) {
             $context = $this->createContextMatchingNodeData($relatedNodeData);
         } else {
             $context = $this->createContentContext($userWorkspace->getName());
         }
         $site = $context->getCurrentSite();
         $node = $this->nodeFactory->createFromNodeData($relatedNodeData, $context);
         $flowQuery = new FlowQuery([$node]);
         /** @var Node $documentNode */
         $documentNode = $flowQuery->closest('[instanceof TYPO3.Neos:Document]')->get(0);
         $documentNodeIdentifier = $documentNode instanceof NodeInterface ? $documentNode->getIdentifier() : null;
         $relatedNodes[$site->getNodeName()]['site'] = $site;
         $relatedNodes[$site->getNodeName()]['documentNodes'][$documentNodeIdentifier]['node'] = $documentNode;
         $relatedNodes[$site->getNodeName()]['documentNodes'][$documentNodeIdentifier]['nodes'][] = ['node' => $node, 'nodeData' => $relatedNodeData, 'contextDocumentNode' => $documentNode, 'accessible' => $accessible];
     }
     $this->view->assignMultiple(['asset' => $asset, 'relatedNodes' => $relatedNodes, 'contentDimensions' => $this->contentDimensionPresetSource->getAllPresets(), 'userWorkspace' => $userWorkspace]);
 }
 /**
  * Get data
  *
  * @param NodeInterface $node The node that is currently edited (optional)
  * @param array $arguments Additional arguments (key / value)
  * @return mixed JSON serializable data
  * @api
  */
 public function getData(NodeInterface $node = NULL, array $arguments)
 {
     return array('name' => $this->userService->getBackendUser()->getName()->getFullName());
 }
 /**
  * Returns the cached json array with the xliff labels
  *
  * @return string
  */
 public function getXliffAsJsonAction()
 {
     $this->response->setHeader('Content-Type', 'application/json');
     $locale = new Locale($this->userService->getInterfaceLanguage());
     return $this->xliffService->getCachedJson($locale);
 }
 /**
  * @return string The current backend users interface language
  */
 public function render()
 {
     return $this->userService->getInterfaceLanguage();
 }
 /**
  * Get Related Nodes for an asset
  *
  * @param AssetInterface $asset
  * @return void
  */
 public function relatedNodesAction(AssetInterface $asset)
 {
     $userWorkspace = $this->userService->getPersonalWorkspace();
     $usageReferences = $this->assetService->getUsageReferences($asset);
     $relatedNodes = [];
     /** @var AssetUsageInNodeProperties $usage */
     foreach ($usageReferences as $usage) {
         $documentNodeIdentifier = $usage->getDocumentNode() instanceof NodeInterface ? $usage->getDocumentNode()->getIdentifier() : null;
         $relatedNodes[$usage->getSite()->getNodeName()]['site'] = $usage->getSite();
         $relatedNodes[$usage->getSite()->getNodeName()]['documentNodes'][$documentNodeIdentifier]['node'] = $usage->getDocumentNode();
         $relatedNodes[$usage->getSite()->getNodeName()]['documentNodes'][$documentNodeIdentifier]['nodes'][] = ['node' => $usage->getNode(), 'nodeData' => $usage->getNode()->getNodeData(), 'contextDocumentNode' => $usage->getDocumentNode(), 'accessible' => $usage->isAccessible()];
     }
     $this->view->assignMultiple(['asset' => $asset, 'relatedNodes' => $relatedNodes, 'contentDimensions' => $this->contentDimensionPresetSource->getAllPresets(), 'userWorkspace' => $userWorkspace]);
 }
 /**
  * Set the locale according to the user settings
  *
  * @return void
  */
 protected function initializeObject()
 {
     $this->_localizationService->getConfiguration()->setCurrentLocale(new \TYPO3\Flow\I18n\Locale($this->_userService->getInterfaceLanguage()));
 }