Completed
Push — master ( 46c3a0...a94e83 )
by Grégoire
13s queued 11s
created

src/Admin/BreadcrumbsBuilder.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Admin;
15
16
use Knp\Menu\ItemInterface;
17
use Symfony\Component\OptionsResolver\OptionsResolver;
18
19
/**
20
 * Stateless breadcrumbs builder (each method needs an Admin object).
21
 *
22
 * @author Grégoire Paris <[email protected]>
23
 */
24
final class BreadcrumbsBuilder implements BreadcrumbsBuilderInterface
25
{
26
    /**
27
     * @var string[]
28
     */
29
    private $config = [];
30
31
    /**
32
     * @param string[] $config
33
     */
34
    public function __construct(array $config = [])
35
    {
36
        $resolver = new OptionsResolver();
37
        $this->configureOptions($resolver);
38
39
        $this->config = $resolver->resolve($config);
40
    }
41
42
    public function configureOptions(OptionsResolver $resolver): void
43
    {
44
        $resolver->setDefaults([
45
            'child_admin_route' => 'edit',
46
        ]);
47
    }
48
49
    public function getBreadcrumbs(AdminInterface $admin, $action): array
50
    {
51
        $breadcrumbs = [];
52
        if ($admin->isChild()) {
53
            return $this->getBreadcrumbs($admin->getParent(), $action);
54
        }
55
56
        $menu = $this->buildBreadcrumbs($admin, $action);
57
58
        do {
59
            $breadcrumbs[] = $menu;
60
        } while ($menu = $menu->getParent());
61
62
        $breadcrumbs = array_reverse($breadcrumbs);
63
        array_shift($breadcrumbs);
64
65
        return $breadcrumbs;
66
    }
67
68
    /**
69
     * Builds breadcrumbs for $action, starting from $menu.
70
     *
71
     * Note: the method will be called by the top admin instance (parent => child)
72
     *
73
     * @param string $action
74
     */
75
    public function buildBreadcrumbs(
76
        AdminInterface $admin,
77
        $action,
78
        ItemInterface $menu = null
79
    ): ItemInterface {
80
        if (!$menu) {
81
            $menu = $admin->getMenuFactory()->createItem('root');
82
83
            $menu = $menu->addChild(
84
                'link_breadcrumb_dashboard',
85
                [
86
                    'uri' => $admin->getRouteGenerator()->generate('sonata_admin_dashboard'),
87
                    'extras' => ['translation_domain' => 'SonataAdminBundle'],
88
                ]
89
            );
90
        }
91
92
        $menu = $this->createMenuItem(
93
            $admin,
94
            $menu,
95
            sprintf('%s_list', $admin->getClassnameLabel()),
96
            $admin->getTranslationDomain(),
97
            [
98
                'uri' => $admin->hasRoute('list') && $admin->hasAccess('list') ?
99
                $admin->generateUrl('list') :
100
                null,
101
            ]
102
        );
103
104
        $childAdmin = $admin->getCurrentChildAdmin();
105
106
        if ($childAdmin) {
107
            $id = $admin->getRequest()->get($admin->getIdParameter());
108
109
            $menu = $menu->addChild(
110
                $admin->toString($admin->getSubject()),
0 ignored issues
show
It seems like $admin->getSubject() targeting Sonata\AdminBundle\Admin...Interface::getSubject() can also be of type null; however, Sonata\AdminBundle\Admin...inInterface::toString() does only seem to accept object, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
111
                [
112
                    'uri' => $admin->hasRoute($this->config['child_admin_route']) && $admin->hasAccess($this->config['child_admin_route'], $admin->getSubject()) ?
113
                    $admin->generateUrl($this->config['child_admin_route'], ['id' => $id]) :
114
                    null,
115
                    'extras' => [
116
                        'translation_domain' => false,
117
                    ],
118
                ]
119
            );
120
121
            $menu->setExtra('safe_label', false);
122
123
            return $this->buildBreadcrumbs($childAdmin, $action, $menu);
124
        }
125
126
        if ('list' === $action) {
127
            $menu->setUri(false);
128
129
            return $menu;
130
        }
131
        if ('create' !== $action && $admin->hasSubject()) {
132
            return $menu->addChild($admin->toString($admin->getSubject()), [
0 ignored issues
show
It seems like $admin->getSubject() targeting Sonata\AdminBundle\Admin...Interface::getSubject() can also be of type null; however, Sonata\AdminBundle\Admin...inInterface::toString() does only seem to accept object, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
133
                'extras' => [
134
                    'translation_domain' => false,
135
                ],
136
            ]);
137
        }
138
139
        return $this->createMenuItem(
140
            $admin,
141
            $menu,
142
            sprintf('%s_%s', $admin->getClassnameLabel(), $action),
143
            $admin->getTranslationDomain()
144
        );
145
    }
146
147
    /**
148
     * Creates a new menu item from a simple name. The name is normalized and
149
     * translated with the specified translation domain.
150
     *
151
     * @param AdminInterface $admin             used for translation
152
     * @param ItemInterface  $menu              will be modified and returned
153
     * @param string         $name              the source of the final label
154
     * @param string         $translationDomain for label translation
155
     * @param array          $options           menu item options
156
     */
157
    private function createMenuItem(
158
        AdminInterface $admin,
159
        ItemInterface $menu,
160
        string $name,
161
        ?string $translationDomain = null,
162
        array $options = []
163
    ): ItemInterface {
164
        $options = array_merge([
165
            'extras' => [
166
                'translation_domain' => $translationDomain,
167
            ],
168
        ], $options);
169
170
        return $menu->addChild(
171
            $admin->getLabelTranslatorStrategy()->getLabel(
172
                $name,
173
                'breadcrumb',
174
                'link'
175
            ),
176
            $options
177
        );
178
    }
179
}
180