1
0
mirror of synced 2025-03-06 12:56:10 +03:00

Entity listeners are now processed by exporters

The current implementation of the exporters are not taking the entity
listeners into account. I have added test cases for most of the edge
cases I could think of and implemented the Exporter handling.

This PR originates from https://github.com/doctrine/doctrine2/pull/5864,
I was overwhelmed by the amount of conflicts I had to resolve so I
started anew on a clean master HEAD.

Squashed commits:

- Code review aftermath
- Add even more return type declarations
- Added `return null` to methods declared with nullable return types
- Removed unneeded docblocks when types are self-explanatory
This commit is contained in:
Thomas Ploch 2017-08-01 12:15:30 +02:00
parent a0c0d3bf2a
commit b7ae5b4afb
10 changed files with 326 additions and 284 deletions

View File

@ -346,7 +346,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function generate(array $metadatas, $outputDirectory) public function generate(array $metadatas, $outputDirectory): void
{ {
foreach ($metadatas as $metadata) { foreach ($metadatas as $metadata) {
$this->writeEntityClass($metadata, $outputDirectory); $this->writeEntityClass($metadata, $outputDirectory);
@ -363,7 +363,7 @@ public function __construct(<params>)
* *
* @throws \RuntimeException * @throws \RuntimeException
*/ */
public function writeEntityClass(ClassMetadataInfo $metadata, $outputDirectory) public function writeEntityClass(ClassMetadataInfo $metadata, $outputDirectory): void
{ {
$path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->extension; $path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->extension;
$dir = dirname($path); $dir = dirname($path);
@ -404,7 +404,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
public function generateEntityClass(ClassMetadataInfo $metadata) public function generateEntityClass(ClassMetadataInfo $metadata): string
{ {
$placeHolders = [ $placeHolders = [
'<namespace>', '<namespace>',
@ -435,7 +435,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
public function generateUpdatedEntityClass(ClassMetadataInfo $metadata, $path) public function generateUpdatedEntityClass(ClassMetadataInfo $metadata, $path): string
{ {
$currentCode = file_get_contents($path); $currentCode = file_get_contents($path);
@ -453,7 +453,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setNumSpaces($numSpaces) public function setNumSpaces($numSpaces): void
{ {
$this->spaces = str_repeat(' ', $numSpaces); $this->spaces = str_repeat(' ', $numSpaces);
$this->numSpaces = $numSpaces; $this->numSpaces = $numSpaces;
@ -466,7 +466,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setExtension($extension) public function setExtension($extension): void
{ {
$this->extension = $extension; $this->extension = $extension;
} }
@ -478,7 +478,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setClassToExtend($classToExtend) public function setClassToExtend($classToExtend): void
{ {
$this->classToExtend = $classToExtend; $this->classToExtend = $classToExtend;
} }
@ -490,7 +490,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setGenerateAnnotations($bool) public function setGenerateAnnotations($bool): void
{ {
$this->generateAnnotations = $bool; $this->generateAnnotations = $bool;
} }
@ -504,7 +504,7 @@ public function __construct(<params>)
* *
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public function setFieldVisibility($visibility) public function setFieldVisibility($visibility): void
{ {
if ($visibility !== static::FIELD_VISIBLE_PRIVATE && $visibility !== static::FIELD_VISIBLE_PROTECTED) { if ($visibility !== static::FIELD_VISIBLE_PRIVATE && $visibility !== static::FIELD_VISIBLE_PROTECTED) {
throw new \InvalidArgumentException('Invalid provided visibility (only private and protected are allowed): ' . $visibility); throw new \InvalidArgumentException('Invalid provided visibility (only private and protected are allowed): ' . $visibility);
@ -518,7 +518,7 @@ public function __construct(<params>)
* *
* @param boolean $embeddablesImmutable * @param boolean $embeddablesImmutable
*/ */
public function setEmbeddablesImmutable($embeddablesImmutable) public function setEmbeddablesImmutable($embeddablesImmutable): void
{ {
$this->embeddablesImmutable = (boolean) $embeddablesImmutable; $this->embeddablesImmutable = (boolean) $embeddablesImmutable;
} }
@ -530,7 +530,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setAnnotationPrefix($prefix) public function setAnnotationPrefix($prefix): void
{ {
$this->annotationsPrefix = $prefix; $this->annotationsPrefix = $prefix;
} }
@ -542,7 +542,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setUpdateEntityIfExists($bool) public function setUpdateEntityIfExists($bool): void
{ {
$this->updateEntityIfExists = $bool; $this->updateEntityIfExists = $bool;
} }
@ -554,7 +554,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setRegenerateEntityIfExists($bool) public function setRegenerateEntityIfExists($bool): void
{ {
$this->regenerateEntityIfExists = $bool; $this->regenerateEntityIfExists = $bool;
} }
@ -566,7 +566,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setGenerateStubMethods($bool) public function setGenerateStubMethods($bool): void
{ {
$this->generateEntityStubMethods = $bool; $this->generateEntityStubMethods = $bool;
} }
@ -578,7 +578,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
public function setBackupExisting($bool) public function setBackupExisting($bool): void
{ {
$this->backupExisting = $bool; $this->backupExisting = $bool;
} }
@ -588,7 +588,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
protected function getType($type) protected function getType($type): string
{ {
if (isset($this->typeAlias[$type])) { if (isset($this->typeAlias[$type])) {
return $this->typeAlias[$type]; return $this->typeAlias[$type];
@ -602,20 +602,22 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
protected function generateEntityNamespace(ClassMetadataInfo $metadata) protected function generateEntityNamespace(ClassMetadataInfo $metadata): ?string
{ {
if ($this->hasNamespace($metadata)) { if (!$this->hasNamespace($metadata)) {
return 'namespace ' . $this->getNamespace($metadata) .';'; return null;
} }
return 'namespace ' . $this->getNamespace($metadata) .';';
} }
protected function generateEntityUse() protected function generateEntityUse(): ?string
{ {
if ($this->generateAnnotations) { if (!$this->generateAnnotations) {
return "\n".'use Doctrine\ORM\Mapping as ORM;'."\n"; return null;
} else {
return "";
} }
return "\n".'use Doctrine\ORM\Mapping as ORM;'."\n";
} }
/** /**
@ -623,7 +625,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
protected function generateEntityClassName(ClassMetadataInfo $metadata) protected function generateEntityClassName(ClassMetadataInfo $metadata): string
{ {
return 'class ' . $this->getClassName($metadata) . return 'class ' . $this->getClassName($metadata) .
($this->extendsClass() ? ' extends ' . $this->getClassToExtendName() : null); ($this->extendsClass() ? ' extends ' . $this->getClassToExtendName() : null);
@ -634,7 +636,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
protected function generateEntityBody(ClassMetadataInfo $metadata) protected function generateEntityBody(ClassMetadataInfo $metadata): string
{ {
$fieldMappingProperties = $this->generateEntityFieldMappingProperties($metadata); $fieldMappingProperties = $this->generateEntityFieldMappingProperties($metadata);
$embeddedProperties = $this->generateEntityEmbeddedProperties($metadata); $embeddedProperties = $this->generateEntityEmbeddedProperties($metadata);
@ -674,7 +676,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
protected function generateEntityConstructor(ClassMetadataInfo $metadata) protected function generateEntityConstructor(ClassMetadataInfo $metadata): string
{ {
if ($this->hasMethod('__construct', $metadata)) { if ($this->hasMethod('__construct', $metadata)) {
return ''; return '';
@ -704,7 +706,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
private function generateEmbeddableConstructor(ClassMetadataInfo $metadata) private function generateEmbeddableConstructor(ClassMetadataInfo $metadata): string
{ {
$paramTypes = []; $paramTypes = [];
$paramVariables = []; $paramVariables = [];
@ -738,9 +740,7 @@ public function __construct(<params>)
} }
foreach ($fieldMappings as $fieldMapping) { foreach ($fieldMappings as $fieldMapping) {
if (isset($fieldMapping['declaredField']) && if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']])) {
isset($metadata->embeddedClasses[$fieldMapping['declaredField']])
) {
continue; continue;
} }
@ -800,7 +800,7 @@ public function __construct(<params>)
* *
* @return void * @return void
*/ */
protected function parseTokensInEntityFile($src) protected function parseTokensInEntityFile($src): void
{ {
$tokens = token_get_all($src); $tokens = token_get_all($src);
$tokensCount = count($tokens); $tokensCount = count($tokens);
@ -848,13 +848,7 @@ public function __construct(<params>)
} }
} }
/** protected function hasProperty(string $property, ClassMetadataInfo $metadata): bool
* @param string $property
* @param ClassMetadataInfo $metadata
*
* @return bool
*/
protected function hasProperty($property, ClassMetadataInfo $metadata)
{ {
if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) { if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) {
// don't generate property if its already on the base class. // don't generate property if its already on the base class.
@ -877,13 +871,7 @@ public function __construct(<params>)
); );
} }
/** protected function hasMethod(string $method, ClassMetadataInfo $metadata): bool
* @param string $method
* @param ClassMetadataInfo $metadata
*
* @return bool
*/
protected function hasMethod($method, ClassMetadataInfo $metadata)
{ {
if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) { if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) {
// don't generate method if its already on the base class. // don't generate method if its already on the base class.
@ -907,20 +895,13 @@ public function __construct(<params>)
); );
} }
/** protected function getTraits(ClassMetadataInfo $metadata): array
* @param ClassMetadataInfo $metadata
*
* @return array
*/
protected function getTraits(ClassMetadataInfo $metadata)
{ {
if (! ($metadata->reflClass !== null || class_exists($metadata->name))) { if (! ($metadata->reflClass !== null || class_exists($metadata->name))) {
return []; return [];
} }
$reflClass = $metadata->reflClass === null $reflClass = $metadata->reflClass ?? new \ReflectionClass($metadata->name);
? new \ReflectionClass($metadata->name)
: $metadata->reflClass;
$traits = []; $traits = [];
@ -933,69 +914,40 @@ public function __construct(<params>)
return $traits; return $traits;
} }
/** protected function hasNamespace(ClassMetadataInfo $metadata): bool
* @param ClassMetadataInfo $metadata
*
* @return bool
*/
protected function hasNamespace(ClassMetadataInfo $metadata)
{ {
return (bool) strpos($metadata->name, '\\'); return (bool) strpos($metadata->name, '\\');
} }
/** protected function extendsClass(): bool
* @return bool
*/
protected function extendsClass()
{ {
return (bool) $this->classToExtend; return (bool) $this->classToExtend;
} }
/** protected function getClassToExtend(): ?string
* @return string
*/
protected function getClassToExtend()
{ {
return $this->classToExtend; return $this->classToExtend;
} }
/** protected function getClassToExtendName(): string
* @return string
*/
protected function getClassToExtendName()
{ {
$refl = new \ReflectionClass($this->getClassToExtend()); $refl = new \ReflectionClass($this->getClassToExtend());
return '\\' . $refl->getName(); return '\\' . $refl->getName();
} }
/** protected function getClassName(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function getClassName(ClassMetadataInfo $metadata)
{ {
return ($pos = strrpos($metadata->name, '\\')) return ($pos = strrpos($metadata->name, '\\'))
? substr($metadata->name, $pos + 1, strlen($metadata->name)) : $metadata->name; ? substr($metadata->name, $pos + 1, strlen($metadata->name)) : $metadata->name;
} }
/** protected function getNamespace(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function getNamespace(ClassMetadataInfo $metadata)
{ {
return substr($metadata->name, 0, strrpos($metadata->name, '\\')); return substr($metadata->name, 0, strrpos($metadata->name, '\\'));
} }
/** protected function generateEntityDocBlock(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateEntityDocBlock(ClassMetadataInfo $metadata)
{ {
$lines = []; $lines = [];
$lines[] = '/**'; $lines[] = '/**';
@ -1010,6 +962,7 @@ public function __construct(<params>)
'generateDiscriminatorColumnAnnotation', 'generateDiscriminatorColumnAnnotation',
'generateDiscriminatorMapAnnotation', 'generateDiscriminatorMapAnnotation',
'generateEntityAnnotation', 'generateEntityAnnotation',
'generateEntityListenerAnnotation',
]; ];
foreach ($methods as $method) { foreach ($methods as $method) {
@ -1028,12 +981,7 @@ public function __construct(<params>)
return implode("\n", $lines); return implode("\n", $lines);
} }
/** protected function generateEntityAnnotation(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateEntityAnnotation(ClassMetadataInfo $metadata)
{ {
$prefix = '@' . $this->annotationsPrefix; $prefix = '@' . $this->annotationsPrefix;
@ -1048,12 +996,7 @@ public function __construct(<params>)
return $prefix . ($metadata->isMappedSuperclass ? 'MappedSuperclass' : 'Entity') . $customRepository; return $prefix . ($metadata->isMappedSuperclass ? 'MappedSuperclass' : 'Entity') . $customRepository;
} }
/** protected function generateTableAnnotation(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateTableAnnotation(ClassMetadataInfo $metadata)
{ {
if ($metadata->isEmbeddedClass) { if ($metadata->isEmbeddedClass) {
return ''; return '';
@ -1086,13 +1029,7 @@ public function __construct(<params>)
return '@' . $this->annotationsPrefix . 'Table(' . implode(', ', $table) . ')'; return '@' . $this->annotationsPrefix . 'Table(' . implode(', ', $table) . ')';
} }
/** protected function generateTableConstraints(string $constraintName, array $constraints): string
* @param string $constraintName
* @param array $constraints
*
* @return string
*/
protected function generateTableConstraints($constraintName, array $constraints)
{ {
$annotations = []; $annotations = [];
foreach ($constraints as $name => $constraint) { foreach ($constraints as $name => $constraint) {
@ -1106,75 +1043,57 @@ public function __construct(<params>)
return implode(', ', $annotations); return implode(', ', $annotations);
} }
/** protected function generateInheritanceAnnotation(ClassMetadataInfo $metadata): ?string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateInheritanceAnnotation(ClassMetadataInfo $metadata)
{ {
if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
return '@' . $this->annotationsPrefix . 'InheritanceType("'.$this->getInheritanceTypeString($metadata->inheritanceType).'")'; return null;
} }
return '@' . $this->annotationsPrefix . 'InheritanceType("'.$this->getInheritanceTypeString($metadata->inheritanceType).'")';
} }
/** protected function generateDiscriminatorColumnAnnotation(ClassMetadataInfo $metadata): ?string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateDiscriminatorColumnAnnotation(ClassMetadataInfo $metadata)
{ {
if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
$discrColumn = $metadata->discriminatorColumn; return null;
$columnDefinition = 'name="' . $discrColumn['name']
. '", type="' . $discrColumn['type']
. '", length=' . $discrColumn['length'];
return '@' . $this->annotationsPrefix . 'DiscriminatorColumn(' . $columnDefinition . ')';
} }
$discrColumn = $metadata->discriminatorColumn;
$columnDefinition = 'name="' . $discrColumn['name']
. '", type="' . $discrColumn['type']
. '", length=' . $discrColumn['length'];
return '@' . $this->annotationsPrefix . 'DiscriminatorColumn(' . $columnDefinition . ')';
} }
/** protected function generateDiscriminatorMapAnnotation(ClassMetadataInfo $metadata): ?string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateDiscriminatorMapAnnotation(ClassMetadataInfo $metadata)
{ {
if ($metadata->inheritanceType != ClassMetadataInfo::INHERITANCE_TYPE_NONE) { if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) {
$inheritanceClassMap = []; return null;
foreach ($metadata->discriminatorMap as $type => $class) {
$inheritanceClassMap[] .= '"' . $type . '" = "' . $class . '"';
}
return '@' . $this->annotationsPrefix . 'DiscriminatorMap({' . implode(', ', $inheritanceClassMap) . '})';
} }
$inheritanceClassMap = [];
foreach ($metadata->discriminatorMap as $type => $class) {
$inheritanceClassMap[] .= '"' . $type . '" = "' . $class . '"';
}
return '@' . $this->annotationsPrefix . 'DiscriminatorMap({' . implode(', ', $inheritanceClassMap) . '})';
} }
/** protected function generateEntityStubMethods(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateEntityStubMethods(ClassMetadataInfo $metadata)
{ {
$methods = []; $methods = [];
foreach ($metadata->fieldMappings as $fieldMapping) { foreach ($metadata->fieldMappings as $fieldMapping) {
if (isset($fieldMapping['declaredField']) && if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']])) {
isset($metadata->embeddedClasses[$fieldMapping['declaredField']])
) {
continue; continue;
} }
$nullableField = $this->nullableFieldExpression($fieldMapping); $nullableField = $this->nullableFieldExpression($fieldMapping);
if (( ! isset($fieldMapping['id']) || if ((!$metadata->isEmbeddedClass || !$this->embeddablesImmutable)
! $fieldMapping['id'] || && (!isset($fieldMapping['id']) || ! $fieldMapping['id'] || $metadata->generatorType === ClassMetadataInfo::GENERATOR_TYPE_NONE)
$metadata->generatorType == ClassMetadataInfo::GENERATOR_TYPE_NONE
) && (! $metadata->isEmbeddedClass || ! $this->embeddablesImmutable)
&& $code = $this->generateEntityStubMethod($metadata, 'set', $fieldMapping['fieldName'], $fieldMapping['type'], $nullableField) && $code = $this->generateEntityStubMethod($metadata, 'set', $fieldMapping['fieldName'], $fieldMapping['type'], $nullableField)
) { ) {
$methods[] = $code; $methods[] = $code;
@ -1226,12 +1145,7 @@ public function __construct(<params>)
return implode("\n\n", $methods); return implode("\n\n", $methods);
} }
/** protected function isAssociationIsNullable(array $associationMapping): bool
* @param array $associationMapping
*
* @return bool
*/
protected function isAssociationIsNullable(array $associationMapping)
{ {
if (isset($associationMapping['id']) && $associationMapping['id']) { if (isset($associationMapping['id']) && $associationMapping['id']) {
return false; return false;
@ -1253,15 +1167,10 @@ public function __construct(<params>)
return true; return true;
} }
/** protected function generateEntityLifecycleCallbackMethods(ClassMetadataInfo $metadata): ?string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateEntityLifecycleCallbackMethods(ClassMetadataInfo $metadata)
{ {
if (empty($metadata->lifecycleCallbacks)) { if (empty($metadata->lifecycleCallbacks)) {
return ''; return null;
} }
$methods = []; $methods = [];
@ -1275,12 +1184,7 @@ public function __construct(<params>)
return implode("\n\n", array_filter($methods)); return implode("\n\n", array_filter($methods));
} }
/** protected function generateEntityAssociationMappingProperties(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateEntityAssociationMappingProperties(ClassMetadataInfo $metadata)
{ {
$lines = []; $lines = [];
@ -1297,22 +1201,14 @@ public function __construct(<params>)
return implode("\n", $lines); return implode("\n", $lines);
} }
/** protected function generateEntityFieldMappingProperties(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateEntityFieldMappingProperties(ClassMetadataInfo $metadata)
{ {
$lines = []; $lines = [];
foreach ($metadata->fieldMappings as $fieldMapping) { foreach ($metadata->fieldMappings as $fieldMapping) {
if ($this->hasProperty($fieldMapping['fieldName'], $metadata) || if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']]) ||
$metadata->isInheritedField($fieldMapping['fieldName']) || $this->hasProperty($fieldMapping['fieldName'], $metadata) ||
( $metadata->isInheritedField($fieldMapping['fieldName'])
isset($fieldMapping['declaredField']) &&
isset($metadata->embeddedClasses[$fieldMapping['declaredField']])
)
) { ) {
continue; continue;
} }
@ -1325,12 +1221,7 @@ public function __construct(<params>)
return implode("\n", $lines); return implode("\n", $lines);
} }
/** protected function generateEntityEmbeddedProperties(ClassMetadataInfo $metadata): string
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateEntityEmbeddedProperties(ClassMetadataInfo $metadata)
{ {
$lines = []; $lines = [];
@ -1346,16 +1237,12 @@ public function __construct(<params>)
return implode("\n", $lines); return implode("\n", $lines);
} }
/** protected function generateEntityStubMethod(
* @param ClassMetadataInfo $metadata ClassMetadataInfo $metadata,
* @param string $type string $type,
* @param string $fieldName string $fieldName,
* @param string|null $typeHint ?string $typeHint = null,
* @param string|null $defaultValue ?string $defaultValue = null): string
*
* @return string
*/
protected function generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null)
{ {
$methodName = $type . Inflector::classify($fieldName); $methodName = $type . Inflector::classify($fieldName);
$variableName = Inflector::camelize($fieldName); $variableName = Inflector::camelize($fieldName);
@ -1401,18 +1288,12 @@ public function __construct(<params>)
return $this->prefixCodeWithSpaces($method); return $this->prefixCodeWithSpaces($method);
} }
/** protected function generateLifecycleCallbackMethod(string $name, string $methodName, ClassMetadataInfo $metadata): ?string
* @param string $name
* @param string $methodName
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateLifecycleCallbackMethod($name, $methodName, ClassMetadataInfo $metadata)
{ {
if ($this->hasMethod($methodName, $metadata)) { if ($this->hasMethod($methodName, $metadata)) {
return ''; return null;
} }
$this->staticReflection[$metadata->name]['methods'][] = $methodName; $this->staticReflection[$metadata->name]['methods'][] = $methodName;
$replacements = [ $replacements = [
@ -1429,12 +1310,7 @@ public function __construct(<params>)
return $this->prefixCodeWithSpaces($method); return $this->prefixCodeWithSpaces($method);
} }
/** protected function generateJoinColumnAnnotation(array $joinColumn): string
* @param array $joinColumn
*
* @return string
*/
protected function generateJoinColumnAnnotation(array $joinColumn)
{ {
$joinColumnAnnot = []; $joinColumnAnnot = [];
@ -1465,13 +1341,7 @@ public function __construct(<params>)
return '@' . $this->annotationsPrefix . 'JoinColumn(' . implode(', ', $joinColumnAnnot) . ')'; return '@' . $this->annotationsPrefix . 'JoinColumn(' . implode(', ', $joinColumnAnnot) . ')';
} }
/** protected function generateAssociationMappingPropertyDocBlock(array $associationMapping, ClassMetadataInfo $metadata): string
* @param array $associationMapping
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateAssociationMappingPropertyDocBlock(array $associationMapping, ClassMetadataInfo $metadata)
{ {
$lines = []; $lines = [];
$lines[] = $this->spaces . '/**'; $lines[] = $this->spaces . '/**';
@ -1617,13 +1487,7 @@ public function __construct(<params>)
return implode("\n", $lines); return implode("\n", $lines);
} }
/** protected function generateFieldMappingPropertyDocBlock(array $fieldMapping, ClassMetadataInfo $metadata): string
* @param array $fieldMapping
* @param ClassMetadataInfo $metadata
*
* @return string
*/
protected function generateFieldMappingPropertyDocBlock(array $fieldMapping, ClassMetadataInfo $metadata)
{ {
$lines = []; $lines = [];
$lines[] = $this->spaces . '/**'; $lines[] = $this->spaces . '/**';
@ -1715,12 +1579,7 @@ public function __construct(<params>)
return implode("\n", $lines); return implode("\n", $lines);
} }
/** protected function generateEmbeddedPropertyDocBlock(array $embeddedClass): string
* @param array $embeddedClass
*
* @return string
*/
protected function generateEmbeddedPropertyDocBlock(array $embeddedClass)
{ {
$lines = []; $lines = [];
$lines[] = $this->spaces . '/**'; $lines[] = $this->spaces . '/**';
@ -1748,13 +1607,28 @@ public function __construct(<params>)
return implode("\n", $lines); return implode("\n", $lines);
} }
/** protected function generateEntityListenerAnnotation(ClassMetadataInfo $metadata): ?string
* @param string $code {
* @param int $num if (0 === \count($metadata->entityListeners)) {
* return null;
* @return string }
*/
protected function prefixCodeWithSpaces($code, $num = 1) $processedClasses = [];
foreach ($metadata->entityListeners as $event => $eventListeners) {
foreach ($eventListeners as $eventListener) {
$processedClasses[] = '"' . $eventListener['class'] . '"';
}
}
return \sprintf(
'%s%s({%s})',
'@' . $this->annotationsPrefix,
'EntityListeners',
\implode(',', \array_unique($processedClasses))
);
}
protected function prefixCodeWithSpaces($code, $num = 1): string
{ {
$lines = explode("\n", $code); $lines = explode("\n", $code);
@ -1774,7 +1648,7 @@ public function __construct(<params>)
* *
* @throws \InvalidArgumentException When the inheritance type does not exist. * @throws \InvalidArgumentException When the inheritance type does not exist.
*/ */
protected function getInheritanceTypeString($type) protected function getInheritanceTypeString($type): string
{ {
if ( ! isset(static::$inheritanceTypeMap[$type])) { if ( ! isset(static::$inheritanceTypeMap[$type])) {
throw new \InvalidArgumentException(sprintf('Invalid provided InheritanceType: %s', $type)); throw new \InvalidArgumentException(sprintf('Invalid provided InheritanceType: %s', $type));
@ -1790,7 +1664,7 @@ public function __construct(<params>)
* *
* @throws \InvalidArgumentException When the change-tracking type does not exist. * @throws \InvalidArgumentException When the change-tracking type does not exist.
*/ */
protected function getChangeTrackingPolicyString($type) protected function getChangeTrackingPolicyString($type): string
{ {
if ( ! isset(static::$changeTrackingPolicyMap[$type])) { if ( ! isset(static::$changeTrackingPolicyMap[$type])) {
throw new \InvalidArgumentException(sprintf('Invalid provided ChangeTrackingPolicy: %s', $type)); throw new \InvalidArgumentException(sprintf('Invalid provided ChangeTrackingPolicy: %s', $type));
@ -1806,7 +1680,7 @@ public function __construct(<params>)
* *
* @throws \InvalidArgumentException When the generator type does not exist. * @throws \InvalidArgumentException When the generator type does not exist.
*/ */
protected function getIdGeneratorTypeString($type) protected function getIdGeneratorTypeString($type): string
{ {
if ( ! isset(static::$generatorStrategyMap[$type])) { if ( ! isset(static::$generatorStrategyMap[$type])) {
throw new \InvalidArgumentException(sprintf('Invalid provided IdGeneratorType: %s', $type)); throw new \InvalidArgumentException(sprintf('Invalid provided IdGeneratorType: %s', $type));
@ -1815,12 +1689,7 @@ public function __construct(<params>)
return static::$generatorStrategyMap[$type]; return static::$generatorStrategyMap[$type];
} }
/** private function nullableFieldExpression(array $fieldMapping): ?string
* @param array $fieldMapping
*
* @return string|null
*/
private function nullableFieldExpression(array $fieldMapping)
{ {
if (isset($fieldMapping['nullable']) && true === $fieldMapping['nullable']) { if (isset($fieldMapping['nullable']) && true === $fieldMapping['nullable']) {
return 'null'; return 'null';
@ -1836,7 +1705,7 @@ public function __construct(<params>)
* *
* @return string * @return string
*/ */
private function exportTableOptions(array $options) private function exportTableOptions(array $options): string
{ {
$optionsStr = []; $optionsStr = [];

View File

@ -44,7 +44,7 @@ class AnnotationExporter extends AbstractExporter
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exportClassMetadata(ClassMetadataInfo $metadata) public function exportClassMetadata(ClassMetadataInfo $metadata): string
{ {
if ( ! $this->_entityGenerator) { if ( ! $this->_entityGenerator) {
throw new \RuntimeException('For the AnnotationExporter you must set an EntityGenerator instance with the setEntityGenerator() method.'); throw new \RuntimeException('For the AnnotationExporter you must set an EntityGenerator instance with the setEntityGenerator() method.');
@ -63,7 +63,7 @@ class AnnotationExporter extends AbstractExporter
* *
* @return string * @return string
*/ */
protected function _generateOutputPath(ClassMetadataInfo $metadata) protected function _generateOutputPath(ClassMetadataInfo $metadata): string
{ {
return $this->_outputDir . '/' . str_replace('\\', '/', $metadata->name) . $this->_extension; return $this->_outputDir . '/' . str_replace('\\', '/', $metadata->name) . $this->_extension;
} }
@ -73,7 +73,7 @@ class AnnotationExporter extends AbstractExporter
* *
* @return void * @return void
*/ */
public function setEntityGenerator(EntityGenerator $entityGenerator) public function setEntityGenerator(EntityGenerator $entityGenerator): void
{ {
$this->_entityGenerator = $entityGenerator; $this->_entityGenerator = $entityGenerator;
} }

View File

@ -38,7 +38,7 @@ class PhpExporter extends AbstractExporter
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exportClassMetadata(ClassMetadataInfo $metadata) public function exportClassMetadata(ClassMetadataInfo $metadata): string
{ {
$lines = []; $lines = [];
$lines[] = '<?php'; $lines[] = '<?php';
@ -82,6 +82,8 @@ class PhpExporter extends AbstractExporter
} }
} }
$lines = array_merge($lines, $this->processEntityListeners($metadata));
foreach ($metadata->fieldMappings as $fieldMapping) { foreach ($metadata->fieldMappings as $fieldMapping) {
$lines[] = '$metadata->mapField(' . $this->_varExport($fieldMapping) . ');'; $lines[] = '$metadata->mapField(' . $this->_varExport($fieldMapping) . ');';
} }
@ -164,7 +166,7 @@ class PhpExporter extends AbstractExporter
* *
* @return string * @return string
*/ */
protected function _varExport($var) protected function _varExport($var): string
{ {
$export = var_export($var, true); $export = var_export($var, true);
$export = str_replace("\n", PHP_EOL . str_repeat(' ', 8), $export); $export = str_replace("\n", PHP_EOL . str_repeat(' ', 8), $export);
@ -177,4 +179,26 @@ class PhpExporter extends AbstractExporter
return $export; return $export;
} }
private function processEntityListeners(ClassMetadataInfo $metadata): array
{
$lines = [];
if (0 === \count($metadata->entityListeners)) {
return $lines;
}
foreach ($metadata->entityListeners as $event => $entityListenerConfig) {
foreach ($entityListenerConfig as $entityListener) {
$lines[] = sprintf(
'$metadata->addEntityListener(%s, %s, %s);',
var_export($event, true),
var_export($entityListener['class'], true),
var_export($entityListener['method'], true)
);
}
}
return $lines;
}
} }

View File

@ -20,6 +20,7 @@
namespace Doctrine\ORM\Tools\Export\Driver; namespace Doctrine\ORM\Tools\Export\Driver;
use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Mapping\ClassMetadataInfo;
use SimpleXMLElement;
/** /**
* ClassMetadata exporter for Doctrine XML mapping files. * ClassMetadata exporter for Doctrine XML mapping files.
@ -38,9 +39,9 @@ class XmlExporter extends AbstractExporter
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exportClassMetadata(ClassMetadataInfo $metadata) public function exportClassMetadata(ClassMetadataInfo $metadata): string
{ {
$xml = new \SimpleXmlElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><doctrine-mapping ". $xml = new SimpleXmlElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><doctrine-mapping ".
"xmlns=\"http://doctrine-project.org/schemas/orm/doctrine-mapping\" " . "xmlns=\"http://doctrine-project.org/schemas/orm/doctrine-mapping\" " .
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ". "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ".
"xsi:schemaLocation=\"http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd\" />"); "xsi:schemaLocation=\"http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd\" />");
@ -390,16 +391,18 @@ class XmlExporter extends AbstractExporter
} }
} }
$this->processEntityListeners($metadata, $root);
return $this->_asXml($xml); return $this->_asXml($xml);
} }
/** /**
* Exports (nested) option elements. * Exports (nested) option elements.
* *
* @param \SimpleXMLElement $parentXml * @param SimpleXMLElement $parentXml
* @param array $options * @param array $options
*/ */
private function exportTableOptions(\SimpleXMLElement $parentXml, array $options) private function exportTableOptions(SimpleXMLElement $parentXml, array $options): void
{ {
foreach ($options as $name => $option) { foreach ($options as $name => $option) {
$isArray = is_array($option); $isArray = is_array($option);
@ -418,12 +421,12 @@ class XmlExporter extends AbstractExporter
/** /**
* Export sequence information (if available/configured) into the current identifier XML node * Export sequence information (if available/configured) into the current identifier XML node
* *
* @param \SimpleXMLElement $identifierXmlNode * @param SimpleXMLElement $identifierXmlNode
* @param ClassMetadataInfo $metadata * @param ClassMetadataInfo $metadata
* *
* @return void * @return void
*/ */
private function exportSequenceInformation(\SimpleXMLElement $identifierXmlNode, ClassMetadataInfo $metadata) private function exportSequenceInformation(SimpleXMLElement $identifierXmlNode, ClassMetadataInfo $metadata): void
{ {
$sequenceDefinition = $metadata->sequenceGeneratorDefinition; $sequenceDefinition = $metadata->sequenceGeneratorDefinition;
@ -438,12 +441,7 @@ class XmlExporter extends AbstractExporter
$sequenceGeneratorXml->addAttribute('initial-value', $sequenceDefinition['initialValue']); $sequenceGeneratorXml->addAttribute('initial-value', $sequenceDefinition['initialValue']);
} }
/** private function _asXml(SimpleXMLElement $simpleXml): string
* @param \SimpleXMLElement $simpleXml
*
* @return string $xml
*/
private function _asXml($simpleXml)
{ {
$dom = new \DOMDocument('1.0', 'UTF-8'); $dom = new \DOMDocument('1.0', 'UTF-8');
$dom->loadXML($simpleXml->asXML()); $dom->loadXML($simpleXml->asXML());
@ -451,4 +449,46 @@ class XmlExporter extends AbstractExporter
return $dom->saveXML(); return $dom->saveXML();
} }
private function processEntityListeners(ClassMetadataInfo $metadata, SimpleXMLElement $root): void
{
if (0 === \count($metadata->entityListeners)) {
return;
}
$entityListenersXml = $root->addChild('entity-listeners');
$entityListenersXmlMap = [];
$this->generateEntityListenerXml($metadata, $entityListenersXmlMap, $entityListenersXml);
}
private function generateEntityListenerXml(ClassMetadataInfo $metadata, array $entityListenersXmlMap, SimpleXMLElement $entityListenersXml): void
{
foreach ($metadata->entityListeners as $event => $entityListenerConfig) {
foreach ($entityListenerConfig as $entityListener) {
$entityListenerXml = $this->addClassToMapIfExists(
$entityListenersXmlMap,
$entityListener,
$entityListenersXml
);
$entityListenerCallbackXml = $entityListenerXml->addChild('lifecycle-callback');
$entityListenerCallbackXml->addAttribute('type', $event);
$entityListenerCallbackXml->addAttribute('method', $entityListener['method']);
}
}
}
private function addClassToMapIfExists(array $entityListenersXmlMap, array $entityListener, SimpleXMLElement $entityListenersXml): SimpleXMLElement
{
if (isset($entityListenersXmlMap[$entityListener['class']])) {
return $entityListenersXmlMap[$entityListener['class']];
}
$entityListenerXml = $entityListenersXml->addChild('entity-listener');
$entityListenerXml->addAttribute('class', $entityListener['class']);
$entityListenersXmlMap[$entityListener['class']] = $entityListenerXml;
return $entityListenerXml;
}
} }

View File

@ -39,7 +39,7 @@ class YamlExporter extends AbstractExporter
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function exportClassMetadata(ClassMetadataInfo $metadata) public function exportClassMetadata(ClassMetadataInfo $metadata): string
{ {
$array = []; $array = [];
@ -214,6 +214,8 @@ class YamlExporter extends AbstractExporter
$array['lifecycleCallbacks'] = $metadata->lifecycleCallbacks; $array['lifecycleCallbacks'] = $metadata->lifecycleCallbacks;
} }
$array = $this->processEntityListeners($metadata, $array);
return $this->yamlDump([$metadata->name => $array], 10); return $this->yamlDump([$metadata->name => $array], 10);
} }
@ -228,8 +230,35 @@ class YamlExporter extends AbstractExporter
* *
* @return string A YAML string representing the original PHP array * @return string A YAML string representing the original PHP array
*/ */
protected function yamlDump($array, $inline = 2) protected function yamlDump($array, $inline = 2): string
{ {
return Yaml::dump($array, $inline); return Yaml::dump($array, $inline);
} }
private function processEntityListeners(ClassMetadataInfo $metadata, array $array): array
{
if (0 === \count($metadata->entityListeners)) {
return $array;
}
$array['entityListeners'] = [];
foreach ($metadata->entityListeners as $event => $entityListenerConfig) {
$array = $this->processEntityListenerConfig($array, $entityListenerConfig, $event);
}
return $array;
}
private function processEntityListenerConfig(array $array, array $entityListenerConfig, string $event): array
{
foreach ($entityListenerConfig as $entityListener) {
if (!isset($array['entityListeners'][$entityListener['class']])) {
$array['entityListeners'][$entityListener['class']] = [];
}
$array['entityListeners'][$entityListener['class']][$event] = [$entityListener['method']];
}
return $array;
}
} }

View File

@ -5,6 +5,8 @@ namespace Doctrine\Tests\ORM\Tools\Export;
use Doctrine\Common\EventManager; use Doctrine\Common\EventManager;
use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver; use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver;
use Doctrine\ORM\Configuration; use Doctrine\ORM\Configuration;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\ClassMetadataFactory; use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver; use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
@ -344,7 +346,7 @@ abstract class AbstractClassMetadataExporterTest extends OrmTestCase
{ {
$this->assertEquals('user', $class->associationMappings['address']['inversedBy']); $this->assertEquals('user', $class->associationMappings['address']['inversedBy']);
} }
/** /**
* @depends testExportDirectoryAndFilesAreCreated * @depends testExportDirectoryAndFilesAreCreated
*/ */
public function testCascadeAllCollapsed() public function testCascadeAllCollapsed()
@ -371,6 +373,26 @@ abstract class AbstractClassMetadataExporterTest extends OrmTestCase
} }
} }
/**
* @depends testExportedMetadataCanBeReadBackIn
*
* @param ClassMetadata $class
*/
public function testEntityListenersAreExported($class)
{
$this->assertNotEmpty($class->entityListeners);
$this->assertCount(2, $class->entityListeners[Events::prePersist]);
$this->assertCount(2, $class->entityListeners[Events::postPersist]);
$this->assertEquals(UserListener::class, $class->entityListeners[Events::prePersist][0]['class']);
$this->assertEquals('customPrePersist', $class->entityListeners[Events::prePersist][0]['method']);
$this->assertEquals(GroupListener::class, $class->entityListeners[Events::prePersist][1]['class']);
$this->assertEquals('prePersist', $class->entityListeners[Events::prePersist][1]['method']);
$this->assertEquals(UserListener::class, $class->entityListeners[Events::postPersist][0]['class']);
$this->assertEquals('customPostPersist', $class->entityListeners[Events::postPersist][0]['method']);
$this->assertEquals(AddressListener::class, $class->entityListeners[Events::postPersist][1]['class']);
$this->assertEquals('customPostPersist', $class->entityListeners[Events::postPersist][1]['method']);
}
public function __destruct() public function __destruct()
{ {
# $this->_deleteDirectory(__DIR__ . '/export/'.$this->_getType()); # $this->_deleteDirectory(__DIR__ . '/export/'.$this->_getType());
@ -406,3 +428,28 @@ class Group
{ {
} }
class UserListener
{
/**
* @\Doctrine\ORM\Mapping\PrePersist
*/
public function customPrePersist(): void {}
/**
* @\Doctrine\ORM\Mapping\PostPersist
*/
public function customPostPersist(): void {}
}
class GroupListener
{
/**
* @\Doctrine\ORM\Mapping\PrePersist
*/
public function prePersist(): void {}
}
class AddressListener
{
/**
* @\Doctrine\ORM\Mapping\PostPersist
*/
public function customPostPersist(): void {}
}

View File

@ -5,6 +5,11 @@ namespace Doctrine\Tests\ORM\Tools\Export;
/** /**
* @Entity * @Entity
* @HasLifecycleCallbacks * @HasLifecycleCallbacks
* @EntityListeners({
* Doctrine\Tests\ORM\Tools\Export\UserListener::class,
* Doctrine\Tests\ORM\Tools\Export\GroupListener::class,
* Doctrine\Tests\ORM\Tools\Export\AddressListener::class
* })
* @Table(name="cms_users",options={"engine"="MyISAM","foo"={"bar"="baz"}}) * @Table(name="cms_users",options={"engine"="MyISAM","foo"={"bar"="baz"}})
*/ */
class User class User
@ -57,21 +62,21 @@ class User
/** /**
* @PrePersist * @PrePersist
*/ */
public function doStuffOnPrePersist() public function doStuffOnPrePersist(): void
{ {
} }
/** /**
* @PrePersist * @PrePersist
*/ */
public function doOtherStuffOnPrePersistToo() public function doOtherStuffOnPrePersistToo(): void
{ {
} }
/** /**
* @PostPersist * @PostPersist
*/ */
public function doStuffOnPostPersist() public function doStuffOnPostPersist(): void
{ {
} }
} }

View File

@ -1,7 +1,11 @@
<?php <?php
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\Tests\ORM\Tools\Export; use Doctrine\Tests\ORM\Tools\Export;
use Doctrine\Tests\ORM\Tools\Export\AddressListener;
use Doctrine\Tests\ORM\Tools\Export\GroupListener;
use Doctrine\Tests\ORM\Tools\Export\UserListener;
$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE); $metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
$metadata->setPrimaryTable( $metadata->setPrimaryTable(
@ -11,9 +15,9 @@ $metadata->setPrimaryTable(
] ]
); );
$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT); $metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT);
$metadata->addLifecycleCallback('doStuffOnPrePersist', 'prePersist'); $metadata->addLifecycleCallback('doStuffOnPrePersist', Events::prePersist);
$metadata->addLifecycleCallback('doOtherStuffOnPrePersistToo', 'prePersist'); $metadata->addLifecycleCallback('doOtherStuffOnPrePersistToo', Events::prePersist);
$metadata->addLifecycleCallback('doStuffOnPostPersist', 'postPersist'); $metadata->addLifecycleCallback('doStuffOnPostPersist', Events::postPersist);
$metadata->mapField( $metadata->mapField(
[ [
'id' => true, 'id' => true,
@ -149,3 +153,7 @@ $metadata->mapManyToMany(
'orderBy' => NULL, 'orderBy' => NULL,
] ]
); );
$metadata->addEntityListener(Events::prePersist, UserListener::class, 'customPrePersist');
$metadata->addEntityListener(Events::postPersist, UserListener::class, 'customPostPersist');
$metadata->addEntityListener(Events::prePersist, GroupListener::class, 'prePersist');
$metadata->addEntityListener(Events::postPersist, AddressListener::class, 'customPostPersist');

View File

@ -77,6 +77,18 @@
</join-table> </join-table>
</many-to-many> </many-to-many>
<entity-listeners>
<entity-listener class="Doctrine\Tests\ORM\Tools\Export\UserListener">
<lifecycle-callback type="prePersist" method="customPrePersist" />
<lifecycle-callback type="postPersist" method="customPostPersist" />
</entity-listener>
<entity-listener class="Doctrine\Tests\ORM\Tools\Export\GroupListener">
<lifecycle-callback type="prePersist" method="prePersist" />
</entity-listener>
<entity-listener class="Doctrine\Tests\ORM\Tools\Export\AddressListener">
<lifecycle-callback type="postPersist" method="customPostPersist" />
</entity-listener>
</entity-listeners>
</entity> </entity>
</doctrine-mapping> </doctrine-mapping>

View File

@ -75,3 +75,11 @@ Doctrine\Tests\ORM\Tools\Export\User:
lifecycleCallbacks: lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ] prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
postPersist: [ doStuffOnPostPersist ] postPersist: [ doStuffOnPostPersist ]
entityListeners:
Doctrine\Tests\ORM\Tools\Export\UserListener:
prePersist: [customPrePersist]
postPersist: [customPostPersist]
Doctrine\Tests\ORM\Tools\Export\GroupListener:
prePersist: [prePersist]
Doctrine\Tests\ORM\Tools\Export\AddressListener:
postPersist: [customPostPersist]