RegisterSerializationClassesCompilerPass.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <?php
  2. namespace Drupal\serialization;
  3. use Drupal\Core\Config\BootstrapConfigStorageFactory;
  4. use Symfony\Component\DependencyInjection\Reference;
  5. use Symfony\Component\DependencyInjection\ContainerBuilder;
  6. use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  7. /**
  8. * Adds services tagged 'normalizer' and 'encoder' to the Serializer.
  9. */
  10. class RegisterSerializationClassesCompilerPass implements CompilerPassInterface {
  11. /**
  12. * Adds services to the Serializer.
  13. *
  14. * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
  15. * The container to process.
  16. */
  17. public function process(ContainerBuilder $container) {
  18. $definition = $container->getDefinition('serializer');
  19. // Retrieve registered Normalizers and Encoders from the container.
  20. foreach ($container->findTaggedServiceIds('normalizer') as $id => $attributes) {
  21. // If there is a BC key present, pass this to determine if the normalizer
  22. // should be skipped.
  23. if (isset($attributes[0]['bc']) && $this->normalizerBcSettingIsEnabled($attributes[0]['bc'], $attributes[0]['bc_config_name'])) {
  24. continue;
  25. }
  26. $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
  27. $normalizers[$priority][] = new Reference($id);
  28. }
  29. foreach ($container->findTaggedServiceIds('encoder') as $id => $attributes) {
  30. $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
  31. $encoders[$priority][] = new Reference($id);
  32. }
  33. // Add the registered Normalizers and Encoders to the Serializer.
  34. if (!empty($normalizers)) {
  35. $definition->replaceArgument(0, $this->sort($normalizers));
  36. }
  37. if (!empty($encoders)) {
  38. $definition->replaceArgument(1, $this->sort($encoders));
  39. }
  40. // Find all serialization formats known.
  41. $formats = [];
  42. $format_providers = [];
  43. foreach ($container->findTaggedServiceIds('encoder') as $service_id => $attributes) {
  44. $format = $attributes[0]['format'];
  45. $formats[] = $format;
  46. if ($provider_tag = $container->getDefinition($service_id)->getTag('_provider')) {
  47. $format_providers[$format] = $provider_tag[0]['provider'];
  48. }
  49. }
  50. $container->setParameter('serializer.formats', $formats);
  51. $container->setParameter('serializer.format_providers', $format_providers);
  52. }
  53. /**
  54. * Returns whether a normalizer BC setting is disabled or not.
  55. *
  56. * @param string $key
  57. *
  58. * @return bool
  59. */
  60. protected function normalizerBcSettingIsEnabled($key, $config_name) {
  61. $settings = BootstrapConfigStorageFactory::get()->read($config_name);
  62. return !empty($settings[$key]);
  63. }
  64. /**
  65. * Sorts by priority.
  66. *
  67. * Order services from highest priority number to lowest (reverse sorting).
  68. *
  69. * @param array $services
  70. * A nested array keyed on priority number. For each priority number, the
  71. * value is an array of Symfony\Component\DependencyInjection\Reference
  72. * objects, each a reference to a normalizer or encoder service.
  73. *
  74. * @return array
  75. * A flattened array of Reference objects from $services, ordered from high
  76. * to low priority.
  77. */
  78. protected function sort($services) {
  79. $sorted = [];
  80. krsort($services);
  81. // Flatten the array.
  82. foreach ($services as $a) {
  83. $sorted = array_merge($sorted, $a);
  84. }
  85. return $sorted;
  86. }
  87. }