Total Complexity | 66 |
Total Lines | 944 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like MakeResourceActionCommand often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use MakeResourceActionCommand, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
68 | class MakeResourceActionCommand extends MakeCommand |
||
69 | { |
||
70 | /** |
||
71 | * {@inheritdoc} |
||
72 | */ |
||
73 | protected string $type = 'resource'; |
||
74 | |||
75 | /** |
||
76 | * The form parameter class name |
||
77 | * @var class-string |
||
78 | */ |
||
79 | protected string $paramClass; |
||
80 | |||
81 | /** |
||
82 | * The form validator class name |
||
83 | * @var class-string |
||
84 | */ |
||
85 | protected string $validatorClass; |
||
86 | |||
87 | /** |
||
88 | * The entity class name |
||
89 | * @var string |
||
90 | */ |
||
91 | protected string $entityClass; |
||
92 | |||
93 | /** |
||
94 | * The repository class name |
||
95 | * @var string |
||
96 | */ |
||
97 | protected string $repositoryClass; |
||
98 | |||
99 | /** |
||
100 | * Create new instance |
||
101 | * @param Application $application |
||
102 | * @param Filesystem $filesystem |
||
103 | */ |
||
104 | public function __construct( |
||
105 | Application $application, |
||
106 | Filesystem $filesystem |
||
107 | ) { |
||
108 | parent::__construct($application, $filesystem); |
||
109 | $this->setName('make:resource') |
||
110 | ->setDescription('Command to generate platine resource action'); |
||
111 | |||
112 | $this->addOption( |
||
113 | '-c|--fields', |
||
114 | 'The entity fields. Example field1:param1,field2:param2,field3', |
||
115 | null, |
||
116 | false |
||
117 | ); |
||
118 | |||
119 | $this->addOption( |
||
120 | '-i|--fields-unique', |
||
121 | 'The entity unique fields. Example field1:param1,field2:param2,field3', |
||
122 | null, |
||
123 | false |
||
124 | ); |
||
125 | |||
126 | $this->addOption( |
||
127 | '-o|--fields-order', |
||
128 | 'The entity orders fields. Example field1:ASC,field2:DESC,field3', |
||
129 | null, |
||
130 | false |
||
131 | ); |
||
132 | |||
133 | $this->addOption( |
||
134 | '-t|--template-prefix', |
||
135 | 'The template prefix', |
||
136 | null, |
||
137 | false |
||
138 | ); |
||
139 | |||
140 | $this->addOption( |
||
141 | '-r|--route-prefix', |
||
142 | 'The route name prefix', |
||
143 | null, |
||
144 | false |
||
145 | ); |
||
146 | |||
147 | $this->addOption( |
||
148 | '-e|--message-not-found', |
||
149 | 'The entity not found error message', |
||
150 | 'This record doesn\'t exist', |
||
151 | false |
||
152 | ); |
||
153 | |||
154 | $this->addOption( |
||
155 | '-l|--message-duplicate', |
||
156 | 'The entity duplicate error message', |
||
157 | 'This record already exist', |
||
158 | false |
||
159 | ); |
||
160 | |||
161 | $this->addOption( |
||
162 | '-a|--message-create', |
||
163 | 'The entity successfully create message', |
||
164 | 'Data successfully created', |
||
165 | false |
||
166 | ); |
||
167 | |||
168 | $this->addOption( |
||
169 | '-u|--message-update', |
||
170 | 'The entity successfully update message', |
||
171 | 'Data successfully updated', |
||
172 | false |
||
173 | ); |
||
174 | |||
175 | $this->addOption( |
||
176 | '-d|--message-delete', |
||
177 | 'The entity successfully delete message', |
||
178 | 'Data successfully deleted', |
||
179 | false |
||
180 | ); |
||
181 | |||
182 | $this->addOption( |
||
183 | '-p|--message-process-error', |
||
184 | 'The entity processing error message', |
||
185 | 'Data processing error', |
||
186 | false |
||
187 | ); |
||
188 | |||
189 | $this->addOption( |
||
190 | '-j|--config', |
||
191 | 'Use JSON config file for options', |
||
192 | null, |
||
193 | false |
||
194 | ); |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * {@inheritdoc} |
||
199 | */ |
||
200 | public function interact(Reader $reader, Writer $writer): void |
||
201 | { |
||
202 | parent::interact($reader, $writer); |
||
203 | |||
204 | // Load configuration file if exist |
||
205 | $this->loadConfig(); |
||
206 | |||
207 | $baseClasses = $this->getBaseClasses(); |
||
208 | |||
209 | foreach ($baseClasses as $value) { |
||
210 | $this->addProperty($value); |
||
211 | } |
||
212 | |||
213 | $this->recordResourceClasses(); |
||
214 | |||
215 | $this->recordProperties(); |
||
216 | |||
217 | $this->addProperty($this->repositoryClass); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * {@inheritdoc} |
||
222 | */ |
||
223 | public function getClassTemplate(): string |
||
224 | { |
||
225 | return <<<EOF |
||
226 | <?php |
||
227 | |||
228 | declare(strict_types=1); |
||
229 | |||
230 | namespace %namespace%; |
||
231 | |||
232 | use Exception; |
||
233 | use Platine\Http\ResponseInterface; |
||
234 | use Platine\Http\ServerRequestInterface; |
||
235 | use Platine\Framework\Http\RequestData; |
||
236 | use Platine\Framework\Http\Response\TemplateResponse; |
||
237 | use Platine\Framework\Http\Response\RedirectResponse; |
||
238 | %uses% |
||
239 | |||
240 | /** |
||
241 | * @class %classname% |
||
242 | * @package %namespace% |
||
243 | */ |
||
244 | class %classname% |
||
245 | { |
||
246 | |||
247 | %properties% |
||
248 | |||
249 | %constructor% |
||
250 | |||
251 | /** |
||
252 | * List all entities |
||
253 | * @param ServerRequestInterface \$request |
||
254 | * @return ResponseInterface |
||
255 | */ |
||
256 | public function index(ServerRequestInterface \$request): ResponseInterface |
||
257 | { |
||
258 | %method_body_index% |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * List entity detail |
||
263 | * @param ServerRequestInterface \$request |
||
264 | * @return ResponseInterface |
||
265 | */ |
||
266 | public function detail(ServerRequestInterface \$request): ResponseInterface |
||
267 | { |
||
268 | %method_body_detail% |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * Create new entity |
||
273 | * @param ServerRequestInterface \$request |
||
274 | * @return ResponseInterface |
||
275 | */ |
||
276 | public function create(ServerRequestInterface \$request): ResponseInterface |
||
277 | { |
||
278 | %method_body_create% |
||
279 | } |
||
280 | |||
281 | /** |
||
282 | * Update existing entity |
||
283 | * @param ServerRequestInterface \$request |
||
284 | * @return ResponseInterface |
||
285 | */ |
||
286 | public function update(ServerRequestInterface \$request): ResponseInterface |
||
287 | { |
||
288 | %method_body_update% |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * Delete the entity |
||
293 | * @param ServerRequestInterface \$request |
||
294 | * @return ResponseInterface |
||
295 | */ |
||
296 | public function delete(ServerRequestInterface \$request): ResponseInterface |
||
297 | { |
||
298 | %method_body_delete% |
||
299 | } |
||
300 | } |
||
301 | |||
302 | EOF; |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * Record class properties |
||
307 | * @return void |
||
308 | */ |
||
309 | protected function recordProperties(): void |
||
310 | { |
||
311 | $io = $this->io(); |
||
312 | |||
313 | $writer = $io->writer(); |
||
314 | |||
315 | $writer->boldYellow('Enter the properties list (empty value to finish):', true); |
||
316 | $value = ''; |
||
317 | while ($value !== null) { |
||
318 | $value = $io->prompt('Property full class name', null, null, false); |
||
319 | |||
320 | if (!empty($value)) { |
||
321 | $value = trim($value); |
||
322 | if (!class_exists($value) && !interface_exists($value)) { |
||
323 | $writer->boldWhiteBgRed(sprintf('The class [%s] does not exists', $value), true); |
||
324 | } else { |
||
325 | $shortClass = $this->getClassBaseName($value); |
||
326 | $name = Str::camel($shortClass, true); |
||
327 | //replace"interface", "abstract" |
||
328 | $nameClean = str_ireplace(['interface', 'abstract'], '', $name); |
||
329 | |||
330 | $this->properties[$value] = [ |
||
331 | 'name' => $nameClean, |
||
332 | 'short' => $shortClass, |
||
333 | ]; |
||
334 | } |
||
335 | } |
||
336 | } |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Record the resource classes |
||
341 | * @return void |
||
342 | */ |
||
343 | protected function recordResourceClasses(): void |
||
344 | { |
||
345 | $io = $this->io(); |
||
346 | |||
347 | $paramClass = $io->prompt('Enter the form parameter full class name', null); |
||
348 | while (!class_exists($paramClass)) { |
||
349 | $paramClass = $io->prompt('Class does not exists, please enter the form parameter full class name', null); |
||
350 | } |
||
351 | |||
352 | $this->paramClass = $paramClass; |
||
353 | |||
354 | $validatorClass = $io->prompt('Enter the form validator full class name', null); |
||
355 | while (!class_exists($validatorClass)) { |
||
356 | $validatorClass = $io->prompt( |
||
357 | 'Class does not exists, please enter the form validator full class name', |
||
358 | null |
||
359 | ); |
||
360 | } |
||
361 | |||
362 | $this->validatorClass = $validatorClass; |
||
363 | |||
364 | $entityClass = $io->prompt('Enter the entity full class name', null); |
||
365 | while (!class_exists($entityClass)) { |
||
366 | $entityClass = $io->prompt('Class does not exists, please enter the entity full class name', null); |
||
367 | } |
||
368 | |||
369 | $this->entityClass = $entityClass; |
||
370 | |||
371 | $repositoryClass = $io->prompt('Enter the repository full class name', null); |
||
372 | while (!class_exists($repositoryClass)) { |
||
373 | $repositoryClass = $io->prompt('Class does not exists, please enter the repository full class name', null); |
||
374 | } |
||
375 | |||
376 | $this->repositoryClass = $repositoryClass; |
||
377 | } |
||
378 | |||
379 | /** |
||
380 | * {@inheritdoc} |
||
381 | */ |
||
382 | protected function createClass(): string |
||
383 | { |
||
384 | $content = parent::createClass(); |
||
385 | |||
386 | |||
387 | $contentIndex = $this->getIndexMethodBody($content); |
||
388 | $contentDetail = $this->getDetailMethodBody($contentIndex); |
||
389 | $contentCreate = $this->getCreateMethodBody($contentDetail); |
||
390 | $contentUpdate = $this->getUpdateMethodBody($contentCreate); |
||
391 | $contentDelete = $this->getDeleteMethodBody($contentUpdate); |
||
392 | |||
393 | return $contentDelete; |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * Return the index method body |
||
398 | * @param string $content |
||
399 | * @return string |
||
400 | */ |
||
401 | protected function getIndexMethodBody(string $content): string |
||
402 | { |
||
403 | $repositoryName = $this->getPropertyName($this->repositoryClass); |
||
404 | $templatePrefix = $this->getTemplatePrefix(); |
||
405 | |||
406 | $orderByTemplate = $this->getOrderByTemplate(); |
||
407 | |||
408 | $result = <<<EOF |
||
409 | \$context = []; |
||
410 | \$param = new RequestData(\$request); |
||
411 | \$totalItems = \$this->{$repositoryName}->query() |
||
412 | ->count('id'); |
||
413 | |||
414 | \$currentPage = (int) \$param->get('page', 1); |
||
415 | |||
416 | \$this->pagination->setTotalItems(\$totalItems) |
||
417 | ->setCurrentPage(\$currentPage); |
||
418 | |||
419 | \$limit = \$this->pagination->getItemsPerPage(); |
||
420 | \$offset = \$this->pagination->getOffset(); |
||
421 | |||
422 | \$results = \$this->{$repositoryName}->query() |
||
423 | ->offset(\$offset) |
||
424 | ->limit(\$limit) |
||
425 | $orderByTemplate |
||
426 | ->all(); |
||
427 | |||
428 | \$context['list'] = \$results; |
||
429 | \$context['pagination'] = \$this->pagination->render(); |
||
430 | |||
431 | |||
432 | return new TemplateResponse( |
||
433 | \$this->template, |
||
434 | '$templatePrefix/list', |
||
435 | \$context |
||
436 | ); |
||
437 | EOF; |
||
438 | |||
439 | return str_replace('%method_body_index%', $result, $content); |
||
440 | } |
||
441 | |||
442 | /** |
||
443 | * Return the detail method body |
||
444 | * @param string $content |
||
445 | * @return string |
||
446 | */ |
||
447 | protected function getDetailMethodBody(string $content): string |
||
448 | { |
||
449 | $repositoryName = $this->getPropertyName($this->repositoryClass); |
||
450 | $entityBaseClass = $this->getClassBaseName($this->entityClass); |
||
451 | $templatePrefix = $this->getTemplatePrefix(); |
||
452 | $notFoundMessage = $this->getMessage('messageNotFound'); |
||
453 | |||
454 | $listRoute = $this->getRouteName('list'); |
||
455 | |||
456 | $result = <<<EOF |
||
457 | \$context = []; |
||
458 | \$id = (int) \$request->getAttribute('id'); |
||
459 | |||
460 | /** @var $entityBaseClass|null \$entity */ |
||
461 | \$entity = \$this->{$repositoryName}->find(\$id); |
||
462 | |||
463 | if (\$entity === null) { |
||
464 | \$this->flash->setError(\$this->lang->tr('$notFoundMessage')); |
||
465 | |||
466 | return new RedirectResponse( |
||
467 | \$this->routeHelper->generateUrl('$listRoute') |
||
468 | ); |
||
469 | } |
||
470 | \$context['entity'] = \$entity; |
||
471 | |||
472 | return new TemplateResponse( |
||
473 | \$this->template, |
||
474 | '$templatePrefix/detail', |
||
475 | \$context |
||
476 | ); |
||
477 | EOF; |
||
478 | |||
479 | |||
480 | return str_replace('%method_body_detail%', $result, $content); |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * Return the create method body |
||
485 | * @param string $content |
||
486 | * @return string |
||
487 | */ |
||
488 | protected function getCreateMethodBody(string $content): string |
||
489 | { |
||
490 | $repositoryName = $this->getPropertyName($this->repositoryClass); |
||
491 | $formParamBaseClass = $this->getClassBaseName($this->paramClass); |
||
492 | $validatorBaseClass = $this->getClassBaseName($this->validatorClass); |
||
493 | $entityBaseClass = $this->getClassBaseName($this->entityClass); |
||
494 | $templatePrefix = $this->getTemplatePrefix(); |
||
495 | $listRoute = $this->getRouteName('list'); |
||
496 | $createMessage = $this->getMessage('messageCreate'); |
||
497 | $processErrorMessage = $this->getMessage('messageProcessError'); |
||
498 | |||
499 | $uniqueCheckStr = $this->getUniqueFieldCheckTemplate(true); |
||
500 | $fieldTemplates = $this->getEntityFieldsTemplate(true); |
||
501 | |||
502 | $result = <<<EOF |
||
503 | \$context = []; |
||
504 | \$param = new RequestData(\$request); |
||
505 | |||
506 | \$formParam = new $formParamBaseClass(\$param->posts()); |
||
507 | \$context['param'] = \$formParam; |
||
508 | |||
509 | if (\$request->getMethod() === 'GET') { |
||
510 | return new TemplateResponse( |
||
511 | \$this->template, |
||
512 | '$templatePrefix/create', |
||
513 | \$context |
||
514 | ); |
||
515 | } |
||
516 | |||
517 | \$validator = new $validatorBaseClass(\$formParam, \$this->lang); |
||
518 | if (\$validator->validate() === false) { |
||
519 | \$context['errors'] = \$validator->getErrors(); |
||
520 | |||
521 | return new TemplateResponse( |
||
522 | \$this->template, |
||
523 | '$templatePrefix/create', |
||
524 | \$context |
||
525 | ); |
||
526 | } |
||
527 | |||
528 | $uniqueCheckStr |
||
529 | |||
530 | /** @var $entityBaseClass \$entity */ |
||
531 | \$entity = \$this->{$repositoryName}->create([ |
||
532 | $fieldTemplates |
||
533 | ]); |
||
534 | |||
535 | try { |
||
536 | \$this->{$repositoryName}->save(\$entity); |
||
537 | |||
538 | \$this->flash->setSuccess(\$this->lang->tr('$createMessage')); |
||
539 | |||
540 | return new RedirectResponse( |
||
541 | \$this->routeHelper->generateUrl('$listRoute') |
||
542 | ); |
||
543 | } catch (Exception \$ex) { |
||
544 | \$this->logger->error('Error when saved the data {error}', ['error' => \$ex->getMessage()]); |
||
545 | |||
546 | \$this->flash->setError(\$this->lang->tr('$processErrorMessage')); |
||
547 | |||
548 | return new TemplateResponse( |
||
549 | \$this->template, |
||
550 | '$templatePrefix/create', |
||
551 | \$context |
||
552 | ); |
||
553 | } |
||
554 | EOF; |
||
555 | |||
556 | |||
557 | return str_replace('%method_body_create%', $result, $content); |
||
558 | } |
||
559 | |||
560 | /** |
||
561 | * Return the update method body |
||
562 | * @param string $content |
||
563 | * @return string |
||
564 | */ |
||
565 | protected function getUpdateMethodBody(string $content): string |
||
566 | { |
||
567 | $repositoryName = $this->getPropertyName($this->repositoryClass); |
||
568 | $formParamBaseClass = $this->getClassBaseName($this->paramClass); |
||
569 | $validatorBaseClass = $this->getClassBaseName($this->validatorClass); |
||
570 | $entityBaseClass = $this->getClassBaseName($this->entityClass); |
||
571 | $templatePrefix = $this->getTemplatePrefix(); |
||
572 | $listRoute = $this->getRouteName('list'); |
||
573 | $notFoundMessage = $this->getMessage('messageNotFound'); |
||
574 | $updateMessage = $this->getMessage('messageUpdate'); |
||
575 | $processErrorMessage = $this->getMessage('messageProcessError'); |
||
576 | |||
577 | $uniqueCheckStr = $this->getUniqueFieldCheckTemplate(false); |
||
578 | $fieldTemplates = $this->getEntityFieldsTemplate(false); |
||
579 | |||
580 | $result = <<<EOF |
||
581 | \$context = []; |
||
582 | \$param = new RequestData(\$request); |
||
583 | |||
584 | \$id = (int) \$request->getAttribute('id'); |
||
585 | |||
586 | /** @var $entityBaseClass|null \$entity */ |
||
587 | \$entity = \$this->{$repositoryName}->find(\$id); |
||
588 | |||
589 | if (\$entity === null) { |
||
590 | \$this->flash->setError(\$this->lang->tr('$notFoundMessage')); |
||
591 | |||
592 | return new RedirectResponse( |
||
593 | \$this->routeHelper->generateUrl('$listRoute') |
||
594 | ); |
||
595 | } |
||
596 | \$context['entity'] = \$entity; |
||
597 | \$context['param'] = (new $formParamBaseClass())->fromEntity(\$entity); |
||
598 | if (\$request->getMethod() === 'GET') { |
||
599 | return new TemplateResponse( |
||
600 | \$this->template, |
||
601 | '$templatePrefix/update', |
||
602 | \$context |
||
603 | ); |
||
604 | } |
||
605 | \$formParam = new $formParamBaseClass(\$param->posts()); |
||
606 | \$context['param'] = \$formParam; |
||
607 | |||
608 | \$validator = new $validatorBaseClass(\$formParam, \$this->lang); |
||
609 | if (\$validator->validate() === false) { |
||
610 | \$context['errors'] = \$validator->getErrors(); |
||
611 | |||
612 | return new TemplateResponse( |
||
613 | \$this->template, |
||
614 | '$templatePrefix/update', |
||
615 | \$context |
||
616 | ); |
||
617 | } |
||
618 | |||
619 | $uniqueCheckStr |
||
620 | |||
621 | $fieldTemplates |
||
622 | |||
623 | try { |
||
624 | \$this->{$repositoryName}->save(\$entity); |
||
625 | |||
626 | \$this->flash->setSuccess(\$this->lang->tr('$updateMessage')); |
||
627 | |||
628 | return new RedirectResponse( |
||
629 | \$this->routeHelper->generateUrl('$listRoute') |
||
630 | ); |
||
631 | } catch (Exception \$ex) { |
||
632 | \$this->logger->error('Error when saved the data {error}', ['error' => \$ex->getMessage()]); |
||
633 | |||
634 | \$this->flash->setError(\$this->lang->tr('$processErrorMessage')); |
||
635 | |||
636 | return new TemplateResponse( |
||
637 | \$this->template, |
||
638 | '$templatePrefix/update', |
||
639 | \$context |
||
640 | ); |
||
641 | } |
||
642 | EOF; |
||
643 | |||
644 | |||
645 | return str_replace('%method_body_update%', $result, $content); |
||
646 | } |
||
647 | |||
648 | /** |
||
649 | * Return the delete method body |
||
650 | * @param string $content |
||
651 | * @return string |
||
652 | */ |
||
653 | protected function getDeleteMethodBody(string $content): string |
||
654 | { |
||
655 | $repositoryName = $this->getPropertyName($this->repositoryClass); |
||
656 | $entityBaseClass = $this->getClassBaseName($this->entityClass); |
||
657 | $notFoundMessage = $this->getMessage('messageNotFound'); |
||
658 | $deleteMessage = $this->getMessage('messageDelete'); |
||
659 | $processErrorMessage = $this->getMessage('messageProcessError'); |
||
660 | |||
661 | $listRoute = $this->getRouteName('list'); |
||
662 | |||
663 | $result = <<<EOF |
||
664 | \$id = (int) \$request->getAttribute('id'); |
||
665 | |||
666 | /** @var $entityBaseClass|null \$entity */ |
||
667 | \$entity = \$this->{$repositoryName}->find(\$id); |
||
668 | |||
669 | if (\$entity === null) { |
||
670 | \$this->flash->setError(\$this->lang->tr('$notFoundMessage')); |
||
671 | |||
672 | return new RedirectResponse( |
||
673 | \$this->routeHelper->generateUrl('$listRoute') |
||
674 | ); |
||
675 | } |
||
676 | |||
677 | try { |
||
678 | \$this->{$repositoryName}->delete(\$entity); |
||
679 | |||
680 | \$this->flash->setSuccess(\$this->lang->tr('$deleteMessage')); |
||
681 | |||
682 | return new RedirectResponse( |
||
683 | \$this->routeHelper->generateUrl('$listRoute') |
||
684 | ); |
||
685 | } catch (Exception \$ex) { |
||
686 | \$this->logger->error('Error when delete the data {error}', ['error' => \$ex->getMessage()]); |
||
687 | |||
688 | \$this->flash->setError(\$this->lang->tr('$processErrorMessage')); |
||
689 | |||
690 | return new RedirectResponse( |
||
691 | \$this->routeHelper->generateUrl('$listRoute') |
||
692 | ); |
||
693 | } |
||
694 | EOF; |
||
695 | |||
696 | |||
697 | return str_replace('%method_body_delete%', $result, $content); |
||
698 | } |
||
699 | |||
700 | /** |
||
701 | * Return the template for unique field check |
||
702 | * @param bool $create |
||
703 | * @return string |
||
704 | */ |
||
705 | protected function getUniqueFieldCheckTemplate(bool $create = true): string |
||
706 | { |
||
707 | $repositoryName = $this->getPropertyName($this->repositoryClass); |
||
708 | $templatePrefix = $this->getTemplatePrefix(); |
||
709 | $uniqueFields = $this->getOptionValue('fieldsUnique'); |
||
710 | $uniqueCheckStr = ''; |
||
711 | if ($uniqueFields !== null) { |
||
712 | $duplicateMessage = $this->getMessage('messageDuplicate'); |
||
713 | |||
714 | $fields = (array) explode(',', $uniqueFields); |
||
715 | $i = 1; |
||
716 | $result = ''; |
||
717 | foreach ($fields as $field) { |
||
718 | $column = $field; |
||
719 | $param = $field; |
||
720 | $uniqueField = (array) explode(':', $field); |
||
721 | if (isset($uniqueField[0])) { |
||
722 | $column = $uniqueField[0]; |
||
723 | } |
||
724 | |||
725 | if (isset($uniqueField[1])) { |
||
726 | $param = $uniqueField[1]; |
||
727 | } |
||
728 | |||
729 | $result .= ($i > 1 ? "\t\t\t\t\t " : '') . |
||
730 | $this->getFormParamEntityFieldTemplate($column, $param, count($fields) > $i, $create); |
||
731 | $i++; |
||
732 | } |
||
733 | |||
734 | $updateStr = $create ? '' : ' && $entityExist->id !== $id'; |
||
735 | $templateName = $create ? 'create' : 'update'; |
||
736 | |||
737 | $uniqueCheckStr = <<<EOF |
||
738 | \$entityExist = \$this->{$repositoryName}->findBy([ |
||
739 | $result |
||
740 | ]); |
||
741 | |||
742 | if(\$entityExist !== null$updateStr){ |
||
743 | \$this->flash->setError(\$this->lang->tr('$duplicateMessage')); |
||
744 | |||
745 | return new TemplateResponse( |
||
746 | \$this->template, |
||
747 | '$templatePrefix/$templateName', |
||
748 | \$context |
||
749 | ); |
||
750 | } |
||
751 | EOF; |
||
752 | } |
||
753 | |||
754 | return $uniqueCheckStr; |
||
755 | } |
||
756 | |||
757 | /** |
||
758 | * Return the template for order by |
||
759 | * @return string |
||
760 | */ |
||
761 | protected function getOrderByTemplate(): string |
||
762 | { |
||
763 | $result = ''; |
||
764 | $orderFields = $this->getOptionValue('fieldsOrder'); |
||
765 | |||
766 | if ($orderFields !== null) { |
||
767 | $fields = (array) explode(',', $orderFields); |
||
768 | $i = 1; |
||
769 | foreach ($fields as $field) { |
||
770 | $column = $field; |
||
771 | $dir = 'ASC'; |
||
772 | $orderField = (array) explode(':', $field); |
||
773 | if (isset($orderField[0])) { |
||
774 | $column = $orderField[0]; |
||
775 | } |
||
776 | |||
777 | if (isset($orderField[1]) && in_array(strtolower($orderField[1]), ['asc', 'desc'])) { |
||
778 | $dir = $orderField[1]; |
||
779 | } |
||
780 | |||
781 | $result .= ($i > 1 ? "\t\t\t\t\t " : '') . |
||
782 | sprintf('->orderBy(\'%s\', \'%s\')', $column, Str::upper($dir)) . |
||
783 | (count($fields) > $i ? PHP_EOL : ''); |
||
784 | $i++; |
||
785 | } |
||
786 | } |
||
787 | |||
788 | return $result; |
||
789 | } |
||
790 | |||
791 | /** |
||
792 | * Return the template for entity field for saving |
||
793 | * @param bool $create |
||
794 | * @return string |
||
795 | */ |
||
796 | protected function getEntityFieldsTemplate(bool $create = true): string |
||
797 | { |
||
798 | $fields = $this->getOptionValue('fields'); |
||
799 | $result = ''; |
||
800 | if ($fields !== null) { |
||
801 | $fields = (array) explode(',', $fields); |
||
802 | $i = 1; |
||
803 | |||
804 | foreach ($fields as $field) { |
||
805 | $column = $field; |
||
806 | $param = $field; |
||
807 | $entityField = (array) explode(':', $field); |
||
808 | if (isset($entityField[0])) { |
||
809 | $column = $entityField[0]; |
||
810 | } |
||
811 | |||
812 | if (isset($entityField[1])) { |
||
813 | $param = $entityField[1]; |
||
814 | } |
||
815 | |||
816 | $result .= ($i > 1 ? "\t " : '') . |
||
817 | $this->getEntityRecordFieldTemplate($column, $param, count($fields) > $i, $create); |
||
818 | $i++; |
||
819 | } |
||
820 | } |
||
821 | |||
822 | return $result; |
||
823 | } |
||
824 | |||
825 | /** |
||
826 | * {@inheritdoc} |
||
827 | */ |
||
828 | protected function getUsesContent(): string |
||
829 | { |
||
830 | $uses = parent::getUsesContent(); |
||
831 | |||
832 | $uses .= $this->getUsesTemplate($this->entityClass); |
||
833 | $uses .= $this->getUsesTemplate($this->paramClass); |
||
834 | $uses .= $this->getUsesTemplate($this->validatorClass); |
||
835 | |||
836 | return <<<EOF |
||
837 | $uses |
||
838 | EOF; |
||
839 | } |
||
840 | |||
841 | /** |
||
842 | * Add new property |
||
843 | * @param class-string $value |
||
844 | * @return $this |
||
845 | */ |
||
846 | protected function addProperty(string $value): self |
||
847 | { |
||
848 | $shortClass = $this->getClassBaseName($value); |
||
849 | $name = Str::camel($shortClass, true); |
||
850 | //replace"interface", "abstract" |
||
851 | $nameClean = str_ireplace(['interface', 'abstract'], '', $name); |
||
852 | |||
853 | $this->properties[$value] = [ |
||
854 | 'name' => $nameClean, |
||
855 | 'short' => $shortClass, |
||
856 | ]; |
||
857 | |||
858 | return $this; |
||
859 | } |
||
860 | |||
861 | /** |
||
862 | * Return the property name |
||
863 | * @param class-string $value |
||
864 | * @return string |
||
865 | */ |
||
866 | protected function getPropertyName(string $value): string |
||
867 | { |
||
868 | if (!isset($this->properties[$value])) { |
||
869 | return ''; |
||
870 | } |
||
871 | |||
872 | return $this->properties[$value]['name']; |
||
873 | } |
||
874 | |||
875 | |||
876 | /** |
||
877 | * Return the route prefix |
||
878 | * @return string |
||
879 | */ |
||
880 | protected function getTemplatePrefix(): string |
||
881 | { |
||
882 | $templatePrefix = $this->getOptionValue('templatePrefix'); |
||
883 | if ($templatePrefix === null) { |
||
884 | $actionName = $this->getShortClassName($this->className); |
||
885 | $templatePrefix = Str::snake(str_ireplace('action', '', $actionName)); |
||
886 | } |
||
887 | |||
888 | return $templatePrefix; |
||
889 | } |
||
890 | |||
891 | /** |
||
892 | * Return the route prefix |
||
893 | * @return string |
||
894 | */ |
||
895 | protected function getRoutePrefix(): string |
||
896 | { |
||
897 | $routePrefix = $this->getOptionValue('routePrefix'); |
||
898 | if ($routePrefix === null) { |
||
899 | $actionName = $this->getShortClassName($this->className); |
||
900 | $routePrefix = Str::snake(str_ireplace('action', '', $actionName)); |
||
901 | } |
||
902 | |||
903 | return $routePrefix; |
||
904 | } |
||
905 | |||
906 | /** |
||
907 | * Return the route name |
||
908 | * @param string $value |
||
909 | * @return string |
||
910 | */ |
||
911 | protected function getRouteName(string $value): string |
||
912 | { |
||
913 | $routePrefix = $this->getRoutePrefix(); |
||
914 | return sprintf('%s_%s', $routePrefix, $value); |
||
915 | } |
||
916 | |||
917 | /** |
||
918 | * Return the form parameter method name of the given name |
||
919 | * @param string $field |
||
920 | * @return string |
||
921 | */ |
||
922 | protected function getFormParamMethodName(string $field): string |
||
923 | { |
||
924 | return sprintf('get%s', Str::camel($field, false)); |
||
925 | } |
||
926 | |||
927 | /** |
||
928 | * Return the base classes |
||
929 | * @return array<class-string> |
||
930 | */ |
||
931 | protected function getBaseClasses(): array |
||
932 | { |
||
933 | return [ |
||
934 | Lang::class, |
||
935 | Pagination::class, |
||
936 | Template::class, |
||
937 | Flash::class, |
||
938 | RouteHelper::class, |
||
939 | LoggerInterface::class, |
||
940 | ]; |
||
941 | } |
||
942 | |||
943 | /** |
||
944 | * Return the message |
||
945 | * @param string $option |
||
946 | * @return string|null |
||
947 | */ |
||
948 | protected function getMessage(string $option): ?string |
||
949 | { |
||
950 | $message = $this->getOptionValue($option); |
||
951 | if (!empty($message)) { |
||
952 | $message = addslashes($message); |
||
953 | } |
||
954 | |||
955 | return $message; |
||
956 | } |
||
957 | |||
958 | /** |
||
959 | * Return the template for entity record fields |
||
960 | * @param string $field |
||
961 | * @param string $param |
||
962 | * @param bool $isLast |
||
963 | * @param bool $create |
||
964 | * @return string |
||
965 | */ |
||
966 | protected function getEntityRecordFieldTemplate( |
||
967 | string $field, |
||
968 | string $param, |
||
969 | bool $isLast = false, |
||
970 | $create = true |
||
971 | ): string { |
||
972 | $fieldMethodName = $this->getFormParamMethodName($param); |
||
973 | if ($create) { |
||
974 | return sprintf('\'%s\' => $formParam->%s(),', $field, $fieldMethodName) . ($isLast ? PHP_EOL : ''); |
||
975 | } |
||
976 | |||
977 | return sprintf('$entity->%s = $formParam->%s();', $field, $fieldMethodName) . ($isLast ? PHP_EOL : ''); |
||
978 | } |
||
979 | |||
980 | /** |
||
981 | * Return the template for form parameter entity field |
||
982 | * @param string $field |
||
983 | * @param string $param |
||
984 | * @param bool $isLast |
||
985 | * @param bool $isArray |
||
986 | * @return string |
||
987 | */ |
||
988 | protected function getFormParamEntityFieldTemplate( |
||
989 | string $field, |
||
990 | string $param, |
||
991 | bool $isLast = false |
||
992 | ): string { |
||
993 | $fieldMethodName = $this->getFormParamMethodName($param); |
||
994 | return sprintf('\'%s\' => $formParam->%s(),', $field, $fieldMethodName) . ($isLast ? PHP_EOL : ''); |
||
995 | } |
||
996 | |||
997 | /** |
||
998 | * Load JSON configuration file if exist |
||
999 | * @return void |
||
1000 | */ |
||
1001 | protected function loadConfig(): void |
||
1002 | { |
||
1003 | $filename = $this->getOptionValue('config'); |
||
1004 | if (!empty($filename)) { |
||
1005 | $file = $this->filesystem->file($filename); |
||
1006 | if ($file->exists() && $file->isReadable()) { |
||
1007 | $content = $file->read(); |
||
1008 | $config = Json::decode($content, true); |
||
1009 | foreach ($config as $option => $value) { |
||
1010 | $optionKey = Str::camel($option, true); |
||
1011 | $this->values[$optionKey] = $value; |
||
1012 | } |
||
1017 |