/**
  * In live workspace this just renders a tag; for logged in users with access to the Backend this also adds required
  * attributes for the editing.
  *
  * @param string $property Name of the property to render. Note: If this tag has child nodes, they overrule this argument!
  * @param string $tag The name of the tag that should be wrapped around the property. By default this is a <div>
  * @param NodeInterface $node The node of the content element. Optional, will be resolved from the TypoScript context by default.
  * @return string The rendered property with a wrapping tag. In the user workspace this adds some required attributes for the RTE to work
  * @throws ViewHelperException
  */
 public function render($property, $tag = 'div', NodeInterface $node = null)
 {
     $this->tag->setTagName($tag);
     $this->tag->forceClosingTag(true);
     $content = $this->renderChildren();
     if ($node === null) {
         $node = $this->getNodeFromTypoScriptContext();
     }
     if ($node === null) {
         throw new ViewHelperException('A node is required, but one was not supplied and could not be found in the TypoScript context.', 1408521638);
     }
     if ($content === null) {
         if (!$this->templateVariableContainer->exists($property)) {
             throw new ViewHelperException(sprintf('The property "%1$s" was not set as a template variable. If you use this ViewHelper in a partial, make sure to pass the node property "%1$s" as an argument.', $property), 1384507046);
         }
         $content = $this->templateVariableContainer->get($property);
     }
     $this->tag->setContent($content);
     /** @var $contentContext ContentContext */
     $contentContext = $node->getContext();
     if ($contentContext->getWorkspaceName() === 'live' || !$this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess')) {
         return $this->tag->render();
     }
     if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) {
         return $this->tag->render();
     }
     $this->tag->addAttribute('property', 'typo3:' . $property);
     $this->tag->addAttribute('class', $this->tag->hasAttribute('class') ? 'neos-inline-editable ' . $this->tag->getAttribute('class') : 'neos-inline-editable');
     return $this->tag->render();
 }
 /**
  * Wrap the $content identified by $node with the needed markup for the backend.
  *
  * @param NodeInterface $node
  * @param string $property
  * @param string $content
  * @return string
  */
 public function wrapContentProperty(NodeInterface $node, $property, $content)
 {
     /** @var $contentContext ContentContext */
     $contentContext = $node->getContext();
     if ($contentContext->getWorkspaceName() === 'live' || !$this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess')) {
         return $content;
     }
     if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) {
         return $content;
     }
     $attributes = array();
     $attributes['class'] = 'neos-inline-editable';
     $attributes['property'] = 'typo3:' . $property;
     $attributes['data-neos-node-type'] = $node->getNodeType()->getName();
     return $this->htmlAugmenter->addAttributes($content, $attributes, 'span');
 }
 /**
  * @test
  */
 public function wrapContentPropertyDoesNotAddEditingMetaDataIfEditNodePrivilegeIsNotGranted()
 {
     $this->mockContentContext->expects($this->atLeastOnce())->method('getWorkspaceName')->will($this->returnValue('not-live'));
     $this->mockPrivilegeManager->expects($this->atLeastOnce())->method('isPrivilegeTargetGranted')->with('TYPO3.Neos:Backend.GeneralAccess')->will($this->returnValue(true));
     $this->mockNodeAuthorizationService->expects($this->atLeastOnce())->method('isGrantedToEditNode')->will($this->returnValue(false));
     $this->mockHtmlAugmenter->expects($this->never())->method('addAttributes');
     $this->contentElementEditableService->wrapContentProperty($this->mockNode, 'someProperty', '<div>someRenderedPropertyValue</div>');
 }
 /**
  * @test
  */
 public function renderDoesNotAddEditingMetaDataIfEditNodePrivilegeIsNotGranted()
 {
     $this->templateVariables = array('someProperty' => 'somePropertyValue');
     $this->mockContentContext->expects($this->atLeastOnce())->method('getWorkspaceName')->will($this->returnValue('not-live'));
     $this->mockPrivilegeManager->expects($this->atLeastOnce())->method('isPrivilegeTargetGranted')->with('TYPO3.Neos:Backend.GeneralAccess')->will($this->returnValue(true));
     $this->mockNodeAuthorizationService->expects($this->atLeastOnce())->method('isGrantedToEditNode')->will($this->returnValue(false));
     $this->tagBuilder->expects($this->never())->method('addAttribute');
     $this->injectDependenciesIntoViewHelper($this->editableViewHelper);
     $this->injectTypoScriptObject();
     $this->editableViewHelper->render('someProperty');
 }
 /**
  * @Given /^I should get (TRUE|FALSE) when asking the node authorization service if setting the "([^"]*)" property is granted$/
  */
 public function iShouldGetFalseWhenAskingTheNodeAuthorizationServiceIfSettingThePropertyIsGranted($expectedResult, $propertyName)
 {
     if ($this->isolated === true) {
         $this->callStepInSubProcess(__METHOD__, sprintf(' %s %s %s %s', 'string', escapeshellarg(trim($expectedResult)), 'string', escapeshellarg($propertyName)));
     } else {
         if ($expectedResult === 'TRUE') {
             if ($this->nodeAuthorizationService->isGrantedToEditNodeProperty($this->currentNodes[0], $propertyName) !== true) {
                 Assert::fail('The node authorization service did not return TRUE!');
             }
         } else {
             if ($this->nodeAuthorizationService->isGrantedToEditNodeProperty($this->currentNodes[0], $propertyName) !== false) {
                 Assert::fail('The node authorization service did not return FALSE!');
             }
         }
     }
 }
 /**
  * Wrap the $content identified by $node with the needed markup for the backend.
  *
  * @param NodeInterface $node
  * @param string $typoScriptPath
  * @param string $content
  * @param boolean $renderCurrentDocumentMetadata When this flag is set we will render the global metadata for the current document
  * @return string
  */
 public function wrapContentObject(NodeInterface $node, $typoScriptPath, $content, $renderCurrentDocumentMetadata = false)
 {
     /** @var $contentContext ContentContext */
     $contentContext = $node->getContext();
     if ($contentContext->getWorkspaceName() === 'live' || !$this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess')) {
         return $content;
     }
     $nodeType = $node->getNodeType();
     $attributes = array();
     $attributes['typeof'] = 'typo3:' . $nodeType->getName();
     $attributes['about'] = $node->getContextPath();
     $classNames = array();
     if ($renderCurrentDocumentMetadata === true) {
         $attributes['data-neos-site-name'] = $contentContext->getCurrentSite()->getName();
         $attributes['data-neos-site-node-context-path'] = $contentContext->getCurrentSiteNode()->getContextPath();
         // Add the workspace of the TYPO3CR context to the attributes
         $attributes['data-neos-context-workspace-name'] = $contentContext->getWorkspaceName();
         $attributes['data-neos-context-dimensions'] = json_encode($contentContext->getDimensions());
         if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) {
             $attributes['data-node-__read-only'] = 'true';
             $attributes['data-nodedatatype-__read-only'] = 'boolean';
         }
     } else {
         if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) {
             return $content;
         }
         if ($node->isRemoved()) {
             $classNames[] = 'neos-contentelement-removed';
         }
         if ($node->isHidden()) {
             $classNames[] = 'neos-contentelement-hidden';
         }
         if ($nodeType->isOfType('TYPO3.Neos:ContentCollection')) {
             $attributes['rel'] = 'typo3:content-collection';
             // This is needed since the backend relies on this class (should not be necessary)
             $classNames[] = 'neos-contentcollection';
         } else {
             $classNames[] = 'neos-contentelement';
         }
         $uiConfiguration = $nodeType->hasConfiguration('ui') ? $nodeType->getConfiguration('ui') : array();
         if (isset($uiConfiguration['inlineEditable']) && $uiConfiguration['inlineEditable'] !== true || !isset($uiConfiguration['inlineEditable']) && !$this->hasInlineEditableProperties($node)) {
             $classNames[] = 'neos-not-inline-editable';
         }
         $attributes['tabindex'] = 0;
     }
     if ($node instanceof Node && !$node->dimensionsAreMatchingTargetDimensionValues()) {
         $classNames[] = 'neos-contentelement-shine-through';
     }
     if (count($classNames) > 0) {
         $attributes['class'] = implode(' ', $classNames);
     }
     // Add the actual workspace of the node, the node identifier and the TypoScript path to the attributes
     $attributes['data-node-_identifier'] = $node->getIdentifier();
     $attributes['data-node-__workspace-name'] = $node->getWorkspace()->getName();
     $attributes['data-node-__typoscript-path'] = $typoScriptPath;
     // these properties are needed together with the current NodeType to evaluate Node Type Constraints
     // TODO: this can probably be greatly cleaned up once we do not use CreateJS or VIE anymore.
     if ($node->getParent()) {
         $attributes['data-node-__parent-node-type'] = $node->getParent()->getNodeType()->getName();
     }
     if ($node->isAutoCreated()) {
         $attributes['data-node-_name'] = $node->getName();
         $attributes['data-node-_is-autocreated'] = 'true';
     }
     if ($node->getParent() && $node->getParent()->isAutoCreated()) {
         $attributes['data-node-_parent-is-autocreated'] = 'true';
         // we shall only add these properties if the parent is actually auto-created; as the Node-Type-Switcher in the UI relies on that.
         $attributes['data-node-__parent-node-name'] = $node->getParent()->getName();
         $attributes['data-node-__grandparent-node-type'] = $node->getParent()->getParent()->getNodeType()->getName();
     }
     $attributes = $this->addNodePropertyAttributes($node, $attributes);
     return $this->htmlAugmenter->addAttributes($content, $attributes, 'div', array('typeof'));
 }
 /**
  * @param NodeInterface $node
  * @param boolean $renderCurrentDocumentMetadata
  * @return boolean
  */
 protected function needsMetadata(NodeInterface $node, $renderCurrentDocumentMetadata)
 {
     /** @var $contentContext ContentContext */
     $contentContext = $node->getContext();
     return $contentContext->isInBackend() === true && ($renderCurrentDocumentMetadata === true || $this->nodeAuthorizationService->isGrantedToEditNode($node) === true);
 }