Passed
Push — main ( 906a0a...e59521 )
by Iain
04:27
created

GenerateEntitySectionCommand::getCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright Iain Cambridge 2020-2023.
7
 *
8
 * Use of this software is governed by the Business Source License included in the LICENSE file and at https://getparthenon.com/docs/next/license.
9
 *
10
 * Change Date: TBD ( 3 years after 2.2.0 release )
11
 *
12
 * On the date above, in accordance with the Business Source License, use of this software will be governed by the open source license specified in the LICENSE file.
13
 */
14
15
namespace Parthenon\Athena\Command;
16
17
use Parthenon\Common\LoggerAwareTrait;
18
use Symfony\Component\Console\Attribute\AsCommand;
19
use Symfony\Component\Console\Command\Command;
20
use Symfony\Component\Console\Input\InputArgument;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Output\OutputInterface;
23
use Symfony\Component\Console\Question\Question;
24
use Symfony\Component\Filesystem\Filesystem;
25
26
#[AsCommand(name: 'parthenon:athena:generate-entity-section', aliases: ['p:a:ges'])]
27
class GenerateEntitySectionCommand extends Command
28
{
29
    use LoggerAwareTrait;
30
31
    public function __construct(private string $projectRoot)
32
    {
33
        parent::__construct(null);
34
    }
35
36
    protected function configure()
37
    {
38
        $this
39
            ->addArgument('entity', InputArgument::REQUIRED, 'The name of the entity to be created')
40
            ->addArgument('config_type', InputArgument::REQUIRED, 'What type of doctrine configuration type that should be used. Annotations or Attributes');
41
    }
42
43
    protected function interact(InputInterface $input, OutputInterface $output)
44
    {
45
        if (!$input->getArgument('entity')) {
46
            $entityQuestion = new Question('Please provide the name of the entity: ');
47
            $entityQuestion->setValidator(function ($entity) {
48
                if (empty($entity)) {
49
                    throw new \Exception('Email can not be empty');
50
                }
51
52
                if (!preg_match('~^[A-Za-z_]+$~isu', $entity)) {
53
                    throw new \Exception('Entity can only be letters and an underscore');
54
                }
55
56
                return $entity;
57
            });
58
59
            $email = $this->getHelper('question')->ask($input, $output, $entityQuestion);
60
61
            $input->setArgument('entity', $email);
62
        }
63
64
        if (!$input->getArgument('config_type')) {
65
            $configTypeQuestion = new Question('Which type of config: [annotations] ', 'annotations');
66
            $configTypeQuestion->setValidator(function ($configType) {
67
                if (empty($configType)) {
68
                    throw new \Exception('Config type can not be empty');
69
                }
70
71
                $configType = strtolower($configType);
72
73
                if (!in_array($configType, ['annotations', 'attributes'])) {
74
                    throw new \Exception('Config type must be either "annotations" or "attributes"');
75
                }
76
77
                return $configType;
78
            });
79
80
            $role = $this->getHelper('question')->ask($input, $output, $configTypeQuestion);
81
            $input->setArgument('config_type', $role);
82
        }
83
    }
84
85
    protected function execute(InputInterface $input, OutputInterface $output)
86
    {
87
        $entityName = $input->getArgument('entity');
88
        $configType = $input->getArgument('config_type');
89
90
        $camelCaseToSnakeCase = function ($input) {
91
            if (0 === preg_match('/[A-Z]/', $input)) {
92
                return $input;
93
            }
94
            $pattern = '/([a-z])([A-Z])/';
95
96
            return strtolower(preg_replace_callback($pattern, function ($a) {
97
                return $a[1].'_'.strtolower($a[2]);
98
            }, $input));
99
        };
100
101
        $tableName = $camelCaseToSnakeCase($entityName);
102
103
        if ('annotations' === $configType) {
104
            $entityCode = $this->getCode('EntityAnnotations.php', $entityName, $tableName);
105
        } else {
106
            $entityCode = $this->getCode('EntityAttributes.php', $entityName, $tableName);
107
        }
108
        $fileSystem = new Filesystem();
109
110
        $fileSystem->mkdir([
111
            $this->projectRoot.'/src/Entity/',
112
            $this->projectRoot.'/src/Repository/',
113
            $this->projectRoot.'/src/Athena/',
114
        ]);
115
116
        $fileSystem->dumpFile($this->projectRoot.'/src/Entity/'.$entityName.'.php', $entityCode);
117
        $fileSystem->dumpFile($this->projectRoot.'/src/Repository/'.$entityName.'Repository.php', $this->getCode('Repository.php', $entityName, $tableName));
118
        $fileSystem->dumpFile($this->projectRoot.'/src/Repository/'.$entityName.'RepositoryInterface.php', $this->getCode('RepositoryInterface.php', $entityName, $tableName));
119
        $fileSystem->dumpFile($this->projectRoot.'/src/Repository/'.$entityName.'ServiceRepository.php', $this->getCode('ServiceRepository.php', $entityName, $tableName));
120
        $fileSystem->dumpFile($this->projectRoot.'/src/Athena/'.$entityName.'Section.php', $this->getCode('AthenaSection.php', $entityName, $tableName));
121
122
        $services = $this->getCode('Services.yaml', $entityName, $tableName);
123
        $fileSystem->appendToFile($this->projectRoot.'/config/services.yaml', $services);
124
125
        return 0;
126
    }
127
128
    protected function getCode(string $file, string $className, string $tableName): string
129
    {
130
        $content = file_get_contents(dirname(__DIR__).'/Templates/'.$file.'.txt');
131
        $content = str_replace('{{className}}', $className, $content);
132
        $content = str_replace('{{tableName}}', $tableName, $content);
133
        $content = str_replace('{{urlTag}}', $tableName, $content);
134
135
        return $content;
136
    }
137
}
138