AddDependencyCallsCompilerPass.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. /*
  3. * This file is part of the Sonata project.
  4. *
  5. * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  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 Sonata\AdminBundle\DependencyInjection\Compiler;
  11. use Symfony\Component\DependencyInjection\Definition;
  12. use Symfony\Component\DependencyInjection\ContainerBuilder;
  13. use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  14. use Symfony\Component\DependencyInjection\Reference;
  15. use Symfony\Component\DependencyInjection\ContainerInterface;
  16. use Sonata\AdminBundle\Admin\BaseFieldDescription;
  17. /**
  18. * Add all dependencies to the Admin class, this avoid to write too many lines
  19. * in the configuration files.
  20. *
  21. * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
  22. */
  23. class AddDependencyCallsCompilerPass implements CompilerPassInterface
  24. {
  25. /**
  26. * {@inheritDoc}
  27. */
  28. public function process(ContainerBuilder $container)
  29. {
  30. $groupDefaults = $admins = $classes = array();
  31. $pool = $container->getDefinition('sonata.admin.pool');
  32. foreach ($container->findTaggedServiceIds('sonata.admin') as $id => $tags) {
  33. foreach ($tags as $attributes) {
  34. $definition = $container->getDefinition($id);
  35. $arguments = $definition->getArguments();
  36. if (strlen($arguments[0]) == 0) {
  37. $definition->replaceArgument(0, $id);
  38. }
  39. if (strlen($arguments[2]) == 0) {
  40. $definition->replaceArgument(2, 'SonataAdminBundle:CRUD');
  41. }
  42. $this->applyConfigurationFromAttribute($definition, $attributes);
  43. $this->applyDefaults($container, $id, $attributes);
  44. $arguments = $definition->getArguments();
  45. $admins[] = $id;
  46. $classes[$arguments[1]] = $id;
  47. $showInDashboard = (boolean) (isset($attributes['show_in_dashboard']) ? $attributes['show_in_dashboard'] : true);
  48. if (!$showInDashboard) {
  49. continue;
  50. }
  51. $groupName = isset($attributes['group']) ? $attributes['group'] : 'default';
  52. $labelCatalogue = isset($attributes['label_catalogue']) ? $attributes['label_catalogue'] : 'SonataAdminBundle';
  53. if (!isset($groupDefaults[$groupName])) {
  54. $groupDefaults[$groupName] = array(
  55. 'label' => $groupName,
  56. 'label_catalogue' => $labelCatalogue,
  57. 'roles' => array()
  58. );
  59. }
  60. $groupDefaults[$groupName]['items'][] = $id;
  61. }
  62. }
  63. $dashboardGroupsSettings = $container->getParameter('sonata.admin.configuration.dashboard_groups');
  64. if (!empty($dashboardGroupsSettings)) {
  65. $groups = $dashboardGroupsSettings;
  66. foreach ($dashboardGroupsSettings as $groupName => $group) {
  67. if (!isset($groupDefaults[$groupName])) {
  68. $groupDefaults[$groupName] = array(
  69. 'items' => array(),
  70. 'label' => $groupName,
  71. 'roles' => array()
  72. );
  73. }
  74. if (empty($group['items'])) {
  75. $groups[$groupName]['items'] = $groupDefaults[$groupName]['items'];
  76. }
  77. if (empty($group['label'])) {
  78. $groups[$groupName]['label'] = $groupDefaults[$groupName]['label'];
  79. }
  80. if (empty($group['label_catalogue'])) {
  81. $groups[$groupName]['label_catalogue'] = 'SonataAdminBundle';
  82. }
  83. if (!empty($group['item_adds'])) {
  84. $group['items'] = array_merge($groupDefaults[$groupName]['items'], $group['item_adds']);
  85. }
  86. if (empty($group['roles'])) {
  87. $groups[$groupName]['roles'] = $groupDefaults[$groupName]['roles'];
  88. }
  89. }
  90. } else {
  91. $groups = $groupDefaults;
  92. }
  93. $pool->addMethodCall('setAdminServiceIds', array($admins));
  94. $pool->addMethodCall('setAdminGroups', array($groups));
  95. $pool->addMethodCall('setAdminClasses', array($classes));
  96. $routeLoader = $container->getDefinition('sonata.admin.route_loader');
  97. $routeLoader->replaceArgument(1, $admins);
  98. }
  99. /**
  100. * This method read the attribute keys and configure admin class to use the related dependency
  101. *
  102. * @param \Symfony\Component\DependencyInjection\Definition $definition
  103. * @param array $attributes
  104. */
  105. public function applyConfigurationFromAttribute(Definition $definition, array $attributes)
  106. {
  107. $keys = array(
  108. 'model_manager',
  109. 'form_contractor',
  110. 'show_builder',
  111. 'list_builder',
  112. 'datagrid_builder',
  113. 'translator',
  114. 'configuration_pool',
  115. 'router',
  116. 'validator',
  117. 'security_handler',
  118. 'menu_factory',
  119. 'route_builder',
  120. 'label_translator_strategy',
  121. );
  122. foreach ($keys as $key) {
  123. $method = 'set' . BaseFieldDescription::camelize($key);
  124. if (!isset($attributes[$key]) || $definition->hasMethodCall($method)) {
  125. continue;
  126. }
  127. $definition->addMethodCall($method, array(new Reference($attributes[$key])));
  128. }
  129. }
  130. /**
  131. * Apply the default values required by the AdminInterface to the Admin service definition
  132. *
  133. * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
  134. * @param string $serviceId
  135. * @param array $attributes
  136. *
  137. * @return \Symfony\Component\DependencyInjection\Definition
  138. */
  139. public function applyDefaults(ContainerBuilder $container, $serviceId, array $attributes = array())
  140. {
  141. $definition = $container->getDefinition($serviceId);
  142. $settings = $container->getParameter('sonata.admin.configuration.admin_services');
  143. $definition->setScope(ContainerInterface::SCOPE_PROTOTYPE);
  144. $manager_type = $attributes['manager_type'];
  145. $addServices = isset($settings[$serviceId]) ? $settings[$serviceId] : array();
  146. $defaultAddServices = array(
  147. 'model_manager' => sprintf('sonata.admin.manager.%s', $manager_type),
  148. 'form_contractor' => sprintf('sonata.admin.builder.%s_form', $manager_type),
  149. 'show_builder' => sprintf('sonata.admin.builder.%s_show', $manager_type),
  150. 'list_builder' => sprintf('sonata.admin.builder.%s_list', $manager_type),
  151. 'datagrid_builder' => sprintf('sonata.admin.builder.%s_datagrid', $manager_type),
  152. 'translator' => 'translator',
  153. 'configuration_pool' => 'sonata.admin.pool',
  154. 'route_generator' => 'sonata.admin.route.default_generator',
  155. 'validator' => 'validator',
  156. 'security_handler' => 'sonata.admin.security.handler',
  157. 'menu_factory' => 'knp_menu.factory',
  158. 'route_builder' => 'sonata.admin.route.path_info',
  159. 'label_translator_strategy' => 'sonata.admin.label.strategy.native'
  160. );
  161. $definition->addMethodCall('setManagerType', array($manager_type));
  162. foreach ($defaultAddServices as $attr => $addServiceId) {
  163. $method = 'set' . BaseFieldDescription::camelize($attr);
  164. if (isset($addServices[$attr]) || !$definition->hasMethodCall($method)) {
  165. $definition->addMethodCall($method, array(new Reference(isset($addServices[$attr]) ? $addServices[$attr] : $addServiceId)));
  166. }
  167. }
  168. if (isset($service['label'])) {
  169. $label = $service['label'];
  170. } elseif (isset($attributes['label'])) {
  171. $label = $attributes['label'];
  172. } else {
  173. $label = '-';
  174. }
  175. $definition->addMethodCall('setLabel', array($label));
  176. if (isset($attributes['persist_filters'])) {
  177. $persistFilters = (bool) $attributes['persist_filters'];
  178. } else {
  179. $persistFilters = (bool) $container->getParameter('sonata.admin.configuration.filters.persist');
  180. }
  181. $definition->addMethodCall('setPersistFilters', array($persistFilters));
  182. $this->fixTemplates($container, $definition);
  183. if ($container->hasParameter('sonata.admin.configuration.security.information') && !$definition->hasMethodCall('setSecurityInformation')) {
  184. $definition->addMethodCall('setSecurityInformation', array('%sonata.admin.configuration.security.information%'));
  185. }
  186. $definition->addMethodCall('initialize');
  187. return $definition;
  188. }
  189. /**
  190. * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
  191. * @param \Symfony\Component\DependencyInjection\Definition $definition
  192. *
  193. * @return void
  194. */
  195. public function fixTemplates(ContainerBuilder $container, Definition $definition)
  196. {
  197. $definedTemplates = $container->getParameter('sonata.admin.configuration.templates');
  198. $methods = array();
  199. $pos = 0;
  200. foreach ($definition->getMethodCalls() as $method) {
  201. if ($method[0] == 'setTemplates') {
  202. $definedTemplates = array_merge($definedTemplates, $method[1][0]);
  203. continue;
  204. }
  205. if ($method[0] == 'setTemplate') {
  206. $definedTemplates[$method[1][0]] = $method[1][1];
  207. continue;
  208. }
  209. $methods[$pos] = $method;
  210. $pos++;
  211. }
  212. $definition->setMethodCalls($methods);
  213. // make sure the default templates are defined
  214. $definedTemplates = array_merge(array(
  215. 'user_block' => 'SonataAdminBundle:Core:user_block.html.twig',
  216. 'layout' => 'SonataAdminBundle::standard_layout.html.twig',
  217. 'ajax' => 'SonataAdminBundle::ajax_layout.html.twig',
  218. 'dashboard' => 'SonataAdminBundle:Core:dashboard.html.twig',
  219. 'list' => 'SonataAdminBundle:CRUD:list.html.twig',
  220. 'show' => 'SonataAdminBundle:CRUD:show.html.twig',
  221. 'edit' => 'SonataAdminBundle:CRUD:edit.html.twig',
  222. 'history' => 'SonataAdminBundle:CRUD:history.html.twig',
  223. 'history_revision' => 'SonataAdminBundle:CRUD:history_revision.html.twig',
  224. 'acl' => 'SonataAdminBundle:CRUD:acl.html.twig',
  225. 'action' => 'SonataAdminBundle:CRUD:action.html.twig',
  226. 'short_object_description' => 'SonataAdminBundle:Helper:short-object-description.html.twig',
  227. 'preview' => 'SonataAdminBundle:CRUD:preview.html.twig',
  228. 'list_block' => 'SonataAdminBundle:Block:block_admin_list.html.twig',
  229. 'delete' => 'SonataAdminBundle:CRUD:delete.html.twig',
  230. 'batch' => 'SonataAdminBundle:CRUD:list__batch.html.twig',
  231. 'select' => 'SonataAdminBundle:CRUD:list__select.html.twig',
  232. 'batch_confirmation' => 'SonataAdminBundle:CRUD:batch_confirmation.html.twig',
  233. 'inner_list_row' => 'SonataAdminBundle:CRUD:list_inner_row.html.twig',
  234. 'base_list_field' => 'SonataAdminBundle:CRUD:base_list_field.html.twig',
  235. 'pager_links' => 'SonataAdminBundle:Pager:links.html.twig',
  236. 'pager_results' => 'SonataAdminBundle:Pager:results.html.twig',
  237. ), $definedTemplates);
  238. $definition->addMethodCall('setTemplates', array($definedTemplates));
  239. }
  240. }