Passed
Push — master ( 769850...cbe010 )
by Jan
05:23
created

SelectAPIController::labelProfilesLot()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 15
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4
 *
5
 * Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as published
9
 * by the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace App\Controller;
22
23
use App\Entity\Base\AbstractStructuralDBElement;
24
use App\Entity\Contracts\NamedElementInterface;
25
use App\Entity\LabelSystem\LabelProfile;
26
use App\Entity\Parts\Category;
27
use App\Entity\Parts\Footprint;
28
use App\Entity\Parts\Manufacturer;
29
use App\Entity\Parts\MeasurementUnit;
30
use App\Entity\ProjectSystem\Project;
31
use App\Services\Trees\NodesListBuilder;
32
use Doctrine\ORM\EntityManagerInterface;
33
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
34
use Symfony\Component\HttpFoundation\Response;
35
use Symfony\Component\Routing\Annotation\Route;
36
use Symfony\Contracts\Translation\TranslatorInterface;
37
38
/**
39
 * @Route("/select_api")
40
 *
41
 * This endpoint is used by the select2 library to dynamically load data (used in the multiselect action helper in parts lists)
42
 */
43
class SelectAPIController extends AbstractController
44
{
45
    private NodesListBuilder $nodesListBuilder;
46
    private TranslatorInterface $translator;
47
48
    public function __construct(NodesListBuilder $nodesListBuilder, TranslatorInterface $translator)
49
    {
50
        $this->nodesListBuilder = $nodesListBuilder;
51
        $this->translator = $translator;
52
    }
53
54
    /**
55
     * @Route("/category", name="select_category")
56
     */
57
    public function category(): Response
58
    {
59
        return $this->getResponseForClass(Category::class);
60
    }
61
62
    /**
63
     * @Route("/footprint", name="select_footprint")
64
     */
65
    public function footprint(): Response
66
    {
67
        return $this->getResponseForClass(Footprint::class, true);
68
    }
69
70
    /**
71
     * @Route("/manufacturer", name="select_manufacturer")
72
     */
73
    public function manufacturer(): Response
74
    {
75
        return $this->getResponseForClass(Manufacturer::class, true);
76
    }
77
78
    /**
79
     * @Route("/measurement_unit", name="select_measurement_unit")
80
     */
81
    public function measurement_unit(): Response
82
    {
83
        return $this->getResponseForClass(MeasurementUnit::class, true);
84
    }
85
86
    /**
87
     * @Route("/project", name="select_project")
88
     */
89
    public function projects(): Response
90
    {
91
        return $this->getResponseForClass(Project::class, false);
92
    }
93
94
    /**
95
     * @Route("/label_profiles", name="select_label_profiles")
96
     * @return Response
97
     */
98
    public function labelProfiles(EntityManagerInterface $entityManager): Response
99
    {
100
        $this->denyAccessUnlessGranted('@labels.create_labels');
101
102
        if ($this->isGranted('@labels.read_profiles')) {
103
            $profiles = $entityManager->getRepository(LabelProfile::class)->getPartLabelProfiles();
104
            $nodes = $this->buildJSONStructure($profiles);
105
        } else {
106
            $nodes = [];
107
        }
108
109
        //Add the empty option
110
        $this->addEmptyNode($nodes, 'part_list.action.generate_label.empty');
111
112
        return $this->json($nodes);
113
    }
114
115
    /**
116
     * @Route("/label_profiles_lot", name="select_label_profiles_lot")
117
     * @return Response
118
     */
119
    public function labelProfilesLot(EntityManagerInterface $entityManager): Response
120
    {
121
        $this->denyAccessUnlessGranted('@labels.create_labels');
122
123
        if ($this->isGranted('@labels.read_profiles')) {
124
            $profiles = $entityManager->getRepository(LabelProfile::class)->getPartLotsLabelProfiles();
125
            $nodes = $this->buildJSONStructure($profiles);
126
        } else {
127
            $nodes = [];
128
        }
129
130
        //Add the empty option
131
        $this->addEmptyNode($nodes, 'part_list.action.generate_label.empty');
132
133
        return $this->json($nodes);
134
    }
135
136
    protected function getResponseForClass(string $class, bool $include_empty = false): Response
137
    {
138
        $test_obj = new $class();
139
        $this->denyAccessUnlessGranted('read', $test_obj);
140
141
        $nodes = $this->nodesListBuilder->typeToNodesList($class);
142
143
        $json = $this->buildJSONStructure($nodes);
144
145
        if ($include_empty) {
146
            $this->addEmptyNode($json);
147
        }
148
149
        return $this->json($json);
150
    }
151
152
    protected function addEmptyNode(array &$arr, string $text = 'part_list.action.select_null'): array
153
    {
154
        array_unshift($arr, [
155
            'text' => $this->translator->trans($text),
156
            'value' => null,
157
        ]);
158
159
        return $arr;
160
    }
161
162
    protected function buildJSONStructure(array $nodes_list): array
163
    {
164
        $entries = [];
165
166
        foreach ($nodes_list as $node) {
167
            if ($node instanceof AbstractStructuralDBElement) {
168
                $entry = [
169
                    'text' => str_repeat('&nbsp;&nbsp;&nbsp;', $node->getLevel()).htmlspecialchars($node->getName()),
170
                    'value' => $node->getID(),
171
                    'data-subtext' => $node->getParent() ? $node->getParent()->getFullPath() : null,
172
                ];
173
            } elseif ($node instanceof NamedElementInterface) {
174
                $entry = [
175
                    'text' => htmlspecialchars($node->getName()),
176
                    'value' => $node->getID(),
0 ignored issues
show
Bug introduced by
The method getID() does not exist on App\Entity\Contracts\NamedElementInterface. It seems like you code against a sub-type of said class. However, the method does not exist in anonymous//tests/Service...ementProviderTest.php$0. Are you sure you never get one of those? ( Ignorable by Annotation )

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

176
                    'value' => $node->/** @scrutinizer ignore-call */ getID(),
Loading history...
177
                ];
178
            } else {
179
                throw new \InvalidArgumentException('Invalid node type!');
180
            }
181
182
            $entries[] = $entry;
183
        }
184
185
        return $entries;
186
    }
187
}
188