/**
  * Adds one (or multiple) properties found in a source code line to the classObject
  *
  * @param array $propertyMatches as returned from preg_match_all
  */
 protected function addProperty(array $propertyMatches, $startLine = NULL)
 {
     $properties = array_combine($propertyMatches['name'], $propertyMatches['value']);
     $isFirstProperty = TRUE;
     foreach ($properties as $propertyName => $propertyValue) {
         try {
             // the property has to exist in the classReflection
             $reflectionProperty = $this->classReflection->getProperty($propertyName);
             if ($reflectionProperty) {
                 $classProperty = new Tx_ExtensionBuilder_Domain_Model_Class_Property($propertyName);
                 $classProperty->mapToReflectionProperty($reflectionProperty);
                 // get the default value from regex matches
                 if (!empty($propertyValue)) {
                     if (strlen($classProperty->getVarType()) < 1) {
                         // try to detect the varType from default value
                         if (strpos($propertyValue, 'array') > -1) {
                             $varType = 'array';
                         } else {
                             eval('$varType = gettype(' . $propertyValue . ');');
                         }
                         if (!empty($varType) && $varType != 'NULL') {
                             $classProperty->setVarType($varType);
                         }
                     }
                     $classProperty->setValue(trim($propertyValue));
                     $classProperty->setDefault(TRUE);
                 }
                 if ($isFirstProperty) {
                     // only the first property will get the preceding block assigned
                     $precedingBlock = $this->concatLinesFromArray($this->lines, $this->lastMatchedLineNumber, $startLine, FALSE);
                     $classProperty->setPrecedingBlock($precedingBlock);
                     $isFirstProperty = FALSE;
                 }
                 $this->classObject->addProperty($classProperty);
                 $this->lastMatchedLineNumber = $this->lineCount;
             } else {
                 throw new Tx_ExtensionBuilder_Exception_ParseError(' Property ' . $propertyName . ' does not exist. Parsed from line ' . $this->lineCount . 'in ' . $this->classReflection->getFileName());
             }
         } catch (ReflectionException $e) {
             // ReflectionClass throws an exception if a property was not found
             t3lib_div::devlog('Exception in line : ' . $e->getMessage() . 'Property ' . $propertyName . ' found in line ' . $this->lineCount, 'extension_builder');
         }
     }
 }
 /**
  * Write a simple model class for a non aggregate root domain object with one to one relation
  *
  * @depends checkRequirements
  * @test
  */
 function writeModelClassWithManyToManyRelation()
 {
     $modelName = 'ModelCgt5';
     $relatedModelName = 'relatedModel';
     $propertyName = 'relNames';
     $domainObject = $this->buildDomainObject($modelName);
     $relatedDomainObject = $this->buildDomainObject($relatedModelName);
     $relation = new Tx_ExtensionBuilder_Domain_Model_DomainObject_Relation_ManyToManyRelation($propertyName);
     $relation->setForeignModel($relatedDomainObject);
     $relation->setInlineEditing(false);
     $domainObject->addProperty($relation);
     $classFileContent = $this->codeGenerator->generateDomainObjectCode($domainObject, $this->extension);
     $modelClassDir = 'Classes/Domain/Model/';
     $result = t3lib_div::mkdir_deep($this->extension->getExtensionDir(), $modelClassDir);
     $absModelClassDir = $this->extension->getExtensionDir() . $modelClassDir;
     $this->assertTrue(is_dir($absModelClassDir), 'Directory ' . $absModelClassDir . ' was not created');
     $modelClassPath = $absModelClassDir . $domainObject->getName() . '.php';
     t3lib_div::writeFile($modelClassPath, $classFileContent);
     $this->assertFileExists($modelClassPath, 'File was not generated: ' . $modelClassPath);
     $className = $domainObject->getClassName();
     include $modelClassPath;
     $this->assertTrue(class_exists($className), 'Class was not generated:' . $className);
     $reflection = new Tx_ExtensionBuilder_Reflection_ClassReflection($className);
     $this->assertTrue($reflection->hasMethod('add' . ucfirst(Tx_ExtensionBuilder_Utility_Inflector::singularize($propertyName))), 'Add method was not generated');
     $this->assertTrue($reflection->hasMethod('remove' . ucfirst(Tx_ExtensionBuilder_Utility_Inflector::singularize($propertyName))), 'Remove method was not generated');
     $this->assertTrue($reflection->hasMethod('get' . ucfirst($propertyName)), 'Getter was not generated');
     $this->assertTrue($reflection->hasMethod('set' . ucfirst($propertyName)), 'Setter was not generated');
     $this->assertTrue($reflection->hasMethod('initStorageObjects'), 'initStorageObjects was not generated');
     //checking methods
     $setterMethod = $reflection->getMethod('set' . ucfirst($propertyName));
     $this->assertTrue($setterMethod->isTaggedWith('param'), 'No param tag set for setter method');
     $paramTagValues = $setterMethod->getTagValues('param');
     $this->assertTrue(strpos($paramTagValues[0], 'Tx_Extbase_Persistence_ObjectStorage<' . $relatedDomainObject->getClassName()) === 0, 'Wrong param tag:' . $paramTagValues[0]);
     $parameters = $setterMethod->getParameters();
     $this->assertTrue(count($parameters) == 1, 'Wrong parameter count in setter method');
     $parameter = current($parameters);
     $this->assertTrue($parameter->getName() == $propertyName, 'Wrong parameter name in setter method');
     $this->assertTrue($parameter->getTypeHint() == 'Tx_Extbase_Persistence_ObjectStorage', 'Wrong type hint for setter parameter:' . $parameter->getTypeHint());
     $addMethod = $reflection->getMethod('add' . ucfirst(Tx_ExtensionBuilder_Utility_Inflector::singularize($propertyName)));
     $this->assertTrue($addMethod->isTaggedWith('param'), 'No param tag set for setter method');
     $paramTagValues = $addMethod->getTagValues('param');
     $this->assertTrue(strpos($paramTagValues[0], $relatedDomainObject->getClassName()) === 0, 'Wrong param tag:' . $paramTagValues[0]);
     $parameters = $addMethod->getParameters();
     $this->assertTrue(count($parameters) == 1, 'Wrong parameter count in add method');
     $parameter = current($parameters);
     $this->assertTrue($parameter->getName() == Tx_ExtensionBuilder_Utility_Inflector::singularize($propertyName), 'Wrong parameter name in add method');
     $this->assertTrue($parameter->getTypeHint() == $relatedDomainObject->getClassName(), 'Wrong type hint for add method parameter:' . $parameter->getTypeHint());
     $removeMethod = $reflection->getMethod('remove' . ucfirst(Tx_ExtensionBuilder_Utility_Inflector::singularize($propertyName)));
     $this->assertTrue($removeMethod->isTaggedWith('param'), 'No param tag set for remove method');
     $paramTagValues = $removeMethod->getTagValues('param');
     $this->assertTrue(strpos($paramTagValues[0], $relatedDomainObject->getClassName()) === 0, 'Wrong param tag:' . $paramTagValues[0]);
     $parameters = $removeMethod->getParameters();
     $this->assertTrue(count($parameters) == 1, 'Wrong parameter count in remove method');
     $parameter = current($parameters);
     $this->assertTrue($parameter->getName() == Tx_ExtensionBuilder_Utility_Inflector::singularize($propertyName) . 'ToRemove', 'Wrong parameter name in remove method');
     $this->assertTrue($parameter->getTypeHint() == $relatedDomainObject->getClassName(), 'Wrong type hint for remove method parameter:' . $parameter->getTypeHint());
 }
 /**
  * compares the number of properties found by parsing with those retrieved from the reflection class
  * @param Tx_ExtensionBuilder_Domain_Model_Class $classObject
  * @param Tx_ExtensionBuilder_Reflection_ClassReflection $classReflection
  * @return void
  */
 public function ParserFindsAllProperties($classObject, $classReflection)
 {
     $reflectionPropertyCount = count($classReflection->getNotInheritedProperties());
     $classObjectPropertCount = count($classObject->getProperties());
     $this->assertEquals($classObjectPropertCount, $reflectionPropertyCount, 'Not all Properties were found!');
 }