Skip to content

Commit 67af691

Browse files
committed
Add a group property list extractor
1 parent ed46093 commit 67af691

File tree

2 files changed

+223
-0
lines changed

2 files changed

+223
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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\Serializer\Extractor;
13+
14+
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
15+
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
16+
17+
/**
18+
* Filter properties given a specific set of groups
19+
*
20+
* @author Joel Wurtz <joel.wurtz@gmail.com>
21+
*/
22+
class GroupPropertyListExtractor implements PropertyListExtractorInterface
23+
{
24+
public const GROUPS = 'groups';
25+
26+
private $classMetadataFactory;
27+
28+
private $extractor;
29+
30+
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory, PropertyListExtractorInterface $extractor = null)
31+
{
32+
$this->extractor = $extractor;
33+
$this->classMetadataFactory = $classMetadataFactory;
34+
}
35+
36+
public function getProperties($class, array $context = [])
37+
{
38+
$properties = null;
39+
40+
if (null !== $this->extractor) {
41+
$properties = $this->extractor->getProperties($class, $context);
42+
43+
if (null === $properties) {
44+
return null;
45+
}
46+
}
47+
48+
$groups = $context[self::GROUPS] ?? null;
49+
$groups = (\is_array($groups) || is_scalar($groups)) ? (array) $groups : false;
50+
$groupProperties = [];
51+
52+
foreach ($this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() as $attributeMetadata) {
53+
$name = $attributeMetadata->getName();
54+
55+
if (false === $groups || array_intersect($attributeMetadata->getGroups(), $groups)) {
56+
$groupProperties[] = $name;
57+
}
58+
}
59+
60+
if (null === $properties) {
61+
return $groupProperties;
62+
}
63+
64+
return array_intersect($properties, $groupProperties);
65+
}
66+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
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\Serializer\Tests\Extractor;
13+
14+
use Doctrine\Common\Annotations\AnnotationReader;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
17+
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
18+
use Symfony\Component\Serializer\Annotation\Groups;
19+
use Symfony\Component\Serializer\Extractor\GroupPropertyListExtractor;
20+
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
21+
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
22+
23+
class GroupPropertyListExtractorTest extends TestCase
24+
{
25+
public function testNoGroups()
26+
{
27+
$extractor = new ReflectionExtractor();
28+
$factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
29+
$groupExtractor = new GroupPropertyListExtractor($factory, $extractor);
30+
31+
$properties = $groupExtractor->getProperties(DummyNoGroups::class);
32+
33+
$this->assertInternalType('array', $properties);
34+
$this->assertContains('foo', $properties);
35+
$this->assertContains('bar', $properties);
36+
$this->assertContains('baz', $properties);
37+
38+
$properties = $groupExtractor->getProperties(DummyNoGroups::class, [
39+
GroupPropertyListExtractor::GROUPS => ['dummy']
40+
]);
41+
42+
$this->assertInternalType('array', $properties);
43+
$this->assertEmpty($properties);
44+
}
45+
46+
public function testGroups()
47+
{
48+
$extractor = new ReflectionExtractor();
49+
$factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
50+
$groupExtractor = new GroupPropertyListExtractor($factory, $extractor);
51+
52+
$properties = $groupExtractor->getProperties(DummyGroups::class);
53+
54+
$this->assertInternalType('array', $properties);
55+
$this->assertContains('foo', $properties);
56+
$this->assertContains('bar', $properties);
57+
$this->assertContains('baz', $properties);
58+
59+
$properties = $groupExtractor->getProperties(DummyGroups::class, [
60+
GroupPropertyListExtractor::GROUPS => ['dummy']
61+
]);
62+
63+
$this->assertInternalType('array', $properties);
64+
$this->assertEmpty($properties);
65+
66+
$properties = $groupExtractor->getProperties(DummyGroups::class, [
67+
GroupPropertyListExtractor::GROUPS => ['foo']
68+
]);
69+
70+
$this->assertInternalType('array', $properties);
71+
$this->assertContains('foo', $properties);
72+
$this->assertNotContains('bar', $properties);
73+
$this->assertNotContains('baz', $properties);
74+
75+
$properties = $groupExtractor->getProperties(DummyGroups::class, [
76+
GroupPropertyListExtractor::GROUPS => ['foo', 'bar']
77+
]);
78+
79+
$this->assertInternalType('array', $properties);
80+
$this->assertContains('foo', $properties);
81+
$this->assertContains('bar', $properties);
82+
$this->assertContains('baz', $properties);
83+
84+
$properties = $groupExtractor->getProperties(DummyGroups::class, [
85+
GroupPropertyListExtractor::GROUPS => ['bar']
86+
]);
87+
88+
$this->assertInternalType('array', $properties);
89+
$this->assertNotContains('foo', $properties);
90+
$this->assertContains('bar', $properties);
91+
$this->assertContains('baz', $properties);
92+
93+
$properties = $groupExtractor->getProperties(DummyGroups::class, [
94+
GroupPropertyListExtractor::GROUPS => ['baz']
95+
]);
96+
97+
$this->assertInternalType('array', $properties);
98+
$this->assertNotContains('foo', $properties);
99+
$this->assertNotContains('bar', $properties);
100+
$this->assertContains('baz', $properties);
101+
}
102+
103+
public function testNullProperties()
104+
{
105+
$extractor = $this
106+
->getMockBuilder(PropertyListExtractorInterface::class)
107+
->getMock()
108+
;
109+
$factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
110+
111+
$extractor->method('getProperties')->willReturn(null);
112+
113+
$ignored = new GroupPropertyListExtractor($factory, $extractor);
114+
$properties = $ignored->getProperties(DummyNoGroups::class);
115+
116+
$this->assertNull($properties);
117+
}
118+
119+
public function testNoExtractor()
120+
{
121+
$factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
122+
$ignored = new GroupPropertyListExtractor($factory);
123+
$properties = $ignored->getProperties(DummyNoGroups::class);
124+
125+
$this->assertInternalType('array', $properties);
126+
$this->assertContains('foo', $properties);
127+
$this->assertContains('bar', $properties);
128+
$this->assertContains('baz', $properties);
129+
}
130+
}
131+
132+
class DummyNoGroups
133+
{
134+
public $foo;
135+
136+
public $bar;
137+
138+
public $baz;
139+
}
140+
141+
class DummyGroups
142+
{
143+
/**
144+
* @Groups("foo")
145+
*/
146+
public $foo;
147+
148+
/**
149+
* @Groups({"bar"})
150+
*/
151+
public $bar;
152+
153+
/**
154+
* @Groups({"bar", "baz"})
155+
*/
156+
public $baz;
157+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy