Skip to content

Commit

Permalink
Deprecate annotations support (#2772)
Browse files Browse the repository at this point in the history
* Deprecate annotations support

* Reverse the inheritance chain for the annotation and attribute driver interfaces

* Flip the inheritance chain between annotation and attribute drivers for the extensions

* Fill in links for deprecations

* Refresh PHPStan
  • Loading branch information
mbabker authored Jun 24, 2024
1 parent a1c2a91 commit 043552d
Show file tree
Hide file tree
Showing 34 changed files with 1,551 additions and 1,401 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ a release.
---

## [Unreleased]
### Deprecated
- Support for `doctrine/annotations` has been deprecated and will be removed in 4.0.

### Fixed
- Tree: Cascade remove not being triggered on entity children at `MaterializedPath::removeNode()`.

Expand Down
35 changes: 15 additions & 20 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ parameters:
path: src/AbstractTrackingListener.php

-
message: "#^Access to an undefined property object\\:\\:\\$value\\.$#"
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/Blameable/Mapping/Driver/Annotation.php
path: src/Blameable/Mapping/Driver/Attribute.php

-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
message: "#^Property Gedmo\\\\Mapping\\\\Annotation\\\\Blameable\\:\\:\\$field \\(array\\<string\\>\\|string\\) in isset\\(\\) is not nullable\\.$#"
count: 1
path: src/Blameable/Mapping/Driver/Annotation.php
path: src/Blameable/Mapping/Driver/Attribute.php

-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:getFieldMapping\\(\\)\\.$#"
Expand All @@ -45,15 +45,10 @@ parameters:
count: 2
path: src/DoctrineExtensions.php

-
message: "#^Access to an undefined property object\\:\\:\\$value\\.$#"
count: 1
path: src/IpTraceable/Mapping/Driver/Annotation.php

-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/IpTraceable/Mapping/Driver/Annotation.php
path: src/IpTraceable/Mapping/Driver/Attribute.php

-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:getFieldMapping\\(\\)\\.$#"
Expand Down Expand Up @@ -223,7 +218,7 @@ parameters:
-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/References/Mapping/Driver/Annotation.php
path: src/References/Mapping/Driver/Attribute.php

-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<object\\>\\:\\:getReflectionProperty\\(\\)\\.$#"
Expand Down Expand Up @@ -333,7 +328,7 @@ parameters:
-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/Sluggable/Mapping/Driver/Annotation.php
path: src/Sluggable/Mapping/Driver/Attribute.php

-
message: "#^Access to an undefined property Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:\\$isMappedSuperclass\\.$#"
Expand Down Expand Up @@ -413,7 +408,7 @@ parameters:
-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/Sortable/Mapping/Driver/Annotation.php
path: src/Sortable/Mapping/Driver/Attribute.php

-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:getFieldMapping\\(\\)\\.$#"
Expand Down Expand Up @@ -451,14 +446,14 @@ parameters:
path: src/Sortable/SortableListener.php

-
message: "#^Access to an undefined property object\\:\\:\\$value\\.$#"
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/Timestampable/Mapping/Driver/Annotation.php
path: src/Timestampable/Mapping/Driver/Attribute.php

-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
message: "#^Property Gedmo\\\\Mapping\\\\Annotation\\\\Timestampable\\:\\:\\$field \\(array\\<string\\>\\|string\\) in isset\\(\\) is not nullable\\.$#"
count: 1
path: src/Timestampable/Mapping/Driver/Annotation.php
path: src/Timestampable/Mapping/Driver/Attribute.php

-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:getFieldMapping\\(\\)\\.$#"
Expand Down Expand Up @@ -513,7 +508,7 @@ parameters:
-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/Translatable/Mapping/Driver/Annotation.php
path: src/Translatable/Mapping/Driver/Attribute.php

-
message: "#^Access to offset 'association' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\FieldMapping\\.$#"
Expand Down Expand Up @@ -628,7 +623,7 @@ parameters:
-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: src/Tree/Mapping/Driver/Annotation.php
path: src/Tree/Mapping/Driver/Attribute.php

-
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:getFieldMapping\\(\\)\\.$#"
Expand Down Expand Up @@ -803,7 +798,7 @@ parameters:
-
message: "#^Access to offset 'inherited' on an unknown class Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\AssociationFieldMapping\\.$#"
count: 1
path: tests/Gedmo/Mapping/Mock/Extension/Encoder/Mapping/Driver/Annotation.php
path: tests/Gedmo/Mapping/Mock/Extension/Encoder/Mapping/Driver/Attribute.php

-
message: "#^Instantiated class Doctrine\\\\ORM\\\\Mapping\\\\Driver\\\\AnnotationDriver not found\\.$#"
Expand Down
82 changes: 4 additions & 78 deletions src/Blameable/Mapping/Driver/Annotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,89 +9,15 @@

namespace Gedmo\Blameable\Mapping\Driver;

use Gedmo\Exception\InvalidMappingException;
use Gedmo\Mapping\Annotation\Blameable;
use Gedmo\Mapping\Driver\AbstractAnnotationDriver;
use Gedmo\Mapping\Driver\AnnotationDriverInterface;

/**
* This is an annotation mapping driver for Blameable
* behavioral extension. Used for extraction of extended
* metadata from Annotations specifically for Blameable
* extension.
* Mapping driver for the blamable extension which reads extended metadata from annotations on a blamable class.
*
* @author David Buchmann <mail@davidbu.ch>
* @deprecated since gedmo/doctrine-extensions 3.16, will be removed in version 4.0.
*
* @internal
*/
class Annotation extends AbstractAnnotationDriver
class Annotation extends Attribute implements AnnotationDriverInterface
{
/**
* Annotation field is blameable
*/
public const BLAMEABLE = Blameable::class;

/**
* List of types which are valid for blame
*
* @var string[]
*/
protected $validTypes = [
'one',
'string',
'int',
'ulid',
'uuid',
'ascii_string',
];

public function readExtendedMetadata($meta, array &$config)
{
$class = $this->getMetaReflectionClass($meta);
// property annotations
foreach ($class->getProperties() as $property) {
if ($meta->isMappedSuperclass && !$property->isPrivate()
|| $meta->isInheritedField($property->name)
|| isset($meta->associationMappings[$property->name]['inherited'])
) {
continue;
}
if ($blameable = $this->reader->getPropertyAnnotation($property, self::BLAMEABLE)) {
$field = $property->getName();

if (!$meta->hasField($field) && !$meta->hasAssociation($field)) {
throw new InvalidMappingException("Unable to find blameable [{$field}] as mapped property in entity - {$meta->getName()}");
}
if ($meta->hasField($field)) {
if (!$this->isValidField($meta, $field)) {
throw new InvalidMappingException("Field - [{$field}] type is not valid and must be 'string' or a one-to-many relation in class - {$meta->getName()}");
}
} else {
// association
if (!$meta->isSingleValuedAssociation($field)) {
throw new InvalidMappingException("Association - [{$field}] is not valid, it must be a one-to-many relation or a string field - {$meta->getName()}");
}
}
if (!in_array($blameable->on, ['update', 'create', 'change'], true)) {
throw new InvalidMappingException("Field - [{$field}] trigger 'on' is not one of [update, create, change] in class - {$meta->getName()}");
}
if ('change' === $blameable->on) {
if (!isset($blameable->field)) {
throw new InvalidMappingException("Missing parameters on property - {$field}, field must be set on [change] trigger in class - {$meta->getName()}");
}
if (is_array($blameable->field) && isset($blameable->value)) {
throw new InvalidMappingException('Blameable extension does not support multiple value changeset detection yet.');
}
$field = [
'field' => $field,
'trackedField' => $blameable->field,
'value' => $blameable->value,
];
}
// properties are unique and mapper checks that, no risk here
$config[$blameable->on][] = $field;
}
}

return $config;
}
}
91 changes: 85 additions & 6 deletions src/Blameable/Mapping/Driver/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,95 @@

namespace Gedmo\Blameable\Mapping\Driver;

use Gedmo\Mapping\Driver\AttributeDriverInterface;
use Gedmo\Exception\InvalidMappingException;
use Gedmo\Mapping\Annotation\Blameable;
use Gedmo\Mapping\Driver\AbstractAnnotationDriver;

/**
* This is an attribute mapping driver for Blameable
* behavioral extension. Used for extraction of extended
* metadata from attribute specifically for Blameable
* extension.
* Mapping driver for the blameable extension which reads extended metadata from attributes on a blameable class.
*
* @author David Buchmann <mail@davidbu.ch>
*
* @internal
*/
final class Attribute extends Annotation implements AttributeDriverInterface
class Attribute extends AbstractAnnotationDriver
{
/**
* Mapping object for the blameable extension.
*/
public const BLAMEABLE = Blameable::class;

/**
* List of types which are valid for blame
*
* @var string[]
*/
protected $validTypes = [
'one',
'string',
'int',
'ulid',
'uuid',
'ascii_string',
];

public function readExtendedMetadata($meta, array &$config)
{
$class = $this->getMetaReflectionClass($meta);

// property annotations
foreach ($class->getProperties() as $property) {
if ($meta->isMappedSuperclass && !$property->isPrivate()
|| $meta->isInheritedField($property->name)
|| isset($meta->associationMappings[$property->name]['inherited'])
) {
continue;
}

if ($blameable = $this->reader->getPropertyAnnotation($property, self::BLAMEABLE)) {
\assert($blameable instanceof Blameable);

$field = $property->getName();

if (!$meta->hasField($field) && !$meta->hasAssociation($field)) {
throw new InvalidMappingException("Unable to find blameable [{$field}] as mapped property in entity - {$meta->getName()}");
}

if ($meta->hasField($field)) {
if (!$this->isValidField($meta, $field)) {
throw new InvalidMappingException("Field - [{$field}] type is not valid and must be 'string' or a one-to-many relation in class - {$meta->getName()}");
}
} else {
// association
if (!$meta->isSingleValuedAssociation($field)) {
throw new InvalidMappingException("Association - [{$field}] is not valid, it must be a one-to-many relation or a string field - {$meta->getName()}");
}
}

if (!in_array($blameable->on, ['update', 'create', 'change'], true)) {
throw new InvalidMappingException("Field - [{$field}] trigger 'on' is not one of [update, create, change] in class - {$meta->getName()}");
}

if ('change' === $blameable->on) {
if (!isset($blameable->field)) {
throw new InvalidMappingException("Missing parameters on property - {$field}, field must be set on [change] trigger in class - {$meta->getName()}");
}

if (is_array($blameable->field) && isset($blameable->value)) {
throw new InvalidMappingException('Blameable extension does not support multiple value changeset detection yet.');
}

$field = [
'field' => $field,
'trackedField' => $blameable->field,
'value' => $blameable->value,
];
}
// properties are unique and mapper checks that, no risk here
$config[$blameable->on][] = $field;
}
}

return $config;
}
}
71 changes: 4 additions & 67 deletions src/IpTraceable/Mapping/Driver/Annotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,78 +9,15 @@

namespace Gedmo\IpTraceable\Mapping\Driver;

use Gedmo\Exception\InvalidMappingException;
use Gedmo\Mapping\Annotation\IpTraceable;
use Gedmo\Mapping\Driver\AbstractAnnotationDriver;
use Gedmo\Mapping\Driver\AnnotationDriverInterface;

/**
* This is an annotation mapping driver for IpTraceable
* behavioral extension. Used for extraction of extended
* metadata from Annotations specifically for IpTraceable
* extension.
* Mapping driver for the IP traceable extension which reads extended metadata from annotations on an IP traceable class.
*
* @author Pierre-Charles Bertineau <pc.bertineau@alterphp.com>
* @deprecated since gedmo/doctrine-extensions 3.16, will be removed in version 4.0.
*
* @internal
*/
class Annotation extends AbstractAnnotationDriver
class Annotation extends Attribute implements AnnotationDriverInterface
{
/**
* Annotation field is ipTraceable
*/
public const IP_TRACEABLE = IpTraceable::class;

/**
* List of types which are valid for IP
*
* @var string[]
*/
protected $validTypes = [
'string',
'ascii_string',
];

public function readExtendedMetadata($meta, array &$config)
{
$class = $this->getMetaReflectionClass($meta);
// property annotations
foreach ($class->getProperties() as $property) {
if ($meta->isMappedSuperclass && !$property->isPrivate()
|| $meta->isInheritedField($property->name)
|| isset($meta->associationMappings[$property->name]['inherited'])
) {
continue;
}
if ($ipTraceable = $this->reader->getPropertyAnnotation($property, self::IP_TRACEABLE)) {
$field = $property->getName();

if (!$meta->hasField($field)) {
throw new InvalidMappingException("Unable to find ipTraceable [{$field}] as mapped property in entity - {$meta->getName()}");
}
if (!$this->isValidField($meta, $field)) {
throw new InvalidMappingException("Field - [{$field}] type is not valid and must be 'string' - {$meta->getName()}");
}
if (!in_array($ipTraceable->on, ['update', 'create', 'change'], true)) {
throw new InvalidMappingException("Field - [{$field}] trigger 'on' is not one of [update, create, change] in class - {$meta->getName()}");
}
if ('change' === $ipTraceable->on) {
if (!isset($ipTraceable->field)) {
throw new InvalidMappingException("Missing parameters on property - {$field}, field must be set on [change] trigger in class - {$meta->getName()}");
}
if (is_array($ipTraceable->field) && isset($ipTraceable->value)) {
throw new InvalidMappingException('IpTraceable extension does not support multiple value changeset detection yet.');
}
$field = [
'field' => $field,
'trackedField' => $ipTraceable->field,
'value' => $ipTraceable->value,
];
}
// properties are unique and mapper checks that, no risk here
$config[$ipTraceable->on][] = $field;
}
}

return $config;
}
}
Loading

0 comments on commit 043552d

Please sign in to comment.