Test Failed
Push — master ( 82742e...5c84c5 )
by Marius
01:36
created

ConfigureCommand::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 51

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 51
ccs 0
cts 33
cp 0
rs 9.069
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Paysera\PhpStormHelper\Command;
6
7
use Paysera\PhpStormHelper\Service\ConfigurationOptionFinder;
8
use Paysera\PhpStormHelper\Service\GitignoreHelper;
9
use Paysera\PhpStormHelper\Service\SourceFolderHelper;
10
use Paysera\PhpStormHelper\Service\StructureConfigurator;
11
use Paysera\PhpStormHelper\Service\WorkspaceConfigurationHelper;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Input\InputArgument;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Input\InputOption;
16
use Symfony\Component\Console\Output\OutputInterface;
17
use Symfony\Component\Filesystem\Filesystem;
18
19
class ConfigureCommand extends Command
20
{
21
    private $structureConfigurator;
22
    private $gitignoreHelper;
23
    private $configurationOptionFinder;
24
    private $workspaceConfigurationHelper;
25
    private $sourceFolderHelper;
26
    private $filesystem;
27
28
    public function __construct(
29
        StructureConfigurator $structureConfigurator,
30
        GitignoreHelper $gitignoreHelper,
31
        ConfigurationOptionFinder $configurationOptionFinder,
32
        WorkspaceConfigurationHelper $workspaceConfigurationHelper,
33
        SourceFolderHelper $sourceFolderHelper,
34
        Filesystem $filesystem
35
    ) {
36
        parent::__construct();
37
38
        $this->structureConfigurator = $structureConfigurator;
39
        $this->gitignoreHelper = $gitignoreHelper;
40
        $this->configurationOptionFinder = $configurationOptionFinder;
41
        $this->workspaceConfigurationHelper = $workspaceConfigurationHelper;
42
        $this->sourceFolderHelper = $sourceFolderHelper;
43
        $this->filesystem = $filesystem;
44
    }
45
46
    protected function configure()
47
    {
48
        $this
49
            ->setName('configure')
50
            ->addArgument(
51
                'project-root-dir',
52
                InputArgument::OPTIONAL,
53
                'Default is current directory'
54
            )
55
            ->addArgument('path-to-configuration-template-structure', InputArgument::OPTIONAL)
56
            ->addOption(
57
                'update-gitignore',
58
                null,
59
                null,
60
                'Modify gitignore file – use this when you intend to version common .idea files'
61
            )
62
            ->addOption(
63
                'docker-image',
64
                null,
65
                InputOption::VALUE_OPTIONAL,
66
                <<<'DOC'
67
Docker image to use for this project. For example, php:7.3-cli or example.org/image:latest.
68
If not provided, currently configured image is maintained in the configuration.
69
DOC
70
            )
71
            ->addOption(
72
                'webpack-config-path',
73
                null,
74
                InputOption::VALUE_OPTIONAL,
75
                <<<'DOC'
76
Relative path from project root dir to webpack configuration file.
77
If not provided, currently configured path is maintained in the configuration.
78
DOC
79
            )
80
            ->addOption(
81
                'server',
82
                's',
83
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
84
                <<<'DOC'
85
Server mappings, for example my-project.docker:443@/path/in/server.
86
Server is added in the list unless one already exists with such host and post.
87
DOC
88
            )
89
            ->addOption(
90
                'no-diff',
91
                null,
92
                InputOption::VALUE_NONE,
93
                'Pass if you don\'t want diff to be outputed'
94
            )
95
        ;
96
    }
97
98
    protected function execute(InputInterface $input, OutputInterface $output)
99
    {
100
        $target = $input->getArgument('project-root-dir');
101
        if ($target === null) {
102
            $target = realpath('.');
103
        }
104
105
        $backupFolder = $this->backupConfiguration($target);
0 ignored issues
show
Bug introduced by
It seems like $target defined by $input->getArgument('project-root-dir') on line 100 can also be of type array<integer,string>; however, Paysera\PhpStormHelper\C...::backupConfiguration() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
106
        $this->configureStructure($input, $target);
107
        $this->configureWorkspace($input, $target);
0 ignored issues
show
Bug introduced by
It seems like $target defined by $input->getArgument('project-root-dir') on line 100 can also be of type array<integer,string>; however, Paysera\PhpStormHelper\C...d::configureWorkspace() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
108
109
        if ($input->getOption('update-gitignore')) {
110
            $this->gitignoreHelper->setupGitignore($target . '/.gitignore');
111
        }
112
113
        $output->writeln('Made backup of <info>.idea</info> to <info>' . $backupFolder . '</info>');
114
        if (!$input->getOption('no-diff')) {
115
            $this->printDiffFromBackup($backupFolder, $target, $output);
0 ignored issues
show
Bug introduced by
It seems like $target defined by $input->getArgument('project-root-dir') on line 100 can also be of type array<integer,string>; however, Paysera\PhpStormHelper\C...::printDiffFromBackup() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
116
        }
117
118
        $output->writeln('Restart PhpStorm instance for changes to take effect');
119
    }
120
121
    /**
122
     * @param InputInterface $input
123
     * @param $target
124
     */
125
    private function configureStructure(InputInterface $input, $target)
126
    {
127
        $path = $input->getArgument('path-to-configuration-template-structure');
128
        if ($path === null) {
129
            $path = __DIR__ . '/../../config/default';
130
        }
131
132
        $composerPath = $target . '/composer.json';
133
        $options = [];
134
135
        if ($input->getOption('docker-image')) {
136
            $options['dockerImage'] = $input->getOption('docker-image');
137
        } else {
138
            $options['dockerImage'] = $this->configurationOptionFinder->findUsedDockerImage($target);
139
        }
140
141
        if ($input->getOption('webpack-config-path')) {
142
            $options['webpackConfigPath'] = $input->getOption('webpack-config-path');
143
        } else {
144
            $options['webpackConfigPath'] = $this->configurationOptionFinder->findWebpackConfigPath($target);
145
        }
146
147
        if (file_exists($target . '/.php_cs')) {
148
            $options['phpCsFixerConfigPath'] = '.php_cs';
149
            $fixerBinary = $this->checkPayseraPhpCsFixerSupport($composerPath) ? 'paysera-php-cs-fixer' : 'php-cs-fixer';
150
            $options['phpCsFixerExecutable'] = $this->getBinDirectory($composerPath) . '/' . $fixerBinary;
151
        }
152
153
        $options['symfonyEnabled'] = $this->checkSymfonySupport($composerPath);
154
155
        $options['sourceFolders'] = $this->sourceFolderHelper->getSourceFolders($target);
156
157
        $this->structureConfigurator->configure($path, $target, $options);
0 ignored issues
show
Bug introduced by
It seems like $path defined by $input->getArgument('pat...on-template-structure') on line 127 can also be of type array<integer,string>; however, Paysera\PhpStormHelper\S...nfigurator::configure() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
158
    }
159
160
    private function configureWorkspace(InputInterface $input, string $target)
161
    {
162
        $pathToWorkspaceXml = $target . '/.idea/workspace.xml';
163
164
        $this->workspaceConfigurationHelper->configureComposer($pathToWorkspaceXml);
165
        $this->workspaceConfigurationHelper->configureFileTemplateScheme($pathToWorkspaceXml);
166
        $this->workspaceConfigurationHelper->setupPhpUnitRunConfiguration($pathToWorkspaceXml);
167
168
        $serverMappings = $input->getOption('server');
169
        $this->workspaceConfigurationHelper->setupServerMappings($pathToWorkspaceXml, $serverMappings);
170
    }
171
172
    private function checkSymfonySupport(string $composerPath)
173
    {
174
        return (
175
            $this->isPackageRequired($composerPath, 'symfony/symfony')
176
            || $this->isPackageRequired($composerPath, 'symfony/framework-bundle')
177
        );
178
    }
179
180
    private function checkPayseraPhpCsFixerSupport(string $composerPath)
181
    {
182
        return $this->isPackageRequired($composerPath, 'paysera/lib-php-cs-fixer-config');
183
    }
184
185
    private function getBinDirectory(string $composerPath)
186
    {
187
        return $this->parseComposer($composerPath)['config']['bin-dir'] ?? 'vendor/bin';
188
    }
189
190
    private function isPackageRequired(string $composerPath, string $package)
191
    {
192
        $composerContents = $this->parseComposer($composerPath);
193
        return isset($composerContents['require'][$package]) || isset($composerContents['require-dev'][$package]);
194
    }
195
196
    private function parseComposer(string $composerPath)
197
    {
198
        if (!file_exists($composerPath)) {
199
            return [];
200
        }
201
202
        return json_decode(file_get_contents($composerPath), true) ?: [];
203
    }
204
205
    private function backupConfiguration(string $target): string
206
    {
207
        $pathToIdea = $target . '/.idea/';
208
        $backupFolder = sprintf(
209
            '%s/phpstorm-helper-backups/%s/%s',
210
            sys_get_temp_dir(),
211
            basename($target),
212
            time()
213
        );
214
215
        $this->filesystem->mirror($pathToIdea, $backupFolder);
216
217
        return $backupFolder;
218
    }
219
220
    private function printDiffFromBackup(string $backupFolder, string $target, OutputInterface $output)
221
    {
222
        $output->writeln("Diff of the changes, excluding workspace.xml file:\n\n");
223
        $command = sprintf(
224
            'diff -N -r -x workspace.xml %s %s',
225
            escapeshellarg($target . '/.idea/'),
226
            escapeshellarg($backupFolder)
227
        );
228
        system($command);
229
    }
230
}
231