Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Context;

/**
* @author Joel Wurtz <joel.wurtz@gmail.com>
*
* @experimental in 4.3
*/
interface ChildContextBuilderInterface
{
/**
* Update the context for a sub level given a specific attribute.
*/
public function createChildContextForAttribute(array $context, string $attribute): array;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Extractor;

use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\Serializer\Context\ChildContextBuilderInterface;

/**
* Allow properties given an allowed list of properties in the context.
*
* @author Joel Wurtz <joel.wurtz@gmail.com>
*
* @experimental in 4.3
*/
final class AllowedPropertyListExtractor implements PropertyListExtractorInterface, ChildContextBuilderInterface
{
public const ATTRIBUTES = 'attributes';

private $extractor;

public function __construct(PropertyListExtractorInterface $extractor)
{
$this->extractor = $extractor;
}

/**
* {@inheritdoc}
*/
public function getProperties($class, array $context = [])
{
$properties = $this->extractor->getProperties($class, $context);

if (null === $properties) {
return null;
}

$allowed = $context[self::ATTRIBUTES] ?? null;

if (null === $allowed) {
return $properties;
}

return array_intersect($properties, $allowed);
}

/**
* {@inheritdoc}
*/
public function createChildContextForAttribute(array $context, string $attribute): array
{
if ($this->extractor instanceof ChildContextBuilderInterface) {
$context = $this->extractor->createChildContextForAttribute($context, $attribute);
}

if (isset($context[self::ATTRIBUTES][$attribute])) {
$context[self::ATTRIBUTES] = $context[self::ATTRIBUTES][$attribute];
} else {
unset($context[self::ATTRIBUTES]);
}

return $context;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Extractor;

use Symfony\Component\Serializer\Context\ChildContextBuilderInterface;

trait DecorateChildContextBuilderTrait
{
private $extractor;

/**
* {@inheritdoc}
*/
public function createChildContextForAttribute(array $context, string $attribute): array
{
if ($this->extractor instanceof ChildContextBuilderInterface) {
return $this->extractor->createChildContextForAttribute($context, $attribute);
}

return $context;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Extractor;

use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\Serializer\Context\ChildContextBuilderInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;

/**
* Filter properties given a specific set of groups.
*
* @author Joel Wurtz <joel.wurtz@gmail.com>
*
* @experimental in 4.3
*/
final class GroupPropertyListExtractor implements PropertyListExtractorInterface, ChildContextBuilderInterface
{
use DecorateChildContextBuilderTrait;

public const GROUPS = 'groups';

private $classMetadataFactory;

public function __construct(ClassMetadataFactoryInterface $classMetadataFactory, PropertyListExtractorInterface $extractor = null)
{
$this->extractor = $extractor;
$this->classMetadataFactory = $classMetadataFactory;
}

public function getProperties($class, array $context = [])
{
$properties = null;

if (null !== $this->extractor) {
$properties = $this->extractor->getProperties($class, $context);

if (null === $properties) {
return null;
}
}

$groups = $context[self::GROUPS] ?? null;
$groups = (\is_array($groups) || is_scalar($groups)) ? (array) $groups : false;
$groupProperties = [];

foreach ($this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() as $attributeMetadata) {
$name = $attributeMetadata->getName();

if (false === $groups || array_intersect($attributeMetadata->getGroups(), $groups)) {
$groupProperties[] = $name;
}
}

if (null === $properties) {
return $groupProperties;
}

return array_intersect($properties, $groupProperties);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Extractor;

use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\Serializer\Context\ChildContextBuilderInterface;

/**
* Remove properties given a ignore list of attributes in the context.
*
* @author Joel Wurtz <joel.wurtz@gmail.com>
*
* @experimental in 4.3
*/
final class IgnoredPropertyListExtractor implements PropertyListExtractorInterface, ChildContextBuilderInterface
{
use DecorateChildContextBuilderTrait;

public const ATTRIBUTES = 'ignored_attributes';

public function __construct(PropertyListExtractorInterface $extractor)
{
$this->extractor = $extractor;
}

/**
* {@inheritdoc}
*/
public function getProperties($class, array $context = [])
{
$properties = $this->extractor->getProperties($class, $context);

if (null === $properties) {
return null;
}

$ignored = $context[self::ATTRIBUTES] ?? null;

if (null === $ignored) {
return $properties;
}

return array_diff($properties, $ignored);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
namespace Symfony\Component\Serializer\Extractor;

use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\Serializer\Context\ChildContextBuilderInterface;

/**
* @author David Maicher <mail@dmaicher.de>
*
* @experimental in 4.3
*/
final class ObjectPropertyListExtractor implements ObjectPropertyListExtractorInterface
final class ObjectPropertyListExtractor implements ObjectPropertyListExtractorInterface, ChildContextBuilderInterface
{
private $propertyListExtractor;
private $objectClassResolver;
Expand All @@ -38,4 +39,16 @@ public function getProperties($object, array $context = []): ?array

return $this->propertyListExtractor->getProperties($class, $context);
}

/**
* {@inheritdoc}
*/
public function createChildContextForAttribute(array $context, string $attribute): array
{
if ($this->propertyListExtractor instanceof ChildContextBuilderInterface) {
return $this->propertyListExtractor->createChildContextForAttribute($context, $attribute);
}

return $context;
}
}
Loading