Passed
Push — master ( ee13c0...fd5ab9 )
by Koldo
02:31
created

AbstractMakerCommand   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 112
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 68
dl 0
loc 112
ccs 0
cts 82
cp 0
rs 10
c 0
b 0
f 0
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
    /** @var GetClassNameFromFQCN */
31
    protected $getClassNameFromFQCN;
32
    /** @var GetNamespaceFromFQCN */
33
    protected $getNamespaceFromFQCN;
34
    /** @var GetRealPathFromNamespace */
35
    protected $getRealPathFromNamespace;
36
    /** @var CreateClassFile */
37
    protected $createClassFile;
38
    /** @var array */
39
    protected $config;
40
41
    public function __construct(
42
        GetClassNameFromFQCN $getClassNameFromFQCN,
43
        GetNamespaceFromFQCN $getNamespaceFromFQCN,
44
        GetRealPathFromNamespace $getRealPathFromNamespace,
45
        CreateClassFile $createClassFile,
46
        array $config
47
    ) {
48
        $this->assertValidConstants();
49
        $this->getClassNameFromFQCN = $getClassNameFromFQCN;
50
        $this->getNamespaceFromFQCN = $getNamespaceFromFQCN;
51
        $this->getRealPathFromNamespace = $getRealPathFromNamespace;
52
        $this->createClassFile = $createClassFile;
53
        $this->config = $config;
54
        parent::__construct();
55
    }
56
57
    protected function configure(): void
58
    {
59
        $this
60
            ->setName(static::NAME)
61
            ->setDescription(static::COMMAND_DESCRIPTION)
62
            ->addArgument(
63
                'fqcn',
64
                InputArgument::OPTIONAL,
65
                static::FQCN_ARGUMENT_DESCRIPTION
66
            );
67
    }
68
69
70
    protected function execute(InputInterface $input, OutputInterface $output): ?int
71
    {
72
        /** @var string $fqcn */
73
        $fqcn = $this->getFQCN($input, $output);
74
        $getClassNameFromFQCN = $this->getClassNameFromFQCN;
75
        $getNamespaceFromFQCN = $this->getNamespaceFromFQCN;
76
        $getRealPathFromNamespace = $this->getRealPathFromNamespace;
77
        $createClassFile = $this->createClassFile;
78
        try {
79
            $className = $getClassNameFromFQCN($fqcn);
80
            $namespace = $getNamespaceFromFQCN($fqcn);
81
            $classDir = $getRealPathFromNamespace($namespace);
82
            $realFilePath = $createClassFile(
83
                $classDir,
84
                $className,
85
                sprintf(static::TEMPLATE, $namespace, $className)
86
            );
87
        } catch (Throwable $exception) {
88
            $output->writeln(sprintf('<error>%s</error>', $exception->getMessage()));
89
            return 1;
90
        }
91
92
        $output->writeln(sprintf(
93
            static::SUCCESS_MESSAGE,
94
            $className,
95
            $realFilePath
96
        ));
97
        $output->writeln(sprintf(
98
            static::SUCCESS_HELP_TEMPLATE,
99
            $this->config['config_dir'],
100
            $fqcn,
101
            $className
102
        ));
103
104
        return 0;
105
    }
106
107
    protected function getFQCN(InputInterface $input, OutputInterface $output): string
108
    {
109
        $fqcn = $input->getArgument('fqcn');
110
        if (null === $fqcn) {
111
            $questionHelper = $this->getHelper('question');
112
            $question = new Question(
113
                static::QUESTION,
114
                static::DEFAULT_RESPONSE
115
            );
116
            $fqcn = $questionHelper->ask($input, $output, $question);
117
        }
118
119
        return $fqcn;
120
    }
121
122
    private function assertValidConstants(): void
123
    {
124
        if (empty(static::TEMPLATE)
0 ignored issues
show
introduced by
The condition empty(static::TEMPLATE) is always true.
Loading history...
125
            || empty(static::SUCCESS_HELP_TEMPLATE)
126
            || empty(static::FQCN_ARGUMENT_DESCRIPTION)
127
            || empty(static::NAME)
128
        ) {
129
            throw new \RuntimeException(
130
                'Constant TEMPLATE, SUCCESS_HELP_TEMPLATE, FQCN_ARGUMENT_DESCRIPTION and NAME'
131
                . ' must have to be defined in your maker command class.'
132
            );
133
        }
134
    }
135
}
136