This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 PierstovalCharacterManagerBundle package. |
||
7 | * |
||
8 | * (c) Alexandre Rock Ancelet <[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 Pierstoval\Bundle\CharacterManagerBundle\Action; |
||
15 | |||
16 | use Doctrine\ORM\EntityManagerInterface; |
||
17 | use Pierstoval\Bundle\CharacterManagerBundle\Model\CharacterInterface; |
||
18 | use Pierstoval\Bundle\CharacterManagerBundle\Model\StepInterface; |
||
19 | use Pierstoval\Bundle\CharacterManagerBundle\Resolver\StepResolverInterface; |
||
20 | use Symfony\Component\HttpFoundation\RedirectResponse; |
||
21 | use Symfony\Component\HttpFoundation\Request; |
||
22 | use Symfony\Component\HttpFoundation\Session\Session; |
||
23 | use Symfony\Component\Routing\RouterInterface; |
||
24 | use Symfony\Contracts\Translation\TranslatorInterface; |
||
25 | use Twig\Environment; |
||
26 | |||
27 | abstract class AbstractStepAction implements StepActionInterface |
||
28 | { |
||
29 | /** |
||
30 | * Used when you need to change the translation domain used in controller-generated messages. |
||
31 | */ |
||
32 | protected static $translationDomain = 'PierstovalCharacterBundle'; |
||
33 | |||
34 | /** @var string */ |
||
35 | protected $class; |
||
36 | |||
37 | /** @var Request */ |
||
38 | protected $request; |
||
39 | |||
40 | /** @var StepInterface */ |
||
41 | protected $step; |
||
42 | |||
43 | /** @var StepInterface[] */ |
||
44 | protected $steps = []; |
||
45 | |||
46 | /** @var string */ |
||
47 | protected $stepName; |
||
48 | |||
49 | /** @var string */ |
||
50 | protected $managerName; |
||
51 | |||
52 | /** @var RouterInterface */ |
||
53 | protected $router; |
||
54 | |||
55 | /** @var EntityManagerInterface */ |
||
56 | protected $em; |
||
57 | |||
58 | /** @var Environment */ |
||
59 | protected $twig; |
||
60 | |||
61 | /** @var TranslatorInterface */ |
||
62 | protected $translator; |
||
63 | |||
64 | private $configured = false; |
||
65 | |||
66 | public function configure(string $managerName, string $stepName, string $characterClassName, StepResolverInterface $resolver): void |
||
67 | { |
||
68 | if ($this->configured) { |
||
69 | throw new \RuntimeException('Cannot reconfigure an already configured step action.'); |
||
70 | } |
||
71 | |||
72 | if (!\class_exists($characterClassName) || !\is_subclass_of($characterClassName, CharacterInterface::class, true)) { |
||
73 | throw new \InvalidArgumentException(\sprintf( |
||
74 | 'Step action must be a valid class implementing %s. "%s" given.', |
||
75 | CharacterInterface::class, |
||
76 | \class_exists($characterClassName) ? $characterClassName : \gettype($characterClassName) |
||
77 | )); |
||
78 | } |
||
79 | |||
80 | $this->class = $characterClassName; |
||
81 | $this->managerName = $managerName; |
||
82 | $this->step = $resolver->resolve($stepName, $managerName); |
||
83 | $this->stepName = $stepName; |
||
84 | $this->setSteps($resolver->getManagerSteps($managerName)); |
||
85 | |||
86 | $this->configured = true; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * {@inheritdoc} |
||
91 | */ |
||
92 | public function setRequest(Request $request): void |
||
93 | { |
||
94 | $this->request = $request; |
||
95 | } |
||
96 | |||
97 | public function setRouter(RouterInterface $router): void |
||
98 | { |
||
99 | $this->router = $router; |
||
100 | } |
||
101 | |||
102 | public function setObjectManager(EntityManagerInterface $em): void |
||
103 | { |
||
104 | $this->em = $em; |
||
105 | } |
||
106 | |||
107 | public function setTwig(Environment $twig): void |
||
108 | { |
||
109 | $this->twig = $twig; |
||
110 | } |
||
111 | |||
112 | public function setTranslator(TranslatorInterface $translator): void |
||
113 | { |
||
114 | $this->translator = $translator; |
||
115 | } |
||
116 | |||
117 | public function getStep(): StepInterface |
||
118 | { |
||
119 | $this->checkConfigured(); |
||
120 | |||
121 | return $this->step; |
||
122 | } |
||
123 | |||
124 | public function stepName(): string |
||
125 | { |
||
126 | $this->checkConfigured(); |
||
127 | |||
128 | return $this->stepName; |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * {@inheritdoc} |
||
133 | */ |
||
134 | protected function getCurrentCharacter(): array |
||
135 | { |
||
136 | return $this->getSession()->get('character.'.$this->managerName, []) ?: []; |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * {@inheritdoc} |
||
141 | */ |
||
142 | protected function getCharacterProperty(string $key = null) |
||
143 | { |
||
144 | if (null === $key) { |
||
145 | $key = $this->getStep()->getName(); |
||
146 | } |
||
147 | |||
148 | $character = $this->getCurrentCharacter(); |
||
149 | |||
150 | return $character[$key] ?? null; |
||
151 | } |
||
152 | |||
153 | protected function nextStep(): RedirectResponse |
||
154 | { |
||
155 | return $this->goToStep($this->getStep()->getNumber() + 1); |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Redirects to a specific step and updates the session. |
||
160 | */ |
||
161 | protected function goToStep(int $stepNumber): RedirectResponse |
||
162 | { |
||
163 | $this->checkConfigured(); |
||
164 | |||
165 | if (!$this->router) { |
||
166 | throw new \InvalidArgumentException('Cannot use '.__METHOD__.' if no router is injected in AbstractStepAction.'); |
||
167 | } |
||
168 | |||
169 | foreach ($this->steps as $step) { |
||
170 | if ($step->getNumber() === $stepNumber) { |
||
171 | $this->getSession()->set('step.'.$this->managerName, $stepNumber); |
||
172 | |||
173 | return new RedirectResponse($this->router->generate('pierstoval_character_generator_step', ['requestStep' => $step->getName()])); |
||
174 | } |
||
175 | } |
||
176 | |||
177 | throw new \InvalidArgumentException('Invalid step: '.$stepNumber); |
||
178 | } |
||
179 | |||
180 | protected function updateCharacterStep($value): void |
||
181 | { |
||
182 | $character = $this->getCurrentCharacter(); |
||
183 | |||
184 | $character[$this->getStep()->getName()] = $value; |
||
185 | |||
186 | foreach ($this->getStep()->getOnchangeClear() as $stepToDisable) { |
||
187 | unset($character[$stepToDisable]); |
||
188 | } |
||
189 | |||
190 | $this->getSession()->set('step.'.$this->managerName, $this->getStep()->getNumber()); |
||
191 | $this->getSession()->set('character.'.$this->managerName, $character); |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Adds a new flash message. |
||
196 | */ |
||
197 | protected function flashMessage(string $msg, string $type = null, array $msgParams = []): self |
||
198 | { |
||
199 | // Allows not knowing about the default type in the method signature. |
||
200 | if (null === $type) { |
||
201 | $type = 'error'; |
||
202 | } |
||
203 | |||
204 | $msg = $this->translator |
||
205 | ? $this->translator->trans($msg, $msgParams, static::$translationDomain) |
||
206 | : \strtr($msg, $msgParams) |
||
207 | ; |
||
208 | |||
209 | $flashbag = $this->getSession()->getFlashBag(); |
||
210 | |||
211 | // Add the message manually. |
||
212 | $existingMessages = $flashbag->peek($type); |
||
213 | $existingMessages[] = $msg; |
||
214 | |||
215 | // And avoid having the same message multiple times. |
||
216 | $flashbag->set($type, \array_unique($existingMessages)); |
||
217 | |||
218 | return $this; |
||
219 | } |
||
220 | |||
221 | protected function getRequest(): Request |
||
222 | { |
||
223 | $this->checkConfigured(); |
||
224 | |||
225 | if (!$this->request) { |
||
226 | throw new \RuntimeException('Request is not set in step action.'); |
||
227 | } |
||
228 | |||
229 | return $this->request; |
||
230 | } |
||
231 | |||
232 | protected function getSession(): Session |
||
233 | { |
||
234 | if (!($this->getRequest()->hasSession())) { |
||
235 | throw new \RuntimeException('The session must be available to manage characters. Did you forget to enable the session in the framework?'); |
||
236 | } |
||
237 | |||
238 | return $this->getRequest()->getSession(); |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * {@inheritdoc} |
||
243 | */ |
||
244 | private function setSteps(array $steps): void |
||
245 | { |
||
246 | foreach ($steps as $step) { |
||
247 | View Code Duplication | if (!$step instanceof StepInterface) { |
|
0 ignored issues
–
show
|
|||
248 | throw new \InvalidArgumentException(\sprintf( |
||
249 | 'Expected %s instance, "%s" given.', |
||
250 | StepActionInterface::class, |
||
251 | \is_object($step) ? \get_class($step) : \gettype($step) |
||
252 | )); |
||
253 | } |
||
254 | } |
||
255 | |||
256 | $this->steps = $steps; |
||
257 | } |
||
258 | |||
259 | private function checkConfigured(): void |
||
260 | { |
||
261 | if (!$this->configured) { |
||
262 | throw new \RuntimeException('Step action is not configured. Did you forget to run the "configure()" method?'); |
||
263 | } |
||
264 | } |
||
265 | } |
||
266 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.