Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature 74827 public route #70

Merged
merged 31 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
24c4c71
feature #72151 createFromStorage now converts file if convert required
TomasHermanek Nov 2, 2023
2eef7dc
feature #74657 public/private feature work. Decorators flags support.…
TomasHermanek Nov 6, 2023
e2a1494
feature #74657 packages update, fixed tests
TomasHermanek Nov 6, 2023
dfd97ae
feature #74657 psalm fixes
TomasHermanek Nov 6, 2023
6e5da7e
feature #74657 removed deprecated column
TomasHermanek Nov 9, 2023
4697e97
feature #74657 changed privacy
TomasHermanek Nov 20, 2023
0ce3c71
feature #74657 changed position doctrine type.
TomasHermanek Nov 21, 2023
d6d2f58
wip #74657 document public/private routes
TomasHermanek Nov 23, 2023
f762ce2
Merge branch 'main' of github.com:anzusystems/core-dam-bundle into fe…
TomasHermanek Nov 27, 2023
856ffef
wip #74657 public routing.
TomasHermanek Nov 28, 2023
75bfd86
Public route next.
TomasHermanek Dec 1, 2023
eda2515
Merge branch 'main' into feature_74827_public_route
TomasHermanek Dec 1, 2023
bab489a
Fixes.
TomasHermanek Dec 1, 2023
2edd716
AssetFileRoue routing, routing mode, ...
TomasHermanek Dec 7, 2023
3c0eaba
Changed redirect domain.
TomasHermanek Dec 7, 2023
e620cb1
Added indexes.
TomasHermanek Dec 7, 2023
5afe6a4
Fixed deprecations
TomasHermanek Dec 8, 2023
27a8571
Cache purge, delete cache purge routing
TomasHermanek Dec 11, 2023
6bd7c78
tests fix
TomasHermanek Dec 11, 2023
39cb89b
Refactor public routing and add URL serialization
TomasHermanek Dec 14, 2023
0790c6c
Refactor code to apply decorator pattern for response detail
TomasHermanek Dec 15, 2023
49aff42
Merge branch 'main' into feature_74827_public_route
TomasHermanek Jan 1, 2024
6d3279f
Refactor links serialization in response and add image animation support
TomasHermanek Jan 2, 2024
2b8e84c
Set default crop dimension and refactor image handling
TomasHermanek Jan 3, 2024
e0a3ca9
package updates, fixed tests.
TomasHermanek Jan 3, 2024
9f18fc4
psalm fixes
TomasHermanek Jan 3, 2024
9631f6e
tests
TomasHermanek Jan 3, 2024
86cb16d
Fixed asset delete with main route.
TomasHermanek Jan 4, 2024
b289458
Renamed custom type number to integer
TomasHermanek Jan 8, 2024
ced76a5
Update Dockerfile and CI with new PHP version
TomasHermanek Jan 8, 2024
81336fb
Updated release changelog.
TomasHermanek Jan 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
matrix:
include:
- php-version: 8.2
docker-image: anzusystems/php:1.1.0-php82-cli-vipsffmpeg
docker-image: anzusystems/php:3.0.0-php83-cli-vipsffmpeg

services:
elasticsearch:
Expand Down
54 changes: 54 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,57 @@
## [1.5.0](https://github.com/anzusystems/core-dam-bundle/compare/1.4.1...1.5.0) (2024-01-09)
### Feature
* php `8.3`
* `AssetFileRoute` allows to generate public routes to assets
* image response streaming
* animated gif response

## [1.4.1](https://github.com/anzusystems/core-dam-bundle/compare/1.4.0...1.4.1) (2023-12-19)
### Feature
* Serialize licenceId in AssetAdmListDto

## [1.4.0](https://github.com/anzusystems/core-dam-bundle/compare/1.3.3...1.4.0) (2023-12-18)
### Feature
* Added sys apis for create and get asset file from storage

## [1.3.3](https://github.com/anzusystems/core-dam-bundle/compare/1.3.2...1.3.3) (2023-11-28)
### Feature
* added API get asset by asset file

## [1.3.2](https://github.com/anzusystems/core-dam-bundle/compare/1.3.1...1.3.2) (2023-11-24)
### Fixes
* fixed tracking modification for async image processing

## [1.3.1](https://github.com/anzusystems/core-dam-bundle/compare/1.3.0...1.3.1) (2023-11-24)
### Fixes
* fixed allow list config - domain override

## [1.3.0](https://github.com/anzusystems/core-dam-bundle/compare/1.2.0...1.3.0) (2023-11-24)
### Features
* method createFromStorage now converts file if convert required
* public/private image feature
* removed deprecated column key from entity CustomFormElement
* custom BigIntType for doctrine (use int instead of string)
* allow extId in AssetLicence to be nullable
* PositionTrait position attribute changed from smallint to integer
* update common bundle -> added prefix
* package updates (psalm/ecs fixes)

## [1.2.0](https://github.com/anzusystems/core-dam-bundle/compare/1.1.1...1.2.0) (2023-10-26)
### Features
* cusomMetadata validation rework
* duplicate image preview rework
* youtube default language

### Bug fixes
* long displayTitle parse fix
* elastcseach keyword support
* youtube redistribute change language fix


## [1.1.1](https://github.com/anzusystems/core-dam-bundle/compare/1.1.0...1.1.1) (2023-07-21)
### Bug fixes
- Set YT thumbnail fix

## [1.1.0](https://github.com/anzusystems/core-dam-bundle/compare/1.0.0...1.1.0) (2023-06-22)

### Features
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM anzusystems/php:1.1.0-php82-cli-vipsffmpeg
FROM anzusystems/php:3.0.0-php83-cli-vipsffmpeg
#
### Basic arguments and variables
ARG DOCKER_USER_ID
Expand Down
40 changes: 20 additions & 20 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
"authors": [
],
"require": {
"php": ">=8.2",
"php": ">=8.3",
"ext-json": "*",
"ext-mongodb": "*",
"ext-redis": "*",
"ext-simplexml": "*",
"ext-vips": "*",
"ext-xmlreader": "*",
"ext-zend-opcache": "*",
"anzusystems/common-bundle": "^3.0",
"anzusystems/common-bundle": "^4.0",
"doctrine/orm": ">=2.10",
"elasticsearch/elasticsearch": "^8.6",
"fakerphp/faker": "^1.20",
Expand All @@ -27,25 +27,25 @@
"petitpress/gps-messenger-bundle": "^1.4",
"php-ffmpeg/php-ffmpeg": "^1.0",
"phpexiftool/exiftool": "^10.16",
"symfony/dependency-injection": "^6.3",
"symfony/doctrine-bridge": "^6.3",
"symfony/dotenv": "^6.3",
"symfony/expression-language": "^6.3",
"symfony/framework-bundle": "^6.3",
"symfony/http-client": "^6.3",
"symfony/http-kernel": "^6.3",
"symfony/lock": "^6.3",
"symfony/messenger": "^6.3",
"symfony/mime": "^6.3",
"symfony/options-resolver": "^6.3",
"symfony/dependency-injection": "^6.4",
"symfony/doctrine-bridge": "^6.4",
"symfony/dotenv": "^6.4",
"symfony/expression-language": "^6.4",
"symfony/framework-bundle": "^6.4",
"symfony/http-client": "^6.4",
"symfony/http-kernel": "^6.4",
"symfony/lock": "^6.4",
"symfony/messenger": "^6.4",
"symfony/mime": "^6.4",
"symfony/options-resolver": "^6.4",
"symfony/polyfill-uuid": "^1.24",
"symfony/process": "^6.3",
"symfony/property-access": "^6.3",
"symfony/runtime": "^6.3",
"symfony/security-bundle": "^6.3",
"symfony/uid": "^6.3",
"symfony/validator": "^6.3",
"symfony/yaml": "^6.3"
"symfony/process": "^6.4",
"symfony/property-access": "^6.4",
"symfony/runtime": "^6.4",
"symfony/security-bundle": "^6.4",
"symfony/uid": "^6.4",
"symfony/validator": "^6.4",
"symfony/yaml": "^6.4"
},
"require-dev": {
"doctrine/doctrine-bundle": "^2.4",
Expand Down
44 changes: 44 additions & 0 deletions src/Cache/AssetFileRouteGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace AnzuSystems\CoreDamBundle\Cache;

use AnzuSystems\CoreDamBundle\Domain\Configuration\ConfigurationProvider;
use AnzuSystems\CoreDamBundle\Domain\Configuration\ExtSystemConfigurationProvider;
use AnzuSystems\CoreDamBundle\Entity\AssetFileRoute;
use AnzuSystems\CoreDamBundle\Helper\UrlHelper;
use AnzuSystems\CoreDamBundle\Model\Configuration\AssetFileRouteConfigurableInterface;

final readonly class AssetFileRouteGenerator
{
public function __construct(
private ExtSystemConfigurationProvider $extSystemConfigurationProvider,
private ConfigurationProvider $configurationProvider,
) {
}

public function getFullUrl(
AssetFileRoute $route
): string {
if (false === $route->getUri()->isMain()) {
return UrlHelper::concatPathWithDomain(
$this->configurationProvider->getSettings()->getRedirectDomain(),
$route->getUri()->getPath()
);
}

$config = $this->extSystemConfigurationProvider->getExtSystemConfigurationByAsset(
$route->getTargetAssetFile()->getAsset()
);

if ($config instanceof AssetFileRouteConfigurableInterface) {
return UrlHelper::concatPathWithDomain(
$config->getPublicDomainName(),
$route->getUri()->getPath()
);
}

return '';
}
}
28 changes: 0 additions & 28 deletions src/Cache/AudioRouteGenerator.php

This file was deleted.

136 changes: 115 additions & 21 deletions src/Controller/AbstractImageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,20 @@

namespace AnzuSystems\CoreDamBundle\Controller;

use AnzuSystems\CoreDamBundle\Domain\Configuration\ConfigurationProvider;
use AnzuSystems\CoreDamBundle\Domain\Configuration\DomainProvider;
use AnzuSystems\CoreDamBundle\Domain\Image\Crop\CropFacade;
use AnzuSystems\CoreDamBundle\Entity\AssetFile;
use AnzuSystems\CoreDamBundle\Entity\ImageFile;
use AnzuSystems\CoreDamBundle\Entity\RegionOfInterest;
use AnzuSystems\CoreDamBundle\Exception\ImageManipulatorException;
use AnzuSystems\CoreDamBundle\Exception\InvalidCropException;
use AnzuSystems\CoreDamBundle\FileSystem\FileSystemProvider;
use AnzuSystems\CoreDamBundle\Helper\FileNameHelper;
use AnzuSystems\CoreDamBundle\Model\Dto\Image\Crop\RequestedCropDto;
use AnzuSystems\CoreDamBundle\Repository\ImageFileRepository;
use Doctrine\ORM\NonUniqueResultException;
use League\Flysystem\FilesystemException;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
Expand All @@ -17,35 +28,58 @@ abstract class AbstractImageController extends AbstractPublicController
{
public const CROP_EXTENSION = 'jpeg';
public const DEFAULT_CROP_MIME_TYPE = 'image/jpeg';
protected DomainProvider $domainProvider;
protected ImageFileRepository $imageFileRepository;

private FileSystemProvider $fileSystemProvider;
private CropFacade $cropFacade;
private ConfigurationProvider $configurationProvider;

#[Required]
public function setFileSystemProvider(FileSystemProvider $fileSystemProvider): void
{
$this->fileSystemProvider = $fileSystemProvider;
}

protected function streamOriginalResponse(AssetFile $assetFile): StreamedResponse
#[Required]
public function setCropFacade(CropFacade $cropFacade): void
{
$fileSystem = $this->fileSystemProvider->getFilesystemByStorable($assetFile);
$this->cropFacade = $cropFacade;
}

$response = new StreamedResponse(
callback: function () use ($fileSystem, $assetFile) {
$outputStream = fopen('php://output', 'wb');
stream_copy_to_stream(
$fileSystem->readStream($assetFile->getAssetAttributes()->getFilePath()),
$outputStream
);
},
status: Response::HTTP_OK,
headers: [
'Content-Type' => $assetFile->getAssetAttributes()->getMimeType(),
'Content-Disposition' => $this->makeDisposition($assetFile),
'Content-Length' => $assetFile->getAssetAttributes()->getSize(),
]
);
$this->assetFileCacheManager->setCache($response, $assetFile);
#[Required]
public function setDomainProvider(DomainProvider $domainProvider): void
{
$this->domainProvider = $domainProvider;
}

#[Required]
public function setConfigurationProvider(ConfigurationProvider $configurationProvider): void
{
$this->configurationProvider = $configurationProvider;
}

#[Required]
public function setImageFileRepository(ImageFileRepository $imageFileRepository): void
{
$this->imageFileRepository = $imageFileRepository;
}

/**
* @throws FilesystemException
* @throws ImageManipulatorException
* @throws InvalidCropException
*/
protected function okImageResponse(
ImageFile $image,
RegionOfInterest $roi,
RequestedCropDto $cropPayload
): Response {
$response = $this->getImageResponse(
content: $this->cropFacade->applyCropPayload($image, $cropPayload, $roi),
assetFile: $image,
)->setStatusCode(Response::HTTP_OK);
$this->assetFileCacheManager->setCache($response, $image);

return $response;
}
Expand All @@ -58,15 +92,75 @@ protected function okResponse(string $content, AssetFile $asset): Response
return $response;
}

protected function notFoundResponse(string $content, AssetFile $asset): Response
protected function notFoundResponse(): Response
{
$response = $this->getImageResponse($content, $asset)->setStatusCode(Response::HTTP_NOT_FOUND);
$response = new Response('', Response::HTTP_NOT_FOUND);
$this->assetFileCacheManager->setNotFoundCache($response);

return $response;
}

protected function getImageResponse(string $content, AssetFile $assetFile): Response
/**
* @throws FilesystemException
* @throws ImageManipulatorException
* @throws InvalidCropException
* @throws NonUniqueResultException
*/
protected function notFoundImageResponse(RequestedCropDto $cropPayload): Response
{
$notFoundImageId = $this->configurationProvider->getSettings()->getNotFoundImageId();
if (empty($notFoundImageId)) {
return $this->notFoundResponse();
}

$notFoundImage = $this->imageFileRepository->findProcessedById($notFoundImageId);
if (null === $notFoundImage) {
return $this->notFoundResponse();
}

$notFoundRoi = $notFoundImage->getRegionsOfInterest()->first();
if ($notFoundRoi instanceof RegionOfInterest) {
$response = $this->getImageResponse(
content: $this->cropFacade->applyCropPayload($notFoundImage, $cropPayload, $notFoundRoi),
assetFile: $notFoundImage,
)->setStatusCode(Response::HTTP_OK);
$this->assetFileCacheManager->setNotFoundCache($response);

return $response;
}

return $this->notFoundResponse();
}

/**
* @throws FilesystemException
*/
protected function streamResponse(AssetFile $assetFile): StreamedResponse
{
$filesystem = $this->fileSystemProvider->getFilesystemByStorable($assetFile);
$fileStream = $filesystem->readStream($assetFile->getAssetAttributes()->getFilePath());

$response = new StreamedResponse(
function () use ($fileStream) {
$outputStream = fopen('php://output', 'wb');
stream_copy_to_stream($fileStream, $outputStream);
},
Response::HTTP_OK,
[
'Content-Transfer-Encoding' => 'binary',
'Content-Type' => $assetFile->getAssetAttributes()->getMimeType(),
'Content-Length' => fstat($fileStream)['size'],
]
);
$this->assetFileCacheManager->setCache(
$response,
$assetFile
);

return $response;
}

private function getImageResponse(string $content, AssetFile $assetFile): Response
{
return new Response($content, Response::HTTP_OK, [
'Content-Type' => self::DEFAULT_CROP_MIME_TYPE,
Expand Down
Loading