FrameworkExtension.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. <?php
  2. namespace Symfony\Bundle\FrameworkBundle\DependencyInjection;
  3. use Symfony\Component\DependencyInjection\Extension\Extension;
  4. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  5. use Symfony\Component\DependencyInjection\Resource\FileResource;
  6. use Symfony\Component\DependencyInjection\ContainerBuilder;
  7. use Symfony\Component\DependencyInjection\Reference;
  8. use Symfony\Component\DependencyInjection\Definition;
  9. use Symfony\Component\DependencyInjection\Parameter;
  10. use Symfony\Component\Finder\Finder;
  11. use Symfony\Component\HttpFoundation\RequestMatcher;
  12. /*
  13. * This file is part of the Symfony framework.
  14. *
  15. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  16. *
  17. * This source file is subject to the MIT license that is bundled
  18. * with this source code in the file LICENSE.
  19. */
  20. /**
  21. * FrameworkExtension.
  22. *
  23. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  24. */
  25. class FrameworkExtension extends Extension
  26. {
  27. /**
  28. * Loads the web configuration.
  29. *
  30. * @param array $config An array of configuration settings
  31. * @param ContainerBuilder $container A ContainerBuilder instance
  32. */
  33. public function configLoad($config, ContainerBuilder $container)
  34. {
  35. $loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
  36. if (!$container->hasDefinition('controller_resolver')) {
  37. $loader->load('web.xml');
  38. }
  39. if (isset($config['ide'])) {
  40. switch ($config['ide']) {
  41. case 'textmate':
  42. $pattern = 'txmt://open?url=file://%%f&line=%%l';
  43. break;
  44. case 'macvim':
  45. $pattern = 'mvim://open?url=file://%%f&line=%%l';
  46. break;
  47. default:
  48. // should be the link pattern then
  49. $pattern = $config['ide'];
  50. }
  51. $container->setParameter('debug.file_link_format', $pattern);
  52. }
  53. foreach (array('csrf_secret', 'csrf-secret') as $key) {
  54. if (isset($config[$key])) {
  55. $container->setParameter('csrf_secret', $config[$key]);
  56. }
  57. }
  58. if (!$container->hasDefinition('event_dispatcher')) {
  59. $loader = new XmlFileLoader($container, array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'));
  60. $loader->load('services.xml');
  61. if ($container->getParameter('kernel.debug')) {
  62. $loader->load('debug.xml');
  63. $container->setDefinition('event_dispatcher', $container->findDefinition('debug.event_dispatcher'));
  64. $container->setAlias('debug.event_dispatcher', 'event_dispatcher');
  65. }
  66. }
  67. if (isset($config['charset'])) {
  68. $container->setParameter('kernel.charset', $config['charset']);
  69. }
  70. foreach (array('error_handler', 'error-handler') as $key) {
  71. if (array_key_exists($key, $config)) {
  72. if (false === $config[$key]) {
  73. $container->getDefinition('error_handler')->setMethodCalls(array());
  74. } else {
  75. $container->getDefinition('error_handler')->addMethodCall('register', array());
  76. $container->setParameter('error_handler.level', $config[$key]);
  77. }
  78. }
  79. }
  80. if (isset($config['router'])) {
  81. $this->registerRouterConfiguration($config, $container);
  82. }
  83. if (isset($config['profiler'])) {
  84. $this->registerProfilerConfiguration($config, $container);
  85. }
  86. if (isset($config['validation']['enabled'])) {
  87. $this->registerValidationConfiguration($config, $container);
  88. }
  89. if (array_key_exists('templating', $config)) {
  90. $this->registerTemplatingConfiguration($config, $container);
  91. }
  92. if (array_key_exists('test', $config)) {
  93. $this->registerTestConfiguration($config, $container);
  94. }
  95. $this->registerSessionConfiguration($config, $container);
  96. $this->registerTranslatorConfiguration($config, $container);
  97. $this->addCompiledClasses($container, array(
  98. 'Symfony\\Component\\HttpFoundation\\ParameterBag',
  99. 'Symfony\\Component\\HttpFoundation\\HeaderBag',
  100. 'Symfony\\Component\\HttpFoundation\\Request',
  101. 'Symfony\\Component\\HttpFoundation\\Response',
  102. 'Symfony\\Component\\HttpFoundation\\ResponseHeaderBag',
  103. 'Symfony\\Component\\HttpKernel\\BaseHttpKernel',
  104. 'Symfony\\Component\\HttpKernel\\HttpKernel',
  105. 'Symfony\\Component\\HttpKernel\\ResponseListener',
  106. 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
  107. 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface',
  108. 'Symfony\\Bundle\\FrameworkBundle\\RequestListener',
  109. 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameConverter',
  110. 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver',
  111. 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
  112. 'Symfony\\Component\\EventDispatcher\\Event',
  113. 'Symfony\\Component\\EventDispatcher\\EventDispatcher',
  114. 'Symfony\\Bundle\\FrameworkBundle\\EventDispatcher',
  115. 'Symfony\\Component\\Form\\FormConfiguration',
  116. ));
  117. }
  118. /**
  119. * Loads the templating configuration.
  120. *
  121. * @param array $config An array of configuration settings
  122. * @param ContainerBuilder $container A ContainerBuilder instance
  123. */
  124. protected function registerTemplatingConfiguration($config, ContainerBuilder $container)
  125. {
  126. $config = isset($config['templating']) ? $config['templating'] : array();
  127. if (!$container->hasDefinition('templating')) {
  128. $loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
  129. $loader->load('templating.xml');
  130. if ($container->getParameter('kernel.debug')) {
  131. $loader->load('templating_debug.xml');
  132. }
  133. }
  134. if (array_key_exists('assets_version', $config)) {
  135. $container->setParameter('templating.assets.version', $config['assets_version']);
  136. }
  137. if (array_key_exists('assets_base_urls', $config)) {
  138. $container->setParameter('templating.assets.base_urls', $config['assets_base_urls']);
  139. }
  140. // template paths
  141. $dirs = array('%kernel.root_dir%/views/%%bundle%%/%%controller%%/%%name%%%%format%%.%%renderer%%');
  142. foreach ($container->getParameter('kernel.bundle_dirs') as $dir) {
  143. $dirs[] = $dir.'/%%bundle%%/Resources/views/%%controller%%/%%name%%%%format%%.%%renderer%%';
  144. }
  145. $container->setParameter('templating.loader.filesystem.path', $dirs);
  146. // path for the filesystem loader
  147. if (isset($config['path'])) {
  148. $container->setParameter('templating.loader.filesystem.path', $config['path']);
  149. }
  150. // loaders
  151. if (isset($config['loader'])) {
  152. $loaders = array();
  153. $ids = is_array($config['loader']) ? $config['loader'] : array($config['loader']);
  154. foreach ($ids as $id) {
  155. $loaders[] = new Reference($id);
  156. }
  157. if (1 === count($loaders)) {
  158. $container->setAlias('templating.loader', (string) $loaders[0]);
  159. } else {
  160. $container->getDefinition('templating.loader.chain')->addArgument($loaders);
  161. $container->setAlias('templating.loader', 'templating.loader.chain');
  162. }
  163. }
  164. // cache?
  165. $container->setParameter('templating.loader.cache.path', null);
  166. if (isset($config['cache'])) {
  167. // wrap the loader with some cache
  168. $container->setDefinition('templating.loader.wrapped', $container->findDefinition('templating.loader'));
  169. $container->setDefinition('templating.loader', $container->getDefinition('templating.loader.cache'));
  170. $container->setParameter('templating.loader.cache.path', $config['cache']);
  171. }
  172. // compilation
  173. $this->addCompiledClasses($container, array(
  174. 'Symfony\\Component\\Templating\\Loader\\LoaderInterface',
  175. 'Symfony\\Component\\Templating\\Loader\\Loader',
  176. 'Symfony\\Component\\Templating\\Loader\\FilesystemLoader',
  177. 'Symfony\\Component\\Templating\\Engine',
  178. 'Symfony\\Component\\Templating\\Renderer\\RendererInterface',
  179. 'Symfony\\Component\\Templating\\Renderer\\Renderer',
  180. 'Symfony\\Component\\Templating\\Renderer\\PhpRenderer',
  181. 'Symfony\\Component\\Templating\\Storage\\Storage',
  182. 'Symfony\\Component\\Templating\\Storage\\FileStorage',
  183. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Engine',
  184. 'Symfony\\Component\\Templating\\Helper\\Helper',
  185. 'Symfony\\Component\\Templating\\Helper\\SlotsHelper',
  186. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Helper\\ActionsHelper',
  187. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Helper\\RouterHelper',
  188. 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Helper\\RouterHelper',
  189. ));
  190. }
  191. /**
  192. * Loads the test configuration.
  193. *
  194. * @param array $config A configuration array
  195. * @param ContainerBuilder $container A ContainerBuilder instance
  196. */
  197. protected function registerTestConfiguration($config, ContainerBuilder $container)
  198. {
  199. $loader = new XmlFileLoader($container, array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'));
  200. $loader->load('test.xml');
  201. }
  202. /**
  203. * Loads the translator configuration.
  204. *
  205. * @param array $config A configuration array
  206. * @param ContainerBuilder $container A ContainerBuilder instance
  207. */
  208. protected function registerTranslatorConfiguration($config, ContainerBuilder $container)
  209. {
  210. $first = false;
  211. if (!$container->hasDefinition('translator')) {
  212. $first = true;
  213. $loader = new XmlFileLoader($container, array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'));
  214. $loader->load('translation.xml');
  215. }
  216. $config = array_key_exists('translator', $config) ? $config['translator'] : array();
  217. if (!is_array($config)) {
  218. $config = array();
  219. }
  220. if (!isset($config['translator']['enabled']) || $config['translator']['enabled']) {
  221. // use the "real" translator
  222. $container->setDefinition('translator', $container->findDefinition('translator.real'));
  223. if ($first) {
  224. // translation directories
  225. $dirs = array();
  226. foreach (array_reverse($container->getParameter('kernel.bundles')) as $bundle) {
  227. $reflection = new \ReflectionClass($bundle);
  228. if (is_dir($dir = dirname($reflection->getFilename()).'/Resources/translations')) {
  229. $dirs[] = $dir;
  230. }
  231. }
  232. if (is_dir($dir = $container->getParameter('kernel.root_dir').'/translations')) {
  233. $dirs[] = $dir;
  234. }
  235. // translation resources
  236. $resources = array();
  237. if ($dirs) {
  238. $finder = new Finder();
  239. $finder->files()->filter(function (\SplFileInfo $file) { return 2 === substr_count($file->getBasename(), '.'); })->in($dirs);
  240. foreach ($finder as $file) {
  241. // filename is domain.locale.format
  242. list($domain, $locale, $format) = explode('.', $file->getBasename());
  243. $resources[] = array($format, (string) $file, $locale, $domain);
  244. }
  245. }
  246. $container->setParameter('translation.resources', $resources);
  247. }
  248. }
  249. if (array_key_exists('fallback', $config)) {
  250. $container->setParameter('translator.fallback_locale', $config['fallback']);
  251. }
  252. }
  253. /**
  254. * Loads the session configuration.
  255. *
  256. * @param array $config A configuration array
  257. * @param ContainerBuilder $container A ContainerBuilder instance
  258. */
  259. protected function registerSessionConfiguration($config, ContainerBuilder $container)
  260. {
  261. if (!$container->hasDefinition('session')) {
  262. $loader = new XmlFileLoader($container, array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'));
  263. $loader->load('session.xml');
  264. }
  265. $config = isset($config['session']) ? $config['session'] : array();
  266. foreach (array('default_locale', 'default-locale') as $key) {
  267. if (isset($config[$key])) {
  268. $container->setParameter('session.default_locale', $config[$key]);
  269. }
  270. }
  271. if (isset($config['auto_start']) || isset($config['auto-start'])) {
  272. $container->getDefinition('session')->addMethodCall('start');
  273. }
  274. if (isset($config['class'])) {
  275. $container->setParameter('session.class', $config['class']);
  276. }
  277. if (isset($config['storage_id'])) {
  278. $container->setAlias('session.storage', 'session.storage.'.$config['storage_id']);
  279. } else {
  280. $config['storage_id'] = 'native';
  281. }
  282. $options = $container->getParameter('session.storage.'.strtolower($config['storage_id']).'.options');
  283. foreach (array('name', 'lifetime', 'path', 'domain', 'secure', 'httponly', 'cache_limiter', 'cache-limiter', 'pdo.db_table') as $name) {
  284. if (isset($config[$name])) {
  285. $options[$name] = $config[$name];
  286. }
  287. }
  288. $container->setParameter('session.storage.'.strtolower($config['storage_id']).'.options', $options);
  289. $this->addCompiledClasses($container, array(
  290. 'Symfony\\Component\\HttpFoundation\\Session',
  291. 'Symfony\\Component\\HttpFoundation\\SessionStorage\\SessionStorageInterface',
  292. ));
  293. }
  294. protected function registerRouterConfiguration($config, ContainerBuilder $container)
  295. {
  296. if (!$container->hasDefinition('router')) {
  297. $loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
  298. $loader->load('routing.xml');
  299. }
  300. $container->setParameter('routing.resource', $config['router']['resource']);
  301. $this->addCompiledClasses($container, array(
  302. 'Symfony\\Component\\Routing\\RouterInterface',
  303. 'Symfony\\Component\\Routing\\Router',
  304. 'Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface',
  305. 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
  306. 'Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface',
  307. 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
  308. 'Symfony\\Component\\Routing\\Loader\\LoaderInterface',
  309. 'Symfony\\Bundle\\FrameworkBundle\\Routing\\LazyLoader',
  310. ));
  311. }
  312. /*
  313. <profiler only-exceptions="false">
  314. <matcher ip="192.168.0.0/24" path="#/admin/#i" />
  315. <matcher>
  316. <service class="MyMatcher" />
  317. </matcher>
  318. <matcher service="my_matcher" />
  319. </profiler>
  320. */
  321. protected function registerProfilerConfiguration($config, ContainerBuilder $container)
  322. {
  323. if ($config['profiler']) {
  324. if (!$container->hasDefinition('profiler')) {
  325. $loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
  326. $loader->load('profiling.xml');
  327. $loader->load('collectors.xml');
  328. }
  329. if (isset($config['profiler']['only-exceptions'])) {
  330. $container->setParameter('profiler_listener.only_exceptions', $config['profiler']['only-exceptions']);
  331. } elseif (isset($config['profiler']['only_exceptions'])) {
  332. $container->setParameter('profiler_listener.only_exceptions', $config['profiler']['only_exceptions']);
  333. }
  334. if (isset($config['profiler']['matcher'])) {
  335. if (isset($config['profiler']['matcher']['service'])) {
  336. $container->setAlias('profiler.request_matcher', $config['profiler']['matcher']['service']);
  337. } elseif (isset($config['profiler']['matcher']['_services'])) {
  338. $container->setAlias('profiler.request_matcher', (string) $config['profiler']['matcher']['_services'][0]);
  339. } else {
  340. $definition = $container->register('profiler.request_matcher', 'Symfony\\Component\\HttpFoundation\\RequestMatcher');
  341. if (isset($config['profiler']['matcher']['ip'])) {
  342. $definition->addMethodCall('matchIp', array($config['profiler']['matcher']['ip']));
  343. }
  344. if (isset($config['profiler']['matcher']['path'])) {
  345. $definition->addMethodCall('matchPath', array($config['profiler']['matcher']['path']));
  346. }
  347. }
  348. } else {
  349. $container->removeAlias('profiler.request_matcher');
  350. }
  351. } elseif ($container->hasDefinition('profiler')) {
  352. $container->getDefinition('profiling')->clearTags();
  353. }
  354. }
  355. protected function registerValidationConfiguration($config, ContainerBuilder $container)
  356. {
  357. if ($config['validation']['enabled']) {
  358. if (!$container->hasDefinition('validator')) {
  359. $loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
  360. $loader->load('validator.xml');
  361. }
  362. $xmlMappingFiles = array();
  363. $yamlMappingFiles = array();
  364. // default entries by the framework
  365. $xmlMappingFiles[] = __DIR__.'/../../../Component/Form/Resources/config/validation.xml';
  366. foreach ($container->getParameter('kernel.bundles') as $className) {
  367. $tmp = dirname(str_replace('\\', '/', $className));
  368. $namespace = str_replace('/', '\\', dirname($tmp));
  369. $bundle = basename($tmp);
  370. foreach ($container->getParameter('kernel.bundle_dirs') as $dir) {
  371. if (file_exists($file = $dir.'/'.$bundle.'/Resources/config/validation.xml')) {
  372. $xmlMappingFiles[] = realpath($file);
  373. }
  374. if (file_exists($file = $dir.'/'.$bundle.'/Resources/config/validation.yml')) {
  375. $yamlMappingFiles[] = realpath($file);
  376. }
  377. }
  378. }
  379. $xmlFilesLoader = new Definition(
  380. $container->getParameter('validator.mapping.loader.xml_files_loader.class'),
  381. array($xmlMappingFiles)
  382. );
  383. $yamlFilesLoader = new Definition(
  384. $container->getParameter('validator.mapping.loader.yaml_files_loader.class'),
  385. array($yamlMappingFiles)
  386. );
  387. $container->setDefinition('validator.mapping.loader.xml_files_loader', $xmlFilesLoader);
  388. $container->setDefinition('validator.mapping.loader.yaml_files_loader', $yamlFilesLoader);
  389. foreach ($xmlMappingFiles as $file) {
  390. $container->addResource(new FileResource($file));
  391. }
  392. foreach ($yamlMappingFiles as $file) {
  393. $container->addResource(new FileResource($file));
  394. }
  395. if (isset($config['validation']['annotations'])) {
  396. if (isset($config['validation']['annotations']['namespaces']) && is_array($config['validation']['annotations']['namespaces'])) {
  397. $container->setParameter('validator.annotations.namespaces', array_merge(
  398. $container->getParameter('validator.annotations.namespaces'),
  399. $config['validation']['annotations']['namespaces']
  400. ));
  401. }
  402. $annotationLoader = new Definition($container->getParameter('validator.mapping.loader.annotation_loader.class'));
  403. $annotationLoader->addArgument(new Parameter('validator.annotations.namespaces'));
  404. $container->setDefinition('validator.mapping.loader.annotation_loader', $annotationLoader);
  405. $loader = $container->getDefinition('validator.mapping.loader.loader_chain');
  406. $arguments = $loader->getArguments();
  407. array_unshift($arguments[0], new Reference('validator.mapping.loader.annotation_loader'));
  408. $loader->setArguments($arguments);
  409. }
  410. } elseif ($container->hasDefinition('validator')) {
  411. $container->getDefinition('validator')->clearTags();
  412. }
  413. }
  414. protected function addCompiledClasses($container, array $classes)
  415. {
  416. $current = $container->hasParameter('kernel.compiled_classes') ? $container->getParameter('kernel.compiled_classes') : array();
  417. $container->setParameter('kernel.compiled_classes', array_merge($current, $classes));
  418. }
  419. /**
  420. * Returns the base path for the XSD files.
  421. *
  422. * @return string The XSD base path
  423. */
  424. public function getXsdValidationBasePath()
  425. {
  426. return __DIR__.'/../Resources/config/schema';
  427. }
  428. public function getNamespace()
  429. {
  430. return 'http://www.symfony-project.org/schema/dic/symfony';
  431. }
  432. public function getAlias()
  433. {
  434. return 'app';
  435. }
  436. }