vendor/liip/imagine-bundle/Binary/Locator/FileSystemLocator.php line 47

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the `liip/LiipImagineBundle` project.
  4. *
  5. * (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
  6. *
  7. * For the full copyright and license information, please view the LICENSE.md
  8. * file that was distributed with this source code.
  9. */
  10. namespace Liip\ImagineBundle\Binary\Locator;
  11. use Liip\ImagineBundle\Exception\Binary\Loader\NotLoadableException;
  12. use Liip\ImagineBundle\Exception\InvalidArgumentException;
  13. class FileSystemLocator implements LocatorInterface
  14. {
  15. /**
  16. * @var string[]
  17. */
  18. private $roots = [];
  19. /**
  20. * @param string[] $roots
  21. */
  22. public function __construct(array $roots = [], bool $allowUnresolvable = false)
  23. {
  24. $this->roots = array_filter(array_map(function (string $root) use ($allowUnresolvable): ?string {
  25. return $this->sanitizeRootPath($root, $allowUnresolvable);
  26. }, $roots));
  27. }
  28. /**
  29. * @throws NotLoadableException
  30. */
  31. public function locate(string $path): string
  32. {
  33. if (null !== $absolute = $this->locateUsingRootPlaceholder($path)) {
  34. return $this->sanitizeAbsolutePath($absolute);
  35. }
  36. if (null !== $absolute = $this->locateUsingRootPathsSearch($path)) {
  37. return $this->sanitizeAbsolutePath($absolute);
  38. }
  39. throw new NotLoadableException(\sprintf('Source image not resolvable "%s" in root path(s) "%s"', $path, implode(':', $this->roots)));
  40. }
  41. protected function generateAbsolutePath(string $root, string $path): ?string
  42. {
  43. if (false !== $absolute = realpath($root.DIRECTORY_SEPARATOR.$path)) {
  44. return $absolute;
  45. }
  46. return null;
  47. }
  48. private function locateUsingRootPathsSearch(string $path): ?string
  49. {
  50. foreach ($this->roots as $root) {
  51. if (null !== $absolute = $this->generateAbsolutePath($root, $path)) {
  52. return $absolute;
  53. }
  54. }
  55. return null;
  56. }
  57. private function locateUsingRootPlaceholder(string $path): ?string
  58. {
  59. if (0 !== mb_strpos($path, '@') || 1 !== preg_match('{^@(?<name>[^:]+):(?<path>.+)$}', $path, $match)) {
  60. return null;
  61. }
  62. if (isset($this->roots[$match['name']])) {
  63. return $this->generateAbsolutePath($this->roots[$match['name']], $match['path']);
  64. }
  65. throw new NotLoadableException(\sprintf('Invalid root placeholder "@%s" for path "%s"', $match['name'], $match['path']));
  66. }
  67. /**
  68. * @throws InvalidArgumentException
  69. */
  70. private function sanitizeRootPath(string $path, bool $allowUnresolvable): ?string
  71. {
  72. if (!empty($path) && false !== $real = realpath($path)) {
  73. return $real;
  74. }
  75. if ($allowUnresolvable) {
  76. return null;
  77. }
  78. throw new InvalidArgumentException(\sprintf('Root image path not resolvable "%s"', $path));
  79. }
  80. /**
  81. * @throws NotLoadableException
  82. */
  83. private function sanitizeAbsolutePath(string $path): string
  84. {
  85. $roots = array_filter($this->roots, function (string $root) use ($path): bool {
  86. return 0 === mb_strpos($path, $root);
  87. });
  88. if (0 === \count($roots)) {
  89. throw new NotLoadableException(\sprintf('Source image invalid "%s" as it is outside of the defined root path(s) "%s"', $path, implode(':', $this->roots)));
  90. }
  91. if (!is_readable($path)) {
  92. throw new NotLoadableException(\sprintf('Source image invalid "%s" as it is not readable', $path));
  93. }
  94. return $path;
  95. }
  96. }