Completed
Push — master ( f51f9e...b04c6e )
by Vladimir
05:26
created

CheckGeneratorCommand::createFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 12
ccs 0
cts 10
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 4
crap 6
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;
0 ignored issues
show
Bug introduced by
The type Twig\Loader\FilesystemLoader was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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
    public 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
0 ignored issues
show
Bug introduced by
The type Twig\Environment was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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('tvi:monitor:check:generator')
51
            ->setDescription('Generate health check skeleton')
52
            ->addArgument('check', InputArgument::REQUIRED, 'Check name')
53
            ->addOption('check-space', 's', InputOption::VALUE_REQUIRED, 'Check space', 'core')
54
            ->addOption('group', 'g', InputOption::VALUE_OPTIONAL, 'Check group')
55
            ->addOption('no-backup', 'b', InputOption::VALUE_NONE, 'Do not backup existing check files.')
56
            ->setHelp(
57
                <<<"EOT"
58
The <info>%command.name%</info> command generates check classes
59
from tvi monitor template:
60
61
* Generate a check skeleton:
62
63
By default, the unmodified version of check is backed up and saved
64
To prevent this task from creating the backup file,
65
pass the <comment>--no-backup</comment> option:
66
  
67
  <info>php %command.full_name% "TviMonitorBundle:Check\Example" --check-space=core [--group=...] [--no-backup]</info>
68
  <info>php %command.full_name% ":Check\Example"</info>
69
  <info>php %command.full_name% "Check\Example"</info>
70
71
EOT
72
            );
73
    }
74
75
    protected function interact(InputInterface $input, OutputInterface $output)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function interact()
Loading history...
76
    {
77
        $this->twig->setLoader(new FilesystemLoader([self::TPL_DIR]));
78
79
        $fn = Finder::create();
80
        $tpls = $fn->in(self::TPL_DIR)->files()->getIterator();
81
        $this->tpls = iterator_to_array($tpls);
82
    }
83
84
    protected function execute(InputInterface $input, OutputInterface $output)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function execute()
Loading history...
85
    {
86
        $this->generate($input, $output);
87
    }
88
89
    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...
90
    {
91
        $NAMESPACE = sprintf('%s\%s\%s', $bundleNamespace, $checkNamespace, $checkName);
92
93
        return preg_replace('#\\\$#', '', $NAMESPACE);
94
    }
95
96
    protected function getServicePrefix(string $bundleNamespace): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getServicePrefix()
Loading history...
97
    {
98
        $SERVICE_PREFIX = preg_replace('#\\\#', '_', $bundleNamespace);
99
        $SERVICE_PREFIX = preg_replace('#bundle$#i', '', $SERVICE_PREFIX);
100
101
        return mb_strtolower($SERVICE_PREFIX);
102
    }
103
104
    protected function getCheckName(string $checkName): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckName()
Loading history...
105
    {
106
        return $checkName;
107
    }
108
109
    protected function getCheckAlias(string $checkName): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckAlias()
Loading history...
110
    {
111
        $CHECK_ALIAS = preg_replace('#([A-Z])#', '_\1', $checkName);
112
        $CHECK_ALIAS = preg_replace('#^_*#', '', $CHECK_ALIAS);
113
114
        return mb_strtolower($CHECK_ALIAS);
115
    }
116
117
    protected function getCheckGroup(InputInterface $input, string $checkAlias): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckGroup()
Loading history...
118
    {
119
        $group = $input->getOption('group');
120
121
        return $group ? $group : $checkAlias;
122
    }
123
124
    protected function getCheckSpace(InputInterface $input, OutputInterface $output): string
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getCheckSpace()
Loading history...
125
    {
126
        $checkSpace = $input->getOption('check-space');
127
        $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

127
        $checkSpace = trim(/** @scrutinizer ignore-type */ $checkSpace);
Loading history...
128
        if (preg_match('/[^\w:]/', $checkSpace, $m)) {
129
            $output->writeln('<error>Bad check-space foramt</error>, check-space has to be like [:\w+]+.');
130
            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...
131
        }
132
        if ('' === $checkSpace) {
133
            $output->writeln('<error>Check-space requeaerd</error>. Use --check-space=... to set it');
134
            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...
135
        }
136
        $checkSpace = preg_replace('/:+/', ':', $checkSpace);
137
138
        return trim($checkSpace, ':').':';
139
    }
140
141
    protected function getBundle(OutputInterface $output, string $bundleName): Bundle
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getBundle()
Loading history...
142
    {
143
        /* @var $bundle Bundle */
144
        if (!$bundleName) {
145
            $defaultBundle = 'TviMonitorBundle';
146
            $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

146
            $bundle = $this->getApplication()->/** @scrutinizer ignore-call */ getKernel()->getBundle($defaultBundle);
Loading history...
147
            $output->writeln(sprintf('<info>Use default bundle <comment>%s</comment></info>', $bundle->getNamespace()));
148
        } else {
149
            try {
150
                $bundle = $this->getApplication()->getKernel()->getBundle($bundleName);
151
            } catch (\InvalidArgumentException $e) {
152
                $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
153
                exit(1);
0 ignored issues
show
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...
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...
154
            }
155
        }
156
157
        return $bundle;
158
    }
159
160
    /**
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...
161
     * @throws \Twig_Error_Loader
162
     * @throws \Twig_Error_Runtime
163
     * @throws \Twig_Error_Syntax
164
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
165
    protected function generate(InputInterface $input, OutputInterface $output): void
166
    {
167
        $check = $input->getArgument('check');
168
        $noBackup = !$input->getOption('no-backup');
169
170
        $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

170
        $r = explode(':', /** @scrutinizer ignore-type */ $check);
Loading history...
171
        @list($bundleName, $checkPath) = (1 === \count($r)) ? [null, current($r)] : $r;
172
173
        $bundle = $this->getBundle($output, $bundleName);
174
175
        preg_match('#^(.*?)(\w+)$#', $checkPath, $m);
176
        list($checkNamespace, $checkName) = [$m[1], $m[2]];
177
178
        $checkNamespace = preg_replace('#\\\$#', '', $checkNamespace);
179
        $bundleNamespace = $bundle->getNamespace();
180
181
        $NAMESPACE = $this->getNamespace($bundleNamespace, $checkNamespace, $checkName);
182
        $SERVICE_PREFIX = $this->getServicePrefix($bundleNamespace);
183
        $CHECK_NAME = $this->getCheckName($checkName);
184
        $CHECK_ALIAS = $this->getCheckAlias($checkName);
185
        $CHECK_GROUP = $this->getCheckGroup($input, $CHECK_ALIAS);
186
        $CHECK_SPACE = $this->getCheckSpace($input, $output);
187
188
        $checkPath = sprintf('%s%s%s', $bundle->getPath(), \DIRECTORY_SEPARATOR, $checkPath);
189
        $checkPath = str_replace('\\', \DIRECTORY_SEPARATOR, $checkPath);
190
191
        if (is_dir($checkPath)) {
192
            if ($noBackup && is_dir($checkPath)) {
193
                $output->writeln(sprintf('<info><error>Check %s exist</error>. Use --no-backup flag to rewrite</info>', $NAMESPACE));
194
                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...
195
            }
196
            $output->writeln(sprintf('<info>Check <comment>%s</comment> exist rewrite them</info>', $NAMESPACE));
197
        } else {
198
            @mkdir($checkPath, 0775, true) && !is_dir($checkPath);
199
        }
200
201
        foreach ($this->tpls as $f) {
202
203
            /* @var SplFileInfo $f */
204
            $fName = $f->getBasename('.twig');
205
206
            $path = sprintf('%s%s%s', $checkPath, \DIRECTORY_SEPARATOR, $fName);
207
208
            $tplData = [
209
                'NAMESPACE' => $NAMESPACE,
210
                'SERVICE_REPFIX' => $SERVICE_PREFIX,
211
                'CHECK_NAME' => $CHECK_NAME,
212
                'CHECK_ALIAS' => $CHECK_ALIAS,
213
                'CHECK_SPACE' => $CHECK_SPACE,
214
                'CHECK_GROUP' => $CHECK_GROUP,
215
            ];
216
            $res = $this->twig->render($f->getRelativePathname(), $tplData);
217
            file_put_contents($path, $res);
218
219
            $output->writeln(sprintf('File <info>%s</info> generated.', $path));
220
        }
221
    }
222
}
223