Completed
Pull Request — 1.0 (#937)
by
unknown
02:35
created

FileSystemLocator::sanitizeRootPath()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 4
nc 2
nop 1
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 = array();
25
26
    public function __construct(array $dataRoots = array())
27
    {
28
        $this->setOptions(array('roots' => $dataRoots));
29
    }
30
31
    /**
32
     * @param array[] $options
33
     */
34
    public function setOptions(array $options = array())
35
    {
36
        $resolver = new OptionsResolver();
37
        $resolver->setDefaults(array('roots' => array()));
38
39
        try {
40
            $options = $resolver->resolve($options);
41
        } catch (ExceptionInterface $e) {
42
            throw new InvalidArgumentException(sprintf('Invalid options provided to %s()', __METHOD__), null, $e);
43
        }
44
45
        $this->roots = array_map(array($this, 'sanitizeRootPath'), (array) $options['roots']);
46
    }
47
48
    /**
49
     * @param string $path
50
     *
51
     * @throws NotLoadableException
52
     *
53
     * @return string
54
     */
55
    public function locate($path)
56
    {
57
        if (false !== $absolute = $this->locateUsingRootPlaceholder($path)) {
58
            return $this->sanitizeAbsolutePath($absolute);
59
        }
60
61
        if (false !== $absolute = $this->locateUsingRootPathsSearch($path)) {
62
            return $this->sanitizeAbsolutePath($absolute);
63
        }
64
65
        throw new NotLoadableException(sprintf('Source image not resolvable "%s" in root path(s) "%s"',
66
            $path, implode(':', $this->roots)));
67
    }
68
69
    /**
70
     * @param string $path
71
     *
72
     * @return bool|string
73
     */
74
    private function locateUsingRootPathsSearch($path)
75
    {
76
        foreach ($this->roots as $root) {
77
            if (false !== $absolute = $this->generateAbsolutePath($root, $path)) {
78
                return $absolute;
79
            }
80
        }
81
82
        return false;
83
    }
84
85
    /**
86
     * @param string $path
87
     *
88
     * @return bool|string
89
     */
90
    private function locateUsingRootPlaceholder($path)
91
    {
92
        if (0 !== strpos($path, '@') || 1 !== preg_match('{@(?<name>[^:]+):(?<path>.+)}', $path, $matches)) {
93
            return false;
94
        }
95
96
        if (isset($this->roots[$matches['name']])) {
97
            return $this->generateAbsolutePath($this->roots[$matches['name']], $matches['path']);
98
        }
99
100
        throw new NotLoadableException(sprintf('Invalid root placeholder "%s" for path "%s"',
101
            $matches['name'], $matches['path']));
102
    }
103
104
    /**
105
     * @param string $root
106
     * @param string $path
107
     *
108
     * @return string|false
109
     */
110
    protected function generateAbsolutePath($root, $path)
111
    {
112
        return realpath($root.DIRECTORY_SEPARATOR.$path);
113
    }
114
115
    /**
116
     * @param string $root
117
     *
118
     * @throws InvalidArgumentException
119
     *
120
     * @return string
121
     */
122
    private function sanitizeRootPath($root)
123
    {
124
        if (!empty($root) && false !== $realRoot = realpath($root)) {
125
            return $realRoot;
126
        }
127
128
        throw new InvalidArgumentException(sprintf('Root image path not resolvable "%s"', $root));
129
    }
130
131
    /**
132
     * @param string $path
133
     *
134
     * @throws NotLoadableException
135
     *
136
     * @return string
137
     */
138
    private function sanitizeAbsolutePath($path)
139
    {
140
        foreach ($this->roots as $root) {
141
            if (0 === strpos($path, $root)) {
142
                return $path;
143
            }
144
        }
145
146
        throw new NotLoadableException(sprintf('Source image invalid "%s" as it is outside of the defined root path(s) "%s"',
147
            $path, implode(':', $this->roots)));
148
    }
149
}
150