vendor/liip/imagine-bundle/Service/FilterService.php line 123

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\Service;
  11. use Liip\ImagineBundle\Binary\BinaryInterface;
  12. use Liip\ImagineBundle\Exception\Imagine\Filter\NonExistingFilterException;
  13. use Liip\ImagineBundle\Imagine\Cache\CacheManager;
  14. use Liip\ImagineBundle\Imagine\Data\DataManager;
  15. use Liip\ImagineBundle\Imagine\Filter\FilterManager;
  16. use Psr\Log\LoggerInterface;
  17. use Psr\Log\NullLogger;
  18. class FilterService
  19. {
  20. /**
  21. * @var DataManager
  22. */
  23. private $dataManager;
  24. /**
  25. * @var FilterManager
  26. */
  27. private $filterManager;
  28. /**
  29. * @var CacheManager
  30. */
  31. private $cacheManager;
  32. /**
  33. * @var LoggerInterface
  34. */
  35. private $logger;
  36. /**
  37. * @var bool
  38. */
  39. private $webpGenerate;
  40. /**
  41. * @var mixed[]
  42. */
  43. private $webpOptions;
  44. public function __construct(
  45. DataManager $dataManager,
  46. FilterManager $filterManager,
  47. CacheManager $cacheManager,
  48. bool $webpGenerate = false,
  49. array $webpOptions = [],
  50. ?LoggerInterface $logger = null
  51. ) {
  52. $this->dataManager = $dataManager;
  53. $this->filterManager = $filterManager;
  54. $this->cacheManager = $cacheManager;
  55. $this->webpGenerate = $webpGenerate;
  56. $this->webpOptions = $webpOptions;
  57. $this->logger = $logger ?: new NullLogger();
  58. }
  59. /**
  60. * @param string $path
  61. * @param string $filter
  62. *
  63. * @return bool Returns true if we removed at least one cached image
  64. */
  65. public function bustCache($path, $filter)
  66. {
  67. $busted = false;
  68. foreach ($this->buildFilterPathContainers($path) as $filterPathContainer) {
  69. if ($this->cacheManager->isStored($filterPathContainer->getTarget(), $filter)) {
  70. $this->cacheManager->remove($filterPathContainer->getTarget(), $filter);
  71. $busted = true;
  72. }
  73. }
  74. return $busted;
  75. }
  76. /**
  77. * @param bool $forced Force warm up cache
  78. *
  79. * @return bool Returns true if the cache is warmed up
  80. */
  81. public function warmUpCache(
  82. string $path,
  83. string $filter,
  84. ?string $resolver = null,
  85. bool $forced = false
  86. ): bool {
  87. $warmedUp = false;
  88. foreach ($this->buildFilterPathContainers($path) as $filterPathContainer) {
  89. if ($this->warmUpCacheFilterPathContainer($filterPathContainer, $filter, $resolver, $forced)) {
  90. $warmedUp = true;
  91. }
  92. }
  93. return $warmedUp;
  94. }
  95. /**
  96. * @param string $path
  97. * @param string $filter
  98. * @param string|null $resolver
  99. *
  100. * @return string
  101. */
  102. public function getUrlOfFilteredImage($path, $filter, $resolver = null, bool $webpSupported = false)
  103. {
  104. foreach ($this->buildFilterPathContainers($path) as $filterPathContainer) {
  105. $this->warmUpCacheFilterPathContainer($filterPathContainer, $filter, $resolver);
  106. }
  107. return $this->resolveFilterPathContainer(new FilterPathContainer($path), $filter, $resolver, $webpSupported);
  108. }
  109. /**
  110. * @param string $path
  111. * @param string $filter
  112. * @param string|null $resolver
  113. *
  114. * @return string
  115. */
  116. public function getUrlOfFilteredImageWithRuntimeFilters(
  117. $path,
  118. $filter,
  119. array $runtimeFilters = [],
  120. $resolver = null,
  121. bool $webpSupported = false
  122. ) {
  123. $runtimePath = $this->cacheManager->getRuntimePath($path, $runtimeFilters);
  124. $runtimeOptions = [
  125. 'filters' => $runtimeFilters,
  126. ];
  127. foreach ($this->buildFilterPathContainers($path, $runtimePath, $runtimeOptions) as $filterPathContainer) {
  128. $this->warmUpCacheFilterPathContainer($filterPathContainer, $filter, $resolver);
  129. }
  130. return $this->resolveFilterPathContainer(
  131. new FilterPathContainer($path, $runtimePath, $runtimeOptions),
  132. $filter,
  133. $resolver,
  134. $webpSupported
  135. );
  136. }
  137. /**
  138. * @param mixed[] $options
  139. *
  140. * @return FilterPathContainer[]
  141. */
  142. private function buildFilterPathContainers(string $source, string $target = '', array $options = []): array
  143. {
  144. $basePathContainer = new FilterPathContainer($source, $target, $options);
  145. $filterPathContainers = [$basePathContainer];
  146. if ($this->webpGenerate) {
  147. $filterPathContainers[] = $basePathContainer->createWebp($this->webpOptions);
  148. }
  149. return $filterPathContainers;
  150. }
  151. private function resolveFilterPathContainer(
  152. FilterPathContainer $filterPathContainer,
  153. string $filter,
  154. ?string $resolver = null,
  155. bool $webpSupported = false
  156. ): string {
  157. $path = $filterPathContainer->getTarget();
  158. if ($this->webpGenerate && $webpSupported) {
  159. $path = $filterPathContainer->createWebp($this->webpOptions)->getTarget();
  160. }
  161. return $this->cacheManager->resolve($path, $filter, $resolver);
  162. }
  163. /**
  164. * @param bool $forced Force warm up cache
  165. *
  166. * @return bool Returns true if the cache is warmed up
  167. */
  168. private function warmUpCacheFilterPathContainer(
  169. FilterPathContainer $filterPathContainer,
  170. string $filter,
  171. ?string $resolver = null,
  172. bool $forced = false
  173. ): bool {
  174. if ($forced || !$this->cacheManager->isStored($filterPathContainer->getTarget(), $filter, $resolver)) {
  175. $this->cacheManager->store(
  176. $this->createFilteredBinary($filterPathContainer, $filter),
  177. $filterPathContainer->getTarget(),
  178. $filter,
  179. $resolver
  180. );
  181. return true;
  182. }
  183. return false;
  184. }
  185. /**
  186. * @throws NonExistingFilterException
  187. */
  188. private function createFilteredBinary(FilterPathContainer $filterPathContainer, string $filter): BinaryInterface
  189. {
  190. $binary = $this->dataManager->find($filter, $filterPathContainer->getSource());
  191. try {
  192. return $this->filterManager->applyFilter($binary, $filter, $filterPathContainer->getOptions());
  193. } catch (NonExistingFilterException $e) {
  194. $this->logger->debug(\sprintf(
  195. 'Could not locate filter "%s" for path "%s". Message was "%s"',
  196. $filter,
  197. $filterPathContainer->getSource(),
  198. $e->getMessage()
  199. ));
  200. throw $e;
  201. }
  202. }
  203. }