Skip to content

Commit

Permalink
initial draft
Browse files Browse the repository at this point in the history
  • Loading branch information
dbu committed Jun 19, 2024
1 parent 68bcdb4 commit f85edf9
Show file tree
Hide file tree
Showing 11 changed files with 452 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/Domain/ImageReference.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Liip\ImagineBundle\Domain;

interface ImageReference
{
public function getContent(): string;

public function getMimeType(): ?string;

public function getFormat(): ?string;
}
8 changes: 8 additions & 0 deletions src/Domain/ImageReferenceFile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Liip\ImagineBundle\Domain;

interface ImageReferenceFile extends ImageReference
{
public function getPath(): string;
}
22 changes: 22 additions & 0 deletions src/Domain/Imagine/Filter/FilterExecutor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/*
* This file is part of the `liip/LiipImagineBundle` project.
*
* (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/

namespace Liip\ImagineBundle\Domain\Imagine\Filter;

use Imagine\Image\ImageInterface;

interface FilterExecutor
{
/**
* Loads and applies a filter on the given image.
*/
public function applyTo(ImageInterface $image, array $options = []): ImageInterface;

Check failure on line 21 in src/Domain/Imagine/Filter/FilterExecutor.php

View workflow job for this annotation

GitHub Actions / phpstan

Method Liip\ImagineBundle\Domain\Imagine\Filter\FilterExecutor::applyTo() has parameter $options with no value type specified in iterable type array.
}
53 changes: 53 additions & 0 deletions src/Domain/ImagineTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Liip\ImagineBundle\Domain;

/**
* Main entry point into the imagine system.
*
* The transformer takes an image id, does all necessary transformations (and potentially caching) and gives the URL to the result image.
*/
interface ImagineTransformer
{
/**
* Determine the URL to the transformed image.
*
* For performance reasons, this method SHOULD cache the resulting images and skip transformation when it already exists.
*
* Calling the URL must result in the image being returned.
* If possible, the image should only be generated on the fly when the URL is called.
*
* @param string $sourceImageId Identifier for the image, for example a file system path
* @param string $stackName The stack name as configured
* @param string $targetFormat Output format to generate
*
* @return string URL to where the image is available
*
* @throws ImageNotFoundException
* @throws StackNotFoundException
* @throws FormatNotSupportedException The requested image format can not be generated by the system (The transformer does not know about browser capabilities)
* @throws TransformingException Something went wrong while transforming the image
*/
public function transformToUrl(string $sourceImageId, string $stackName, string $targetFormat): string;

Check failure on line 31 in src/Domain/ImagineTransformer.php

View workflow job for this annotation

GitHub Actions / phpstan

PHPDoc tag @throws with type Liip\ImagineBundle\Domain\FormatNotSupportedException|Liip\ImagineBundle\Domain\ImageNotFoundException|Liip\ImagineBundle\Domain\StackNotFoundException|Liip\ImagineBundle\Domain\TransformingException is not subtype of Throwable

/**
* Force generating the transformed image.
*
* If the result image is already cached, it will be regenerated and overwritten.
*
* There is no cache lifetime defined. The application is expected to use active invalidation if the source image changes.
*
* @param string $sourceImageId Identifier for the image, for example a file system path
* @param string[] $stackNames
* @param string[] $targetFormats
*/
public function warmupCache(string $sourceImageId, array $stackNames, array $targetFormats): void;

/**
* Remove cached images for the specified source image.
*
* @param string $sourceImageId Identifier for the image, for example a file system path
* @param string[] $stackNames Limit invalidation to the specified stacks. If empty, all stacks are invalidated.
*/
public function invalidateCache(string $sourceImageId, array $stackNames = []): void;
}
54 changes: 54 additions & 0 deletions src/Domain/LiipImagineTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Liip\ImagineBundle\Domain;

use Liip\ImagineBundle\Domain\Stack\TransformerStackExecutor;
use Liip\ImagineBundle\Domain\Storage\ImageLoader;
use Liip\ImagineBundle\Domain\Storage\ImageStore;

/**
* Main entry point into the imagine system.
*
* The transformer takes an image id, does all necessary transformations (and potentially caching) and gives the URL to the result image.
*/
final class LiipImagineTransformer implements ImagineTransformer
{
public function __construct(
private ImageLoader $sourceImageLoader,
private TransformerStackExecutor $transformerStackExecutor,
private ImageStore $imageStore,
) {}

public function transformToUrl(string $sourceImageId, string $stackName, string $targetFormat): string
{
if ($this->imageStore->supportsOnDemandCreation()
|| $this->imageStore->exists($sourceImageId, $stackName, $targetFormat)
) {
return $this->imageStore->getUrl($sourceImageId, $stackName, $targetFormat);
}

$this->warmupCache($sourceImageId, [$stackName], [$targetFormat]);

return $this->imageStore->getUrl($sourceImageId, $stackName, $targetFormat);
}

public function warmupCache(string $sourceImageId, array $stackNames, array $targetFormats): void
{
if (0 === count($stackNames)) {
throw new \Exception('TODO: implement determining all stack names');
}
$sourceImage = $this->sourceImageLoader->loadImage($sourceImageId);
foreach ($stackNames as $stackName) {
foreach ($targetFormats as $targetFormat) {
// TODO: if we would separate stack executor creation and execution, we could build the stack only once and apply it for each target format
$transformedImage = $this->transformerStackExecutor->apply($stackName, $sourceImage);
$this->imageStore->store($transformedImage, $sourceImageId, $stackName, $targetFormat);
}
}
}

public function invalidateCache(string $sourceImageId, array $stackNames = []): void
{
$this->imageStore->delete($sourceImageId, $stackNames);
}
}
29 changes: 29 additions & 0 deletions src/Domain/PostProcessor/PostProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of the `liip/LiipImagineBundle` project.
*
* (c) https://github.com/liip/LiipImagineBundle/graphs/contributors
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/

namespace Liip\ImagineBundle\Domain\PostProcessor;

use Liip\ImagineBundle\Domain\ImageReference;

/**
* Post processors do additional work on the resulting image after filters have been applied.
*
* @author Konstantin Tjuterev <[email protected]>
*/
interface PostProcessor
{
/**
* Allows processing a BinaryInterface, with run-time options, so PostProcessors remain stateless.
*
* @param array<mixed> $options Operation-specific options
*/
public function process(ImageReference $binary, array $options = []): ImageReference;
}
31 changes: 31 additions & 0 deletions src/Domain/Stack/LiipTransformerStack.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Liip\ImagineBundle\Domain\Stack;

use Liip\ImagineBundle\Domain\ImageReference;
use Liip\ImagineBundle\Imagine\Filter\PostProcessor\PostProcessorInterface;

class LiipTransformerStack implements TransformerStack

Check failure on line 8 in src/Domain/Stack/LiipTransformerStack.php

View workflow job for this annotation

GitHub Actions / phpstan

Class Liip\ImagineBundle\Domain\Stack\LiipTransformerStack implements unknown interface Liip\ImagineBundle\Domain\Stack\TransformerStack.
{
/**
* @param FilterInterface[] $filters # used to be Filter\Loader\LoaderInterface
* @param PostProcessorInterface[] $postProcessors
*/
public function __construct(
private array $filters,

Check failure on line 15 in src/Domain/Stack/LiipTransformerStack.php

View workflow job for this annotation

GitHub Actions / phpstan

Parameter $filters of method Liip\ImagineBundle\Domain\Stack\LiipTransformerStack::__construct() has invalid type Liip\ImagineBundle\Domain\Stack\FilterInterface.

Check failure on line 15 in src/Domain/Stack/LiipTransformerStack.php

View workflow job for this annotation

GitHub Actions / phpstan

Property Liip\ImagineBundle\Domain\Stack\LiipTransformerStack::$filters has unknown class Liip\ImagineBundle\Domain\Stack\FilterInterface as its type.
private array $postProcessors,
) {}

public function applyTo(ImageReference $image): ImageReference
{
foreach ($this->filters as $filter) {
$image = $filter->applyTo($image);

Check failure on line 22 in src/Domain/Stack/LiipTransformerStack.php

View workflow job for this annotation

GitHub Actions / phpstan

Call to method applyTo() on an unknown class Liip\ImagineBundle\Domain\Stack\FilterInterface.
}

foreach ($this->postProcessors as $postProcessor) {
$image = $postProcessor->process($image);
}

return $image;
}
}
Loading

0 comments on commit f85edf9

Please sign in to comment.