AddDependencyCallsCompilerPass.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
  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. $groups = $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. $showInDashBord = (boolean)(isset($attributes['show_in_dashboard']) ? $attributes['show_in_dashboard'] : true);
  48. if (!$showInDashBord) {
  49. continue;
  50. }
  51. $groupName = isset($attributes['group']) ? $attributes['group'] : 'default';
  52. if (!isset($groupDefaults[$groupName])) {
  53. $groupDefaults[$groupName] = array(
  54. 'label' => $groupName
  55. );
  56. }
  57. $groupDefaults[$groupName]['items'][] = $id;
  58. }
  59. }
  60. $dashboardGroupsSettings = $container->getParameter('sonata.admin.configuration.dashboard_groups');
  61. if (!empty($dashboardGroupsSettings)) {
  62. $groups = $dashboardGroupsSettings;
  63. foreach ($dashboardGroupsSettings as $groupName => $group) {
  64. if (!isset($groupDefaults[$groupName])) {
  65. $groupDefaults[$groupName] = array(
  66. 'items' => array(),
  67. 'label' => $groupName
  68. );
  69. }
  70. if (empty($group['items'])) {
  71. $groups[$groupName]['items'] = $groupDefaults[$groupName]['items'];
  72. }
  73. if (empty($group['label'])) {
  74. $groups[$groupName]['label'] = $groupDefaults[$groupName]['label'];
  75. }
  76. if (!empty($group['item_adds'])) {
  77. $group['items'] = array_merge($groupDefaults[$groupName]['items'], $group['item_adds']);
  78. }
  79. }
  80. } else {
  81. $groups = $groupDefaults;
  82. }
  83. $pool->addMethodCall('setAdminServiceIds', array($admins));
  84. $pool->addMethodCall('setAdminGroups', array($groups));
  85. $pool->addMethodCall('setAdminClasses', array($classes));
  86. $routeLoader = $container->getDefinition('sonata.admin.route_loader');
  87. $routeLoader->replaceArgument(1, $admins);
  88. }
  89. /**
  90. * This method read the attribute keys and configure admin class to use the related dependency
  91. *
  92. * @param \Symfony\Component\DependencyInjection\Definition $definition
  93. * @param array $attributes
  94. */
  95. public function applyConfigurationFromAttribute(Definition $definition, array $attributes) {
  96. $keys = array(
  97. 'model_manager',
  98. 'form_contractor',
  99. 'show_builder',
  100. 'list_builder',
  101. 'datagrid_builder',
  102. 'translator',
  103. 'configuration_pool',
  104. 'router',
  105. 'validator',
  106. 'security_handler',
  107. 'menu_factory',
  108. 'label_translator_strategy',
  109. );
  110. foreach ($keys as $key) {
  111. $method = 'set'.$this->camelize($key);
  112. if (!isset($attributes[$key]) || $definition->hasMethodCall($method)) {
  113. continue;
  114. }
  115. $definition->addMethodCall($method, array(new Reference($attributes[$key])));
  116. }
  117. }
  118. /**
  119. * Apply the default values required by the AdminInterface to the Admin service definition
  120. *
  121. * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
  122. * @param string $serviceId
  123. * @param array $attributes
  124. * @return \Symfony\Component\DependencyInjection\Definition
  125. */
  126. public function applyDefaults(ContainerBuilder $container, $serviceId, array $attributes = array())
  127. {
  128. $definition = $container->getDefinition($serviceId);
  129. $settings = $container->getParameter('sonata.admin.configuration.admin_services');
  130. $definition->setScope(ContainerInterface::SCOPE_PROTOTYPE);
  131. $manager_type = $attributes['manager_type'];
  132. $addServices = isset($settings[$serviceId]) ? $settings[$serviceId] : array();
  133. $defaultAddServices = array(
  134. 'model_manager' => sprintf('sonata.admin.manager.%s', $manager_type),
  135. 'form_contractor' => sprintf('sonata.admin.builder.%s_form', $manager_type),
  136. 'show_builder' => sprintf('sonata.admin.builder.%s_show', $manager_type),
  137. 'list_builder' => sprintf('sonata.admin.builder.%s_list', $manager_type),
  138. 'datagrid_builder' => sprintf('sonata.admin.builder.%s_datagrid', $manager_type),
  139. 'translator' => 'translator',
  140. 'configuration_pool' => 'sonata.admin.pool',
  141. 'router' => 'router',
  142. 'validator' => 'validator',
  143. 'security_handler' => 'sonata.admin.security.handler',
  144. 'menu_factory' => 'knp_menu.factory',
  145. );
  146. foreach ($defaultAddServices as $attr => $addServiceId) {
  147. $method = 'set'.$this->camelize($attr);
  148. if (isset($addServices[$attr]) || !$definition->hasMethodCall($method)) {
  149. $definition->addMethodCall($method, array(new Reference(isset($addServices[$attr]) ? $addServices[$attr] : $addServiceId)));
  150. }
  151. }
  152. if (!$definition->hasMethodCall('setRouteBuilder')) {
  153. $definition->addMethodCall('setRouteBuilder', array(new Reference('sonata.admin.route.path_info')));
  154. }
  155. if (!$definition->hasMethodCall('setLabelTranslatorStrategy')) {
  156. $definition->addMethodCall('setLabelTranslatorStrategy', array(new Reference('sonata.admin.label.strategy.form_component')));
  157. }
  158. if (isset($service['label'])) {
  159. $label = $service['label'];
  160. } elseif (isset($attributes['label'])) {
  161. $label = $attributes['label'];
  162. } else {
  163. $label = '-';
  164. }
  165. $definition->addMethodCall('setLabel', array($label));
  166. $definition->addMethodCall('configure');
  167. if (!$definition->hasMethodCall('setTemplates')) {
  168. $definition->addMethodCall('setTemplates', array('%sonata.admin.configuration.templates%'));
  169. }
  170. return $definition;
  171. }
  172. /**
  173. * method taken from PropertyPath
  174. *
  175. * @param $property
  176. * @return mixed
  177. */
  178. protected function camelize($property)
  179. {
  180. return preg_replace(array('/(^|_)+(.)/e', '/\.(.)/e'), array("strtoupper('\\2')", "'_'.strtoupper('\\1')"), $property);
  181. }
  182. }