CheckGeneratorCommand::getBundle()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 17
ccs 0
cts 15
cp 0
rs 9.9
c 0
b 0
f 0
cc 3
nc 3
nop 2
crap 12
1
<?php
2
3
/**
4
 * This file is part of the `tvi/monitor-bundle` project.
5
 *
6
 * (c) https://github.com/turnaev/monitor-bundle/graphs/contributors
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
Coding Style introduced by
Missing @link tag in file comment
Loading history...
11
12
namespace Tvi\MonitorBundle\Command;
13
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Input\InputArgument;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Finder\Finder;
20
use Symfony\Component\Finder\SplFileInfo;
21
use Symfony\Component\HttpKernel\Bundle\Bundle;
22
use Twig\Loader\FilesystemLoader;
23
24
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
25
 * @author Vladimir Turnaev <[email protected]>
26
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
27
class CheckGeneratorCommand extends Command
28
{
29
    const TPL_DIR = __DIR__.'/../Resources/generator/Check';
30
31
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
32
     * @var \Twig\Environment
33
     */
34
    private $twig;
0 ignored issues
show
Coding Style introduced by
Private member variable "twig" must be prefixed with an underscore
Loading history...
35
36
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
37
     * @var SplFileInfo[]
38
     */
39
    private $tpls;
0 ignored issues
show
Coding Style introduced by
Private member variable "tpls" must be prefixed with an underscore
Loading history...
40
41
    public function __construct(\Twig\Environment $twig, string $name = null)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
42
    {
43
        parent::__construct($name);
44
        $this->twig = $twig;
45
    }
46
47
    protected function configure()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function configure()
Loading history...
48
    {
49
        $this
50
            ->setName(
51
                'tvi:monitor:check:generator'
52
            )
53
            ->setDescription(
54
                'Generate health check skeleton'
55
            )
56
            ->addArgument('check',
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
57
                InputArgument::REQUIRED, 'Check name'
58
            )
59
            ->addOption(
60
                'check-space',
61
                's',
62
                InputOption::VALUE_REQUIRED,
63
                'Check space',
64
                'core'
65
            )
66
            ->addOption(
67
                'group',
68
                'g',
69
                InputOption::VALUE_OPTIONAL,
70
                'Check group')
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 12 spaces, but found 16.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
71
            ->addOption(
72
                'no-backup',
73
                'b',
74
                InputOption::VALUE_NONE,
75
                'Do not backup existing check files.'
76
            )
77
            ->setHelp(
78
                <<<"EOT"
79
The <info>%command.name%</info> command generates check classes
80
from tvi monitor template:
81
82
* Generate a check skeleton:
83
84
By default, the unmodified version of check is backed up and saved
85
To prevent this task from creating the backup file,
86
pass the <comment>--no-backup</comment> option:
87
  
88
  <info>php %command.full_name% "TviMonitorBundle:Check\Example" [--check-space=...] [--group=...] [--no-backup]</info>
89
  <info>php %command.full_name% ":Check\Example"</info>
90
  <info>php %command.full_name% "Check\Example"</info>
91
92
EOT
93
            );
94
    }
95
96
    protected function interact(InputInterface $input, OutputInterface $output)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function interact()
Loading history...
97
    {
98
        $this->twig->setLoader(new FilesystemLoader([self::TPL_DIR]));
99
100
        $fn = Finder::create();
101
        $tpls = $fn->in(self::TPL_DIR)->files()->getIterator();
102
        $this->tpls = iterator_to_array($tpls);
103
    }
104
105
    protected function execute(InputInterface $input, OutputInterface $output)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function execute()
Loading history...
106
    {
107
        $this->generate($input, $output);
108
    }
109
110
    protected function getNamespace(string $bundleNamespace, string $checkNamespace, string $checkName): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getNamespace()
Loading history...
111
    {
112
        $NAMESPACE = sprintf('%s\%s\%s', $bundleNamespace, $checkNamespace, $checkName);
113
114
        return preg_replace('#\\\$#', '', $NAMESPACE);
115
    }
116
117
    protected function getServicePrefix(string $bundleNamespace): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getServicePrefix()
Loading history...
118
    {
119
        $SERVICE_PREFIX = preg_replace('#\\\#', '_', $bundleNamespace);
120
        $SERVICE_PREFIX = preg_replace('#bundle$#i', '', $SERVICE_PREFIX);
121
122
        return mb_strtolower($SERVICE_PREFIX);
123
    }
124
125
    protected function getCheckName(string $checkName): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckName()
Loading history...
126
    {
127
        return $checkName;
128
    }
129
130
    protected function getCheckAlias(string $checkName): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckAlias()
Loading history...
131
    {
132
        $CHECK_ALIAS = preg_replace('#([A-Z])#', '_\1', $checkName);
133
        $CHECK_ALIAS = preg_replace('#^_*#', '', $CHECK_ALIAS);
134
135
        return mb_strtolower($CHECK_ALIAS);
136
    }
137
138
    protected function getCheckGroup(InputInterface $input, string $checkAlias): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckGroup()
Loading history...
139
    {
140
        $group = $input->getOption('group');
141
142
        return $group ? $group : $checkAlias;
143
    }
144
145
    protected function getCheckSpace(InputInterface $input, OutputInterface $output): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckSpace()
Loading history...
146
    {
147
        $checkSpace = $input->getOption('check-space');
148
        $checkSpace = trim($checkSpace);
0 ignored issues
show
Bug introduced by
It seems like $checkSpace can also be of type string[]; however, parameter $str of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

148
        $checkSpace = trim(/** @scrutinizer ignore-type */ $checkSpace);
Loading history...
149
        if (preg_match('/[^\w:]/', $checkSpace, $m)) {
150
            $output->writeln('<error>Bad check-space foramt</error>, check-space has to be like [:\w+]+.');
151
            exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
152
        }
153
        if ('' === $checkSpace) {
154
            $output->writeln('<error>Check-space requeaerd</error>. Use --check-space=... to set it');
155
            exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
156
        }
157
        $checkSpace = preg_replace('/:+/', ':', $checkSpace);
158
159
        return trim($checkSpace, ':').':';
160
    }
161
162
    protected function getBundle(OutputInterface $output, string $bundleName): Bundle
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getBundle()
Loading history...
163
    {
164
        /* @var $bundle Bundle */
165
        if (!$bundleName) {
166
            $defaultBundle = 'TviMonitorBundle';
167
            $bundle = $this->getApplication()->getKernel()->getBundle($defaultBundle);
0 ignored issues
show
Bug introduced by
The method getKernel() does not exist on Symfony\Component\Console\Application. It seems like you code against a sub-type of Symfony\Component\Console\Application such as Symfony\Bundle\FrameworkBundle\Console\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

167
            $bundle = $this->getApplication()->/** @scrutinizer ignore-call */ getKernel()->getBundle($defaultBundle);
Loading history...
168
            $output->writeln(sprintf('<info>Use default bundle <comment>%s</comment></info>', $bundle->getNamespace()));
169
        } else {
170
            try {
171
                $bundle = $this->getApplication()->getKernel()->getBundle($bundleName);
172
            } catch (\InvalidArgumentException $e) {
173
                $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
174
                exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Symfony\Component\HttpKernel\Bundle\Bundle. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
175
            }
176
        }
177
178
        return $bundle;
179
    }
180
181
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $input should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $output should have a doc-comment as per coding-style.
Loading history...
182
     * @throws \Twig_Error_Loader
183
     * @throws \Twig_Error_Runtime
184
     * @throws \Twig_Error_Syntax
185
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
186
    protected function generate(InputInterface $input, OutputInterface $output): void
187
    {
188
        $check = $input->getArgument('check');
189
        $noBackup = !$input->getOption('no-backup');
190
191
        $r = explode(':', $check);
0 ignored issues
show
Bug introduced by
It seems like $check can also be of type string[]; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

191
        $r = explode(':', /** @scrutinizer ignore-type */ $check);
Loading history...
192
        @list($bundleName, $checkPath) = (1 === \count($r)) ? [null, current($r)] : $r;
193
194
        $bundle = $this->getBundle($output, $bundleName);
195
196
        preg_match('#^(.*?)(\w+)$#', $checkPath, $m);
197
        list($checkNamespace, $checkName) = [$m[1], $m[2]];
198
199
        $checkNamespace = preg_replace('#\\\$#', '', $checkNamespace);
200
        $bundleNamespace = $bundle->getNamespace();
201
202
        $NAMESPACE = $this->getNamespace($bundleNamespace, $checkNamespace, $checkName);
203
        $SERVICE_PREFIX = $this->getServicePrefix($bundleNamespace);
204
        $CHECK_NAME = $this->getCheckName($checkName);
205
        $CHECK_ALIAS = $this->getCheckAlias($checkName);
206
        $CHECK_GROUP = $this->getCheckGroup($input, $CHECK_ALIAS);
207
        $CHECK_SPACE = $this->getCheckSpace($input, $output);
208
209
        $checkPath = sprintf('%s%s%s', $bundle->getPath(), \DIRECTORY_SEPARATOR, $checkPath);
210
        $checkPath = str_replace('\\', \DIRECTORY_SEPARATOR, $checkPath);
211
212
        if (is_dir($checkPath)) {
213
            if ($noBackup && is_dir($checkPath)) {
214
                $output->writeln(sprintf('<info><error>Check %s exist</error>. Use --no-backup flag to rewrite</info>', $NAMESPACE));
215
                exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
216
            }
217
            $output->writeln(sprintf('<info>Check <comment>%s</comment> exist rewrite them</info>', $NAMESPACE));
218
        } else {
219
            @mkdir($checkPath, 0775, true) && !is_dir($checkPath);
220
        }
221
222
        foreach ($this->tpls as $f) {
223
224
            /* @var SplFileInfo $f */
225
            $fName = $f->getBasename('.twig');
226
227
            $path = sprintf('%s%s%s', $checkPath, \DIRECTORY_SEPARATOR, $fName);
228
229
            $tplData = [
230
                'NAMESPACE' => $NAMESPACE,
231
                'SERVICE_REPFIX' => $SERVICE_PREFIX,
232
                'CHECK_NAME' => $CHECK_NAME,
233
                'CHECK_ALIAS' => $CHECK_ALIAS,
234
                'CHECK_SPACE' => $CHECK_SPACE,
235
                'CHECK_GROUP' => $CHECK_GROUP,
236
            ];
237
            $res = $this->twig->render($f->getRelativePathname(), $tplData);
238
            file_put_contents($path, $res);
239
240
            $output->writeln(sprintf('File <info>%s</info> generated.', $path));
241
        }
242
    }
243
}
244