Completed
Push — develop ( 34db25...1b1cc6 )
by Paul
02:36
created

FileExecutor   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 110
rs 10
c 0
b 0
f 0
wmc 11

3 Methods

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