123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- <?php
- /*
- * This file is part of the Sonata Project package.
- *
- * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Sonata\AdminBundle\DependencyInjection\Compiler;
- use Doctrine\Common\Inflector\Inflector;
- use Sonata\AdminBundle\Datagrid\Pager;
- use Symfony\Component\DependencyInjection\ChildDefinition;
- use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
- use Symfony\Component\DependencyInjection\ContainerBuilder;
- use Symfony\Component\DependencyInjection\ContainerInterface;
- use Symfony\Component\DependencyInjection\Definition;
- use Symfony\Component\DependencyInjection\DefinitionDecorator;
- use Symfony\Component\DependencyInjection\Reference;
- /**
- * Add all dependencies to the Admin class, this avoid to write too many lines
- * in the configuration files.
- *
- * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
- */
- class AddDependencyCallsCompilerPass implements CompilerPassInterface
- {
- /**
- * {@inheritdoc}
- */
- public function process(ContainerBuilder $container)
- {
- // check if translator service exist
- if (!$container->has('translator')) {
- throw new \RuntimeException('The "translator" service is not yet enabled.
- It\'s required by SonataAdmin to display all labels properly.
- To learn how to enable the translator service please visit:
- http://symfony.com/doc/current/translation.html#configuration
- ');
- }
- $parameterBag = $container->getParameterBag();
- $groupDefaults = $admins = $classes = array();
- $pool = $container->getDefinition('sonata.admin.pool');
- foreach ($container->findTaggedServiceIds('sonata.admin') as $id => $tags) {
- foreach ($tags as $attributes) {
- $definition = $container->getDefinition($id);
- $parentDefinition = null;
- // NEXT_MAJOR: Remove check for DefinitionDecorator instance when dropping Symfony <3.3 support
- if ($definition instanceof ChildDefinition || $definition instanceof DefinitionDecorator) {
- $parentDefinition = $container->getDefinition($definition->getParent());
- }
- $this->replaceDefaultArguments(array(
- 0 => $id,
- 2 => 'SonataAdminBundle:CRUD',
- ), $definition, $parentDefinition);
- $this->applyConfigurationFromAttribute($definition, $attributes);
- $this->applyDefaults($container, $id, $attributes);
- $arguments = $parentDefinition ?
- array_merge($parentDefinition->getArguments(), $definition->getArguments()) :
- $definition->getArguments();
- $admins[] = $id;
- if (!isset($classes[$arguments[1]])) {
- $classes[$arguments[1]] = array();
- }
- $classes[$arguments[1]][] = $id;
- $showInDashboard = (bool) (isset($attributes['show_in_dashboard']) ? $parameterBag->resolveValue($attributes['show_in_dashboard']) : true);
- if (!$showInDashboard) {
- continue;
- }
- $resolvedGroupName = isset($attributes['group']) ? $parameterBag->resolveValue($attributes['group']) : 'default';
- $labelCatalogue = isset($attributes['label_catalogue']) ? $attributes['label_catalogue'] : 'SonataAdminBundle';
- $icon = isset($attributes['icon']) ? $attributes['icon'] : '<i class="fa fa-folder"></i>';
- $onTop = isset($attributes['on_top']) ? $attributes['on_top'] : false;
- $keepOpen = isset($attributes['keep_open']) ? $attributes['keep_open'] : false;
- if (!isset($groupDefaults[$resolvedGroupName])) {
- $groupDefaults[$resolvedGroupName] = array(
- 'label' => $resolvedGroupName,
- 'label_catalogue' => $labelCatalogue,
- 'icon' => $icon,
- 'roles' => array(),
- 'on_top' => false,
- 'keep_open' => false,
- );
- }
- $groupDefaults[$resolvedGroupName]['items'][] = array(
- 'admin' => $id,
- 'label' => !empty($attributes['label']) ? $attributes['label'] : '',
- 'route' => '',
- 'route_params' => array(),
- 'route_absolute' => false,
- );
- if (isset($groupDefaults[$resolvedGroupName]['on_top']) && $groupDefaults[$resolvedGroupName]['on_top']
- || $onTop && (count($groupDefaults[$resolvedGroupName]['items']) > 1)) {
- throw new \RuntimeException('You can\'t use "on_top" option with multiple same name groups.');
- }
- $groupDefaults[$resolvedGroupName]['on_top'] = $onTop;
- $groupDefaults[$resolvedGroupName]['keep_open'] = $keepOpen;
- }
- }
- $dashboardGroupsSettings = $container->getParameter('sonata.admin.configuration.dashboard_groups');
- if (!empty($dashboardGroupsSettings)) {
- $groups = $dashboardGroupsSettings;
- foreach ($dashboardGroupsSettings as $groupName => $group) {
- $resolvedGroupName = $parameterBag->resolveValue($groupName);
- if (!isset($groupDefaults[$resolvedGroupName])) {
- $groupDefaults[$resolvedGroupName] = array(
- 'items' => array(),
- 'label' => $resolvedGroupName,
- 'roles' => array(),
- 'on_top' => false,
- 'keep_open' => false,
- );
- }
- if (empty($group['items'])) {
- $groups[$resolvedGroupName]['items'] = $groupDefaults[$resolvedGroupName]['items'];
- }
- if (empty($group['label'])) {
- $groups[$resolvedGroupName]['label'] = $groupDefaults[$resolvedGroupName]['label'];
- }
- if (empty($group['label_catalogue'])) {
- $groups[$resolvedGroupName]['label_catalogue'] = 'SonataAdminBundle';
- }
- if (empty($group['icon'])) {
- $groups[$resolvedGroupName]['icon'] = $groupDefaults[$resolvedGroupName]['icon'];
- }
- if (!empty($group['item_adds'])) {
- $groups[$resolvedGroupName]['items'] = array_merge($groups[$resolvedGroupName]['items'], $group['item_adds']);
- }
- if (empty($group['roles'])) {
- $groups[$resolvedGroupName]['roles'] = $groupDefaults[$resolvedGroupName]['roles'];
- }
- if (isset($groups[$resolvedGroupName]['on_top']) && !empty($group['on_top']) && $group['on_top']
- && (count($groups[$resolvedGroupName]['items']) > 1)) {
- throw new \RuntimeException('You can\'t use "on_top" option with multiple same name groups.');
- }
- if (empty($group['on_top'])) {
- $groups[$resolvedGroupName]['on_top'] = $groupDefaults[$resolvedGroupName]['on_top'];
- }
- if (empty($group['keep_open'])) {
- $groups[$resolvedGroupName]['keep_open'] = $groupDefaults[$resolvedGroupName]['keep_open'];
- }
- }
- } elseif ($container->getParameter('sonata.admin.configuration.sort_admins')) {
- $groups = $groupDefaults;
- $elementSort = function (&$element) {
- usort(
- $element['items'],
- function ($a, $b) {
- $a = !empty($a['label']) ? $a['label'] : $a['admin'];
- $b = !empty($b['label']) ? $b['label'] : $b['admin'];
- if ($a === $b) {
- return 0;
- }
- return $a < $b ? -1 : 1;
- }
- );
- };
- /*
- * 1) sort the groups by their index
- * 2) sort the elements within each group by label/admin
- */
- ksort($groups);
- array_walk($groups, $elementSort);
- } else {
- $groups = $groupDefaults;
- }
- $pool->addMethodCall('setAdminServiceIds', array($admins));
- $pool->addMethodCall('setAdminGroups', array($groups));
- $pool->addMethodCall('setAdminClasses', array($classes));
- $routeLoader = $container->getDefinition('sonata.admin.route_loader');
- $routeLoader->replaceArgument(1, $admins);
- }
- /**
- * This method read the attribute keys and configure admin class to use the related dependency.
- *
- * @param Definition $definition
- * @param array $attributes
- */
- public function applyConfigurationFromAttribute(Definition $definition, array $attributes)
- {
- $keys = array(
- 'model_manager',
- 'form_contractor',
- 'show_builder',
- 'list_builder',
- 'datagrid_builder',
- 'translator',
- 'configuration_pool',
- 'router',
- 'validator',
- 'security_handler',
- 'menu_factory',
- 'route_builder',
- 'label_translator_strategy',
- );
- foreach ($keys as $key) {
- $method = 'set'.Inflector::classify($key);
- if (!isset($attributes[$key]) || $definition->hasMethodCall($method)) {
- continue;
- }
- $definition->addMethodCall($method, array(new Reference($attributes[$key])));
- }
- }
- /**
- * Apply the default values required by the AdminInterface to the Admin service definition.
- *
- * @param ContainerBuilder $container
- * @param string $serviceId
- * @param array $attributes
- *
- * @return Definition
- */
- public function applyDefaults(ContainerBuilder $container, $serviceId, array $attributes = array())
- {
- $definition = $container->getDefinition($serviceId);
- $settings = $container->getParameter('sonata.admin.configuration.admin_services');
- if (method_exists($definition, 'setShared')) { // Symfony 2.8+
- $definition->setShared(false);
- } else { // For Symfony <2.8 compatibility
- $definition->setScope(ContainerInterface::SCOPE_PROTOTYPE);
- }
- $manager_type = $attributes['manager_type'];
- $overwriteAdminConfiguration = isset($settings[$serviceId]) ? $settings[$serviceId] : array();
- $defaultAddServices = array(
- 'model_manager' => sprintf('sonata.admin.manager.%s', $manager_type),
- 'form_contractor' => sprintf('sonata.admin.builder.%s_form', $manager_type),
- 'show_builder' => sprintf('sonata.admin.builder.%s_show', $manager_type),
- 'list_builder' => sprintf('sonata.admin.builder.%s_list', $manager_type),
- 'datagrid_builder' => sprintf('sonata.admin.builder.%s_datagrid', $manager_type),
- 'translator' => 'translator',
- 'configuration_pool' => 'sonata.admin.pool',
- 'route_generator' => 'sonata.admin.route.default_generator',
- 'validator' => 'validator',
- 'security_handler' => 'sonata.admin.security.handler',
- 'menu_factory' => 'knp_menu.factory',
- 'route_builder' => 'sonata.admin.route.path_info'.
- (($manager_type == 'doctrine_phpcr') ? '_slashes' : ''),
- 'label_translator_strategy' => 'sonata.admin.label.strategy.native',
- );
- $definition->addMethodCall('setManagerType', array($manager_type));
- foreach ($defaultAddServices as $attr => $addServiceId) {
- $method = 'set'.Inflector::classify($attr);
- if (isset($overwriteAdminConfiguration[$attr]) || !$definition->hasMethodCall($method)) {
- $args = array(new Reference(isset($overwriteAdminConfiguration[$attr]) ? $overwriteAdminConfiguration[$attr] : $addServiceId));
- if ('translator' === $attr) {
- $args[] = false;
- }
- $definition->addMethodCall($method, $args);
- }
- }
- if (isset($overwriteAdminConfiguration['pager_type'])) {
- $pagerType = $overwriteAdminConfiguration['pager_type'];
- } elseif (isset($attributes['pager_type'])) {
- $pagerType = $attributes['pager_type'];
- } else {
- $pagerType = Pager::TYPE_DEFAULT;
- }
- $definition->addMethodCall('setPagerType', array($pagerType));
- if (isset($overwriteAdminConfiguration['label'])) {
- $label = $overwriteAdminConfiguration['label'];
- } elseif (isset($attributes['label'])) {
- $label = $attributes['label'];
- } else {
- $label = '-';
- }
- $definition->addMethodCall('setLabel', array($label));
- if (isset($attributes['persist_filters'])) {
- $persistFilters = (bool) $attributes['persist_filters'];
- } else {
- $persistFilters = (bool) $container->getParameter('sonata.admin.configuration.filters.persist');
- }
- $definition->addMethodCall('setPersistFilters', array($persistFilters));
- if (isset($overwriteAdminConfiguration['show_mosaic_button'])) {
- $showMosaicButton = $overwriteAdminConfiguration['show_mosaic_button'];
- } elseif (isset($attributes['show_mosaic_button'])) {
- $showMosaicButton = $attributes['show_mosaic_button'];
- } else {
- $showMosaicButton = $container->getParameter('sonata.admin.configuration.show.mosaic.button');
- }
- $definition->addMethodCall('showMosaicButton', array($showMosaicButton));
- $this->fixTemplates($container, $definition, isset($overwriteAdminConfiguration['templates']) ? $overwriteAdminConfiguration['templates'] : array('view' => array()));
- if ($container->hasParameter('sonata.admin.configuration.security.information') && !$definition->hasMethodCall('setSecurityInformation')) {
- $definition->addMethodCall('setSecurityInformation', array('%sonata.admin.configuration.security.information%'));
- }
- $definition->addMethodCall('initialize');
- return $definition;
- }
- /**
- * @param ContainerBuilder $container
- * @param Definition $definition
- * @param array $overwrittenTemplates
- */
- public function fixTemplates(ContainerBuilder $container, Definition $definition, array $overwrittenTemplates = array())
- {
- $definedTemplates = $container->getParameter('sonata.admin.configuration.templates');
- $methods = array();
- $pos = 0;
- foreach ($definition->getMethodCalls() as $method) {
- if ($method[0] == 'setTemplates') {
- $definedTemplates = array_merge($definedTemplates, $method[1][0]);
- continue;
- }
- if ($method[0] == 'setTemplate') {
- $definedTemplates[$method[1][0]] = $method[1][1];
- continue;
- }
- // set template for simple pager if it is not already overwritten
- if ($method[0] === 'setPagerType'
- && $method[1][0] === Pager::TYPE_SIMPLE
- && (
- !isset($definedTemplates['pager_results'])
- || $definedTemplates['pager_results'] === 'SonataAdminBundle:Pager:results.html.twig'
- )
- ) {
- $definedTemplates['pager_results'] = 'SonataAdminBundle:Pager:simple_pager_results.html.twig';
- }
- $methods[$pos] = $method;
- ++$pos;
- }
- $definition->setMethodCalls($methods);
- $definedTemplates = $overwrittenTemplates['view'] + $definedTemplates;
- if ($container->getParameter('sonata.admin.configuration.templates') !== $definedTemplates) {
- $definition->addMethodCall('setTemplates', array($definedTemplates));
- } else {
- $definition->addMethodCall('setTemplates', array('%sonata.admin.configuration.templates%'));
- }
- }
- /**
- * Replace the empty arguments required by the Admin service definition.
- *
- * @param array $defaultArguments
- * @param Definition $definition
- * @param Definition|null $parentDefinition
- */
- private function replaceDefaultArguments(array $defaultArguments, Definition $definition, Definition $parentDefinition = null)
- {
- $arguments = $definition->getArguments();
- $parentArguments = $parentDefinition ? $parentDefinition->getArguments() : array();
- foreach ($defaultArguments as $index => $value) {
- $declaredInParent = $parentDefinition && array_key_exists($index, $parentArguments);
- if (strlen($declaredInParent ? $parentArguments[$index] : $arguments[$index]) == 0) {
- $arguments[$declaredInParent ? sprintf('index_%s', $index) : $index] = $value;
- }
- }
- $definition->setArguments($arguments);
- }
- }
|