UseSortCommand::execute()   B
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 51
Code Lines 22

Duplication

Lines 3
Ratio 5.88 %

Importance

Changes 0
Metric Value
cc 4
eloc 22
nc 4
nop 2
dl 3
loc 51
rs 8.8981
c 0
b 0
f 0

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
/*
4
 * This file is part of the php-formatter package
5
 *
6
 * Copyright (c) 2014-2016 Marc Morera
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * Feel free to edit as you please, and have fun.
12
 *
13
 * @author Marc Morera <[email protected]>
14
 */
15
16
namespace Mmoreram\PHPFormatter\Command;
17
18
use Exception;
19
use IteratorAggregate;
20
use Symfony\Component\Console\Command\Command;
21
use Symfony\Component\Console\Input\InputArgument;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Input\InputOption;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use Symfony\Component\Filesystem\Filesystem;
26
27
use Mmoreram\PHPFormatter\Finder\ConfigFinder;
28
use Mmoreram\PHPFormatter\Finder\FileFinder;
29
use Mmoreram\PHPFormatter\Loader\ConfigLoader;
30
use Mmoreram\PHPFormatter\Sorter\UseSorter;
31
32
/**
33
 * Class UseSortCommand.
34
 */
35
class UseSortCommand extends Command
36
{
37
    /**
38
     * @var string
39
     *
40
     * Command name
41
     */
42
    const COMMAND_NAME = 'use-sort';
43
44
    /**
45
     * configure.
46
     */
47
    protected function configure()
48
    {
49
        $this
50
            ->setName('formatter:use:sort')
51
            ->setDescription('Sort Use statements')
52
            ->addArgument(
53
                'path',
54
                InputArgument::REQUIRED,
55
                'Path'
56
            )
57
            ->addOption(
58
                'group',
59
                null,
60
                InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
61
                'Groups defined?'
62
            )
63
            ->addOption(
64
                'sort-type',
65
                null,
66
                InputOption::VALUE_OPTIONAL,
67
                'Sort type'
68
            )
69
            ->addOption(
70
                'sort-direction',
71
                null,
72
                InputOption::VALUE_OPTIONAL,
73
                'Sort direction'
74
            )
75
            ->addOption(
76
                'group-type',
77
                null,
78
                InputOption::VALUE_OPTIONAL,
79
                'Type of grouping'
80
            )
81
            ->addOption(
82
                'group-skip-empty',
83
                null,
84
                InputOption::VALUE_NONE,
85
                'Skip empty groups'
86
            )
87
            ->addOption(
88
                '--config',
89
                '-c',
90
                InputOption::VALUE_OPTIONAL,
91
                'Config file directory',
92
                getcwd()
93
            )
94
            ->addOption(
95
                'dry-run',
96
                null,
97
                InputOption::VALUE_NONE,
98
                'Just print the result, nothing is overwritten'
99
            );
100
    }
101
102
    /**
103
     * Execute command.
104
     *
105
     * @param InputInterface  $input  Input
106
     * @param OutputInterface $output Output
107
     *
108
     * @return int|null|void
109
     *
110
     * @throws Exception
111
     */
112
    protected function execute(InputInterface $input, OutputInterface $output)
113
    {
114
        $path = $input->getArgument('path');
115
116
        /**
117
         * We load the options to work with.
118
         */
119
        $options = $this->getUsableConfig($input);
120
121
        /**
122
         * Building the real directory or file to work in.
123
         */
124
        $filesystem = new Filesystem();
125
        if (!$filesystem->isAbsolutePath($path)) {
126
            $path = getcwd() . DIRECTORY_SEPARATOR . $path;
127
        }
128
129 View Code Duplication
        if (!is_file($path) && !is_dir($path)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
130
            throw new Exception('Directory or file "' . $path . '" does not exist');
131
        }
132
133
        /*
134
         * Print dry-run message if needed
135
         */
136
        $this->printDryRunMessage(
137
            $input,
138
            $output,
139
            $path
140
        );
141
142
        /*
143
         * Print all configuration block if verbose level allows it
144
         */
145
        $this->printConfigUsed(
146
            $output,
147
            $options
148
        );
149
150
        $fileFinder = new FileFinder();
151
        $files = $fileFinder->findPHPFilesByPath($path);
152
153
        /*
154
         * Parse and fix all found files
155
         */
156
        $this->parseAndFixFiles(
157
            $input,
158
            $output,
159
            $files,
160
            $options
161
        );
162
    }
163
164
    /**
165
     * Load config.
166
     *
167
     * @param InputInterface $input Input
168
     *
169
     * @return array Config array
170
     */
171
    private function getUsableConfig(InputInterface $input)
172
    {
173
        $configLoader = new ConfigLoader();
174
        $configFinder = new ConfigFinder();
175
176
        /**
177
         * This section is just for finding the right values to work with in
178
         * this execution.
179
         *
180
         * $options array will have, after this block, all these values
181
         */
182
        $configPath = rtrim($input->getOption('config'), DIRECTORY_SEPARATOR);
183
184
        return $configLoader->loadConfigValues(
185
            self::COMMAND_NAME,
186
            $configFinder->findConfigFile($configPath),
187
            [
188
                'group' => $input->getOption('group'),
189
                'group-type' => $input->getOption('group-type'),
190
                'group-skip-empty' => $input->getOption('group-skip-empty'),
191
                'sort-type' => $input->getOption('sort-type'),
192
                'sort-direction' => $input->getOption('sort-direction'),
193
            ],
194
            [
195
                'group' => ['_main'],
196
                'group-type' => UseSorter::GROUP_TYPE_EACH,
197
                'group-skip-empty' => false,
198
                'sort-type' => UseSorter::SORT_TYPE_ALPHABETIC,
199
                'sort-direction' => UseSorter::SORT_DIRECTION_ASC,
200
            ]
201
        );
202
    }
203
204
    /**
205
     * Print the Dry-run message if needed.
206
     *
207
     * @param InputInterface  $input  Input
208
     * @param OutputInterface $output Output
209
     * @param string          $path   Path
210
     *
211
     * @return UseSortCommand self Object
212
     */
213
    private function printDryRunMessage(
214
        InputInterface $input,
215
        OutputInterface $output,
216
        $path
217
    ) {
218
        $dryRun = $input->getOption('dry-run');
219
        $verbose = $output->getVerbosity();
220
221
        /*
222
         * Dry-run message
223
         */
224
        if ($dryRun && $verbose >= OutputInterface::VERBOSITY_VERBOSE) {
225
            $output->writeln('# This process has been executed in mode dry-run');
226
        }
227
228
        if ($verbose >= OutputInterface::VERBOSITY_VERBOSE) {
229
            $output->writeln('# Executing process in ' . $path);
230
        }
231
232
        return $this;
233
    }
234
235
    /**
236
     * Print the configuration used by the command.
237
     *
238
     * @param OutputInterface $output  Output
239
     * @param array           $options Options used by the command
240
     *
241
     * @return UseSortCommand self Object
242
     */
243
    private function printConfigUsed(
244
        OutputInterface $output,
245
        array $options
246
    ) {
247
        $verbose = $output->getVerbosity();
248
249
        /*
250
         * If verbose level is higher or equal than -vv, we print the config
251
         * file data, if is not empty.
252
         */
253
        if ($verbose >= OutputInterface::VERBOSITY_VERBOSE) {
254
            $output->writeln('# Executing process with this configuration');
255
            if (!empty($options['group'])) {
256
                foreach ($options['group'] as $group) {
257
                    $output->writeln('#   --group="' . $group . '"');
258
                }
259
            }
260
261
            if (!empty($options['group-type'])) {
262
                $output->writeln('#   --group-type="' . $options['group-type'] . '"');
263
            }
264
265
            if (!empty($options['group-skip-empty'])) {
266
                $output->writeln('#   --group-skip-empty="' . $options['group-skip-empty'] . '"');
267
            }
268
269
            if (!empty($options['sort-type'])) {
270
                $output->writeln('#   --sort-type="' . $options['sort-type'] . '"');
271
            }
272
273
            if (!empty($options['sort-direction'])) {
274
                $output->writeln('#   --sort-direction="' . $options['sort-direction'] . '"');
275
            }
276
        }
277
278
        $output->writeln('#');
279
280
        return $this;
281
    }
282
283
    /**
284
     * Parse and fix all files found.
285
     *
286
     * @param InputInterface    $input   Input
287
     * @param OutputInterface   $output  Output
288
     * @param IteratorAggregate $files   Files
289
     * @param array             $options Options
290
     *
291
     * @return UseSortCommand self Object
292
     */
293
    private function parseAndFixFiles(
294
        InputInterface $input,
295
        OutputInterface $output,
296
        IteratorAggregate $files,
297
        array $options
298
299
    ) {
300
        $dryRun = $input->getOption('dry-run');
301
        $verbose = $output->getVerbosity();
302
        $useSorter = $this->createUseSorter($options);
303
304
        /*
305
         * Each found php file is processed
306
         */
307 View Code Duplication
        foreach ($files as $file) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
308
            $data = file_get_contents($file);
309
            $result = $useSorter->sort($data);
310
311
            if ($result === false || $data === $result) {
312
                continue;
313
            }
314
315
            if ($verbose >= OutputInterface::VERBOSITY_NORMAL) {
316
                $output->writeln('# ' . $file);
317
            }
318
319
            if (!$dryRun) {
320
                file_put_contents($file, $result);
321
            }
322
        }
323
324
        return $this;
325
    }
326
327
    /**
328
     * Create UseSorter Object given a configuration.
329
     *
330
     * @param array $options Options
331
     *
332
     * @return UseSorter Use sorter instance
333
     */
334
    private function createUseSorter(array $options)
335
    {
336
        /**
337
         * Creates the new UseSorter file, given config values.
338
         */
339
        $useSorter = new UseSorter();
340
        $useSorter
341
            ->setGroups($options['group'])
342
            ->setGroupType($options['group-type'])
343
            ->setGroupSkipEmpty($options['group-skip-empty'])
344
            ->setSortType($options['sort-type'])
345
            ->setSortDirection($options['sort-direction']);
346
347
        return $useSorter;
348
    }
349
}
350