Completed
Push — master ( 4e1c5d...6050c4 )
by Grégoire
22:25 queued 19:06
created

Pool::hasAdminByAdminCode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
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 InvalidArgumentException;
17
use Symfony\Component\DependencyInjection\ContainerInterface;
18
use Symfony\Component\PropertyAccess\PropertyAccess;
19
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
20
21
/**
22
 * @final since sonata-project/admin-bundle 3.52
23
 *
24
 * @author Thomas Rabaix <[email protected]>
25
 */
26
class Pool
27
{
28
    /**
29
     * @var ContainerInterface
30
     */
31
    protected $container;
32
33
    /**
34
     * @var string[]
35
     */
36
    protected $adminServiceIds = [];
37
38
    /**
39
     * @var array
40
     */
41
    protected $adminGroups = [];
42
43
    /**
44
     * @var array
45
     */
46
    protected $adminClasses = [];
47
48
    /**
49
     * @var array
50
     */
51
    protected $assets = [];
52
53
    /**
54
     * @var string
55
     */
56
    protected $title;
57
58
    /**
59
     * @var string
60
     */
61
    protected $titleLogo;
62
63
    /**
64
     * @var array
65
     */
66
    protected $options;
67
68
    /**
69
     * @var PropertyAccessorInterface
70
     */
71
    protected $propertyAccessor;
72
73
    /**
74
     * @param string $title
75
     * @param string $logoTitle
76
     * @param array  $options
77
     */
78
    public function __construct(
79
        ContainerInterface $container,
80
        $title,
81
        $logoTitle,
82
        $options = [],
83
        PropertyAccessorInterface $propertyAccessor = null
84
    ) {
85
        $this->container = $container;
86
        $this->title = $title;
87
        $this->titleLogo = $logoTitle;
88
        $this->options = $options;
89
        $this->propertyAccessor = $propertyAccessor;
90
    }
91
92
    /**
93
     * @return array
94
     */
95
    public function getGroups()
96
    {
97
        $groups = $this->adminGroups;
98
99
        foreach ($this->adminGroups as $name => $adminGroup) {
100
            foreach ($adminGroup as $id => $options) {
101
                $groups[$name][$id] = $this->getInstance($id);
102
            }
103
        }
104
105
        return $groups;
106
    }
107
108
    /**
109
     * Returns whether an admin group exists or not.
110
     *
111
     * @param string $group
112
     *
113
     * @return bool
114
     */
115
    public function hasGroup($group)
116
    {
117
        return isset($this->adminGroups[$group]);
118
    }
119
120
    /**
121
     * @return array
122
     */
123
    public function getDashboardGroups()
124
    {
125
        $groups = $this->adminGroups;
126
127
        foreach ($this->adminGroups as $name => $adminGroup) {
128
            if (isset($adminGroup['items'])) {
129
                foreach ($adminGroup['items'] as $key => $item) {
130
                    // Only Admin Group should be returned
131
                    if ('' !== $item['admin']) {
132
                        $admin = $this->getInstance($item['admin']);
133
134
                        if ($admin->showIn(AbstractAdmin::CONTEXT_DASHBOARD)) {
135
                            $groups[$name]['items'][$key] = $admin;
136
                        } else {
137
                            unset($groups[$name]['items'][$key]);
138
                        }
139
                    } else {
140
                        unset($groups[$name]['items'][$key]);
141
                    }
142
                }
143
            }
144
145
            if (empty($groups[$name]['items'])) {
146
                unset($groups[$name]);
147
            }
148
        }
149
150
        return $groups;
151
    }
152
153
    /**
154
     * Returns all admins related to the given $group.
155
     *
156
     * @param string $group
157
     *
158
     * @throws \InvalidArgumentException
159
     *
160
     * @return AdminInterface[]
161
     */
162
    public function getAdminsByGroup($group)
163
    {
164
        if (!isset($this->adminGroups[$group])) {
165
            throw new \InvalidArgumentException(sprintf('Group "%s" not found in admin pool.', $group));
166
        }
167
168
        $admins = [];
169
170
        if (!isset($this->adminGroups[$group]['items'])) {
171
            return $admins;
172
        }
173
174
        foreach ($this->adminGroups[$group]['items'] as $item) {
175
            $admins[] = $this->getInstance($item['admin']);
176
        }
177
178
        return $admins;
179
    }
180
181
    /**
182
     * Return the admin related to the given $class.
183
     *
184
     * @param string $class
185
     *
186
     * @return \Sonata\AdminBundle\Admin\AdminInterface|null
187
     */
188
    public function getAdminByClass($class)
189
    {
190
        if (!$this->hasAdminByClass($class)) {
191
            return null;
192
        }
193
194
        if (!\is_array($this->adminClasses[$class])) {
195
            throw new \RuntimeException('Invalid format for the Pool::adminClass property');
196
        }
197
198
        if (\count($this->adminClasses[$class]) > 1) {
199
            throw new \RuntimeException(sprintf(
200
                'Unable to find a valid admin for the class: %s, there are too many registered: %s',
201
                $class,
202
                implode(', ', $this->adminClasses[$class])
203
            ));
204
        }
205
206
        return $this->getInstance($this->adminClasses[$class][0]);
207
    }
208
209
    /**
210
     * @param string $class
211
     *
212
     * @return bool
213
     */
214
    public function hasAdminByClass($class)
215
    {
216
        return isset($this->adminClasses[$class]);
217
    }
218
219
    /**
220
     * Returns an admin class by its Admin code
221
     * ie : sonata.news.admin.post|sonata.news.admin.comment => return the child class of post.
222
     *
223
     * @throws \InvalidArgumentException if the root admin code is an empty string
224
     */
225
    public function getAdminByAdminCode(string $adminCode): AdminInterface
226
    {
227
        $codes = explode('|', $adminCode);
228
        $code = trim(array_shift($codes));
229
230
        if ('' === $code) {
231
            throw new \InvalidArgumentException('Root admin code must contain a valid admin reference, empty string given.');
232
        }
233
234
        $admin = $this->getInstance($code);
235
236
        foreach ($codes as $code) {
237
            if (!\in_array($code, $this->adminServiceIds, true)) {
238
                throw new \InvalidArgumentException(sprintf(
239
                    'Argument 1 passed to %s() must contain a valid admin reference, "%s" found at "%s".',
240
                    __METHOD__,
241
                    $code,
242
                    $adminCode
243
                ));
244
            }
245
246
            if (!$admin->hasChild($code)) {
247
                throw new \InvalidArgumentException(sprintf(
248
                   'Argument 1 passed to %s() must contain a valid admin hierarchy, "%s" is not a valid child for "%s"',
249
                   __METHOD__,
250
                   $code,
251
                   $admin->getCode()
252
                ));
253
            }
254
255
            $admin = $admin->getChild($code);
256
        }
257
258
        return $admin;
259
    }
260
261
    /**
262
     * Checks if an admin with a certain admin code exists.
263
     */
264
    final public function hasAdminByAdminCode(string $adminCode): bool
265
    {
266
        try {
267
            $this->getAdminByAdminCode($adminCode);
268
        } catch (\InvalidArgumentException $e) {
269
            return false;
270
        }
271
272
        return true;
273
    }
274
275
    /**
276
     * Returns a new admin instance depends on the given code.
277
     *
278
     * @param string $id
279
     *
280
     * @throws \InvalidArgumentException
281
     *
282
     * @return AdminInterface
283
     */
284
    public function getInstance($id)
285
    {
286
        if (!\in_array($id, $this->adminServiceIds, true)) {
287
            $msg = sprintf('Admin service "%s" not found in admin pool.', $id);
288
            $shortest = -1;
289
            $closest = null;
290
            $alternatives = [];
291
            foreach ($this->adminServiceIds as $adminServiceId) {
292
                $lev = levenshtein($id, $adminServiceId);
293
                if ($lev <= $shortest || $shortest < 0) {
294
                    $closest = $adminServiceId;
295
                    $shortest = $lev;
296
                }
297
                if ($lev <= \strlen($adminServiceId) / 3 || false !== strpos($adminServiceId, $id)) {
298
                    $alternatives[$adminServiceId] = $lev;
299
                }
300
            }
301
            if (null !== $closest) {
302
                asort($alternatives);
303
                unset($alternatives[$closest]);
304
                $msg = sprintf(
305
                    'Admin service "%s" not found in admin pool. Did you mean "%s" or one of those: [%s]?',
306
                    $id,
307
                    $closest,
308
                    implode(', ', array_keys($alternatives))
309
                );
310
            }
311
            throw new \InvalidArgumentException($msg);
312
        }
313
314
        $admin = $this->container->get($id);
315
316
        if (!$admin instanceof AdminInterface) {
317
            throw new InvalidArgumentException(sprintf('Found service "%s" is not a valid admin service', $id));
318
        }
319
320
        return $admin;
321
    }
322
323
    /**
324
     * @return ContainerInterface|null
325
     */
326
    public function getContainer()
327
    {
328
        return $this->container;
329
    }
330
331
    public function setAdminGroups(array $adminGroups): void
332
    {
333
        $this->adminGroups = $adminGroups;
334
    }
335
336
    /**
337
     * @return array
338
     */
339
    public function getAdminGroups()
340
    {
341
        return $this->adminGroups;
342
    }
343
344
    public function setAdminServiceIds(array $adminServiceIds): void
345
    {
346
        $this->adminServiceIds = $adminServiceIds;
347
    }
348
349
    /**
350
     * @return array
351
     */
352
    public function getAdminServiceIds()
353
    {
354
        return $this->adminServiceIds;
355
    }
356
357
    public function setAdminClasses(array $adminClasses): void
358
    {
359
        $this->adminClasses = $adminClasses;
360
    }
361
362
    /**
363
     * @return array
364
     */
365
    public function getAdminClasses()
366
    {
367
        return $this->adminClasses;
368
    }
369
370
    /**
371
     * @return string
372
     */
373
    public function getTitleLogo()
374
    {
375
        return $this->titleLogo;
376
    }
377
378
    /**
379
     * @return string
380
     */
381
    public function getTitle()
382
    {
383
        return $this->title;
384
    }
385
386
    /**
387
     * @param string $name
388
     * @param mixed  $default
389
     *
390
     * @return mixed
391
     */
392
    public function getOption($name, $default = null)
393
    {
394
        if (isset($this->options[$name])) {
395
            return $this->options[$name];
396
        }
397
398
        return $default;
399
    }
400
401
    public function getPropertyAccessor()
402
    {
403
        if (null === $this->propertyAccessor) {
404
            $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
405
        }
406
407
        return $this->propertyAccessor;
408
    }
409
}
410