JMSSerializerExtension.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. /*
  3. * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. namespace JMS\SerializerBundle\DependencyInjection;
  18. use JMS\SerializerBundle\SerializerBundleAwareInterface;
  19. use Symfony\Component\HttpKernel\KernelInterface;
  20. use Symfony\Component\DependencyInjection\Alias;
  21. use Symfony\Component\DependencyInjection\DefinitionDecorator;
  22. use JMS\SerializerBundle\Exception\RuntimeException;
  23. use Symfony\Component\Config\FileLocator;
  24. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  25. use Symfony\Component\DependencyInjection\Reference;
  26. use Symfony\Component\Config\Definition\Processor;
  27. use Symfony\Component\DependencyInjection\ContainerBuilder;
  28. use Symfony\Component\HttpKernel\DependencyInjection\Extension;
  29. class JMSSerializerExtension extends Extension
  30. {
  31. private $kernel;
  32. private $factories = array();
  33. public function __construct(KernelInterface $kernel)
  34. {
  35. $this->kernel = $kernel;
  36. }
  37. public function addHandlerFactory(HandlerFactoryInterface $factory)
  38. {
  39. $this->factories[$factory->getConfigKey()] = $factory;
  40. }
  41. public function load(array $configs, ContainerBuilder $container)
  42. {
  43. $config = $this->processConfiguration($this->getConfiguration($configs, $container), $configs);
  44. $loader = new XmlFileLoader($container, new FileLocator(array(
  45. __DIR__.'/../Resources/config/')));
  46. $loader->load('services.xml');
  47. // add factories as resource
  48. foreach ($this->factories as $factory) {
  49. $container->addObjectResource($factory);
  50. }
  51. // property naming
  52. $container
  53. ->getDefinition('jms_serializer.camel_case_naming_strategy')
  54. ->addArgument($config['property_naming']['separator'])
  55. ->addArgument($config['property_naming']['lower_case'])
  56. ;
  57. if ($config['property_naming']['enable_cache']) {
  58. $container
  59. ->getDefinition('jms_serializer.cache_naming_strategy')
  60. ->addArgument(new Reference((string) $container->getAlias('jms_serializer.naming_strategy')))
  61. ;
  62. $container->setAlias('jms_serializer.naming_strategy', 'jms_serializer.cache_naming_strategy');
  63. }
  64. // gather handlers
  65. $serializationHandlers = $deserializationHandlers = array();
  66. foreach ($config['handlers'] as $k => $handlerConfig) {
  67. $id = $this->factories[$k]->getHandlerId($container, $handlerConfig);
  68. $type = $this->factories[$k]->getType($handlerConfig);
  69. if (0 !== ($type & HandlerFactoryInterface::TYPE_SERIALIZATION)) {
  70. $serializationHandlers[] = new Reference($id);
  71. }
  72. if (0 !== ($type & HandlerFactoryInterface::TYPE_DESERIALIZATION)) {
  73. $deserializationHandlers[] = new Reference($id);
  74. }
  75. }
  76. foreach (array('json', 'xml', 'yaml') as $format) {
  77. $container
  78. ->getDefinition('jms_serializer.'.$format.'_serialization_visitor')
  79. ->replaceArgument(1, $serializationHandlers)
  80. ;
  81. }
  82. foreach (array('json', 'xml') as $format) {
  83. $container
  84. ->getDefinition('jms_serializer.'.$format.'_deserialization_visitor')
  85. ->replaceArgument(1, $deserializationHandlers)
  86. ;
  87. }
  88. // metadata
  89. if ('none' === $config['metadata']['cache']) {
  90. $container->removeAlias('jms_serializer.metadata.cache');
  91. } else if ('file' === $config['metadata']['cache']) {
  92. $container
  93. ->getDefinition('jms_serializer.metadata.cache.file_cache')
  94. ->replaceArgument(0, $config['metadata']['file_cache']['dir'])
  95. ;
  96. $dir = $container->getParameterBag()->resolveValue($config['metadata']['file_cache']['dir']);
  97. if (!file_exists($dir)) {
  98. if (!$rs = @mkdir($dir, 0777, true)) {
  99. throw new RuntimeException(sprintf('Could not create cache directory "%s".', $dir));
  100. }
  101. }
  102. } else {
  103. $container->setAlias('jms_serializer.metadata.cache', new Alias($config['metadata']['cache'], false));
  104. }
  105. $container
  106. ->getDefinition('jms_serializer.metadata_factory')
  107. ->replaceArgument(2, $config['metadata']['debug'])
  108. ;
  109. // directories
  110. $directories = array();
  111. $bundles = $container->getParameter('kernel.bundles');
  112. if ($config['metadata']['auto_detection']) {
  113. foreach ($bundles as $name => $class) {
  114. $ref = new \ReflectionClass($class);
  115. $directories[$ref->getNamespaceName()] = dirname($ref->getFileName()).'/Resources/config/serializer';
  116. }
  117. }
  118. foreach ($config['metadata']['directories'] as $directory) {
  119. $directory['path'] = rtrim(str_replace('\\', '/', $directory['path']), '/');
  120. if ('@' === $directory['path'][0]) {
  121. $bundleName = substr($directory['path'], 1, strpos($directory['path'], '/') - 1);
  122. if (!isset($bundles[$bundleName])) {
  123. throw new RuntimeException(sprintf('The bundle "%s" has not been registered with AppKernel. Available bundles: %s', $bundleName, implode(', ', array_keys($bundles))));
  124. }
  125. $ref = new \ReflectionClass($bundles[$bundleName]);
  126. $directory['path'] = dirname($ref->getFileName()).substr($directory['path'], strlen('@'.$bundleName));
  127. }
  128. $directories[rtrim($directory['namespace_prefix'], '\\')] = rtrim($directory['path'], '\\/');
  129. }
  130. $container
  131. ->getDefinition('jms_serializer.metadata.file_locator')
  132. ->replaceArgument(0, $directories)
  133. ;
  134. $container
  135. ->setParameter('jms_serializer.json_serialization_visitor.options', $config['visitors']['json']['options'])
  136. ;
  137. }
  138. public function getConfiguration(array $config, ContainerBuilder $container)
  139. {
  140. foreach ($this->kernel->getBundles() as $bundle) {
  141. if (!method_exists($bundle, 'configureSerializerExtension')) {
  142. continue;
  143. }
  144. $bundle->configureSerializerExtension($this);
  145. }
  146. return new Configuration($this->kernel->isDebug(), $this->factories);
  147. }
  148. }