/** * @param ORM\Mapping\ClassMetadata $metadata * @param array $config * * @return array * * @throws Exceptions\InvalidMappingException * @throws ORM\Mapping\MappingException */ private function readExtendedMetadata(ORM\Mapping\ClassMetadata $metadata, array $config) { $class = $metadata->getReflectionClass(); // Create doctrine annotation reader $reader = $this->getDefaultAnnotationReader(); // Property annotations foreach ($class->getProperties() as $property) { if ($metadata->isMappedSuperclass && $property->isPrivate() === FALSE || $metadata->isInheritedField($property->getName()) || isset($metadata->associationMappings[$property->getName()]['inherited'])) { continue; } /** @var Mapping\Annotation\Timestampable $timestampable */ if ($timestampable = $reader->getPropertyAnnotation($property, self::EXTENSION_ANNOTATION)) { $field = $property->getName(); // No map field nor association if ($metadata->hasField($field) === FALSE && $metadata->hasAssociation($field) === FALSE && $this->configuration->useLazyAssociation() === FALSE) { if ($this->configuration->autoMapField()) { $metadata->mapField(['fieldName' => $field, 'type' => $this->configuration->dbFieldType, 'nullable' => TRUE]); } else { throw new Exceptions\InvalidMappingException("Unable to find timestampable [{$field}] as mapped property in entity - {$metadata->getName()}"); } } if ($metadata->hasField($field)) { if (!$this->isValidField($metadata, $field) && $this->configuration->useLazyAssociation() === FALSE) { throw new Exceptions\InvalidMappingException("Field - [{$field}] type is not valid and must be 'string' or a one-to-many relation in class - {$metadata->getName()}"); } } // Check for valid events if (!in_array($timestampable->on, ['update', 'create', 'change', 'delete'])) { throw new Exceptions\InvalidMappingException("Field - [{$field}] trigger 'on' is not one of [update, create, change] in class - {$metadata->getName()}"); } if ($timestampable->on === 'change') { if (!isset($timestampable->field)) { throw new Exceptions\InvalidMappingException("Missing parameters on property - {$field}, field must be set on [change] trigger in class - {$metadata->getName()}"); } if (is_array($timestampable->field) && isset($timestampable->value)) { throw new Exceptions\InvalidMappingException("Timestampable extension does not support multiple value changeset detection yet."); } $field = ['field' => $field, 'trackedField' => $timestampable->field, 'value' => is_array($timestampable->value) ? $timestampable->value : [$timestampable->value]]; } // properties are unique and mapper checks that, no risk here $config[$timestampable->on][] = $field; } } return $config; }