Passed
Push — master ( 99a92e...b669f8 )
by Marius
04:00
created

ConfigureCommand::configureStructure()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 32
ccs 19
cts 19
cp 1
rs 8.7857
c 0
b 0
f 0
cc 6
nc 24
nop 2
crap 6
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\StructureConfigurator;
10
use Paysera\PhpStormHelper\Service\WorkspaceConfigurationHelper;
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Input\InputArgument;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16
17
class ConfigureCommand extends Command
18
{
19
    private $structureConfigurator;
20
    private $gitignoreHelper;
21
    private $configurationOptionFinder;
22
    private $workspaceConfigurationHelper;
23
24 5
    public function __construct(
25
        StructureConfigurator $structureConfigurator,
26
        GitignoreHelper $gitignoreHelper,
27
        ConfigurationOptionFinder $configurationOptionFinder,
28
        WorkspaceConfigurationHelper $workspaceConfigurationHelper
29
    ) {
30 5
        parent::__construct();
31
32 5
        $this->structureConfigurator = $structureConfigurator;
33 5
        $this->gitignoreHelper = $gitignoreHelper;
34 5
        $this->configurationOptionFinder = $configurationOptionFinder;
35 5
        $this->workspaceConfigurationHelper = $workspaceConfigurationHelper;
36 5
    }
37
38 5
    protected function configure()
39
    {
40
        $this
41 5
            ->setName('configure')
42 5
            ->addArgument(
43 5
                'project-root-dir',
44 5
                InputArgument::OPTIONAL,
45 5
                'Default is current directory'
46
            )
47 5
            ->addArgument('path-to-configuration-template-structure', InputArgument::OPTIONAL)
48 5
            ->addOption(
49 5
                'update-gitignore',
50 5
                null,
51 5
                null,
52 5
                'Modify gitignore file – use this when you intend to version common .idea files'
53
            )
54 5
            ->addOption(
55 5
                'docker-image',
56 5
                null,
57 5
                InputOption::VALUE_OPTIONAL,
58
                <<<'DOC'
59 5
Docker image to use for this project. For example, php:7.3-cli or example.org/image:latest.
60
If not provided, currently configured image is maintained in the configuration.
61
DOC
62
            )
63 5
            ->addOption(
64 5
                'webpack-config-path',
65 5
                null,
66 5
                InputOption::VALUE_OPTIONAL,
67
                <<<'DOC'
68 5
Relative path from project root dir to webpack configuration file.
69
If not provided, currently configured path is maintained in the configuration.
70
DOC
71
            )
72 5
            ->addOption(
73 5
                'server',
74 5
                's',
75 5
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
76
                <<<'DOC'
77 5
Server mappings, for example my-project.docker:443@/path/in/server.
78
Server is added in the list unless one already exists with such host and post.
79
DOC
80
            )
81
        ;
82 5
    }
83
84 5
    protected function execute(InputInterface $input, OutputInterface $output)
85
    {
86 5
        $target = $input->getArgument('project-root-dir');
87 5
        if ($target === null) {
88
            $target = realpath('.');
89
        }
90
91 5
        $this->configureStructure($input, $target);
92 5
        $this->configureWorkspace($input, $target);
0 ignored issues
show
Bug introduced by
It seems like $target defined by $input->getArgument('project-root-dir') on line 86 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...
93
94 5
        if ($input->getOption('update-gitignore')) {
95 1
            $this->gitignoreHelper->setupGitignore($target . '/.gitignore');
96
        }
97
98 5
        $output->writeln('Restart PhpStorm instance for changes to take effect');
99 5
    }
100
101
    /**
102
     * @param InputInterface $input
103
     * @param $target
104
     */
105 5
    private function configureStructure(InputInterface $input, $target)
106
    {
107 5
        $path = $input->getArgument('path-to-configuration-template-structure');
108 5
        if ($path === null) {
109 4
            $path = __DIR__ . '/../../config/default';
110
        }
111
112 5
        $composerPath = $target . '/composer.json';
113 5
        $options = [];
114
115 5
        if ($input->getOption('docker-image')) {
116 1
            $options['dockerImage'] = $input->getOption('docker-image');
117
        } else {
118 4
            $options['dockerImage'] = $this->configurationOptionFinder->findUsedDockerImage($target);
119
        }
120
121 5
        if ($input->getOption('webpack-config-path')) {
122 1
            $options['webpackConfigPath'] = $input->getOption('webpack-config-path');
123
        } else {
124 4
            $options['webpackConfigPath'] = $this->configurationOptionFinder->findWebpackConfigPath($target);
125
        }
126
127 5
        if (file_exists($target . '/.php_cs')) {
128 1
            $options['phpCsFixerConfigPath'] = '.php_cs';
129 1
            $fixerBinary = $this->checkPayseraPhpCsFixerSupport($composerPath) ? 'paysera-php-cs-fixer' : 'php-cs-fixer';
130 1
            $options['phpCsFixerExecutable'] = $this->getBinDirectory($composerPath) . '/' . $fixerBinary;
131
        }
132
133 5
        $options['symfonyEnabled'] = $this->checkSymfonySupport($composerPath);
134
135 5
        $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 107 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...
136 5
    }
137
138 5
    private function configureWorkspace(InputInterface $input, string $target)
139
    {
140 5
        $pathToWorkspaceXml = $target . '/.idea/workspace.xml';
141
142 5
        $this->workspaceConfigurationHelper->configureComposer($pathToWorkspaceXml);
143 5
        $this->workspaceConfigurationHelper->configureFileTemplateScheme($pathToWorkspaceXml);
144 5
        $this->workspaceConfigurationHelper->setupPhpUnitRunConfiguration($pathToWorkspaceXml);
145
146 5
        $serverMappings = $input->getOption('server');
147 5
        $this->workspaceConfigurationHelper->setupServerMappings($pathToWorkspaceXml, $serverMappings);
148 5
    }
149
150 5
    private function checkSymfonySupport(string $composerPath)
151
    {
152
        return (
153 5
            $this->isPackageRequired($composerPath, 'symfony/symfony')
154 5
            || $this->isPackageRequired($composerPath, 'symfony/framework-bundle')
155
        );
156
    }
157
158 1
    private function checkPayseraPhpCsFixerSupport(string $composerPath)
159
    {
160 1
        return $this->isPackageRequired($composerPath, 'paysera/lib-php-cs-fixer-config');
161
    }
162
163 1
    private function getBinDirectory(string $composerPath)
164
    {
165 1
        return $this->parseComposer($composerPath)['config']['bin-dir'] ?? 'vendor/bin';
166
    }
167
168 5
    private function isPackageRequired(string $composerPath, string $package)
169
    {
170 5
        $composerContents = $this->parseComposer($composerPath);
171 5
        return isset($composerContents['require'][$package]) || isset($composerContents['require-dev'][$package]);
172
    }
173
174 5
    private function parseComposer(string $composerPath)
175
    {
176 5
        if (!file_exists($composerPath)) {
177 4
            return [];
178
        }
179
180 1
        return json_decode(file_get_contents($composerPath), true) ?: [];
181
    }
182
}
183