Skip to content

Commit

Permalink
Update dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Devlamynck committed Mar 11, 2024
1 parent 8528e11 commit be5ce7a
Show file tree
Hide file tree
Showing 13 changed files with 1,363 additions and 1,595 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
<?php declare(strict_types=1);

namespace RichId\CsvGeneratorBundle\Annotation;
namespace RichId\CsvGeneratorBundle\Attribute;

/**
* Class CsvContentTranslationPrefix.
*
* @package RichId\CsvGeneratorBundle\Annotation
* @package RichId\CsvGeneratorBundle\Attribute
* @author Hugo Dumazeau <[email protected]>
* @copyright 2014 - 2021 RichId (https://www.rich-id.fr)
*
* @Annotation
* @Target({"PROPERTY"})
*/
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class CsvContentTranslationPrefix
{
/** @var string */
public $translationPrefix;
public function __construct(
public string $translationPrefix
) {}
}

1 change: 1 addition & 0 deletions Resources/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<service id="RichId\CsvGeneratorBundle\Generator\CsvGenerator" />
<service id="RichId\CsvGeneratorBundle\Generator\CsvGeneratorInterface" alias="RichId\CsvGeneratorBundle\Generator\CsvGenerator" />

<service id="RichId\CsvGeneratorBundle\Utility\ObjectNormalizer" />
<service id="RichId\CsvGeneratorBundle\Utility\PropertiesUtility" />
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use RichCongress\TestFramework\TestConfiguration\Annotation\TestConfig;
use RichCongress\TestFramework\TestConfiguration\Attribute\TestConfig;
use RichCongress\TestSuite\TestCase\TestCase;
use RichId\CsvGeneratorBundle\Configuration\AbstractCsvGeneratorConfiguration;
use RichId\CsvGeneratorBundle\Configuration\CsvQueryBuilderGeneratorConfiguration;
Expand All @@ -19,9 +19,8 @@
*
* @covers \RichId\CsvGeneratorBundle\Configuration\AbstractCsvGeneratorConfiguration
* @covers \RichId\CsvGeneratorBundle\Configuration\CsvQueryBuilderGeneratorConfiguration
*
* @TestConfig("fixtures")
*/
#[TestConfig('fixtures')]
class CsvQueryBuilderGeneratorConfigurationTest extends TestCase
{
/** @var EntityManagerInterface */
Expand Down
5 changes: 2 additions & 3 deletions Tests/Generator/CsvGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use RichCongress\TestFramework\TestConfiguration\Annotation\TestConfig;
use RichCongress\TestFramework\TestConfiguration\Attribute\TestConfig;
use RichCongress\TestSuite\TestCase\TestCase;
use RichId\CsvGeneratorBundle\Configuration\CsvGeneratorConfiguration;
use RichId\CsvGeneratorBundle\Configuration\CsvQueryBuilderGeneratorConfiguration;
Expand All @@ -22,9 +22,8 @@
* @copyright 2014 - 2021 RichId (https://www.rich-id.fr)
*
* @covers \RichId\CsvGeneratorBundle\Generator\CsvGenerator
*
* @TestConfig("fixtures")
*/
#[TestConfig('fixtures')]
class CsvGeneratorTest extends TestCase
{
protected const RESOURCES_DIR = __DIR__ . '/../Resources/files/';
Expand Down
68 changes: 21 additions & 47 deletions Tests/Resources/Entity/DummyEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,34 @@
namespace RichId\CsvGeneratorBundle\Tests\Resources\Entity;

use Doctrine\ORM\Mapping as ORM;
use RichId\CsvGeneratorBundle\Annotation\CsvContentTranslationPrefix;
use Symfony\Component\Serializer\Annotation\Groups;
use RichId\CsvGeneratorBundle\Attribute\CsvContentTranslationPrefix;
use Symfony\Component\Serializer\Attribute\Groups;

/**
* @ORM\Table("dummy_entity")
* @ORM\Entity
*/
#[ORM\Table('dummy_entity')]
#[ORM\Entity]
class DummyEntity
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups("my_serialization_group")
*/
private $id;
#[ORM\Id]
#[ORM\Column(type: 'integer')]
#[ORM\GeneratedValue(strategy: 'AUTO')]
#[Groups('my_serialization_group')]
private int $id;

/**
* @var string
*
* @ORM\Column(type="string", length=250, nullable=false, name="name")
*
* @Groups("my_serialization_group")
*/
private $name;
#[ORM\Column(name: 'name', type: 'string', length: 250, nullable: false)]
#[Groups("my_serialization_group")]
private string $name;

/**
* @var string
*
* @ORM\Column(type="string", length=250, nullable=false, name="other")
*
* @Groups("my_serialization_group")
* @CsvContentTranslationPrefix("my_content_translation_prefix.")
*/
private $other;
#[ORM\Column(name: 'other', type: 'string', length: 250, nullable: false)]
#[Groups('my_serialization_group')]
#[CsvContentTranslationPrefix('my_content_translation_prefix.')]
private string $other;

/**
* @var string
*
* @ORM\Column(type="string", length=250, nullable=false, name="title")
*/
private $title;
#[ORM\Column(name: 'title', type: 'string', length: 250, nullable: false)]
private string $title;

/**
* @var string
*
* @ORM\Column(type="string", length=250, nullable=true, name="other_title")
*
* @CsvContentTranslationPrefix("my_content_translation_prefix.")
*/
public $otherTitle;
#[ORM\Column(name: 'other_title', type: 'string', length: 250, nullable: true)]
#[CsvContentTranslationPrefix("my_content_translation_prefix.")]
public ?string $otherTitle;

public static function build(int $id, string $name, string $other): DummyEntity
{
Expand Down
2 changes: 1 addition & 1 deletion Tests/Resources/config/packages/doctrine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ doctrine:
mappings:
Test:
is_bundle: false
type: annotation
type: attribute
dir: '%kernel.project_dir%/Tests/Resources/Entity'
prefix: 'RichId\CsvGeneratorBundle\Tests\Resources\Entity'
alias: Test
Expand Down
4 changes: 2 additions & 2 deletions Tests/Resources/config/packages/framework.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ framework:
cache:
app: cache.adapter.array
session:
handler_id: session.handler.native_file
storage_id: session.storage.mock_file
handler_id: ~
storage_factory_id: session.storage.factory.mock_file
save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
5 changes: 2 additions & 3 deletions Tests/Utility/PropertiesUtilityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace RichId\CsvGeneratorBundle\Tests\Utility;

use RichCongress\TestFramework\TestConfiguration\Annotation\TestConfig;
use RichCongress\TestFramework\TestConfiguration\Attribute\TestConfig;
use RichCongress\TestSuite\TestCase\TestCase;
use RichId\CsvGeneratorBundle\Configuration\CsvGeneratorConfiguration;
use RichId\CsvGeneratorBundle\Data\Property;
Expand All @@ -17,9 +17,8 @@
* @copyright 2014 - 2021 RichId (https://www.rich-id.fr)
*
* @covers \RichId\CsvGeneratorBundle\Utility\PropertiesUtility
*
* @TestConfig("kernel")
*/
#[TestConfig('kernel')]
class PropertiesUtilityTest extends TestCase
{
/** @var PropertiesUtility */
Expand Down
143 changes: 143 additions & 0 deletions Utility/ObjectNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

namespace RichId\CsvGeneratorBundle\Utility;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Mapping\AttributeMetadata;
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;

/** Copy of symfony ObjectNormalizer to override getAttributeValue() */
class ObjectNormalizer extends AbstractObjectNormalizer
{
public const ALL_NULL_VALUES = 'all_null_values';

private readonly \Closure $objectClassResolver;

public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = [])
{
if (!class_exists(PropertyAccess::class)) {
throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Try running "composer require symfony/property-access".');
}

parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext);

$this->objectClassResolver = ($objectClassResolver ?? static fn ($class) => \is_object($class) ? $class::class : $class)(...);
}

public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
{
return parent::supportsNormalization($data, $format, $context)
&& ($context[self::ALL_NULL_VALUES] ?? false);
}

public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
{
return false;
}

public function getSupportedTypes(?string $format): array
{
return ['object' => false];
}

protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed
{
return null;
}

protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = [])
{
}

protected function extractAttributes(object $object, ?string $format = null, array $context = []): array
{
if (\stdClass::class === $object::class) {
return array_keys((array) $object);
}

// If not using groups, detect manually
$attributes = [];

// methods
$class = ($this->objectClassResolver)($object);
$reflClass = new \ReflectionClass($class);

foreach ($reflClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflMethod) {
if (
0 !== $reflMethod->getNumberOfRequiredParameters()
|| $reflMethod->isStatic()
|| $reflMethod->isConstructor()
|| $reflMethod->isDestructor()
) {
continue;
}

$name = $reflMethod->name;
$attributeName = null;

if (str_starts_with($name, 'get') || str_starts_with($name, 'has') || str_starts_with($name, 'can')) {
// getters, hassers and canners
$attributeName = substr($name, 3);

if (!$reflClass->hasProperty($attributeName)) {
$attributeName = lcfirst($attributeName);
}
} elseif (str_starts_with($name, 'is')) {
// issers
$attributeName = substr($name, 2);

if (!$reflClass->hasProperty($attributeName)) {
$attributeName = lcfirst($attributeName);
}
}

if (null !== $attributeName && $this->isAllowedAttribute($object, $attributeName, $format, $context)) {
$attributes[$attributeName] = true;
}
}

// properties
foreach ($reflClass->getProperties() as $reflProperty) {
if (!$reflProperty->isPublic()) {
continue;
}

if ($reflProperty->isStatic() || !$this->isAllowedAttribute($object, $reflProperty->name, $format, $context)) {
continue;
}

$attributes[$reflProperty->name] = true;
}

return array_keys($attributes);
}

protected function getAllowedAttributes(string|object $classOrObject, array $context, bool $attributesAsString = false): array|bool
{
if (false === $allowedAttributes = parent::getAllowedAttributes($classOrObject, $context, $attributesAsString)) {
return false;
}

if (null !== $this->classDiscriminatorResolver) {
$class = \is_object($classOrObject) ? $classOrObject::class : $classOrObject;
if (null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForMappedObject($classOrObject)) {
$allowedAttributes[] = $attributesAsString ? $discriminatorMapping->getTypeProperty() : new AttributeMetadata($discriminatorMapping->getTypeProperty());
}

if (null !== $discriminatorMapping = $this->classDiscriminatorResolver->getMappingForClass($class)) {
$attributes = [];
foreach ($discriminatorMapping->getTypesMapping() as $mappedClass) {
$attributes[] = parent::getAllowedAttributes($mappedClass, $context, $attributesAsString);
}
$allowedAttributes = array_merge($allowedAttributes, ...$attributes);
}
}

return $allowedAttributes;
}
}
26 changes: 14 additions & 12 deletions Utility/PropertiesUtility.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

namespace RichId\CsvGeneratorBundle\Utility;

use Doctrine\Common\Annotations\AnnotationReader;
use RichId\CsvGeneratorBundle\Annotation\CsvContentTranslationPrefix;
use RichId\CsvGeneratorBundle\Attribute\CsvContentTranslationPrefix;
use RichId\CsvGeneratorBundle\Configuration\AbstractCsvGeneratorConfiguration;
use RichId\CsvGeneratorBundle\Data\Property;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
Expand All @@ -18,8 +17,7 @@
*/
final class PropertiesUtility
{
/** @var NormalizerInterface */
protected $normalizer;
protected NormalizerInterface $normalizer;

public function __construct(NormalizerInterface $normalizer)
{
Expand Down Expand Up @@ -55,27 +53,31 @@ public function getPropertiesForConfig(AbstractCsvGeneratorConfiguration $config

public function getPropertiesWithContentTranslationPrefix(AbstractCsvGeneratorConfiguration $configuration): array
{
$propertiesWithAnnotation = [];
$annotationReader = new AnnotationReader();
$propertiesWithAttribute = [];
$properties = $this->getPropertiesForConfig($configuration);

foreach ($properties as $property) {
$annotation = $annotationReader->getPropertyAnnotation($property->getReflectionProperty(), CsvContentTranslationPrefix::class);
$attribute = $property->getReflectionProperty()->getAttributes(CsvContentTranslationPrefix::class, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null;
$attribute = $attribute?->newInstance();

if (!$annotation instanceof CsvContentTranslationPrefix) {
if (!$attribute instanceof CsvContentTranslationPrefix) {
continue;
}

$propertiesWithAnnotation[$property->getName()] = $annotation->translationPrefix;
$propertiesWithAttribute[$property->getName()] = $attribute->translationPrefix;
}

return $propertiesWithAnnotation;
return $propertiesWithAttribute;
}

private function getPropertiesName(AbstractCsvGeneratorConfiguration $configuration, $object): array
{
$context = empty($configuration->getSerializationGroups()) ? [] : [AbstractNormalizer::GROUPS => $configuration->getSerializationGroups()];
$context = [ObjectNormalizer::ALL_NULL_VALUES => true];

return array_keys($this->normalizer->normalize($object, null, $context));
if (!empty($configuration->getSerializationGroups())) {
$context[AbstractNormalizer::GROUPS] = $configuration->getSerializationGroups();
}

return \array_keys($this->normalizer->normalize($object, null, $context));
}
}
Loading

0 comments on commit be5ce7a

Please sign in to comment.