Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Synchronize metadata driver setup with upstream changes #933

Merged
merged 1 commit into from
Dec 8, 2023
Merged
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
94 changes: 57 additions & 37 deletions DependencyInjection/JMSSerializerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

namespace JMS\SerializerBundle\DependencyInjection;

use Doctrine\Common\Annotations\Reader;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Expression\CompilableExpressionEvaluatorInterface;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\Handler\SymfonyUidHandler;
use JMS\Serializer\Metadata\Driver\AttributeDriver;
use JMS\Serializer\Metadata\Driver\AttributeDriver\AttributeReader;
use JMS\Serializer\Metadata\Driver\DocBlockDriver;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\FileLocator;
Expand All @@ -24,6 +23,7 @@
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Templating\Helper\Helper;
use Symfony\Component\Uid\AbstractUid;
use Symfony\Component\Yaml\Yaml;

/**
* @internal
Expand All @@ -44,25 +44,7 @@ public function load(array $rawConfigs, ContainerBuilder $container): void
$loader->load('debug.xml');
}

$metadataDrivers = [
new Reference('jms_serializer.metadata.yaml_driver'),
new Reference('jms_serializer.metadata.xml_driver'),
// new Reference('jms_serializer.metadata.attribute_driver'), // TODO - Re-enable this driver at a later time
new Reference('jms_serializer.metadata.annotation_driver'),
];

// enable attributes support on php 8
if (PHP_VERSION_ID >= 80000 && class_exists(AttributeReader::class)) {
$container->register('jms_serializer.metadata.annotation_and_attributes_reader', AttributeReader::class)
->setArgument(0, new Reference('annotation_reader'));

$container->findDefinition('jms_serializer.metadata.annotation_driver')
->replaceArgument(0, new Reference('jms_serializer.metadata.annotation_and_attributes_reader'));
}

$container
->getDefinition('jms_serializer.metadata_driver')
->replaceArgument(0, $metadataDrivers);
$this->configureMetadataDrivers($container);

DIUtils::cloneDefinitions($container, array_keys($configs['instances']));

Expand All @@ -86,6 +68,45 @@ public function load(array $rawConfigs, ContainerBuilder $container): void
->addTag('jms_serializer.subscribing_handler');
}

private function configureMetadataDrivers(ContainerBuilder $container): void
{
// The old annotation driver service is now always removed from the container in favor of the combined annotation/attribute driver
$container->removeDefinition('jms_serializer.metadata.annotation_driver');

/*
* Build the sorted list of metadata drivers based on the environment. The final order should be:
*
* - YAML Driver
* - XML Driver
* - Annotations/Attributes Driver
* - Null (Fallback) Driver
*/
$metadataDrivers = [];

if (class_exists(Yaml::class)) {
$metadataDrivers[] = new Reference('jms_serializer.metadata.yaml_driver');
} else {
$container->removeDefinition('jms_serializer.metadata.yaml_driver');
}

// The XML driver is always available
$metadataDrivers[] = new Reference('jms_serializer.metadata.xml_driver');

// The combined annotation/attribute driver is available if `doctrine/annotations` is installed or when running PHP 8
if (interface_exists(Reader::class) || PHP_VERSION_ID >= 80000) {
$metadataDrivers[] = new Reference('jms_serializer.metadata.annotation_or_attribute_driver');
} else {
$container->removeDefinition('jms_serializer.metadata.annotation_or_attribute_driver');
}

// The null driver is always available
$metadataDrivers[] = new Reference('jms_serializer.metadata.null_driver');

$container
->getDefinition('jms_serializer.metadata_driver')
->replaceArgument(0, $metadataDrivers);
}

/**
* @param array $rawConfigs
* @param ContainerBuilder $container
Expand Down Expand Up @@ -154,41 +175,40 @@ private function loadInternal(array $config, ScopedContainer $container, array $
}

if (!empty($config['expression_evaluator']['id'])) {
$evaluator = new Reference($config['expression_evaluator']['id']);

$container
->getDefinition('jms_serializer.deserialization_graph_navigator_factory')
->replaceArgument(5, new Reference($config['expression_evaluator']['id']));
->replaceArgument(5, $evaluator);

$container
->getDefinition('jms_serializer.serialization_graph_navigator_factory')
->replaceArgument(4, new Reference($config['expression_evaluator']['id']));
->replaceArgument(4, $evaluator);

$container
->getDefinition('jms_serializer.accessor_strategy.default')
->replaceArgument(0, new Reference($config['expression_evaluator']['id']));
->replaceArgument(0, $evaluator);

if (is_a($container->findDefinition($config['expression_evaluator']['id'])->getClass(), CompilableExpressionEvaluatorInterface::class, true)) {
$container
->getDefinition('jms_serializer.metadata.yaml_driver')
->replaceArgument(3, new Reference($config['expression_evaluator']['id']));
try {
$container
->getDefinition('jms_serializer.metadata.yaml_driver')
->replaceArgument(3, $evaluator);
} catch (ServiceNotFoundException $exception) {
// Removed by conditional checks earlier
}

$container
->getDefinition('jms_serializer.metadata.xml_driver')
->replaceArgument(3, new Reference($config['expression_evaluator']['id']));

$container
->getDefinition('jms_serializer.metadata.annotation_driver')
->replaceArgument(3, new Reference($config['expression_evaluator']['id']));
->replaceArgument(3, $evaluator);

// TODO - Re-enable this driver at a later time
/*
try {
$container
->getDefinition('jms_serializer.metadata.attribute_driver')
->replaceArgument(2, new Reference($config['expression_evaluator']['id']));
->getDefinition('jms_serializer.metadata.annotation_or_attribute_driver')
->replaceArgument(2, $evaluator);
} catch (ServiceNotFoundException $exception) {
// Removed by conditional checks earlier
}
*/
}
} else {
$container->removeDefinition('jms_serializer.expression_evaluator');
Expand Down
10 changes: 7 additions & 3 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,22 @@
<argument type="service" id="jms_serializer.type_parser" on-invalid="null" />
<argument type="constant">NULL</argument> <!-- expression evaluator -->
</service>
<!-- The `JMS\Serializer\Metadata\Driver\AnnotationDriver` class and its corresponding `jms_serializer.metadata.annotation_driver` service are deprecated in favor of the `jms_serializer.metadata.annotation_or_attribute_driver` service -->
<service id="jms_serializer.metadata.annotation_driver" class="JMS\Serializer\Metadata\Driver\AnnotationDriver" public="false">
<argument type="service" id="annotation_reader" />
<argument type="service" id="jms_serializer.naming_strategy" />
<argument type="service" id="jms_serializer.type_parser" on-invalid="null" />
<argument type="constant">NULL</argument> <!-- expression evaluator -->
</service>
<!-- TODO - Re-enable this driver at a later time -->
<!-- <service id="jms_serializer.metadata.attribute_driver" class="JMS\Serializer\Metadata\Driver\AttributeDriver" public="false">
<service id="jms_serializer.metadata.annotation_or_attribute_driver" class="JMS\Serializer\Metadata\Driver\AnnotationOrAttributeDriver" public="false">
<argument type="service" id="jms_serializer.naming_strategy" />
<argument type="service" id="jms_serializer.type_parser" on-invalid="null" />
<argument type="constant">NULL</argument>
</service> -->
<argument type="service" id="annotation_reader" on-invalid="null" />
</service>
<service id="jms_serializer.metadata.null_driver" class="JMS\Serializer\Metadata\Driver\NullDriver" public="false">
<argument type="service" id="jms_serializer.naming_strategy" />
</service>
<service id="jms_serializer.metadata_driver" class="Metadata\Driver\DriverChain" public="false">
<argument type="collection">
<argument type="constant">NULL</argument> <!-- list of metadata drivers -->
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
],
"require": {
"php": "^7.2 || ^8.0",
"jms/serializer": "^3.20",
"jms/metadata": "^2.5",
"jms/serializer": "^3.28",
"jms/metadata": "^2.6",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bump on the metadata package isn't strictly needed, but the serializer package has this as its minimum so figured I'd change it to match.

"symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/framework-bundle": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
Expand Down