Skip to content

Commit 8aec093

Browse files
committed
[PropertyInfo][FrameworkBundle] Allow defining accessors and mutators via an attribute
1 parent cad21a9 commit 8aec093

30 files changed

+1168
-27
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

+1
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,7 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild
20692069

20702070
if ($container->getParameter('kernel.debug')) {
20712071
$container->removeDefinition('property_info.cache');
2072+
$container->removeDefinition('property_info.mapping.cached_class_metadata_factory');
20722073
}
20732074
}
20742075

src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.php

+22
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
use Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor;
1515
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
16+
use Symfony\Component\PropertyInfo\Mapping\Factory\CachedClassMetadataFactory;
17+
use Symfony\Component\PropertyInfo\Mapping\Factory\ClassMetadataFactory;
18+
use Symfony\Component\PropertyInfo\Mapping\Factory\ClassMetadataFactoryInterface;
19+
use Symfony\Component\PropertyInfo\Mapping\Loader\AttributeLoader;
1620
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
1721
use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
1822
use Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor;
@@ -40,8 +44,26 @@
4044
->decorate('property_info')
4145
->args([service('property_info.cache.inner'), service('cache.property_info')])
4246

47+
// Loader
48+
->set('property_info.mapping.attribute_loader', AttributeLoader::class)
49+
50+
// Class Metadata Factory
51+
->set('property_info.mapping.class_metadata_factory', ClassMetadataFactory::class)
52+
->args([service('property_info.mapping.attribute_loader')])
53+
54+
->alias(ClassMetadataFactoryInterface::class, 'property_info.mapping.class_metadata_factory')
55+
56+
// Cache
57+
->set('property_info.mapping.cached_class_metadata_factory', CachedClassMetadataFactory::class)
58+
->decorate('property_info.mapping.class_metadata_factory')
59+
->args([
60+
service('property_info.mapping.cached_class_metadata_factory.inner'),
61+
service('cache.property_info'),
62+
])
63+
4364
// Extractor
4465
->set('property_info.reflection_extractor', ReflectionExtractor::class)
66+
->arg('$classMetadataFactory', service(ClassMetadataFactoryInterface::class))
4567
->tag('property_info.list_extractor', ['priority' => -1000])
4668
->tag('property_info.type_extractor', ['priority' => -1002])
4769
->tag('property_info.constructor_extractor', ['priority' => -1002])

src/Symfony/Bundle/FrameworkBundle/composer.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"symfony/validator": "^6.4|^7.0",
6969
"symfony/workflow": "^6.4|^7.0",
7070
"symfony/yaml": "^6.4|^7.0",
71-
"symfony/property-info": "^6.4|^7.0",
71+
"symfony/property-info": "^7.3",
7272
"symfony/json-encoder": "7.3.*",
7373
"symfony/uid": "^6.4|^7.0",
7474
"symfony/web-link": "^6.4|^7.0",
@@ -93,7 +93,7 @@
9393
"symfony/mailer": "<6.4",
9494
"symfony/messenger": "<6.4",
9595
"symfony/mime": "<6.4",
96-
"symfony/property-info": "<6.4",
96+
"symfony/property-info": "<7.3",
9797
"symfony/property-access": "<6.4",
9898
"symfony/runtime": "<6.4.13|>=7.0,<7.1.6",
9999
"symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo\Attribute;
13+
14+
use Symfony\Component\PropertyInfo\Exception\LogicException;
15+
16+
#[\Attribute(\Attribute::TARGET_PROPERTY)]
17+
final readonly class WithAccessors
18+
{
19+
public function __construct(
20+
public ?string $getter = null,
21+
public ?string $setter = null,
22+
public ?string $adder = null,
23+
public ?string $remover = null,
24+
) {
25+
if (null === $this->getter && null === $this->setter && null === $this->adder && null === $this->remover) {
26+
throw new LogicException('You need to have at least one method name set.');
27+
}
28+
if (null === $this->adder xor null === $this->remover) {
29+
throw new LogicException('You need to have both an adder and remover set.');
30+
}
31+
}
32+
}

src/Symfony/Component/PropertyInfo/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Add support for `non-positive-int`, `non-negative-int` and `non-zero-int` PHPStan types to `PhpStanExtractor`
88
* Add `PropertyDescriptionExtractorInterface` to `PhpStanExtractor`
9+
* Allow defining accessors and mutators via the `#[WithAccessors]` attribute
910

1011
7.1
1112
---
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo\Exception;
13+
14+
interface ExceptionInterface extends \Throwable
15+
{
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo\Exception;
13+
14+
class LogicException extends \LogicException implements ExceptionInterface
15+
{
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo\Exception;
13+
14+
class MappingException extends RuntimeException
15+
{
16+
/**
17+
* @param list<string> $invalidMethods
18+
*/
19+
public function __construct(
20+
string $message,
21+
public readonly string $forClass,
22+
public readonly array $invalidMethods,
23+
?\Throwable $previous = null,
24+
) {
25+
parent::__construct($message, 0, $previous);
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo\Exception;
13+
14+
class RuntimeException extends \RuntimeException implements ExceptionInterface
15+
{
16+
}

0 commit comments

Comments
 (0)