AddDependencyCallsCompilerPass.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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. use Sonata\AdminBundle\Datagrid\Pager;
  18. /**
  19. * Add all dependencies to the Admin class, this avoid to write too many lines
  20. * in the configuration files.
  21. *
  22. * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
  23. */
  24. class AddDependencyCallsCompilerPass implements CompilerPassInterface
  25. {
  26. /**
  27. * {@inheritDoc}
  28. */
  29. public function process(ContainerBuilder $container)
  30. {
  31. // check if translator service exist
  32. if (!$container->hasAlias('translator')) {
  33. throw new \RuntimeException('The "translator" service is not yet enabled.
  34. It\'s required by SonataAdmin to display all labels properly.
  35. To learn how to enable the translator service please visit:
  36. http://symfony.com/doc/current/book/translation.html#book-translation-configuration
  37. ');
  38. }
  39. $parameterBag = $container->getParameterBag();
  40. $groupDefaults = $admins = $classes = array();
  41. $pool = $container->getDefinition('sonata.admin.pool');
  42. foreach ($container->findTaggedServiceIds('sonata.admin') as $id => $tags) {
  43. foreach ($tags as $attributes) {
  44. $definition = $container->getDefinition($id);
  45. $arguments = $definition->getArguments();
  46. if (strlen($arguments[0]) == 0) {
  47. $definition->replaceArgument(0, $id);
  48. }
  49. if (strlen($arguments[2]) == 0) {
  50. $definition->replaceArgument(2, 'SonataAdminBundle:CRUD');
  51. }
  52. $this->applyConfigurationFromAttribute($definition, $attributes);
  53. $this->applyDefaults($container, $id, $attributes);
  54. $arguments = $definition->getArguments();
  55. $admins[] = $id;
  56. if (!isset($classes[$arguments[1]])) {
  57. $classes[$arguments[1]] = array();
  58. }
  59. $classes[$arguments[1]][] = $id;
  60. $showInDashboard = (boolean) (isset($attributes['show_in_dashboard']) ? $parameterBag->resolveValue($attributes['show_in_dashboard']) : true);
  61. if (!$showInDashboard) {
  62. continue;
  63. }
  64. $resolvedGroupName = isset($attributes['group']) ? $parameterBag->resolveValue($attributes['group']) : 'default';
  65. $labelCatalogue = isset($attributes['label_catalogue']) ? $attributes['label_catalogue'] : 'SonataAdminBundle';
  66. $icon = isset($attributes['icon']) ? $attributes['icon'] : '<i class="fa fa-folder"></i>';
  67. if (!isset($groupDefaults[$resolvedGroupName])) {
  68. $groupDefaults[$resolvedGroupName] = array(
  69. 'label' => $resolvedGroupName,
  70. 'label_catalogue' => $labelCatalogue,
  71. 'icon' => $icon,
  72. 'roles' => array()
  73. );
  74. }
  75. $groupDefaults[$resolvedGroupName]['items'][] = array(
  76. 'admin' => $id,
  77. 'label' => '',
  78. 'route' => '',
  79. 'route_params' => array()
  80. );
  81. }
  82. }
  83. $dashboardGroupsSettings = $container->getParameter('sonata.admin.configuration.dashboard_groups');
  84. if (!empty($dashboardGroupsSettings)) {
  85. $groups = $dashboardGroupsSettings;
  86. foreach ($dashboardGroupsSettings as $groupName => $group) {
  87. $resolvedGroupName = $parameterBag->resolveValue($groupName);
  88. if (!isset($groupDefaults[$resolvedGroupName])) {
  89. $groupDefaults[$resolvedGroupName] = array(
  90. 'items' => array(),
  91. 'label' => $resolvedGroupName,
  92. 'roles' => array()
  93. );
  94. }
  95. if (empty($group['items'])) {
  96. $groups[$resolvedGroupName]['items'] = $groupDefaults[$resolvedGroupName]['items'];
  97. }
  98. if (empty($group['label'])) {
  99. $groups[$resolvedGroupName]['label'] = $groupDefaults[$resolvedGroupName]['label'];
  100. }
  101. if (empty($group['label_catalogue'])) {
  102. $groups[$resolvedGroupName]['label_catalogue'] = 'SonataAdminBundle';
  103. }
  104. if (empty($group['icon'])) {
  105. $groups[$resolvedGroupName]['icon'] = $groupDefaults[$resolvedGroupName]['icon'];
  106. }
  107. if (!empty($group['item_adds'])) {
  108. $groups[$resolvedGroupName]['items'] = array_merge($groups[$resolvedGroupName]['items'], $group['item_adds']);
  109. }
  110. if (empty($group['roles'])) {
  111. $groups[$resolvedGroupName]['roles'] = $groupDefaults[$resolvedGroupName]['roles'];
  112. }
  113. }
  114. } else {
  115. $groups = $groupDefaults;
  116. }
  117. $pool->addMethodCall('setAdminServiceIds', array($admins));
  118. $pool->addMethodCall('setAdminGroups', array($groups));
  119. $pool->addMethodCall('setAdminClasses', array($classes));
  120. $routeLoader = $container->getDefinition('sonata.admin.route_loader');
  121. $routeLoader->replaceArgument(1, $admins);
  122. }
  123. /**
  124. * This method read the attribute keys and configure admin class to use the related dependency
  125. *
  126. * @param Definition $definition
  127. * @param array $attributes
  128. */
  129. public function applyConfigurationFromAttribute(Definition $definition, array $attributes)
  130. {
  131. $keys = array(
  132. 'model_manager',
  133. 'form_contractor',
  134. 'show_builder',
  135. 'list_builder',
  136. 'datagrid_builder',
  137. 'translator',
  138. 'configuration_pool',
  139. 'router',
  140. 'validator',
  141. 'security_handler',
  142. 'menu_factory',
  143. 'route_builder',
  144. 'label_translator_strategy',
  145. );
  146. foreach ($keys as $key) {
  147. $method = 'set' . BaseFieldDescription::camelize($key);
  148. if (!isset($attributes[$key]) || $definition->hasMethodCall($method)) {
  149. continue;
  150. }
  151. $definition->addMethodCall($method, array(new Reference($attributes[$key])));
  152. }
  153. }
  154. /**
  155. * Apply the default values required by the AdminInterface to the Admin service definition
  156. *
  157. * @param ContainerBuilder $container
  158. * @param string $serviceId
  159. * @param array $attributes
  160. *
  161. * @return Definition
  162. */
  163. public function applyDefaults(ContainerBuilder $container, $serviceId, array $attributes = array())
  164. {
  165. $definition = $container->getDefinition($serviceId);
  166. $settings = $container->getParameter('sonata.admin.configuration.admin_services');
  167. $definition->setScope(ContainerInterface::SCOPE_PROTOTYPE);
  168. $manager_type = $attributes['manager_type'];
  169. $overwriteAdminConfiguration = isset($settings[$serviceId]) ? $settings[$serviceId] : array();
  170. $defaultAddServices = array(
  171. 'model_manager' => sprintf('sonata.admin.manager.%s', $manager_type),
  172. 'form_contractor' => sprintf('sonata.admin.builder.%s_form', $manager_type),
  173. 'show_builder' => sprintf('sonata.admin.builder.%s_show', $manager_type),
  174. 'list_builder' => sprintf('sonata.admin.builder.%s_list', $manager_type),
  175. 'datagrid_builder' => sprintf('sonata.admin.builder.%s_datagrid', $manager_type),
  176. 'translator' => 'translator',
  177. 'configuration_pool' => 'sonata.admin.pool',
  178. 'route_generator' => 'sonata.admin.route.default_generator',
  179. 'validator' => 'validator',
  180. 'security_handler' => 'sonata.admin.security.handler',
  181. 'menu_factory' => 'knp_menu.factory',
  182. 'route_builder' => 'sonata.admin.route.path_info' .
  183. (($manager_type == 'doctrine_phpcr') ? '_slashes' : ''),
  184. 'label_translator_strategy' => 'sonata.admin.label.strategy.native'
  185. );
  186. $definition->addMethodCall('setManagerType', array($manager_type));
  187. foreach ($defaultAddServices as $attr => $addServiceId) {
  188. $method = 'set' . BaseFieldDescription::camelize($attr);
  189. if (isset($overwriteAdminConfiguration[$attr]) || !$definition->hasMethodCall($method)) {
  190. $definition->addMethodCall($method, array(new Reference(isset($overwriteAdminConfiguration[$attr]) ? $overwriteAdminConfiguration[$attr] : $addServiceId)));
  191. }
  192. }
  193. if (isset($overwriteAdminConfiguration['pager_type'])) {
  194. $pagerType = $overwriteAdminConfiguration['pager_type'];
  195. } elseif (isset($attributes['pager_type'])) {
  196. $pagerType = $attributes['pager_type'];
  197. } else {
  198. $pagerType = Pager::TYPE_DEFAULT;
  199. }
  200. $definition->addMethodCall('setPagerType', array($pagerType));
  201. if (isset($overwriteAdminConfiguration['label'])) {
  202. $label = $overwriteAdminConfiguration['label'];
  203. } elseif (isset($attributes['label'])) {
  204. $label = $attributes['label'];
  205. } else {
  206. $label = '-';
  207. }
  208. $definition->addMethodCall('setLabel', array($label));
  209. if (isset($attributes['persist_filters'])) {
  210. $persistFilters = (bool) $attributes['persist_filters'];
  211. } else {
  212. $persistFilters = (bool) $container->getParameter('sonata.admin.configuration.filters.persist');
  213. }
  214. $definition->addMethodCall('setPersistFilters', array($persistFilters));
  215. $this->fixTemplates($container, $definition, isset($overwriteAdminConfiguration['templates']) ? $overwriteAdminConfiguration['templates'] : array('view' => array()));
  216. if ($container->hasParameter('sonata.admin.configuration.security.information') && !$definition->hasMethodCall('setSecurityInformation')) {
  217. $definition->addMethodCall('setSecurityInformation', array('%sonata.admin.configuration.security.information%'));
  218. }
  219. $definition->addMethodCall('initialize');
  220. return $definition;
  221. }
  222. /**
  223. * @param ContainerBuilder $container
  224. * @param Definition $definition
  225. * @param array $overwrittenTemplates
  226. *
  227. * @return void
  228. */
  229. public function fixTemplates(ContainerBuilder $container, Definition $definition, array $overwrittenTemplates = array())
  230. {
  231. $definedTemplates = $container->getParameter('sonata.admin.configuration.templates');
  232. $methods = array();
  233. $pos = 0;
  234. foreach ($definition->getMethodCalls() as $method) {
  235. if ($method[0] == 'setTemplates') {
  236. $definedTemplates = array_merge($definedTemplates, $method[1][0]);
  237. continue;
  238. }
  239. if ($method[0] == 'setTemplate') {
  240. $definedTemplates[$method[1][0]] = $method[1][1];
  241. continue;
  242. }
  243. // set template for simple pager if it is not already overwritten
  244. if ($method[0] === 'setPagerType'
  245. && $method[1][0] === Pager::TYPE_SIMPLE
  246. && (
  247. !isset($definedTemplates['pager_results'])
  248. || $definedTemplates['pager_results'] === 'SonataAdminBundle:Pager:results.html.twig'
  249. )
  250. ) {
  251. $definedTemplates['pager_results'] = 'SonataAdminBundle:Pager:simple_pager_results.html.twig';
  252. }
  253. $methods[$pos] = $method;
  254. $pos++;
  255. }
  256. $definition->setMethodCalls($methods);
  257. // make sure the default templates are defined
  258. $definedTemplates = array_merge(array(
  259. 'user_block' => 'SonataAdminBundle:Core:user_block.html.twig',
  260. 'add_block' => 'SonataAdminBundle:Core:add_block.html.twig',
  261. 'layout' => 'SonataAdminBundle::standard_layout.html.twig',
  262. 'ajax' => 'SonataAdminBundle::ajax_layout.html.twig',
  263. 'dashboard' => 'SonataAdminBundle:Core:dashboard.html.twig',
  264. 'list' => 'SonataAdminBundle:CRUD:list.html.twig',
  265. 'filter' => 'SonataAdminBundle:Form:filter_admin_fields.html.twig',
  266. 'show' => 'SonataAdminBundle:CRUD:show.html.twig',
  267. 'show_compare' => 'SonataAdminBundle:CRUD:show_compare.html.twig',
  268. 'edit' => 'SonataAdminBundle:CRUD:edit.html.twig',
  269. 'history' => 'SonataAdminBundle:CRUD:history.html.twig',
  270. 'history_revision_timestamp' => 'SonataAdminBundle:CRUD:history_revision_timestamp.html.twig',
  271. 'acl' => 'SonataAdminBundle:CRUD:acl.html.twig',
  272. 'action' => 'SonataAdminBundle:CRUD:action.html.twig',
  273. 'short_object_description' => 'SonataAdminBundle:Helper:short-object-description.html.twig',
  274. 'preview' => 'SonataAdminBundle:CRUD:preview.html.twig',
  275. 'list_block' => 'SonataAdminBundle:Block:block_admin_list.html.twig',
  276. 'delete' => 'SonataAdminBundle:CRUD:delete.html.twig',
  277. 'batch' => 'SonataAdminBundle:CRUD:list__batch.html.twig',
  278. 'select' => 'SonataAdminBundle:CRUD:list__select.html.twig',
  279. 'batch_confirmation' => 'SonataAdminBundle:CRUD:batch_confirmation.html.twig',
  280. 'inner_list_row' => 'SonataAdminBundle:CRUD:list_inner_row.html.twig',
  281. 'base_list_field' => 'SonataAdminBundle:CRUD:base_list_field.html.twig',
  282. 'pager_links' => 'SonataAdminBundle:Pager:links.html.twig',
  283. 'pager_results' => 'SonataAdminBundle:Pager:results.html.twig',
  284. 'tab_menu_template' => 'SonataAdminBundle:Core:tab_menu_template.html.twig',
  285. 'knp_menu_template' => 'SonataAdminBundle:Menu:sonata_menu.html.twig',
  286. 'outer_list_rows_mosaic' => 'SonataAdminBundle:CRUD:list_outer_rows_mosaic.html.twig',
  287. 'outer_list_rows_list' => 'SonataAdminBundle:CRUD:list_outer_rows_list.html.twig',
  288. 'outer_list_rows_tree' => 'SonataAdminBundle:CRUD:list_outer_rows_tree.html.twig',
  289. ), $definedTemplates, $overwrittenTemplates['view']);
  290. $definition->addMethodCall('setTemplates', array($definedTemplates));
  291. }
  292. }