• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tito10047 / progressive-image-bundle / 20661461972

02 Jan 2026 03:57PM UTC coverage: 89.065% (+0.2%) from 88.816%
20661461972

push

github

tito10047
add Point of Interest (PoI) cropping: implement PoI support in URL generation, runtime configuration, and image rendering; update tests and documentation

28 of 28 new or added lines in 5 files covered. (100.0%)

2 existing lines in 1 file now uncovered.

562 of 631 relevant lines covered (89.06%)

166.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.88
/src/Resolver/FileSystemResolver.php
1
<?php
2

3
/*
4
 * This file was 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 Tito10047\ProgressiveImageBundle\Resolver;
13

14
use Tito10047\ProgressiveImageBundle\Exception\PathResolutionException;
15

16
class FileSystemResolver implements PathResolverInterface
17
{
18
    /**
19
     * @var string[]
20
     */
21
    private $roots = [];
22

23
    /**
24
     * @param string[] $roots
25
     */
26
    public function __construct(array $roots = [], bool $allowUnresolvable = false)
27
    {
28
        $this->roots = array_filter(array_map(function (string $root) use ($allowUnresolvable): ?string {
362✔
29
            return $this->sanitizeRootPath($root, $allowUnresolvable);
362✔
30
        }, $roots));
362✔
31
    }
32

33
    /**
34
     * @throws PathResolutionException
35
     */
36
    public function resolve(string $path): string
37
    {
38
        if (null !== $absolute = $this->locateUsingRootPlaceholder($path)) {
305✔
39
            return $this->sanitizeAbsolutePath($absolute);
15✔
40
        }
41

42
        if (null !== $absolute = $this->locateUsingRootPathsSearch($path)) {
290✔
43
            return $this->sanitizeAbsolutePath($absolute);
171✔
44
        }
45

46
        throw new PathResolutionException(\sprintf('Source image not resolvable "%s" in root path(s) "%s"', $path, implode(':', $this->roots)));
119✔
47
    }
48

49
    protected function generateAbsolutePath(string $root, string $path): ?string
50
    {
51
        if (false !== $absolute = realpath($root.DIRECTORY_SEPARATOR.$path)) {
300✔
52
            return $absolute;
186✔
53
        }
54

55
        return null;
114✔
56
    }
57

58
    private function locateUsingRootPathsSearch(string $path): ?string
59
    {
60
        foreach ($this->roots as $root) {
290✔
61
            if (null !== $absolute = $this->generateAbsolutePath($root, $path)) {
285✔
62
                return $absolute;
171✔
63
            }
64
        }
65

66
        return null;
119✔
67
    }
68

69
    private function locateUsingRootPlaceholder(string $path): ?string
70
    {
71
        if (0 !== mb_strpos($path, '@') || 1 !== preg_match('{^@(?<name>[^:]+):(?<path>.+)$}', $path, $match)) {
305✔
72
            return null;
290✔
73
        }
74

75
        if (isset($this->roots[$match['name']])) {
15✔
76
            return $this->generateAbsolutePath($this->roots[$match['name']], $match['path']);
15✔
77
        }
78

79
        throw new PathResolutionException(\sprintf('Invalid root placeholder "@%s" for path "%s"', $match['name'], $match['path']));
×
80
    }
81

82
    /**
83
     * @throws \InvalidArgumentException
84
     */
85
    private function sanitizeRootPath(string $path, bool $allowUnresolvable): ?string
86
    {
87
        if (!empty($path) && false !== $real = realpath($path)) {
362✔
88
            return $real;
356✔
89
        }
90

UNCOV
91
        if ($allowUnresolvable) {
6✔
UNCOV
92
            return null;
6✔
93
        }
94

95
        throw new \InvalidArgumentException(\sprintf('Root image path not resolvable "%s"', $path));
×
96
    }
97

98
    /**
99
     * @throws PathResolutionException
100
     */
101
    private function sanitizeAbsolutePath(string $path): string
102
    {
103
        $roots = array_filter($this->roots, function (string $root) use ($path): bool {
186✔
104
            return 0 === mb_strpos($path, $root);
186✔
105
        });
186✔
106

107
        if (0 === \count($roots)) {
186✔
108
            throw new PathResolutionException(\sprintf('Source image invalid "%s" as it is outside of the defined root path(s) "%s"', $path, implode(':', $this->roots)));
×
109
        }
110

111
        if (!is_readable($path)) {
186✔
112
            throw new PathResolutionException(\sprintf('Source image invalid "%s" as it is not readable', $path));
×
113
        }
114

115
        return $path;
186✔
116
    }
117
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc