/**
  * {@inheritDoc}
  */
 public function readExtendedMetadata($meta, array &$config)
 {
     $validator = new Validator();
     $class = $this->getMetaReflectionClass($meta);
     // class annotations
     if ($annot = $this->reader->getClassAnnotation($class, self::TREE)) {
         if (!in_array($annot->type, $this->strategies)) {
             throw new InvalidMappingException("Tree type: {$annot->type} is not available.");
         }
         $config['strategy'] = $annot->type;
         $config['activate_locking'] = $annot->activateLocking;
         $config['locking_timeout'] = (int) $annot->lockingTimeout;
         if ($config['locking_timeout'] < 1) {
             throw new InvalidMappingException("Tree Locking Timeout must be at least of 1 second.");
         }
     }
     if ($annot = $this->reader->getClassAnnotation($class, self::CLOSURE)) {
         if (!class_exists($annot->class)) {
             throw new InvalidMappingException("Tree closure class: {$annot->class} does not exist.");
         }
         $config['closure'] = $annot->class;
     }
     // property annotations
     foreach ($class->getProperties() as $property) {
         if ($meta->isMappedSuperclass && !$property->isPrivate() || $meta->isInheritedField($property->name) || isset($meta->associationMappings[$property->name]['inherited'])) {
             continue;
         }
         // left
         if ($this->reader->getPropertyAnnotation($property, self::LEFT)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'left' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidField($meta, $field)) {
                 throw new InvalidMappingException("Tree left field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
             }
             $config['left'] = $field;
         }
         // right
         if ($this->reader->getPropertyAnnotation($property, self::RIGHT)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'right' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidField($meta, $field)) {
                 throw new InvalidMappingException("Tree right field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
             }
             $config['right'] = $field;
         }
         // ancestor/parent
         if ($this->reader->getPropertyAnnotation($property, self::PARENT)) {
             $field = $property->getName();
             if (!$meta->isSingleValuedAssociation($field)) {
                 throw new InvalidMappingException("Unable to find ancestor/parent child relation through ancestor field - [{$field}] in class - {$meta->name}");
             }
             $config['parent'] = $field;
         }
         // root
         if ($this->reader->getPropertyAnnotation($property, self::ROOT)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'root' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidFieldForRoot($meta, $field)) {
                 throw new InvalidMappingException("Tree root field - [{$field}] type is not valid and must be any of the 'integer' types or 'string' in class - {$meta->name}");
             }
             $config['root'] = $field;
         }
         // level
         if ($this->reader->getPropertyAnnotation($property, self::LEVEL)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'level' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidField($meta, $field)) {
                 throw new InvalidMappingException("Tree level field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
             }
             $config['level'] = $field;
         }
         // path
         if ($pathAnnotation = $this->reader->getPropertyAnnotation($property, self::PATH)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'path' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidFieldForPath($meta, $field)) {
                 throw new InvalidMappingException("Tree Path field - [{$field}] type is not valid. It must be string or text in class - {$meta->name}");
             }
             if (strlen($pathAnnotation->separator) > 1) {
                 throw new InvalidMappingException("Tree Path field - [{$field}] Separator {$pathAnnotation->separator} is invalid. It must be only one character long.");
             }
             $config['path'] = $field;
             $config['path_separator'] = $pathAnnotation->separator;
             $config['path_append_id'] = $pathAnnotation->appendId;
             $config['path_starts_with_separator'] = $pathAnnotation->startsWithSeparator;
             $config['path_ends_with_separator'] = $pathAnnotation->endsWithSeparator;
         }
         // path source
         if ($this->reader->getPropertyAnnotation($property, self::PATH_SOURCE)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'path_source' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidFieldForPathSource($meta, $field)) {
                 throw new InvalidMappingException("Tree PathSource field - [{$field}] type is not valid. It can be any of the integer variants, double, float or string in class - {$meta->name}");
             }
             $config['path_source'] = $field;
         }
         // path hash
         if ($this->reader->getPropertyAnnotation($property, self::PATH_HASH)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'path_hash' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidFieldForPathHash($meta, $field)) {
                 throw new InvalidMappingException("Tree PathHash field - [{$field}] type is not valid. It can be any of the integer variants, double, float or string in class - {$meta->name}");
             }
             $config['path_hash'] = $field;
         }
         // lock time
         if ($this->reader->getPropertyAnnotation($property, self::LOCK_TIME)) {
             $field = $property->getName();
             if (!$meta->hasField($field)) {
                 throw new InvalidMappingException("Unable to find 'lock_time' - [{$field}] as mapped property in entity - {$meta->name}");
             }
             if (!$validator->isValidFieldForLockTime($meta, $field)) {
                 throw new InvalidMappingException("Tree PathSource field - [{$field}] type is not valid. It must be \"date\" in class - {$meta->name}");
             }
             $config['lock_time'] = $field;
         }
     }
     if (isset($config['activate_locking']) && $config['activate_locking'] && !isset($config['lock_time'])) {
         throw new InvalidMappingException("You need to map a date field as the tree lock time field to activate locking support.");
     }
     if (!$meta->isMappedSuperclass && $config) {
         if (isset($config['strategy'])) {
             if (is_array($meta->identifier) && count($meta->identifier) > 1) {
                 throw new InvalidMappingException("Tree does not support composite identifiers in class - {$meta->name}");
             }
             $method = 'validate' . ucfirst($config['strategy']) . 'TreeMetadata';
             $validator->{$method}($meta, $config);
         } else {
             throw new InvalidMappingException("Cannot find Tree type for class: {$meta->name}");
         }
     }
 }
Example #2
0
 /**
  * {@inheritDoc}
  */
 public function readExtendedMetadata($meta, array &$config)
 {
     /**
      * @var \SimpleXmlElement $xml
      */
     $xml = $this->_getMapping($meta->name);
     $xmlDoctrine = $xml;
     $xml = $xml->children(self::GEDMO_NAMESPACE_URI);
     $validator = new Validator();
     if (isset($xml->tree) && $this->_isAttributeSet($xml->tree, 'type')) {
         $strategy = $this->_getAttribute($xml->tree, 'type');
         if (!in_array($strategy, $this->strategies)) {
             throw new InvalidMappingException("Tree type: {$strategy} is not available.");
         }
         $config['strategy'] = $strategy;
         $config['activate_locking'] = $this->_getAttribute($xml->tree, 'activate-locking') === 'true' ? true : false;
         if ($lockingTimeout = $this->_getAttribute($xml->tree, 'locking-timeout')) {
             $config['locking_timeout'] = (int) $lockingTimeout;
             if ($config['locking_timeout'] < 1) {
                 throw new InvalidMappingException("Tree Locking Timeout must be at least of 1 second.");
             }
         } else {
             $config['locking_timeout'] = 3;
         }
     }
     if (isset($xml->{'tree-closure'}) && $this->_isAttributeSet($xml->{'tree-closure'}, 'class')) {
         $class = $this->_getAttribute($xml->{'tree-closure'}, 'class');
         if (!class_exists($class)) {
             throw new InvalidMappingException("Tree closure class: {$class} does not exist.");
         }
         $config['closure'] = $class;
     }
     if (isset($xmlDoctrine->field)) {
         foreach ($xmlDoctrine->field as $mapping) {
             $mappingDoctrine = $mapping;
             $mapping = $mapping->children(self::GEDMO_NAMESPACE_URI);
             $field = $this->_getAttribute($mappingDoctrine, 'name');
             if (isset($mapping->{'tree-left'})) {
                 if (!$validator->isValidField($meta, $field)) {
                     throw new InvalidMappingException("Tree left field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
                 }
                 $config['left'] = $field;
             } elseif (isset($mapping->{'tree-right'})) {
                 if (!$validator->isValidField($meta, $field)) {
                     throw new InvalidMappingException("Tree right field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
                 }
                 $config['right'] = $field;
             } elseif (isset($mapping->{'tree-root'})) {
                 if (!$validator->isValidFieldForRoot($meta, $field)) {
                     throw new InvalidMappingException("Tree root field - [{$field}] type is not valid and must be any of the 'integer' types or 'string' in class - {$meta->name}");
                 }
                 $config['root'] = $field;
             } elseif (isset($mapping->{'tree-level'})) {
                 if (!$validator->isValidField($meta, $field)) {
                     throw new InvalidMappingException("Tree level field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
                 }
                 $config['level'] = $field;
             } elseif (isset($mapping->{'tree-path'})) {
                 if (!$validator->isValidFieldForPath($meta, $field)) {
                     throw new InvalidMappingException("Tree Path field - [{$field}] type is not valid. It must be string or text in class - {$meta->name}");
                 }
                 $separator = $this->_getAttribute($mapping->{'tree-path'}, 'separator');
                 if (strlen($separator) > 1) {
                     throw new InvalidMappingException("Tree Path field - [{$field}] Separator {$separator} is invalid. It must be only one character long.");
                 }
                 $appendId = $this->_getAttribute($mapping->{'tree-path'}, 'append_id');
                 if (!$appendId) {
                     $appendId = true;
                 } else {
                     $appendId = strtolower($appendId) == 'false' ? false : true;
                 }
                 $startsWithSeparator = $this->_getAttribute($mapping->{'tree-path'}, 'starts_with_separator');
                 if (!$startsWithSeparator) {
                     $startsWithSeparator = false;
                 } else {
                     $startsWithSeparator = strtolower($startsWithSeparator) == 'false' ? false : true;
                 }
                 $endsWithSeparator = $this->_getAttribute($mapping->{'tree-path'}, 'ends_with_separator');
                 if (!$endsWithSeparator) {
                     $endsWithSeparator = true;
                 } else {
                     $endsWithSeparator = strtolower($endsWithSeparator) == 'false' ? false : true;
                 }
                 $config['path'] = $field;
                 $config['path_separator'] = $separator;
                 $config['path_append_id'] = $appendId;
                 $config['path_starts_with_separator'] = $startsWithSeparator;
                 $config['path_ends_with_separator'] = $endsWithSeparator;
             } elseif (isset($mapping->{'tree-path-source'})) {
                 if (!$validator->isValidFieldForPathSource($meta, $field)) {
                     throw new InvalidMappingException("Tree PathSource field - [{$field}] type is not valid. It can be any of the integer variants, double, float or string in class - {$meta->name}");
                 }
                 $config['path_source'] = $field;
             } elseif (isset($mapping->{'tree-lock-time'})) {
                 if (!$validator->isValidFieldForLockTime($meta, $field)) {
                     throw new InvalidMappingException("Tree LockTime field - [{$field}] type is not valid. It must be \"date\" in class - {$meta->name}");
                 }
                 $config['lock_time'] = $field;
             }
         }
     }
     if (isset($config['activate_locking']) && $config['activate_locking'] && !isset($config['lock_time'])) {
         throw new InvalidMappingException("You need to map a date field as the tree lock time field to activate locking support.");
     }
     if ($xmlDoctrine->getName() == 'entity' || $xmlDoctrine->getName() == 'mapped-superclass') {
         if (isset($xmlDoctrine->{'many-to-one'})) {
             foreach ($xmlDoctrine->{'many-to-one'} as $manyToOneMapping) {
                 /**
                  * @var \SimpleXMLElement $manyToOneMapping
                  */
                 $manyToOneMappingDoctrine = $manyToOneMapping;
                 $manyToOneMapping = $manyToOneMapping->children(self::GEDMO_NAMESPACE_URI);
                 if (isset($manyToOneMapping->{'tree-parent'})) {
                     $field = $this->_getAttribute($manyToOneMappingDoctrine, 'field');
                     $targetEntity = $meta->associationMappings[$field]['targetEntity'];
                     $reflectionClass = new \ReflectionClass($targetEntity);
                     if ($targetEntity != $meta->name && !$reflectionClass->isSubclassOf($meta->name)) {
                         throw new InvalidMappingException("Unable to find ancestor/parent child relation through ancestor field - [{$field}] in class - {$meta->name}");
                     }
                     $config['parent'] = $field;
                 }
             }
         }
     } else {
         if ($xmlDoctrine->getName() == 'document') {
             if (isset($xmlDoctrine->{'reference-one'})) {
                 foreach ($xmlDoctrine->{'reference-one'} as $referenceOneMapping) {
                     /**
                      * @var \SimpleXMLElement $referenceOneMapping
                      */
                     $referenceOneMappingDoctrine = $referenceOneMapping;
                     $referenceOneMapping = $referenceOneMapping->children(self::GEDMO_NAMESPACE_URI);
                     if (isset($referenceOneMapping->{'tree-parent'})) {
                         $field = $this->_getAttribute($referenceOneMappingDoctrine, 'field');
                         if ($this->_getAttribute($referenceOneMappingDoctrine, 'target-document') != $meta->name) {
                             throw new InvalidMappingException("Unable to find ancestor/parent child relation through ancestor field - [{$field}] in class - {$meta->name}");
                         }
                         $config['parent'] = $field;
                     }
                 }
             }
         }
     }
     if (!$meta->isMappedSuperclass && $config) {
         if (isset($config['strategy'])) {
             if (is_array($meta->identifier) && count($meta->identifier) > 1) {
                 throw new InvalidMappingException("Tree does not support composite identifiers in class - {$meta->name}");
             }
             $method = 'validate' . ucfirst($config['strategy']) . 'TreeMetadata';
             $validator->{$method}($meta, $config);
         } else {
             throw new InvalidMappingException("Cannot find Tree type for class: {$meta->name}");
         }
     }
 }
Example #3
0
 /**
  * {@inheritDoc}
  */
 public function readExtendedMetadata($meta, array &$config)
 {
     $mapping = $this->_getMapping($meta->name);
     $validator = new Validator();
     if (isset($mapping['gedmo'])) {
         $classMapping = $mapping['gedmo'];
         if (isset($classMapping['tree']['type'])) {
             $strategy = $classMapping['tree']['type'];
             if (!in_array($strategy, $this->strategies)) {
                 throw new InvalidMappingException("Tree type: {$strategy} is not available.");
             }
             $config['strategy'] = $strategy;
             $config['activate_locking'] = isset($classMapping['tree']['activateLocking']) ? $classMapping['tree']['activateLocking'] : false;
             $config['locking_timeout'] = isset($classMapping['tree']['lockingTimeout']) ? (int) $classMapping['tree']['lockingTimeout'] : 3;
             if ($config['locking_timeout'] < 1) {
                 throw new InvalidMappingException("Tree Locking Timeout must be at least of 1 second.");
             }
         }
         if (isset($classMapping['tree']['closure'])) {
             $class = $classMapping['tree']['closure'];
             if (!class_exists($class)) {
                 throw new InvalidMappingException("Tree closure class: {$class} does not exist.");
             }
             $config['closure'] = $class;
         }
     }
     if (isset($mapping['fields'])) {
         foreach ($mapping['fields'] as $field => $fieldMapping) {
             if (isset($fieldMapping['gedmo'])) {
                 if (in_array('treeLeft', $fieldMapping['gedmo'])) {
                     if (!$validator->isValidField($meta, $field)) {
                         throw new InvalidMappingException("Tree left field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
                     }
                     $config['left'] = $field;
                 } elseif (in_array('treeRight', $fieldMapping['gedmo'])) {
                     if (!$validator->isValidField($meta, $field)) {
                         throw new InvalidMappingException("Tree right field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
                     }
                     $config['right'] = $field;
                 } elseif (in_array('treeLevel', $fieldMapping['gedmo'])) {
                     if (!$validator->isValidField($meta, $field)) {
                         throw new InvalidMappingException("Tree level field - [{$field}] type is not valid and must be 'integer' in class - {$meta->name}");
                     }
                     $config['level'] = $field;
                 } elseif (in_array('treeRoot', $fieldMapping['gedmo'])) {
                     if (!$validator->isValidFieldForRoot($meta, $field)) {
                         throw new InvalidMappingException("Tree root field - [{$field}] type is not valid and must be any of the 'integer' types or 'string' in class - {$meta->name}");
                     }
                     $config['root'] = $field;
                 } elseif (in_array('treePath', $fieldMapping['gedmo']) || isset($fieldMapping['gedmo']['treePath'])) {
                     if (!$validator->isValidFieldForPath($meta, $field)) {
                         throw new InvalidMappingException("Tree Path field - [{$field}] type is not valid. It must be string or text in class - {$meta->name}");
                     }
                     $treePathInfo = isset($fieldMapping['gedmo']['treePath']) ? $fieldMapping['gedmo']['treePath'] : $fieldMapping['gedmo'][array_search('treePath', $fieldMapping['gedmo'])];
                     if (is_array($treePathInfo) && isset($treePathInfo['separator'])) {
                         $separator = $treePathInfo['separator'];
                     } else {
                         $separator = '|';
                     }
                     if (strlen($separator) > 1) {
                         throw new InvalidMappingException("Tree Path field - [{$field}] Separator {$separator} is invalid. It must be only one character long.");
                     }
                     $config['path'] = $field;
                     $config['path_separator'] = $separator;
                 } elseif (in_array('treePathSource', $fieldMapping['gedmo'])) {
                     if (!$validator->isValidFieldForPathSource($meta, $field)) {
                         throw new InvalidMappingException("Tree PathSource field - [{$field}] type is not valid. It can be any of the integer variants, double, float or string in class - {$meta->name}");
                     }
                     $config['path_source'] = $field;
                 } elseif (in_array('treeLockTime', $fieldMapping['gedmo'])) {
                     if (!$validator->isValidFieldForLocktime($meta, $field)) {
                         throw new InvalidMappingException("Tree LockTime field - [{$field}] type is not valid. It must be \"date\" in class - {$meta->name}");
                     }
                     $config['lock_time'] = $field;
                 }
             }
         }
     }
     if (isset($config['activate_locking']) && $config['activate_locking'] && !isset($config['lock_time'])) {
         throw new InvalidMappingException("You need to map a date|datetime|timestamp field as the tree lock time field to activate locking support.");
     }
     if (isset($mapping['manyToOne'])) {
         foreach ($mapping['manyToOne'] as $field => $relationMapping) {
             if (isset($relationMapping['gedmo'])) {
                 if (in_array('treeParent', $relationMapping['gedmo'])) {
                     if ($relationMapping['targetEntity'] != $meta->name) {
                         throw new InvalidMappingException("Unable to find ancestor/parent child relation through ancestor field - [{$field}] in class - {$meta->name}");
                     }
                     $config['parent'] = $field;
                 }
             }
         }
     }
     if (!$meta->isMappedSuperclass && $config) {
         if (isset($config['strategy'])) {
             if (is_array($meta->identifier) && count($meta->identifier) > 1) {
                 throw new InvalidMappingException("Tree does not support composite identifiers in class - {$meta->name}");
             }
             $method = 'validate' . ucfirst($config['strategy']) . 'TreeMetadata';
             $validator->{$method}($meta, $config);
         } else {
             throw new InvalidMappingException("Cannot find Tree type for class: {$meta->name}");
         }
     }
 }