/**
  * Generate a TypoScript prototype definition for a given node type
  *
  * A node will be rendered by TYPO3.Neos:Content by default with a template in
  * resource://PACKAGE_KEY/Private/Templates/NodeTypes/NAME.html and forwards all public
  * node properties to the template TypoScript object.
  *
  * @param NodeType $nodeType
  * @return string
  */
 public function generate(NodeType $nodeType)
 {
     if (strpos($nodeType->getName(), ':') === false) {
         return '';
     }
     if ($nodeType->isOfType('TYPO3.Neos:Content')) {
         $basePrototypeName = 'TYPO3.Neos:Content';
     } elseif ($nodeType->isOfType('TYPO3.Neos:Document')) {
         $basePrototypeName = 'TYPO3.Neos:Document';
     } else {
         $basePrototypeName = 'TYPO3.TypoScript:Template';
     }
     $output = 'prototype(' . $nodeType->getName() . ') < prototype(' . $basePrototypeName . ') {' . chr(10);
     list($packageKey, $relativeName) = explode(':', $nodeType->getName(), 2);
     $templatePath = 'resource://' . $packageKey . '/Private/Templates/NodeTypes/' . $relativeName . '.html';
     $output .= "\t" . 'templatePath = \'' . $templatePath . '\'' . chr(10);
     foreach ($nodeType->getProperties() as $propertyName => $propertyConfiguration) {
         if (isset($propertyName[0]) && $propertyName[0] !== '_') {
             $output .= "\t" . $propertyName . ' = ${q(node).property("' . $propertyName . '")}' . chr(10);
             if (isset($propertyConfiguration['type']) && isset($propertyConfiguration['ui']['inlineEditable']) && $propertyConfiguration['type'] === 'string' && $propertyConfiguration['ui']['inlineEditable'] === true) {
                 $output .= "\t" . $propertyName . '.@process.convertUris = TYPO3.Neos:ConvertUris' . chr(10);
             }
         }
     }
     $output .= '}' . chr(10);
     return $output;
 }
 /**
  * @test
  */
 public function nodeTypesCanHaveAnyNumberOfSuperTypes()
 {
     $baseType = new NodeType('TYPO3.TYPO3CR:Base', array(), array());
     $folderType = new NodeType('TYPO3.TYPO3CR.Testing:Document', array($baseType), array());
     $hideableNodeType = new NodeType('TYPO3.TYPO3CR.Testing:HideableContent', array(), array());
     $pageType = new NodeType('TYPO3.TYPO3CR.Testing:Page', array($folderType, $hideableNodeType), array());
     $this->assertEquals(array($folderType, $hideableNodeType), $pageType->getDeclaredSuperTypes());
     $this->assertTrue($pageType->isOfType('TYPO3.TYPO3CR.Testing:Page'));
     $this->assertTrue($pageType->isOfType('TYPO3.TYPO3CR.Testing:HideableContent'));
     $this->assertTrue($pageType->isOfType('TYPO3.TYPO3CR.Testing:Document'));
     $this->assertTrue($pageType->isOfType('TYPO3.TYPO3CR:Base'));
     $this->assertFalse($pageType->isOfType('TYPO3.TYPO3CR:Exotic'));
 }
 /**
  * @param NodeType $nodeType The (uninitialized) node type to process
  * @param array $configuration The configuration of the node type
  * @param array $options The processor options
  * @return void
  */
 public function process(NodeType $nodeType, array &$configuration, array $options)
 {
     if ($nodeType->isOfType('TYPO3.TYPO3CR.Testing:NodeTypeWithProcessor')) {
         $someOption = isset($options['someOption']) ? $options['someOption'] : '';
         $someOtherOption = isset($options['someOtherOption']) ? $options['someOtherOption'] : '';
         $configuration['properties']['test1']['defaultValue'] = sprintf('The value of "someOption" is "%s", the value of "someOtherOption" is "%s"', $someOption, $someOtherOption);
     }
 }
 /**
  * This method loops over the constraints and finds node types that the given node type inherits from. For all
  * matched super types, their super types are traversed to find the closest super node with a constraint which
  * is used to evaluated if the node type is allowed. It finds the closest results for true and false, and uses
  * the distance to choose which one wins (lowest). If no result is found the node type is allowed.
  *
  * @param NodeType $nodeType
  * @param array $constraints
  * @return boolean|NULL if no constraint matched
  */
 protected function isNodeTypeAllowedByInheritanceConstraints(NodeType $nodeType, array $constraints)
 {
     $constraintDistanceForTrue = null;
     $constraintDistanceForFalse = null;
     foreach ($constraints as $superType => $constraint) {
         if ($nodeType->isOfType($superType)) {
             $distance = $this->traverseSuperTypes($nodeType, $superType, 0);
             if ($constraint === true && ($constraintDistanceForTrue === null || $constraintDistanceForTrue > $distance)) {
                 $constraintDistanceForTrue = $distance;
             }
             if ($constraint === false && ($constraintDistanceForFalse === null || $constraintDistanceForFalse > $distance)) {
                 $constraintDistanceForFalse = $distance;
             }
         }
     }
     if ($constraintDistanceForTrue !== null && $constraintDistanceForFalse !== null) {
         return $constraintDistanceForTrue < $constraintDistanceForFalse ? true : false;
     }
     if ($constraintDistanceForFalse !== null) {
         return false;
     }
     if ($constraintDistanceForTrue !== null) {
         return true;
     }
     return null;
 }
 /**
  * This method loops over the constraints and finds node types that the given node type inherits from. For all
  * matched super types, their super types are traversed to find the closest super node with a constraint which
  * is used to evaluated if the node type is allowed. It finds the closest results for true and false, and uses
  * the distance to choose which one wins (lowest). If no result is found the node type is allowed.
  *
  * @param NodeType $nodeType
  * @param array $constraints
  * @return boolean|NULL if no constraint matched
  */
 protected function isNodeTypeAllowedByInheritanceConstraints(NodeType $nodeType, array $constraints)
 {
     $constraintDistanceForTrue = NULL;
     $constraintDistanceForFalse = NULL;
     foreach ($constraints as $superType => $constraint) {
         if ($nodeType->isOfType($superType)) {
             $distance = $this->traverseSuperTypes($nodeType, $superType, 0);
             if ($constraint === TRUE && ($constraintDistanceForTrue === NULL || $constraintDistanceForTrue > $distance)) {
                 $constraintDistanceForTrue = $distance;
             }
             if ($constraint === FALSE && ($constraintDistanceForFalse === NULL || $constraintDistanceForFalse > $distance)) {
                 $constraintDistanceForFalse = $distance;
             }
         }
     }
     if ($constraintDistanceForTrue !== NULL && $constraintDistanceForFalse !== NULL) {
         return $constraintDistanceForTrue < $constraintDistanceForFalse ? TRUE : FALSE;
     }
     if ($constraintDistanceForFalse !== NULL) {
         return FALSE;
     }
     if ($constraintDistanceForTrue !== NULL) {
         return TRUE;
     }
     return NULL;
 }