Completed
Push — master ( 0c5b7b...2c9e38 )
by Tom
13:30
created

MakeCommandCommand::addExecuteMethod()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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