Completed
Push — upgrade-2.0-from-1.0 ( 918602 )
by David
13:04
created

FileSystemLocator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 3
dl 0
loc 141
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setOptions() 0 18 2
A locate() 0 13 3
A locateUsingRootPathsSearch() 0 10 3
A locateUsingRootPlaceholder() 0 13 4
A generateAbsolutePath() 0 4 1
A sanitizeRootPath() 0 8 3
A sanitizeAbsolutePath() 0 11 3
1
<?php
2
3
/*
4
 * This file is part of the `liip/LiipImagineBundle` project.
5
 *
6
 * (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
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 Liip\ImagineBundle\Binary\Locator;
13
14
use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
15
use Liip\ImagineBundle\Exception\InvalidArgumentException;
16
use Symfony\Component\OptionsResolver\Exception\ExceptionInterface;
17
use Symfony\Component\OptionsResolver\OptionsResolver;
18
19
class FileSystemLocator implements LocatorInterface
20
{
21
    /**
22
     * @var string[]
23
     */
24
    private $roots = [];
25
26
    /**
27
     * @param string[] $roots
28
     */
29
    public function __construct(array $roots = array())
30
    {
31
        $this->roots = array_map(array($this, 'sanitizeRootPath'), $roots);
32
    }
33
34
    /**
35
     * @deprecated Since version 0.9.0, use __construct(array $roots) instead
36
     *
37
     * @param array[] $options
38
     */
39
    public function setOptions(array $options = [])
40
    {
41
        $resolver = new OptionsResolver();
42
        $resolver->setDefaults(['roots' => []]);
43
44
        try {
45
            $options = $resolver->resolve($options);
46
        } catch (ExceptionInterface $e) {
47
            throw new InvalidArgumentException(sprintf('Invalid options provided to %s()', __METHOD__), null, $e);
48
        }
49
50
        @trigger_error(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
51
            sprintf('%s() is deprecated. Pass the data roots to the constructor instead.', __METHOD__),
52
            E_USER_DEPRECATED
53
        );
54
55
        $this->roots = array_map([$this, 'sanitizeRootPath'], (array) $options['roots']);
56
    }
57
58
    /**
59
     * @param string $path
60
     *
61
     * @throws NotLoadableException
62
     *
63
     * @return string
64
     */
65
    public function locate($path)
66
    {
67
        if (false !== $absolute = $this->locateUsingRootPlaceholder($path)) {
68
            return $this->sanitizeAbsolutePath($absolute);
69
        }
70
71
        if (false !== $absolute = $this->locateUsingRootPathsSearch($path)) {
72
            return $this->sanitizeAbsolutePath($absolute);
73
        }
74
75
        throw new NotLoadableException(sprintf('Source image not resolvable "%s" in root path(s) "%s"',
76
            $path, implode(':', $this->roots)));
77
    }
78
79
    /**
80
     * @param string $path
81
     *
82
     * @return bool|string
83
     */
84
    private function locateUsingRootPathsSearch($path)
85
    {
86
        foreach ($this->roots as $root) {
87
            if (false !== $absolute = $this->generateAbsolutePath($root, $path)) {
88
                return $absolute;
89
            }
90
        }
91
92
        return false;
93
    }
94
95
    /**
96
     * @param string $path
97
     *
98
     * @return bool|string
99
     */
100
    private function locateUsingRootPlaceholder($path)
101
    {
102
        if (0 !== strpos($path, '@') || 1 !== preg_match('{@(?<name>[^:]+):(?<path>.+)}', $path, $matches)) {
103
            return false;
104
        }
105
106
        if (isset($this->roots[$matches['name']])) {
107
            return $this->generateAbsolutePath($this->roots[$matches['name']], $matches['path']);
108
        }
109
110
        throw new NotLoadableException(sprintf('Invalid root placeholder "%s" for path "%s"',
111
            $matches['name'], $matches['path']));
112
    }
113
114
    /**
115
     * @param string $root
116
     * @param string $path
117
     *
118
     * @return string|false
119
     */
120
    protected function generateAbsolutePath($root, $path)
121
    {
122
        return realpath($root.DIRECTORY_SEPARATOR.$path);
123
    }
124
125
    /**
126
     * @param string $root
127
     *
128
     * @throws InvalidArgumentException
129
     *
130
     * @return string
131
     */
132
    private function sanitizeRootPath($root)
133
    {
134
        if (!empty($root) && false !== $realRoot = realpath($root)) {
135
            return $realRoot;
136
        }
137
138
        throw new InvalidArgumentException(sprintf('Root image path not resolvable "%s"', $root));
139
    }
140
141
    /**
142
     * @param string $path
143
     *
144
     * @throws NotLoadableException
145
     *
146
     * @return string
147
     */
148
    private function sanitizeAbsolutePath($path)
149
    {
150
        foreach ($this->roots as $root) {
151
            if (0 === strpos($path, $root)) {
152
                return $path;
153
            }
154
        }
155
156
        throw new NotLoadableException(sprintf('Source image invalid "%s" as it is outside of the defined root path(s) "%s"',
157
            $path, implode(':', $this->roots)));
158
    }
159
}
160