FileExecutor   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 38
c 1
b 0
f 0
dl 0
loc 117
rs 10
wmc 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A checkTargetPath() 0 17 5
A invoke() 0 30 4
A __construct() 0 14 1
1
<?php
2
3
/**
4
 * This file is part of PhpUnitGen.
5
 *
6
 * (c) 2017-2018 Paul Thébaud <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace PhpUnitGen\Executor;
13
14
use League\Flysystem\FilesystemInterface;
15
use PhpUnitGen\Configuration\ConfigurationInterface\ConsoleConfigInterface;
16
use PhpUnitGen\Exception\FileExistsException;
17
use PhpUnitGen\Exception\ParseException;
18
use PhpUnitGen\Executor\ExecutorInterface\ExecutorInterface;
19
use PhpUnitGen\Executor\ExecutorInterface\FileExecutorInterface;
20
use PhpUnitGen\Report\ReportInterface\ReportInterface;
21
use PhpUnitGen\Validator\ValidatorInterface\FileValidatorInterface;
22
use Symfony\Component\Console\Style\StyleInterface;
23
24
/**
25
 * Class FileExecutor.
26
 *
27
 * @author     Paul Thébaud <[email protected]>.
28
 * @copyright  2017-2018 Paul Thébaud <[email protected]>.
29
 * @license    https://opensource.org/licenses/MIT The MIT license.
30
 * @link       https://github.com/paul-thebaud/phpunit-generator
31
 * @since      Class available since Release 2.0.0.
32
 */
33
class FileExecutor implements FileExecutorInterface
34
{
35
    /**
36
     * @var ConsoleConfigInterface $config The configuration to use.
37
     */
38
    private $config;
39
40
    /**
41
     * @var StyleInterface $output The output to display message.
42
     */
43
    private $output;
44
45
    /**
46
     * @var ExecutorInterface $executor The executor for php code.
47
     */
48
    private $executor;
49
50
    /**
51
     * @var FilesystemInterface $fileSystem The file system to use.
52
     */
53
    private $fileSystem;
54
55
    /**
56
     * @var FileValidatorInterface $fileValidator The file validator to know which files we need to parse.
57
     */
58
    private $fileValidator;
59
60
    /**
61
     * @var ReportInterface $report The report to use.
62
     */
63
    private $report;
64
65
    /**
66
     * DirectoryParser constructor.
67
     *
68
     * @param ConsoleConfigInterface $config        A config instance.
69
     * @param StyleInterface         $output        An output to display message.
70
     * @param ExecutorInterface      $executor      A PhpUnitGen executor.
71
     * @param FilesystemInterface    $fileSystem    A file system instance.
72
     * @param FileValidatorInterface $fileValidator A file validator.
73
     * @param ReportInterface        $report        The report to use.
74
     */
75
    public function __construct(
76
        ConsoleConfigInterface $config,
77
        StyleInterface $output,
78
        ExecutorInterface $executor,
79
        FilesystemInterface $fileSystem,
80
        FileValidatorInterface $fileValidator,
81
        ReportInterface $report
82
    ) {
83
        $this->config        = $config;
84
        $this->output        = $output;
85
        $this->executor      = $executor;
86
        $this->fileSystem    = $fileSystem;
87
        $this->fileValidator = $fileValidator;
88
        $this->report        = $report;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function invoke(string $sourcePath, string $targetPath, string $name): bool
95
    {
96
        if (! $this->fileValidator->validate($sourcePath)) {
97
            return false;
98
        }
99
100
        $content = $this->fileSystem->read($sourcePath);
101
102
        if ($content === false) {
103
            throw new ParseException(sprintf('The file "%s" is not readable', $sourcePath));
104
        }
105
106
        // We ignore the type checked because we already check the readability
107
        $code = $this->executor->invoke($content, $name);
108
109
        if ($code === null) {
110
            $this->output->note(sprintf('Parsing file "%s" completed: no testable functions in code', $sourcePath));
111
            return false;
112
        }
113
114
        $this->checkTargetPath($targetPath);
115
116
        $this->fileSystem->write($targetPath, $code);
117
118
        // Output that a file is parsed
119
        $this->output->text(sprintf('Parsing file "%s" completed', $sourcePath));
120
121
        $this->report->increaseParsedFileNumber();
122
123
        return true;
124
    }
125
126
    /**
127
     * Check if an old file exists. If overwrite option is activated, delete it, else, throw an exception.
128
     *
129
     * @param string $targetPath The target file path.
130
     *
131
     * @throws FileExistsException If overwrite option is deactivated and file exists.
132
     */
133
    public function checkTargetPath(string $targetPath): void
134
    {
135
        if ($this->fileSystem->has($targetPath)) {
136
            if (! $this->config->hasOverwrite()) {
137
                throw new FileExistsException(sprintf('The target file "%s" already exists', $targetPath));
138
            }
139
            if ($this->config->hasBackup()) {
140
                $backupTarget = $targetPath . '.bak';
141
                if ($this->fileSystem->has($backupTarget)) {
142
                    throw new FileExistsException(sprintf(
143
                        'The backup target file "%s" already exists',
144
                        $backupTarget
145
                    ));
146
                }
147
                $this->fileSystem->copy($targetPath, $backupTarget);
148
            }
149
            $this->fileSystem->delete($targetPath);
150
        }
151
    }
152
}
153