AnnotationDriver.php
9 months ago
AttributeDriver.php
9 months ago
AttributeReader.php
9 months ago
CompatibilityAnnotationDriver.php
9 months ago
DriverChain.php
9 months ago
PHPDriver.php
9 months ago
ReflectionBasedDriver.php
9 months ago
RepeatableAttributeCollection.php
9 months ago
StaticPHPDriver.php
9 months ago
index.php
9 months ago
AnnotationDriver.php
525 lines
| 1 | <?php |
| 2 | declare (strict_types=1); |
| 3 | namespace MailPoetVendor\Doctrine\ORM\Mapping\Driver; |
| 4 | if (!defined('ABSPATH')) exit; |
| 5 | use MailPoetVendor\Doctrine\Common\Annotations\AnnotationReader; |
| 6 | use MailPoetVendor\Doctrine\Common\Annotations\Reader; |
| 7 | use MailPoetVendor\Doctrine\Deprecations\Deprecation; |
| 8 | use MailPoetVendor\Doctrine\ORM\Events; |
| 9 | use MailPoetVendor\Doctrine\ORM\Mapping; |
| 10 | use MailPoetVendor\Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; |
| 11 | use MailPoetVendor\Doctrine\ORM\Mapping\ClassMetadata; |
| 12 | use MailPoetVendor\Doctrine\ORM\Mapping\MappingException; |
| 13 | use MailPoetVendor\Doctrine\Persistence\Mapping\ClassMetadata as PersistenceClassMetadata; |
| 14 | use MailPoetVendor\Doctrine\Persistence\Mapping\Driver\ColocatedMappingDriver; |
| 15 | use ReflectionClass; |
| 16 | use ReflectionMethod; |
| 17 | use ReflectionProperty; |
| 18 | use UnexpectedValueException; |
| 19 | use function assert; |
| 20 | use function class_exists; |
| 21 | use function constant; |
| 22 | use function count; |
| 23 | use function defined; |
| 24 | use function get_class; |
| 25 | use function is_array; |
| 26 | use function is_numeric; |
| 27 | class AnnotationDriver extends CompatibilityAnnotationDriver |
| 28 | { |
| 29 | use ColocatedMappingDriver; |
| 30 | use ReflectionBasedDriver; |
| 31 | protected $reader; |
| 32 | protected $entityAnnotationClasses = [Mapping\Entity::class => 1, Mapping\MappedSuperclass::class => 2]; |
| 33 | public function __construct($reader, $paths = null, bool $reportFieldsWhereDeclared = \false) |
| 34 | { |
| 35 | Deprecation::trigger('doctrine/orm', 'https://github.com/doctrine/orm/issues/10098', 'The annotation mapping driver is deprecated and will be removed in Doctrine ORM 3.0, please migrate to the attribute or XML driver.'); |
| 36 | $this->reader = $reader; |
| 37 | $this->addPaths((array) $paths); |
| 38 | if (!$reportFieldsWhereDeclared) { |
| 39 | Deprecation::trigger('doctrine/orm', 'https://github.com/doctrine/orm/pull/10455', 'In ORM 3.0, the AttributeDriver will report fields for the classes where they are declared. This may uncover invalid mapping configurations. To opt into the new mode also with the AnnotationDriver today, set the "reportFieldsWhereDeclared" constructor parameter to true.', self::class); |
| 40 | } |
| 41 | $this->reportFieldsWhereDeclared = $reportFieldsWhereDeclared; |
| 42 | } |
| 43 | public function loadMetadataForClass($className, PersistenceClassMetadata $metadata) |
| 44 | { |
| 45 | $class = $metadata->getReflectionClass() ?? new ReflectionClass($metadata->name); |
| 46 | $classAnnotations = $this->reader->getClassAnnotations($class); |
| 47 | foreach ($classAnnotations as $key => $annot) { |
| 48 | if (!is_numeric($key)) { |
| 49 | continue; |
| 50 | } |
| 51 | $classAnnotations[get_class($annot)] = $annot; |
| 52 | } |
| 53 | // Evaluate Entity annotation |
| 54 | if (isset($classAnnotations[Mapping\Entity::class])) { |
| 55 | $entityAnnot = $classAnnotations[Mapping\Entity::class]; |
| 56 | assert($entityAnnot instanceof Mapping\Entity); |
| 57 | if ($entityAnnot->repositoryClass !== null) { |
| 58 | $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass); |
| 59 | } |
| 60 | if ($entityAnnot->readOnly) { |
| 61 | $metadata->markReadOnly(); |
| 62 | } |
| 63 | } elseif (isset($classAnnotations[Mapping\MappedSuperclass::class])) { |
| 64 | $mappedSuperclassAnnot = $classAnnotations[Mapping\MappedSuperclass::class]; |
| 65 | assert($mappedSuperclassAnnot instanceof Mapping\MappedSuperclass); |
| 66 | $metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass); |
| 67 | $metadata->isMappedSuperclass = \true; |
| 68 | } elseif (isset($classAnnotations[Mapping\Embeddable::class])) { |
| 69 | $metadata->isEmbeddedClass = \true; |
| 70 | } else { |
| 71 | throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); |
| 72 | } |
| 73 | // Evaluate Table annotation |
| 74 | if (isset($classAnnotations[Mapping\Table::class])) { |
| 75 | $tableAnnot = $classAnnotations[Mapping\Table::class]; |
| 76 | assert($tableAnnot instanceof Mapping\Table); |
| 77 | $primaryTable = ['name' => $tableAnnot->name, 'schema' => $tableAnnot->schema]; |
| 78 | foreach ($tableAnnot->indexes ?? [] as $indexAnnot) { |
| 79 | $index = []; |
| 80 | if (!empty($indexAnnot->columns)) { |
| 81 | $index['columns'] = $indexAnnot->columns; |
| 82 | } |
| 83 | if (!empty($indexAnnot->fields)) { |
| 84 | $index['fields'] = $indexAnnot->fields; |
| 85 | } |
| 86 | if (isset($index['columns'], $index['fields']) || !isset($index['columns']) && !isset($index['fields'])) { |
| 87 | throw MappingException::invalidIndexConfiguration($className, (string) ($indexAnnot->name ?? count($primaryTable['indexes']))); |
| 88 | } |
| 89 | if (!empty($indexAnnot->flags)) { |
| 90 | $index['flags'] = $indexAnnot->flags; |
| 91 | } |
| 92 | if (!empty($indexAnnot->options)) { |
| 93 | $index['options'] = $indexAnnot->options; |
| 94 | } |
| 95 | if (!empty($indexAnnot->name)) { |
| 96 | $primaryTable['indexes'][$indexAnnot->name] = $index; |
| 97 | } else { |
| 98 | $primaryTable['indexes'][] = $index; |
| 99 | } |
| 100 | } |
| 101 | foreach ($tableAnnot->uniqueConstraints ?? [] as $uniqueConstraintAnnot) { |
| 102 | $uniqueConstraint = []; |
| 103 | if (!empty($uniqueConstraintAnnot->columns)) { |
| 104 | $uniqueConstraint['columns'] = $uniqueConstraintAnnot->columns; |
| 105 | } |
| 106 | if (!empty($uniqueConstraintAnnot->fields)) { |
| 107 | $uniqueConstraint['fields'] = $uniqueConstraintAnnot->fields; |
| 108 | } |
| 109 | if (isset($uniqueConstraint['columns'], $uniqueConstraint['fields']) || !isset($uniqueConstraint['columns']) && !isset($uniqueConstraint['fields'])) { |
| 110 | throw MappingException::invalidUniqueConstraintConfiguration($className, (string) ($uniqueConstraintAnnot->name ?? count($primaryTable['uniqueConstraints']))); |
| 111 | } |
| 112 | if (!empty($uniqueConstraintAnnot->options)) { |
| 113 | $uniqueConstraint['options'] = $uniqueConstraintAnnot->options; |
| 114 | } |
| 115 | if (!empty($uniqueConstraintAnnot->name)) { |
| 116 | $primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint; |
| 117 | } else { |
| 118 | $primaryTable['uniqueConstraints'][] = $uniqueConstraint; |
| 119 | } |
| 120 | } |
| 121 | if ($tableAnnot->options) { |
| 122 | $primaryTable['options'] = $tableAnnot->options; |
| 123 | } |
| 124 | $metadata->setPrimaryTable($primaryTable); |
| 125 | } |
| 126 | // Evaluate @Cache annotation |
| 127 | if (isset($classAnnotations[Mapping\Cache::class])) { |
| 128 | $cacheAnnot = $classAnnotations[Mapping\Cache::class]; |
| 129 | $cacheMap = ['region' => $cacheAnnot->region, 'usage' => (int) constant('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage)]; |
| 130 | $metadata->enableCache($cacheMap); |
| 131 | } |
| 132 | // Evaluate NamedNativeQueries annotation |
| 133 | if (isset($classAnnotations[Mapping\NamedNativeQueries::class])) { |
| 134 | $namedNativeQueriesAnnot = $classAnnotations[Mapping\NamedNativeQueries::class]; |
| 135 | foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) { |
| 136 | $metadata->addNamedNativeQuery(['name' => $namedNativeQuery->name, 'query' => $namedNativeQuery->query, 'resultClass' => $namedNativeQuery->resultClass, 'resultSetMapping' => $namedNativeQuery->resultSetMapping]); |
| 137 | } |
| 138 | } |
| 139 | // Evaluate SqlResultSetMappings annotation |
| 140 | if (isset($classAnnotations[Mapping\SqlResultSetMappings::class])) { |
| 141 | $sqlResultSetMappingsAnnot = $classAnnotations[Mapping\SqlResultSetMappings::class]; |
| 142 | foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) { |
| 143 | $entities = []; |
| 144 | $columns = []; |
| 145 | foreach ($resultSetMapping->entities as $entityResultAnnot) { |
| 146 | $entityResult = ['fields' => [], 'entityClass' => $entityResultAnnot->entityClass, 'discriminatorColumn' => $entityResultAnnot->discriminatorColumn]; |
| 147 | foreach ($entityResultAnnot->fields as $fieldResultAnnot) { |
| 148 | $entityResult['fields'][] = ['name' => $fieldResultAnnot->name, 'column' => $fieldResultAnnot->column]; |
| 149 | } |
| 150 | $entities[] = $entityResult; |
| 151 | } |
| 152 | foreach ($resultSetMapping->columns as $columnResultAnnot) { |
| 153 | $columns[] = ['name' => $columnResultAnnot->name]; |
| 154 | } |
| 155 | $metadata->addSqlResultSetMapping(['name' => $resultSetMapping->name, 'entities' => $entities, 'columns' => $columns]); |
| 156 | } |
| 157 | } |
| 158 | // Evaluate NamedQueries annotation |
| 159 | if (isset($classAnnotations[Mapping\NamedQueries::class])) { |
| 160 | $namedQueriesAnnot = $classAnnotations[Mapping\NamedQueries::class]; |
| 161 | if (!is_array($namedQueriesAnnot->value)) { |
| 162 | throw new UnexpectedValueException('@NamedQueries should contain an array of @NamedQuery annotations.'); |
| 163 | } |
| 164 | foreach ($namedQueriesAnnot->value as $namedQuery) { |
| 165 | if (!$namedQuery instanceof Mapping\NamedQuery) { |
| 166 | throw new UnexpectedValueException('@NamedQueries should contain an array of @NamedQuery annotations.'); |
| 167 | } |
| 168 | $metadata->addNamedQuery(['name' => $namedQuery->name, 'query' => $namedQuery->query]); |
| 169 | } |
| 170 | } |
| 171 | // Evaluate InheritanceType annotation |
| 172 | if (isset($classAnnotations[Mapping\InheritanceType::class])) { |
| 173 | $inheritanceTypeAnnot = $classAnnotations[Mapping\InheritanceType::class]; |
| 174 | assert($inheritanceTypeAnnot instanceof Mapping\InheritanceType); |
| 175 | $metadata->setInheritanceType(constant('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value)); |
| 176 | if ($metadata->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) { |
| 177 | // Evaluate DiscriminatorColumn annotation |
| 178 | if (isset($classAnnotations[Mapping\DiscriminatorColumn::class])) { |
| 179 | $discrColumnAnnot = $classAnnotations[Mapping\DiscriminatorColumn::class]; |
| 180 | assert($discrColumnAnnot instanceof Mapping\DiscriminatorColumn); |
| 181 | $columnDef = ['name' => $discrColumnAnnot->name, 'type' => $discrColumnAnnot->type ?: 'string', 'length' => $discrColumnAnnot->length ?? 255, 'columnDefinition' => $discrColumnAnnot->columnDefinition, 'enumType' => $discrColumnAnnot->enumType]; |
| 182 | if ($discrColumnAnnot->options) { |
| 183 | $columnDef['options'] = $discrColumnAnnot->options; |
| 184 | } |
| 185 | $metadata->setDiscriminatorColumn($columnDef); |
| 186 | } else { |
| 187 | $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]); |
| 188 | } |
| 189 | // Evaluate DiscriminatorMap annotation |
| 190 | if (isset($classAnnotations[Mapping\DiscriminatorMap::class])) { |
| 191 | $discrMapAnnot = $classAnnotations[Mapping\DiscriminatorMap::class]; |
| 192 | assert($discrMapAnnot instanceof Mapping\DiscriminatorMap); |
| 193 | $metadata->setDiscriminatorMap($discrMapAnnot->value); |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | // Evaluate DoctrineChangeTrackingPolicy annotation |
| 198 | if (isset($classAnnotations[Mapping\ChangeTrackingPolicy::class])) { |
| 199 | $changeTrackingAnnot = $classAnnotations[Mapping\ChangeTrackingPolicy::class]; |
| 200 | assert($changeTrackingAnnot instanceof Mapping\ChangeTrackingPolicy); |
| 201 | $metadata->setChangeTrackingPolicy(constant('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value)); |
| 202 | } |
| 203 | // Evaluate annotations on properties/fields |
| 204 | foreach ($class->getProperties() as $property) { |
| 205 | if ($this->isRepeatedPropertyDeclaration($property, $metadata)) { |
| 206 | continue; |
| 207 | } |
| 208 | $mapping = []; |
| 209 | $mapping['fieldName'] = $property->name; |
| 210 | // Evaluate @Cache annotation |
| 211 | $cacheAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Cache::class); |
| 212 | if ($cacheAnnot !== null) { |
| 213 | $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], ['usage' => (int) constant('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage), 'region' => $cacheAnnot->region]); |
| 214 | } |
| 215 | // Check for JoinColumn/JoinColumns annotations |
| 216 | $joinColumns = []; |
| 217 | $joinColumnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumn::class); |
| 218 | if ($joinColumnAnnot) { |
| 219 | $joinColumns[] = $this->joinColumnToArray($joinColumnAnnot); |
| 220 | } else { |
| 221 | $joinColumnsAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumns::class); |
| 222 | if ($joinColumnsAnnot) { |
| 223 | foreach ($joinColumnsAnnot->value as $joinColumn) { |
| 224 | $joinColumns[] = $this->joinColumnToArray($joinColumn); |
| 225 | } |
| 226 | } |
| 227 | } |
| 228 | // Field can only be annotated with one of: |
| 229 | // @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany |
| 230 | $columnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Column::class); |
| 231 | if ($columnAnnot) { |
| 232 | $mapping = $this->columnToArray($property->name, $columnAnnot); |
| 233 | $idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class); |
| 234 | if ($idAnnot) { |
| 235 | $mapping['id'] = \true; |
| 236 | } |
| 237 | $generatedValueAnnot = $this->reader->getPropertyAnnotation($property, Mapping\GeneratedValue::class); |
| 238 | if ($generatedValueAnnot) { |
| 239 | $metadata->setIdGeneratorType(constant('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy)); |
| 240 | } |
| 241 | if ($this->reader->getPropertyAnnotation($property, Mapping\Version::class)) { |
| 242 | $metadata->setVersionMapping($mapping); |
| 243 | } |
| 244 | $metadata->mapField($mapping); |
| 245 | // Check for SequenceGenerator/TableGenerator definition |
| 246 | $seqGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\SequenceGenerator::class); |
| 247 | if ($seqGeneratorAnnot) { |
| 248 | $metadata->setSequenceGeneratorDefinition(['sequenceName' => $seqGeneratorAnnot->sequenceName, 'allocationSize' => $seqGeneratorAnnot->allocationSize, 'initialValue' => $seqGeneratorAnnot->initialValue]); |
| 249 | } else { |
| 250 | $customGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\CustomIdGenerator::class); |
| 251 | if ($customGeneratorAnnot) { |
| 252 | $metadata->setCustomGeneratorDefinition(['class' => $customGeneratorAnnot->class]); |
| 253 | } |
| 254 | } |
| 255 | } else { |
| 256 | $this->loadRelationShipMapping($property, $mapping, $metadata, $joinColumns, $className); |
| 257 | } |
| 258 | } |
| 259 | // Evaluate AssociationOverrides annotation |
| 260 | if (isset($classAnnotations[Mapping\AssociationOverrides::class])) { |
| 261 | $associationOverridesAnnot = $classAnnotations[Mapping\AssociationOverrides::class]; |
| 262 | assert($associationOverridesAnnot instanceof Mapping\AssociationOverrides); |
| 263 | foreach ($associationOverridesAnnot->overrides as $associationOverride) { |
| 264 | $override = []; |
| 265 | $fieldName = $associationOverride->name; |
| 266 | // Check for JoinColumn/JoinColumns annotations |
| 267 | if ($associationOverride->joinColumns) { |
| 268 | $joinColumns = []; |
| 269 | foreach ($associationOverride->joinColumns as $joinColumn) { |
| 270 | $joinColumns[] = $this->joinColumnToArray($joinColumn); |
| 271 | } |
| 272 | $override['joinColumns'] = $joinColumns; |
| 273 | } |
| 274 | // Check for JoinTable annotations |
| 275 | if ($associationOverride->joinTable) { |
| 276 | $joinTableAnnot = $associationOverride->joinTable; |
| 277 | $joinTable = ['name' => $joinTableAnnot->name, 'schema' => $joinTableAnnot->schema]; |
| 278 | foreach ($joinTableAnnot->joinColumns as $joinColumn) { |
| 279 | $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); |
| 280 | } |
| 281 | foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { |
| 282 | $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); |
| 283 | } |
| 284 | $override['joinTable'] = $joinTable; |
| 285 | } |
| 286 | // Check for inversedBy |
| 287 | if ($associationOverride->inversedBy) { |
| 288 | $override['inversedBy'] = $associationOverride->inversedBy; |
| 289 | } |
| 290 | // Check for `fetch` |
| 291 | if ($associationOverride->fetch) { |
| 292 | $override['fetch'] = constant(Mapping\ClassMetadata::class . '::FETCH_' . $associationOverride->fetch); |
| 293 | } |
| 294 | $metadata->setAssociationOverride($fieldName, $override); |
| 295 | } |
| 296 | } |
| 297 | // Evaluate AttributeOverrides annotation |
| 298 | if (isset($classAnnotations[Mapping\AttributeOverrides::class])) { |
| 299 | $attributeOverridesAnnot = $classAnnotations[Mapping\AttributeOverrides::class]; |
| 300 | assert($attributeOverridesAnnot instanceof Mapping\AttributeOverrides); |
| 301 | foreach ($attributeOverridesAnnot->overrides as $attributeOverrideAnnot) { |
| 302 | $attributeOverride = $this->columnToArray($attributeOverrideAnnot->name, $attributeOverrideAnnot->column); |
| 303 | $metadata->setAttributeOverride($attributeOverrideAnnot->name, $attributeOverride); |
| 304 | } |
| 305 | } |
| 306 | // Evaluate EntityListeners annotation |
| 307 | if (isset($classAnnotations[Mapping\EntityListeners::class])) { |
| 308 | $entityListenersAnnot = $classAnnotations[Mapping\EntityListeners::class]; |
| 309 | assert($entityListenersAnnot instanceof Mapping\EntityListeners); |
| 310 | foreach ($entityListenersAnnot->value as $item) { |
| 311 | $listenerClassName = $metadata->fullyQualifiedClassName($item); |
| 312 | if (!class_exists($listenerClassName)) { |
| 313 | throw MappingException::entityListenerClassNotFound($listenerClassName, $className); |
| 314 | } |
| 315 | $hasMapping = \false; |
| 316 | $listenerClass = new ReflectionClass($listenerClassName); |
| 317 | foreach ($listenerClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { |
| 318 | // find method callbacks. |
| 319 | $callbacks = $this->getMethodCallbacks($method); |
| 320 | $hasMapping = $hasMapping ?: !empty($callbacks); |
| 321 | foreach ($callbacks as $value) { |
| 322 | $metadata->addEntityListener($value[1], $listenerClassName, $value[0]); |
| 323 | } |
| 324 | } |
| 325 | // Evaluate the listener using naming convention. |
| 326 | if (!$hasMapping) { |
| 327 | EntityListenerBuilder::bindEntityListener($metadata, $listenerClassName); |
| 328 | } |
| 329 | } |
| 330 | } |
| 331 | // Evaluate @HasLifecycleCallbacks annotation |
| 332 | if (isset($classAnnotations[Mapping\HasLifecycleCallbacks::class])) { |
| 333 | foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { |
| 334 | foreach ($this->getMethodCallbacks($method) as $value) { |
| 335 | $metadata->addLifecycleCallback($value[0], $value[1]); |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | } |
| 340 | private function loadRelationShipMapping(ReflectionProperty $property, array &$mapping, PersistenceClassMetadata $metadata, array $joinColumns, string $className) : void |
| 341 | { |
| 342 | $oneToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToOne::class); |
| 343 | if ($oneToOneAnnot) { |
| 344 | $idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class); |
| 345 | if ($idAnnot) { |
| 346 | $mapping['id'] = \true; |
| 347 | } |
| 348 | $mapping['targetEntity'] = $oneToOneAnnot->targetEntity; |
| 349 | $mapping['joinColumns'] = $joinColumns; |
| 350 | $mapping['mappedBy'] = $oneToOneAnnot->mappedBy; |
| 351 | $mapping['inversedBy'] = $oneToOneAnnot->inversedBy; |
| 352 | $mapping['cascade'] = $oneToOneAnnot->cascade; |
| 353 | $mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval; |
| 354 | $mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch); |
| 355 | $metadata->mapOneToOne($mapping); |
| 356 | return; |
| 357 | } |
| 358 | $oneToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToMany::class); |
| 359 | if ($oneToManyAnnot) { |
| 360 | $mapping['mappedBy'] = $oneToManyAnnot->mappedBy; |
| 361 | $mapping['targetEntity'] = $oneToManyAnnot->targetEntity; |
| 362 | $mapping['cascade'] = $oneToManyAnnot->cascade; |
| 363 | $mapping['indexBy'] = $oneToManyAnnot->indexBy; |
| 364 | $mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval; |
| 365 | $mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch); |
| 366 | $orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class); |
| 367 | if ($orderByAnnot) { |
| 368 | $mapping['orderBy'] = $orderByAnnot->value; |
| 369 | } |
| 370 | $metadata->mapOneToMany($mapping); |
| 371 | } |
| 372 | $manyToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToOne::class); |
| 373 | if ($manyToOneAnnot) { |
| 374 | $idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class); |
| 375 | if ($idAnnot) { |
| 376 | $mapping['id'] = \true; |
| 377 | } |
| 378 | $mapping['joinColumns'] = $joinColumns; |
| 379 | $mapping['cascade'] = $manyToOneAnnot->cascade; |
| 380 | $mapping['inversedBy'] = $manyToOneAnnot->inversedBy; |
| 381 | $mapping['targetEntity'] = $manyToOneAnnot->targetEntity; |
| 382 | $mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch); |
| 383 | $metadata->mapManyToOne($mapping); |
| 384 | } |
| 385 | $manyToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToMany::class); |
| 386 | if ($manyToManyAnnot) { |
| 387 | $joinTable = []; |
| 388 | $joinTableAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinTable::class); |
| 389 | if ($joinTableAnnot) { |
| 390 | $joinTable = ['name' => $joinTableAnnot->name, 'schema' => $joinTableAnnot->schema]; |
| 391 | if ($joinTableAnnot->options) { |
| 392 | $joinTable['options'] = $joinTableAnnot->options; |
| 393 | } |
| 394 | foreach ($joinTableAnnot->joinColumns as $joinColumn) { |
| 395 | $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); |
| 396 | } |
| 397 | foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { |
| 398 | $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); |
| 399 | } |
| 400 | } |
| 401 | $mapping['joinTable'] = $joinTable; |
| 402 | $mapping['targetEntity'] = $manyToManyAnnot->targetEntity; |
| 403 | $mapping['mappedBy'] = $manyToManyAnnot->mappedBy; |
| 404 | $mapping['inversedBy'] = $manyToManyAnnot->inversedBy; |
| 405 | $mapping['cascade'] = $manyToManyAnnot->cascade; |
| 406 | $mapping['indexBy'] = $manyToManyAnnot->indexBy; |
| 407 | $mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval; |
| 408 | $mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch); |
| 409 | $orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class); |
| 410 | if ($orderByAnnot) { |
| 411 | $mapping['orderBy'] = $orderByAnnot->value; |
| 412 | } |
| 413 | $metadata->mapManyToMany($mapping); |
| 414 | } |
| 415 | $embeddedAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Embedded::class); |
| 416 | if ($embeddedAnnot) { |
| 417 | $mapping['class'] = $embeddedAnnot->class; |
| 418 | $mapping['columnPrefix'] = $embeddedAnnot->columnPrefix; |
| 419 | $metadata->mapEmbedded($mapping); |
| 420 | } |
| 421 | } |
| 422 | private function getFetchMode(string $className, string $fetchMode) : int |
| 423 | { |
| 424 | if (!defined('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::FETCH_' . $fetchMode)) { |
| 425 | throw MappingException::invalidFetchMode($className, $fetchMode); |
| 426 | } |
| 427 | return constant('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::FETCH_' . $fetchMode); |
| 428 | } |
| 429 | private function getGeneratedMode(string $generatedMode) : int |
| 430 | { |
| 431 | if (!defined('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::GENERATED_' . $generatedMode)) { |
| 432 | throw MappingException::invalidGeneratedMode($generatedMode); |
| 433 | } |
| 434 | return constant('MailPoetVendor\\Doctrine\\ORM\\Mapping\\ClassMetadata::GENERATED_' . $generatedMode); |
| 435 | } |
| 436 | private function getMethodCallbacks(ReflectionMethod $method) : array |
| 437 | { |
| 438 | $callbacks = []; |
| 439 | $annotations = $this->reader->getMethodAnnotations($method); |
| 440 | foreach ($annotations as $annot) { |
| 441 | if ($annot instanceof Mapping\PrePersist) { |
| 442 | $callbacks[] = [$method->name, Events::prePersist]; |
| 443 | } |
| 444 | if ($annot instanceof Mapping\PostPersist) { |
| 445 | $callbacks[] = [$method->name, Events::postPersist]; |
| 446 | } |
| 447 | if ($annot instanceof Mapping\PreUpdate) { |
| 448 | $callbacks[] = [$method->name, Events::preUpdate]; |
| 449 | } |
| 450 | if ($annot instanceof Mapping\PostUpdate) { |
| 451 | $callbacks[] = [$method->name, Events::postUpdate]; |
| 452 | } |
| 453 | if ($annot instanceof Mapping\PreRemove) { |
| 454 | $callbacks[] = [$method->name, Events::preRemove]; |
| 455 | } |
| 456 | if ($annot instanceof Mapping\PostRemove) { |
| 457 | $callbacks[] = [$method->name, Events::postRemove]; |
| 458 | } |
| 459 | if ($annot instanceof Mapping\PostLoad) { |
| 460 | $callbacks[] = [$method->name, Events::postLoad]; |
| 461 | } |
| 462 | if ($annot instanceof Mapping\PreFlush) { |
| 463 | $callbacks[] = [$method->name, Events::preFlush]; |
| 464 | } |
| 465 | } |
| 466 | return $callbacks; |
| 467 | } |
| 468 | private function joinColumnToArray(Mapping\JoinColumn $joinColumn) : array |
| 469 | { |
| 470 | $mapping = ['name' => $joinColumn->name, 'unique' => $joinColumn->unique, 'nullable' => $joinColumn->nullable, 'onDelete' => $joinColumn->onDelete, 'columnDefinition' => $joinColumn->columnDefinition, 'referencedColumnName' => $joinColumn->referencedColumnName]; |
| 471 | if ($joinColumn->options) { |
| 472 | $mapping['options'] = $joinColumn->options; |
| 473 | } |
| 474 | return $mapping; |
| 475 | } |
| 476 | private function columnToArray(string $fieldName, Mapping\Column $column) : array |
| 477 | { |
| 478 | $mapping = ['fieldName' => $fieldName, 'type' => $column->type, 'scale' => $column->scale, 'length' => $column->length, 'unique' => $column->unique, 'nullable' => $column->nullable, 'precision' => $column->precision]; |
| 479 | if (!$column->insertable) { |
| 480 | $mapping['notInsertable'] = \true; |
| 481 | } |
| 482 | if (!$column->updatable) { |
| 483 | $mapping['notUpdatable'] = \true; |
| 484 | } |
| 485 | if ($column->generated) { |
| 486 | $mapping['generated'] = $this->getGeneratedMode($column->generated); |
| 487 | } |
| 488 | if ($column->options) { |
| 489 | $mapping['options'] = $column->options; |
| 490 | } |
| 491 | if (isset($column->name)) { |
| 492 | $mapping['columnName'] = $column->name; |
| 493 | } |
| 494 | if (isset($column->columnDefinition)) { |
| 495 | $mapping['columnDefinition'] = $column->columnDefinition; |
| 496 | } |
| 497 | if ($column->enumType !== null) { |
| 498 | $mapping['enumType'] = $column->enumType; |
| 499 | } |
| 500 | return $mapping; |
| 501 | } |
| 502 | public function getReader() |
| 503 | { |
| 504 | Deprecation::trigger('doctrine/orm', 'https://github.com/doctrine/orm/pull/9587', '%s is deprecated with no replacement', __METHOD__); |
| 505 | return $this->reader; |
| 506 | } |
| 507 | public function isTransient($className) |
| 508 | { |
| 509 | $classAnnotations = $this->reader->getClassAnnotations(new ReflectionClass($className)); |
| 510 | foreach ($classAnnotations as $annot) { |
| 511 | if (isset($this->entityAnnotationClasses[get_class($annot)])) { |
| 512 | return \false; |
| 513 | } |
| 514 | } |
| 515 | return \true; |
| 516 | } |
| 517 | public static function create($paths = [], ?AnnotationReader $reader = null) |
| 518 | { |
| 519 | if ($reader === null) { |
| 520 | $reader = new AnnotationReader(); |
| 521 | } |
| 522 | return new self($reader, $paths); |
| 523 | } |
| 524 | } |
| 525 |