AthenaCompilerPass   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 83
dl 0
loc 160
rs 10
c 1
b 0
f 0
wmc 25

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getServiceName() 0 6 1
A handleFilters() 0 7 2
A processSectionDefinitions() 0 30 2
A isExtended() 0 18 4
A handleController() 0 10 2
A handleSections() 0 21 4
A handleDashboardSections() 0 23 5
A process() 0 11 2
A handleSectionNormalisers() 0 2 1
A handleViewTypes() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (C) 2020-2025 Iain Cambridge
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
10
 * the Free Software Foundation, either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Parthenon\Athena\Compiler;
23
24
use Parthenon\Athena\AccessRightsManagerInterface;
25
use Parthenon\Athena\Crud\CrudController;
26
use Parthenon\Athena\Export\NormaliserFactoryInterface;
27
use Parthenon\Athena\Filters\FilterManager;
28
use Parthenon\Athena\ViewTypeManager;
29
use Parthenon\Export\Normaliser\NormaliserInterface;
30
use Symfony\Bundle\SecurityBundle\Security;
31
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
32
use Symfony\Component\DependencyInjection\ContainerBuilder;
33
use Symfony\Component\DependencyInjection\Definition;
34
use Symfony\Component\DependencyInjection\Reference;
35
36
final class AthenaCompilerPass implements CompilerPassInterface
37
{
38
    public function process(ContainerBuilder $container)
39
    {
40
        if (!$container->hasDefinition('parthenon.athena.view_type_manager')) {
41
            return;
42
        }
43
44
        $this->handleSections($container);
45
        $this->handleDashboardSections($container);
46
        $this->handleController($container);
47
        $this->handleFilters($container);
48
        $this->handleViewTypes($container);
49
    }
50
51
    public function handleSectionNormalisers(ContainerBuilder $containerBuilder): void
0 ignored issues
show
Unused Code introduced by
The parameter $containerBuilder is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

51
    public function handleSectionNormalisers(/** @scrutinizer ignore-unused */ ContainerBuilder $containerBuilder): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
52
    {
53
    }
54
55
    private function handleViewTypes(ContainerBuilder $container): void
56
    {
57
        $viewTypeManager = $container->getDefinition('parthenon.athena.view_type_manager');
58
        $definitions = $container->findTaggedServiceIds('parthenon.athena.view_type');
59
60
        foreach ($definitions as $id => $tag) {
61
            $viewTypeManager->addMethodCall('add', [new Reference($id)]);
62
        }
63
    }
64
65
    private function handleFilters(ContainerBuilder $container): void
66
    {
67
        $filterManager = $container->getDefinition('parthenon.athena.filter.filter_manager');
68
        $definitions = $container->findTaggedServiceIds('parthenon.athena.filter');
69
70
        foreach ($definitions as $name => $defintion) {
71
            $filterManager->addMethodCall('add', [new Reference($name)]);
72
        }
73
    }
74
75
    private function handleSections(ContainerBuilder $container): void
76
    {
77
        $definitions = $container->findTaggedServiceIds('parthenon.athena.section');
78
        /** @var Definition[] $sectionDefitions */
79
        $sectionDefitions = [];
80
        $classNames = [];
81
        foreach ($definitions as $id => $tag) {
82
            $defintion = $container->getDefinition($id);
83
            $className = $defintion->getClass();
84
85
            $sectionDefitions[$id] = $defintion;
86
            $classNames[$id] = $className;
87
        }
88
89
        foreach ($sectionDefitions as $id => $section) {
90
            if ($this->isExtended($section, $classNames)) {
91
                unset($sectionDefitions[$id]);
92
            }
93
        }
94
95
        $this->processSectionDefinitions($container, $sectionDefitions);
96
    }
97
98
    private function handleDashboardSections(ContainerBuilder $container): void
99
    {
100
        $definitions = $container->findTaggedServiceIds('parthenon.athena.dashboard_section');
101
        /** @var Definition[] $sectionDefitions */
102
        $sectionDefitions = [];
103
        $classNames = [];
104
        foreach ($definitions as $id => $tag) {
105
            $defintion = $container->getDefinition($id);
106
            $className = $defintion->getClass();
107
108
            $sectionDefitions[$id] = $defintion;
109
            $classNames[$id] = $className;
110
        }
111
112
        foreach ($sectionDefitions as $id => $section) {
113
            if ($this->isExtended($section, $classNames)) {
114
                unset($sectionDefitions[$id]);
115
            }
116
        }
117
118
        $dashboardSectionManagerDefinition = $container->getDefinition('parthenon.athena.dashboard_section_manager');
119
        foreach ($sectionDefitions as $id => $sectionDefition) {
120
            $dashboardSectionManagerDefinition->addMethodCall('add', [new Reference($id)]);
121
        }
122
    }
123
124
    private function isExtended(Definition $definition, array $classNames): bool
125
    {
126
        $className = $definition->getClass();
127
128
        $reflectionClass = new \ReflectionClass($className);
129
130
        if ($reflectionClass->isAbstract()) {
131
            return true;
132
        }
133
134
        foreach ($classNames as $name) {
135
            $parentName = get_parent_class($name);
136
            if ($parentName === $className) {
137
                return true;
138
            }
139
        }
140
141
        return false;
142
    }
143
144
    private function processSectionDefinitions(ContainerBuilder $container, array $definitions): void
145
    {
146
        $sectionManagerDefinition = $container->getDefinition('parthenon.athena.section_manager');
147
        foreach ($definitions as $name => $definition) {
148
            $className = $definition->getClass();
149
150
            $servicePart = $this->getServiceName($className);
151
            $sectionManagerDefinition->addMethodCall('addSection', [new Reference($name)]);
152
153
            $controllerDefinition = new Definition();
154
            $controllerDefinition->setClass(CrudController::class);
155
            $controllerDefinition->setArgument('$section', new Reference($name));
156
            $controllerDefinition->setArgument('$viewTypeManager', new Reference(ViewTypeManager::class));
157
            $controllerDefinition->setArgument('$filterManager', new Reference(FilterManager::class));
158
            $controllerDefinition->setArgument('$accessRightsManager', new Reference(AccessRightsManagerInterface::class));
159
            $controllerDefinition->setArgument('$security', new Reference(Security::class));
160
            $controllerDefinition->setPublic(true);
161
            $controllerDefinition->addTag('controller.service_arguments');
162
            $controllerDefinition->setAutoconfigured(true);
163
            $controllerDefinition->setAutowired(true);
164
165
            $container->setDefinition('athena_controller_'.$servicePart, $controllerDefinition);
166
167
            $normaliserDefinition = new Definition();
168
            $normaliserDefinition->setClass(NormaliserInterface::class);
169
            $normaliserDefinition->setFactory([new Reference(NormaliserFactoryInterface::class), 'build']);
170
            $normaliserDefinition->setArgument('$section', new Reference($name));
171
            $normaliserDefinition->addTag('parthenon.export.normaliser');
172
173
            $container->setDefinition('athena_export_normaliser_'.$servicePart, $normaliserDefinition);
174
        }
175
    }
176
177
    private function handleController(ContainerBuilder $container): void
178
    {
179
        $sectionManagerDefinition = $container->getDefinition('parthenon.athena.section_manager');
180
181
        $definitions = $container->findTaggedServiceIds('parthenon.athena.controller');
182
183
        foreach ($definitions as $id => $tag) {
184
            $sectionManagerDefinition->addMethodCall('addController', [new Reference($id)]);
185
            $defintion = $container->getDefinition($id);
186
            $defintion->addTag('controller.service_arguments');
187
        }
188
    }
189
190
    private function getServiceName(string $className): string
191
    {
192
        $parts = explode('\\', $className);
193
        $className = end($parts);
194
195
        return strtolower($className);
196
    }
197
}
198