Passed
Branch master (9232c0)
by Johannes
02:26
created

FileCache::renameFile()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.5555
c 0
b 0
f 0
cc 5
nc 5
nop 2
1
<?php
2
3
namespace Metadata\Cache;
4
5
use Metadata\ClassMetadata;
6
7
class FileCache implements CacheInterface
8
{
9
    private $dir;
10
11
    public function __construct(string $dir)
12
    {
13
        if (!is_dir($dir)) {
14
            throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
15
        }
16
        if (!is_writable($dir)) {
17
            throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.', $dir));
18
        }
19
20
        $this->dir = rtrim($dir, '\\/');
21
    }
22
23
    /**
24
     * {@inheritDoc}
25
     */
26
    public function load(string $class): ?ClassMetadata
27
    {
28
        $path = $this->dir . '/' . strtr($class, '\\', '-') . '.cache.php';
29
        if (!file_exists($path)) {
30
            return null;
31
        }
32
33
        return include $path;
34
    }
35
36
    /**
37
     * {@inheritDoc}
38
     */
39
    public function put(ClassMetadata $metadata): void
40
    {
41
        $path = $this->dir . '/' . strtr($metadata->name, '\\', '-') . '.cache.php';
42
43
        $tmpFile = tempnam($this->dir, 'metadata-cache');
44
        file_put_contents($tmpFile, '<?php return unserialize(' . var_export(serialize($metadata), true) . ');');
45
46
        // Let's not break filesystems which do not support chmod.
47
        @chmod($tmpFile, 0666 & ~umask());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

47
        /** @scrutinizer ignore-unhandled */ @chmod($tmpFile, 0666 & ~umask());

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
48
49
        $this->renameFile($tmpFile, $path);
50
    }
51
52
    /**
53
     * Renames a file with fallback for windows
54
     *
55
     * @param string $source
56
     * @param string $target
57
     */
58
    private function renameFile($source, $target)
59
    {
60
        if (false === @rename($source, $target)) {
61
            if (defined('PHP_WINDOWS_VERSION_BUILD')) {
62
                if (false === copy($source, $target)) {
63
                    throw new \RuntimeException(sprintf('(WIN) Could not write new cache file to %s.', $target));
64
                }
65
                if (false === unlink($source)) {
66
                    throw new \RuntimeException(sprintf('(WIN) Could not delete temp cache file to %s.', $source));
67
                }
68
            } else {
69
                throw new \RuntimeException(sprintf('Could not write new cache file to %s.', $target));
70
            }
71
        }
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     */
77
    public function evict(string $class): void
78
    {
79
        $path = $this->dir . '/' . strtr($class, '\\', '-') . '.cache.php';
80
        if (file_exists($path)) {
81
            unlink($path);
82
        }
83
    }
84
}
85