Completed
Push — feature/merge-build-stop-step ( d59daf )
by Tom
8s
created

MakeCommandCommand::execute()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 38
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 2
Metric Value
c 2
b 0
f 2
dl 0
loc 38
rs 8.8571
cc 3
eloc 22
nc 4
nop 2
1
<?php
2
3
namespace N98\Magento\Command\Developer\Console;
4
5
use Magento\Framework\Module\Dir;
6
use N98\Magento\Command\Developer\Console\Util\Config\DiFileWriter;
7
use N98\Util\BinaryString;
8
use Symfony\Component\Console\Input\InputArgument;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Magento\Framework\Code\Generator\ClassGenerator;
12
use Zend\Code\Generator\DocBlockGenerator;
13
use Zend\Code\Generator\MethodGenerator;
14
15
class MakeCommandCommand extends AbstractGeneratorCommand
16
{
17
    protected function configure()
18
    {
19
        $this
20
            ->setName('make:command')
21
            ->addArgument('classpath', InputArgument::REQUIRED)
22
            ->addArgument('command_name', InputArgument::OPTIONAL)
23
            ->setDescription('Creates a cli command');
24
    }
25
26
    /**
27
     * @param InputInterface $input
28
     * @param OutputInterface $output
29
     *
30
     * @return int|void
31
     */
32
    protected function execute(InputInterface $input, OutputInterface $output)
33
    {
34
        $commandFileName = $this->getNormalizedPathByArgument($input->getArgument('classpath'));
35
        $classNameToGenerate = $this->getCurrentModuleNamespace()
36
            . '\\Console\\Command\\'
37
            . $this->getNormalizedClassnameByArgument($input->getArgument('classpath'));
38
39
        // always suffix class names with "Command"
40
        if (!BinaryString::endsWith($classNameToGenerate, 'Command')) {
41
            $classNameToGenerate .= 'Command';
42
        }
43
44
        // always suffix file names with "Command"
45
        if (!BinaryString::endsWith($commandFileName, 'Command')) {
46
            $commandFileName .= 'Command';
47
        }
48
        $filePathToGenerate = 'Console/Command/' . $commandFileName . '.php';
49
50
        $classGenerator = $this->create(ClassGenerator::class);
51
        /** @var $classGenerator ClassGenerator */
52
        $classGenerator->setName($classNameToGenerate);
53
        $classGenerator->setExtendedClass('Command');
54
        $classGenerator->addUse('Symfony\Component\Console\Command\Command');
55
        $classGenerator->addUse('Symfony\Component\Console\Input\InputInterface');
56
        $classGenerator->addUse('Symfony\Component\Console\Output\OutputInterface');
57
        $classGenerator->addUse('Symfony\Component\Console\Command\Command');
58
59
        $commandName = $this->prepareCommandName($input);
60
61
        $this->addConfigureMethod($classGenerator, $commandName);
62
        $this->addExecuteMethod($classGenerator);
63
64
        // Write class
65
        $this->writeClassToFile($output, $classGenerator, $filePathToGenerate);
66
67
        // new class to di config
68
        $this->writeNewCommandToDiConfig($input, $classNameToGenerate);
69
    }
70
71
    /**
72
     * @param ClassGenerator $classGenerator
73
     * @param string $commandName
74
     */
75
    private function addConfigureMethod(ClassGenerator $classGenerator, $commandName)
76
    {
77
        $methodConfigureBody = <<<BODY
78
\$this->setName('$commandName');
79
\$this->setDescription('$commandName');
80
BODY;
81
;
82
        $classGenerator->addMethod(
83
            'configure',
84
            [],
85
            MethodGenerator::FLAG_PUBLIC,
86
            $methodConfigureBody,
87
            'Configures the current command.'
88
        );
89
    }
90
91
    /**
92
     * @param ClassGenerator $classGenerator
93
     */
94
    private function addExecuteMethod(ClassGenerator $classGenerator)
95
    {
96
        $docblock = DocBlockGenerator::fromArray(array(
97
            'shortDescription' => '',
98
            'longDescription'  => '',
99
            'tags'             => array(
100
                array(
101
                    'name'        => 'param',
102
                    'description' => 'InputInterface $input An InputInterface instance',
103
                ),
104
                array(
105
                    'name'        => 'param',
106
                    'description' => 'OutputInterface $output An OutputInterface instance',
107
                ),
108
                array(
109
                    'name'        => 'return',
110
                    'description' => 'null|int null or 0 if everything went fine, or an error code',
111
                ),
112
            ),
113
        ));
114
115
        $classGenerator->addMethod(
116
            'execute',
117
            [
118
                [
119
                    'name' => 'input',
120
                    'type' => 'InputInterface',
121
                ],
122
                [
123
                    'name' => 'output',
124
                    'type' => 'OutputInterface',
125
                ],
126
            ],
127
            MethodGenerator::FLAG_PUBLIC,
128
            '$output->writeln(\'' . $classGenerator->getName() . '\');',
129
            $docblock
130
        );
131
    }
132
133
    /**
134
     * @param InputInterface $input
135
     * @return mixed
136
     */
137
    private function prepareCommandName(InputInterface $input)
138
    {
139
        $commandName = $input->getArgument('command_name');
140
141
        if (empty($commandName)) {
142
            $commandName = strtolower(str_replace('\\', ':', $this->getCurrentModuleNamespace())) . ':';
143
            $commandName .= str_replace('.', ':', $input->getArgument('classpath'));
144
        }
145
146
        return $commandName;
147
    }
148
149
    /**
150
     * @param InputInterface $input
151
     * @param $classNameToGenerate
152
     */
153
    private function writeNewCommandToDiConfig(InputInterface $input, $classNameToGenerate)
154
    {
155
        $diPath = $this->getCurrentModuleFilePath('etc/di.xml');
156
157
        $configWriter = $this->createDiFileWriter($diPath);
158
        /** @var $configWriter DiFileWriter */
159
160
        $configWriter->addConsoleCommand(
161
            str_replace(
162
                '\\',
163
                '',
164
                $this->getCurrentModuleNamespace() .
165
                $this->getNormalizedClassnameByArgument($input->getArgument('classpath'))
166
            ),
167
            $classNameToGenerate
168
        );
169
170
        $configWriter->save($diPath);
171
    }
172
173
    /**
174
     * @param $diPath
175
     * @return Util\Config\FileWriter
176
     */
177
    protected function createDiFileWriter($diPath)
178
    {
179
        $configWriter = DiFileWriter::createByFilepath($diPath);
180
        return $configWriter;
181
    }
182
}
183