FrameworkExtension.php 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
  11. use Symfony\Component\Config\Loader\LoaderInterface;
  12. use Symfony\Component\DependencyInjection\ContainerBuilder;
  13. use Symfony\Component\DependencyInjection\DefinitionDecorator;
  14. use Symfony\Component\DependencyInjection\Reference;
  15. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  16. use Symfony\Component\Config\Resource\FileResource;
  17. use Symfony\Component\Config\Resource\DirectoryResource;
  18. use Symfony\Component\Finder\Finder;
  19. use Symfony\Component\HttpKernel\DependencyInjection\Extension;
  20. use Symfony\Component\Config\FileLocator;
  21. /**
  22. * FrameworkExtension.
  23. *
  24. * @author Fabien Potencier <fabien@symfony.com>
  25. * @author Jeremy Mikola <jmikola@gmail.com>
  26. */
  27. class FrameworkExtension extends Extension
  28. {
  29. /**
  30. * Responds to the app.config configuration parameter.
  31. *
  32. * @param array $configs
  33. * @param ContainerBuilder $container
  34. */
  35. public function load(array $configs, ContainerBuilder $container)
  36. {
  37. $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
  38. $loader->load('web.xml');
  39. $loader->load('services.xml');
  40. // A translator must always be registered (as support is included by
  41. // default in the Form component). If disabled, an identity translator
  42. // will be used and everything will still work as expected.
  43. $loader->load('translation.xml');
  44. if ($container->getParameter('kernel.debug')) {
  45. $loader->load('debug.xml');
  46. $container->setDefinition('event_dispatcher', $container->findDefinition('debug.event_dispatcher'));
  47. $container->setAlias('debug.event_dispatcher', 'event_dispatcher');
  48. }
  49. $configuration = new Configuration($container->getParameter('kernel.debug'));
  50. $config = $this->processConfiguration($configuration, $configs);
  51. if (isset($config['charset'])) {
  52. $container->setParameter('kernel.charset', $config['charset']);
  53. }
  54. $container->setParameter('kernel.secret', $config['secret']);
  55. $container->setParameter('kernel.trust_proxy_headers', $config['trust_proxy_headers']);
  56. if (!empty($config['test'])) {
  57. $loader->load('test.xml');
  58. }
  59. if (isset($config['session'])) {
  60. $this->registerSessionConfiguration($config['session'], $container, $loader);
  61. }
  62. if (isset($config['form']) && !empty($config['form']['enabled'])) {
  63. $this->registerFormConfiguration($config, $container, $loader);
  64. $config['validation']['enabled'] = true;
  65. }
  66. if (!empty($config['validation']['enabled'])) {
  67. $this->registerValidationConfiguration($config['validation'], $container, $loader);
  68. }
  69. if (isset($config['esi'])) {
  70. $this->registerEsiConfiguration($config['esi'], $loader);
  71. }
  72. if (isset($config['profiler'])) {
  73. $this->registerProfilerConfiguration($config['profiler'], $container, $loader);
  74. }
  75. if (isset($config['router'])) {
  76. $this->registerRouterConfiguration($config['router'], $container, $loader);
  77. }
  78. if (isset($config['templating'])) {
  79. $this->registerTemplatingConfiguration($config['templating'], $config['ide'], $container, $loader);
  80. }
  81. if (isset($config['translator'])) {
  82. $this->registerTranslatorConfiguration($config['translator'], $container);
  83. }
  84. $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader);
  85. $this->addClassesToCompile(array(
  86. 'Symfony\\Component\\HttpFoundation\\ParameterBag',
  87. 'Symfony\\Component\\HttpFoundation\\HeaderBag',
  88. 'Symfony\\Component\\HttpFoundation\\FileBag',
  89. 'Symfony\\Component\\HttpFoundation\\ServerBag',
  90. 'Symfony\\Component\\HttpFoundation\\Request',
  91. 'Symfony\\Component\\HttpFoundation\\Response',
  92. 'Symfony\\Component\\HttpFoundation\\ResponseHeaderBag',
  93. 'Symfony\\Component\\Config\\FileLocator',
  94. 'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface',
  95. 'Symfony\\Component\\EventDispatcher\\EventDispatcher',
  96. 'Symfony\\Component\\EventDispatcher\\Event',
  97. 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface',
  98. 'Symfony\\Component\\HttpKernel\\HttpKernel',
  99. 'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener',
  100. 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
  101. 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface',
  102. 'Symfony\\Component\\HttpKernel\\Event\\KernelEvent',
  103. 'Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent',
  104. 'Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent',
  105. 'Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent',
  106. 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent',
  107. 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent',
  108. 'Symfony\\Component\\HttpKernel\\KernelEvents',
  109. 'Symfony\\Component\\HttpKernel\\Config\\FileLocator',
  110. 'Symfony\\Bundle\\FrameworkBundle\\EventListener\\RouterListener',
  111. 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameParser',
  112. 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
  113. // Cannot be included because annotations will parse the big compiled class file
  114. // 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
  115. 'Symfony\\Bundle\\FrameworkBundle\\ContainerAwareEventDispatcher',
  116. 'Symfony\\Bundle\\FrameworkBundle\\HttpKernel',
  117. ));
  118. }
  119. /**
  120. * Loads Form configuration.
  121. *
  122. * @param array $config A configuration array
  123. * @param ContainerBuilder $container A ContainerBuilder instance
  124. * @param XmlFileLoader $loader An XmlFileLoader instance
  125. */
  126. private function registerFormConfiguration($config, ContainerBuilder $container, XmlFileLoader $loader)
  127. {
  128. $loader->load('form.xml');
  129. if (isset($config['csrf_protection'])) {
  130. if (!isset($config['session'])) {
  131. throw new \LogicException('CSRF protection needs that sessions are enabled.');
  132. }
  133. $loader->load('form_csrf.xml');
  134. $container->setParameter('form.type_extension.csrf.enabled', $config['csrf_protection']['enabled']);
  135. $container->setParameter('form.type_extension.csrf.field_name', $config['csrf_protection']['field_name']);
  136. }
  137. }
  138. /**
  139. * Loads the ESI configuration.
  140. *
  141. * @param array $config An ESI configuration array
  142. * @param XmlFileLoader $loader An XmlFileLoader instance
  143. */
  144. private function registerEsiConfiguration(array $config, XmlFileLoader $loader)
  145. {
  146. if (!empty($config['enabled'])) {
  147. $loader->load('esi.xml');
  148. }
  149. }
  150. /**
  151. * Loads the profiler configuration.
  152. *
  153. * @param array $config A profiler configuration array
  154. * @param ContainerBuilder $container A ContainerBuilder instance
  155. * @param XmlFileLoader $loader An XmlFileLoader instance
  156. */
  157. private function registerProfilerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
  158. {
  159. $loader->load('profiling.xml');
  160. $loader->load('collectors.xml');
  161. $container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']);
  162. $container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']);
  163. // Choose storage class based on the DSN
  164. $supported = array(
  165. 'sqlite' => 'Symfony\Component\HttpKernel\Profiler\SqliteProfilerStorage',
  166. 'mysql' => 'Symfony\Component\HttpKernel\Profiler\MysqlProfilerStorage',
  167. );
  168. list($class, ) = explode(':', $config['dsn'], 2);
  169. if (!isset($supported[$class])) {
  170. throw new \LogicException(sprintf('Driver "%s" is not supported for the profiler.', $class));
  171. }
  172. $container->setParameter('profiler.storage.dsn', $config['dsn']);
  173. $container->setParameter('profiler.storage.username', $config['username']);
  174. $container->setParameter('profiler.storage.password', $config['password']);
  175. $container->setParameter('profiler.storage.lifetime', $config['lifetime']);
  176. $container->getDefinition('profiler.storage')->setClass($supported[$class]);
  177. if (isset($config['matcher'])) {
  178. if (isset($config['matcher']['service'])) {
  179. $container->setAlias('profiler.request_matcher', $config['matcher']['service']);
  180. } elseif (isset($config['matcher']['ip']) || isset($config['matcher']['path'])) {
  181. $definition = $container->register('profiler.request_matcher', 'Symfony\\Component\\HttpFoundation\\RequestMatcher');
  182. $definition->setPublic(false);
  183. if (isset($config['matcher']['ip'])) {
  184. $definition->addMethodCall('matchIp', array($config['matcher']['ip']));
  185. }
  186. if (isset($config['matcher']['path'])) {
  187. $definition->addMethodCall('matchPath', array($config['matcher']['path']));
  188. }
  189. }
  190. }
  191. }
  192. /**
  193. * Loads the router configuration.
  194. *
  195. * @param array $config A router configuration array
  196. * @param ContainerBuilder $container A ContainerBuilder instance
  197. * @param XmlFileLoader $loader An XmlFileLoader instance
  198. */
  199. private function registerRouterConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
  200. {
  201. $loader->load('routing.xml');
  202. $container->setParameter('router.resource', $config['resource']);
  203. $router = $container->findDefinition('router.default');
  204. if (isset($config['type'])) {
  205. $argument = $router->getArgument(2);
  206. $argument['resource_type'] = $config['type'];
  207. $router->replaceArgument(2, $argument);
  208. }
  209. $container->setParameter('request_listener.http_port', $config['http_port']);
  210. $container->setParameter('request_listener.https_port', $config['https_port']);
  211. $this->addClassesToCompile(array(
  212. 'Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface',
  213. 'Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface',
  214. 'Symfony\\Component\\Routing\\RouterInterface',
  215. 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
  216. 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
  217. 'Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface',
  218. 'Symfony\\Component\\Routing\\RequestContextAwareInterface',
  219. 'Symfony\\Component\\Routing\\RequestContext',
  220. 'Symfony\\Component\\Routing\\Router',
  221. 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableUrlMatcher',
  222. $container->findDefinition('router.default')->getClass(),
  223. ));
  224. }
  225. /**
  226. * Loads the session configuration.
  227. *
  228. * @param array $config A session configuration array
  229. * @param ContainerBuilder $container A ContainerBuilder instance
  230. * @param XmlFileLoader $loader An XmlFileLoader instance
  231. */
  232. private function registerSessionConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
  233. {
  234. $loader->load('session.xml');
  235. // session
  236. $container->getDefinition('session_listener')->addArgument($config['auto_start']);
  237. $container->setParameter('session.default_locale', $config['default_locale']);
  238. // session storage
  239. $container->setAlias('session.storage', $config['storage_id']);
  240. $options = array();
  241. foreach (array('name', 'lifetime', 'path', 'domain', 'secure', 'httponly') as $key) {
  242. if (isset($config[$key])) {
  243. $options[$key] = $config[$key];
  244. }
  245. }
  246. $container->setParameter('session.storage.options', $options);
  247. $this->addClassesToCompile(array(
  248. 'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
  249. 'Symfony\\Component\\HttpFoundation\\SessionStorage\\SessionStorageInterface',
  250. $container->getDefinition('session')->getClass(),
  251. ));
  252. if ($container->hasDefinition($config['storage_id'])) {
  253. $this->addClassesToCompile(array(
  254. $container->findDefinition('session.storage')->getClass(),
  255. ));
  256. }
  257. }
  258. /**
  259. * Loads the templating configuration.
  260. *
  261. * @param array $config A templating configuration array
  262. * @param string $ide
  263. * @param ContainerBuilder $container A ContainerBuilder instance
  264. * @param XmlFileLoader $loader An XmlFileLoader instance
  265. */
  266. private function registerTemplatingConfiguration(array $config, $ide, ContainerBuilder $container, XmlFileLoader $loader)
  267. {
  268. $loader->load('templating.xml');
  269. $loader->load('templating_php.xml');
  270. $links = array(
  271. 'textmate' => 'txmt://open?url=file://%%f&line=%%l',
  272. 'macvim' => 'mvim://open?url=file://%%f&line=%%l',
  273. );
  274. $container->setParameter('templating.helper.code.file_link_format', isset($links[$ide]) ? $links[$ide] : $ide);
  275. $container->setParameter('templating.helper.form.resources', $config['form']['resources']);
  276. if ($container->getParameter('kernel.debug')) {
  277. $loader->load('templating_debug.xml');
  278. }
  279. // create package definitions and add them to the assets helper
  280. $defaultPackage = $this->createPackageDefinition($container, $config['assets_base_urls']['http'], $config['assets_base_urls']['ssl'], $config['assets_version'], $config['assets_version_format']);
  281. $container->setDefinition('templating.asset.default_package', $defaultPackage);
  282. $namedPackages = array();
  283. foreach ($config['packages'] as $name => $package) {
  284. $namedPackage = $this->createPackageDefinition($container, $package['base_urls']['http'], $package['base_urls']['ssl'], $package['version'], $package['version_format'], $name);
  285. $container->setDefinition('templating.asset.package.'.$name, $namedPackage);
  286. $namedPackages[$name] = new Reference('templating.asset.package.'.$name);
  287. }
  288. $container->getDefinition('templating.helper.assets')->setArguments(array(
  289. new Reference('templating.asset.default_package'),
  290. $namedPackages,
  291. ));
  292. // Apply request scope to assets helper if one or more packages are request-scoped
  293. $requireRequestScope = array_reduce(
  294. $namedPackages,
  295. function($v, Reference $ref) use ($container) {
  296. return $v || 'request' === $container->getDefinition($ref)->getScope();
  297. },
  298. 'request' === $defaultPackage->getScope()
  299. );
  300. if ($requireRequestScope) {
  301. $container->getDefinition('templating.helper.assets')->setScope('request');
  302. }
  303. if (!empty($config['loaders'])) {
  304. $loaders = array_map(function($loader) { return new Reference($loader); }, $config['loaders']);
  305. // Use a delegation unless only a single loader was registered
  306. if (1 === count($loaders)) {
  307. $container->setAlias('templating.loader', (string) reset($loaders));
  308. } else {
  309. $container->getDefinition('templating.loader.chain')->addArgument($loaders);
  310. $container->setAlias('templating.loader', 'templating.loader.chain');
  311. }
  312. }
  313. $container->setParameter('templating.loader.cache.path', null);
  314. if (isset($config['cache'])) {
  315. // Wrap the existing loader with cache (must happen after loaders are registered)
  316. $container->setDefinition('templating.loader.wrapped', $container->findDefinition('templating.loader'));
  317. $loaderCache = $container->getDefinition('templating.loader.cache');
  318. $container->setParameter('templating.loader.cache.path', $config['cache']);
  319. $container->setDefinition('templating.loader', $loaderCache);
  320. }
  321. $this->addClassesToCompile(array(
  322. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables',
  323. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\EngineInterface',
  324. 'Symfony\\Component\\Templating\\TemplateNameParserInterface',
  325. 'Symfony\\Component\\Templating\\TemplateNameParser',
  326. 'Symfony\\Component\\Templating\\EngineInterface',
  327. 'Symfony\\Component\\Config\\FileLocatorInterface',
  328. 'Symfony\\Component\\Templating\\TemplateReferenceInterface',
  329. 'Symfony\\Component\\Templating\\TemplateReference',
  330. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference',
  331. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser',
  332. $container->findDefinition('templating.locator')->getClass(),
  333. ));
  334. if (in_array('php', $config['engines'], true)) {
  335. $this->addClassesToCompile(array(
  336. 'Symfony\\Component\\Templating\\PhpEngine',
  337. 'Symfony\\Component\\Templating\\Loader\\LoaderInterface',
  338. 'Symfony\\Component\\Templating\\Storage\\Storage',
  339. 'Symfony\\Component\\Templating\\Storage\\FileStorage',
  340. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\PhpEngine',
  341. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Loader\\FilesystemLoader',
  342. ));
  343. }
  344. $container->setParameter('templating.engines', $config['engines']);
  345. $engines = array_map(function($engine) { return new Reference('templating.engine.'.$engine); }, $config['engines']);
  346. // Use a delegation unless only a single engine was registered
  347. if (1 === count($engines)) {
  348. $container->setAlias('templating', (string) reset($engines));
  349. } else {
  350. $container->getDefinition('templating.engine.delegating')->replaceArgument(1, $engines);
  351. $container->setAlias('templating', 'templating.engine.delegating');
  352. }
  353. }
  354. /**
  355. * Returns a definition for an asset package.
  356. */
  357. private function createPackageDefinition(ContainerBuilder $container, array $httpUrls, array $sslUrls, $version, $format, $name = null)
  358. {
  359. if (!$httpUrls) {
  360. $package = new DefinitionDecorator('templating.asset.path_package');
  361. $package
  362. ->setPublic(false)
  363. ->setScope('request')
  364. ->replaceArgument(1, $version)
  365. ->replaceArgument(2, $format)
  366. ;
  367. return $package;
  368. }
  369. if ($httpUrls == $sslUrls) {
  370. $package = new DefinitionDecorator('templating.asset.url_package');
  371. $package
  372. ->setPublic(false)
  373. ->replaceArgument(0, $sslUrls)
  374. ->replaceArgument(1, $version)
  375. ->replaceArgument(2, $format)
  376. ;
  377. return $package;
  378. }
  379. $prefix = $name ? 'templating.asset.package.'.$name : 'templating.asset.default_package';
  380. $httpPackage = new DefinitionDecorator('templating.asset.url_package');
  381. $httpPackage
  382. ->replaceArgument(0, $httpUrls)
  383. ->replaceArgument(1, $version)
  384. ->replaceArgument(2, $format)
  385. ;
  386. $container->setDefinition($prefix.'.http', $httpPackage);
  387. if ($sslUrls) {
  388. $sslPackage = new DefinitionDecorator('templating.asset.url_package');
  389. $sslPackage
  390. ->replaceArgument(0, $sslUrls)
  391. ->replaceArgument(1, $version)
  392. ->replaceArgument(2, $format)
  393. ;
  394. } else {
  395. $sslPackage = new DefinitionDecorator('templating.asset.path_package');
  396. $sslPackage
  397. ->setScope('request')
  398. ->replaceArgument(1, $version)
  399. ->replaceArgument(2, $format)
  400. ;
  401. }
  402. $container->setDefinition($prefix.'.ssl', $sslPackage);
  403. $package = new DefinitionDecorator('templating.asset.request_aware_package');
  404. $package
  405. ->setPublic(false)
  406. ->setScope('request')
  407. ->replaceArgument(1, $prefix.'.http')
  408. ->replaceArgument(2, $prefix.'.ssl')
  409. ;
  410. return $package;
  411. }
  412. /**
  413. * Loads the translator configuration.
  414. *
  415. * @param array $config A translator configuration array
  416. * @param ContainerBuilder $container A ContainerBuilder instance
  417. */
  418. private function registerTranslatorConfiguration(array $config, ContainerBuilder $container)
  419. {
  420. if (!empty($config['enabled'])) {
  421. // Use the "real" translator instead of the identity default
  422. $container->setAlias('translator', 'translator.default');
  423. $translator = $container->findDefinition('translator.default');
  424. $translator->addMethodCall('setFallbackLocale', array($config['fallback']));
  425. // Discover translation directories
  426. $dirs = array();
  427. foreach ($container->getParameter('kernel.bundles') as $bundle) {
  428. $reflection = new \ReflectionClass($bundle);
  429. if (is_dir($dir = dirname($reflection->getFilename()).'/Resources/translations')) {
  430. $dirs[] = $dir;
  431. }
  432. }
  433. if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/translations')) {
  434. $dirs[] = $dir;
  435. }
  436. // Register translation resources
  437. if ($dirs) {
  438. foreach ($dirs as $dir) {
  439. $container->addResource(new DirectoryResource($dir));
  440. }
  441. $finder = new Finder();
  442. $finder->files()->filter(function (\SplFileInfo $file) {
  443. return 2 === substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename());
  444. })->in($dirs);
  445. foreach ($finder as $file) {
  446. // filename is domain.locale.format
  447. list($domain, $locale, $format) = explode('.', $file->getBasename(), 3);
  448. $translator->addMethodCall('addResource', array($format, (string) $file, $locale, $domain));
  449. }
  450. }
  451. }
  452. }
  453. /**
  454. * Loads the validator configuration.
  455. *
  456. * @param array $config A validation configuration array
  457. * @param ContainerBuilder $container A ContainerBuilder instance
  458. * @param XmlFileLoader $loader An XmlFileLoader instance
  459. */
  460. private function registerValidationConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
  461. {
  462. $loader->load('validator.xml');
  463. $container->setParameter('validator.mapping.loader.xml_files_loader.mapping_files', $this->getValidatorXmlMappingFiles($container));
  464. $container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $this->getValidatorYamlMappingFiles($container));
  465. if (array_key_exists('enable_annotations', $config) && $config['enable_annotations']) {
  466. $loaderChain = $container->getDefinition('validator.mapping.loader.loader_chain');
  467. $arguments = $loaderChain->getArguments();
  468. array_unshift($arguments[0], new Reference('validator.mapping.loader.annotation_loader'));
  469. $loaderChain->setArguments($arguments);
  470. }
  471. if (isset($config['cache'])) {
  472. $container->getDefinition('validator.mapping.class_metadata_factory')
  473. ->replaceArgument(1, new Reference('validator.mapping.cache.'.$config['cache']));
  474. $container->setParameter(
  475. 'validator.mapping.cache.prefix',
  476. 'validator_'.md5($container->getParameter('kernel.root_dir'))
  477. );
  478. }
  479. }
  480. private function getValidatorXmlMappingFiles(ContainerBuilder $container)
  481. {
  482. $reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface');
  483. $files = array(dirname($reflClass->getFileName()).'/Resources/config/validation.xml');
  484. $container->addResource(new FileResource($files[0]));
  485. foreach ($container->getParameter('kernel.bundles') as $bundle) {
  486. $reflection = new \ReflectionClass($bundle);
  487. if (file_exists($file = dirname($reflection->getFilename()).'/Resources/config/validation.xml')) {
  488. $files[] = realpath($file);
  489. $container->addResource(new FileResource($file));
  490. }
  491. }
  492. return $files;
  493. }
  494. private function getValidatorYamlMappingFiles(ContainerBuilder $container)
  495. {
  496. $files = array();
  497. foreach ($container->getParameter('kernel.bundles') as $bundle) {
  498. $reflection = new \ReflectionClass($bundle);
  499. if (file_exists($file = dirname($reflection->getFilename()).'/Resources/config/validation.yml')) {
  500. $files[] = realpath($file);
  501. $container->addResource(new FileResource($file));
  502. }
  503. }
  504. return $files;
  505. }
  506. private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container,$loader)
  507. {
  508. $loader->load('annotations.xml');
  509. if ('file' === $config['cache']) {
  510. $cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']);
  511. if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true)) {
  512. throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir));
  513. }
  514. $container
  515. ->getDefinition('annotations.file_cache_reader')
  516. ->replaceArgument(1, $cacheDir)
  517. ->replaceArgument(2, $config['debug'])
  518. ;
  519. $container->setAlias('annotation_reader', 'annotations.file_cache_reader');
  520. } else if('none' !== $config['cache']) {
  521. $container
  522. ->getDefinition('annotations.cached_reader')
  523. ->replaceArgument(1, new Reference($config['cache']))
  524. ->replaceArgument(2, $config['debug'])
  525. ;
  526. $container->setAlias('annotation_reader', 'annotations.cached_reader');
  527. }
  528. }
  529. /**
  530. * Returns the base path for the XSD files.
  531. *
  532. * @return string The XSD base path
  533. */
  534. public function getXsdValidationBasePath()
  535. {
  536. return __DIR__.'/../Resources/config/schema';
  537. }
  538. public function getNamespace()
  539. {
  540. return 'http://symfony.com/schema/dic/symfony';
  541. }
  542. }