Completed
Push — master ( 3be072...ba2d3a )
by Marco
231:32 queued 209:55
created

FileWriterGeneratorStrategy   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 65
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 65
c 0
b 0
f 0
wmc 5
lcom 1
cbo 1
ccs 23
cts 23
cp 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManager\GeneratorStrategy;
6
7
use Closure;
8
use ProxyManager\Exception\FileNotWritableException;
9
use ProxyManager\FileLocator\FileLocatorInterface;
10
use Zend\Code\Generator\ClassGenerator;
11
use function chmod;
12
use function dirname;
13
use function file_put_contents;
14
use function rename;
15
use function restore_error_handler;
16
use function set_error_handler;
17
use function tempnam;
18
use function trim;
19
use function umask;
20
use function unlink;
21
22
/**
23
 * Generator strategy that writes the generated classes to disk while generating them
24
 *
25
 * {@inheritDoc}
26
 */
27
class FileWriterGeneratorStrategy implements GeneratorStrategyInterface
28
{
29
    protected FileLocatorInterface $fileLocator;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
30
    private Closure $emptyErrorHandler;
31
32
    public function __construct(FileLocatorInterface $fileLocator)
33
    {
34
        $this->fileLocator       = $fileLocator;
35 4
        $this->emptyErrorHandler = static function () : void {
36
        };
37 4
    }
38
39 3
    /**
40 4
     * Write generated code to disk and return the class code
41
     *
42
     * {@inheritDoc}
43
     *
44
     * @throws FileNotWritableException
45
     */
46
    public function generate(ClassGenerator $classGenerator) : string
47
    {
48
        $className     = trim($classGenerator->getNamespaceName(), '\\')
49 4
            . '\\' . trim($classGenerator->getName(), '\\');
50
        $generatedCode = $classGenerator->generate();
51 4
        $fileName      = $this->fileLocator->getProxyFileName($className);
52 4
53 4
        set_error_handler($this->emptyErrorHandler);
54 4
55
        try {
56 4
            $this->writeFile("<?php\n\n" . $generatedCode, $fileName);
57
58
            return $generatedCode;
59 4
        } finally {
60
            restore_error_handler();
61 1
        }
62
    }
63 4
64
    /**
65
     * Writes the source file in such a way that race conditions are avoided when the same file is written
66
     * multiple times in a short time period
67
     *
68
     * @throws FileNotWritableException
69
     */
70
    private function writeFile(string $source, string $location) : void
71
    {
72
        $directory   = dirname($location);
73
        $tmpFileName = tempnam($directory, 'temporaryProxyManagerFile');
74 4
75
        if ($tmpFileName === false) {
76 4
            throw FileNotWritableException::fromNotWritableDirectory($directory);
77 4
        }
78
79 4
        file_put_contents($tmpFileName, $source);
80 1
        chmod($tmpFileName, 0666 & ~umask());
81
82
        if (! rename($tmpFileName, $location)) {
83 3
            unlink($tmpFileName);
84 3
85
            throw FileNotWritableException::fromInvalidMoveOperation($tmpFileName, $location);
86 3
        }
87 2
    }
88
}
89