AbstractMakerCommand   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 68
c 1
b 0
f 0
dl 0
loc 111
ccs 0
cts 58
cp 0
rs 10
wmc 11

5 Methods

Rating   Name   Duplication   Size   Complexity  
A assertValidConstants() 0 10 5
A configure() 0 9 1
A __construct() 0 14 1
A getFQCN() 0 13 2
A execute() 0 35 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Antidot\DevTools\Application\Command;
6
7
use Antidot\DevTools\Application\Service\CreateClassFile;
8
use Antidot\DevTools\Application\Service\GetClassNameFromFQCN;
9
use Antidot\DevTools\Application\Service\GetNamespaceFromFQCN;
10
use Antidot\DevTools\Application\Service\GetRealPathFromNamespace;
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Input\InputArgument;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Question\Question;
16
use Throwable;
17
18
use function sprintf;
19
20
abstract class AbstractMakerCommand extends Command
21
{
22
    public const NAME = '';
23
    protected const COMMAND_DESCRIPTION = '';
24
    protected const FQCN_ARGUMENT_DESCRIPTION = '';
25
    protected const TEMPLATE = '';
26
    protected const SUCCESS_HELP_TEMPLATE = '';
27
    protected const QUESTION = '<fg=blue>Please enter the name of the class <info>[App\My\Class]</info>: </> ';
28
    protected const DEFAULT_RESPONSE = 'App\My\NewClass';
29
    protected const SUCCESS_MESSAGE = '<info>Class %s successfully created in file %s</info>';
30
    protected GetClassNameFromFQCN $getClassNameFromFQCN;
31
    protected GetNamespaceFromFQCN $getNamespaceFromFQCN;
32
    protected GetRealPathFromNamespace $getRealPathFromNamespace;
33
    protected CreateClassFile $createClassFile;
34
    /** @var array<mixed>  */
35
    protected array $config;
36
37
    /**
38
     * @param array<mixed> $config
39
     */
40
    public function __construct(
41
        GetClassNameFromFQCN $getClassNameFromFQCN,
42
        GetNamespaceFromFQCN $getNamespaceFromFQCN,
43
        GetRealPathFromNamespace $getRealPathFromNamespace,
44
        CreateClassFile $createClassFile,
45
        array $config
46
    ) {
47
        $this->assertValidConstants();
48
        $this->getClassNameFromFQCN = $getClassNameFromFQCN;
49
        $this->getNamespaceFromFQCN = $getNamespaceFromFQCN;
50
        $this->getRealPathFromNamespace = $getRealPathFromNamespace;
51
        $this->createClassFile = $createClassFile;
52
        $this->config = $config;
53
        parent::__construct();
54
    }
55
56
    protected function configure(): void
57
    {
58
        $this
59
            ->setName(static::NAME)
60
            ->setDescription(static::COMMAND_DESCRIPTION)
61
            ->addArgument(
62
                'fqcn',
63
                InputArgument::OPTIONAL,
64
                static::FQCN_ARGUMENT_DESCRIPTION
65
            );
66
    }
67
68
69
    protected function execute(InputInterface $input, OutputInterface $output): ?int
70
    {
71
        /** @var string $fqcn */
72
        $fqcn = $this->getFQCN($input, $output);
73
        $getClassNameFromFQCN = $this->getClassNameFromFQCN;
74
        $getNamespaceFromFQCN = $this->getNamespaceFromFQCN;
75
        $getRealPathFromNamespace = $this->getRealPathFromNamespace;
76
        $createClassFile = $this->createClassFile;
77
        try {
78
            $className = $getClassNameFromFQCN($fqcn);
79
            $namespace = $getNamespaceFromFQCN($fqcn);
80
            $classDir = $getRealPathFromNamespace($namespace);
81
            $realFilePath = $createClassFile(
82
                $classDir,
83
                $className,
84
                sprintf(static::TEMPLATE, $namespace, $className)
85
            );
86
        } catch (Throwable $exception) {
87
            $output->writeln(sprintf('<error>%s</error>', $exception->getMessage()));
88
            return 1;
89
        }
90
91
        $output->writeln(sprintf(
92
            static::SUCCESS_MESSAGE,
93
            $className,
94
            $realFilePath
95
        ));
96
        $output->writeln(sprintf(
97
            static::SUCCESS_HELP_TEMPLATE,
98
            $this->config['config_dir'],
99
            $fqcn,
100
            $className
101
        ));
102
103
        return 0;
104
    }
105
106
    protected function getFQCN(InputInterface $input, OutputInterface $output): string
107
    {
108
        $fqcn = $input->getArgument('fqcn');
109
        if (null === $fqcn) {
110
            $questionHelper = $this->getHelper('question');
111
            $question = new Question(
112
                static::QUESTION,
113
                static::DEFAULT_RESPONSE
114
            );
115
            $fqcn = $questionHelper->ask($input, $output, $question);
116
        }
117
118
        return $fqcn;
119
    }
120
121
    private function assertValidConstants(): void
122
    {
123
        if (empty(static::TEMPLATE)
0 ignored issues
show
introduced by
The condition empty(static::TEMPLATE) is always true.
Loading history...
124
            || empty(static::SUCCESS_HELP_TEMPLATE)
125
            || empty(static::FQCN_ARGUMENT_DESCRIPTION)
126
            || empty(static::NAME)
127
        ) {
128
            throw new \RuntimeException(
129
                'Constant TEMPLATE, SUCCESS_HELP_TEMPLATE, FQCN_ARGUMENT_DESCRIPTION and NAME'
130
                . ' must have to be defined in your maker command class.'
131
            );
132
        }
133
    }
134
}
135