Skip to content

Commit 731ab75

Browse files
Feat/url generator (#161)
* CS fixes * Implement configurable url generator for uploadable fields * Run ci on all branches except v1 * Fix version checker test * Test break with http-client 6.2.5. Added conflict to use 6.2.2 * Initial services to provide public and temporary urls * Introduce constructor arguments that a user can overwrite to provide configuration for the new url generators
1 parent ba3d9b8 commit 731ab75

File tree

13 files changed

+151
-39
lines changed

13 files changed

+151
-39
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: CI
33
on:
44
push:
55
branches:
6-
- main
6+
- '!v1'
77
pull_request:
88
branches-ignore:
99
- v1

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@
142142
"symfony/web-link": "<=6.0",
143143
"doctrine/collections": "<1.7",
144144
"doctrine/orm": "<2.13",
145-
"api-platform/core": "3.1.0"
145+
"api-platform/core": "3.1.0",
146+
"symfony/http-client": "6.2.5"
146147
}
147148
}

features/bootstrap/ProfilerContext.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ public function theResourceShouldBePurgedFromTheCache(string $resourceName)
169169
/** @var HttpClientDataCollector $collector */
170170
$collector = $this->getProfile()->getCollector('http_client');
171171
$purged = [];
172-
foreach ($collector->getClients() as $clientName => $clientInfo) {
172+
foreach ($collector->getClients() as $clientInfo) {
173173
foreach ($clientInfo['traces'] as $trace) {
174174
/** @var Data $data */
175175
$data = $trace['options']->getValue()['normalized_headers'];

features/main/current_version.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Feature: In order to detect the current API Components Bundle Version
88
And I add "Content-Type" header equal to "<header>"
99
When I send a "GET" request to "/docs.<ext>"
1010
Then the response status code should be 200
11-
And the JSON node "info.version" should match the regex '/^1\.0\.0 \((?:dev-main|1\.0\.0\+no\-version\-set)@(?:[a-zA-Z0-9]+)?\)$/'
11+
And the JSON node "info.version" should match the regex '/^1\.0\.0 \((?:dev-[a-zA-Z0-9]+|1\.0\.0\+no\-version\-set)@(?:[a-zA-Z0-9]+)?\)$/'
1212
Examples:
1313
| header | ext |
1414
| application/json | json |

src/Annotation/UploadableField.php

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,15 @@
1919
#[\Attribute(\Attribute::TARGET_PROPERTY)]
2020
final class UploadableField
2121
{
22-
public string $property;
23-
24-
public ?string $prefix;
25-
26-
public ?array $imagineFilters;
27-
2822
// Nice to have - feature to configure the IRI in the output media objects for this field
2923
// public string $iri = 'http://schema.org/MediaObject';
3024

31-
public ?string $adapter;
32-
33-
public function __construct(string $adapter, string $property = 'filename', ?string $prefix = null, ?array $imagineFilters = [])
34-
{
35-
$this->property = $property;
36-
$this->prefix = $prefix;
37-
$this->imagineFilters = $imagineFilters;
38-
$this->adapter = $adapter;
25+
public function __construct(
26+
public string $adapter,
27+
public string $urlGenerator = 'api',
28+
public string $property = 'filename',
29+
public ?string $prefix = null,
30+
public ?array $imagineFilters = []
31+
) {
3932
}
4033
}
Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
<?php
22

3+
/*
4+
* This file is part of the Silverback API Components Bundle Project
5+
*
6+
* (c) Daniel West <daniel@silverback.is>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
314
namespace Silverback\ApiComponentsBundle\Factory\Uploadable;
415

516
use ApiPlatform\Api\IriConverterInterface;
17+
use League\Flysystem\Filesystem;
618
use Symfony\Component\HttpFoundation\UrlHelper;
719
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
820

9-
class ApiUrlGenerator implements UploadableUrlGenerator
21+
class ApiUrlGenerator implements UploadableUrlGeneratorInterface
1022
{
1123
public function __construct(private readonly IriConverterInterface $iriConverter, private readonly UrlHelper $urlHelper)
12-
{}
24+
{
25+
}
1326

14-
public function generateUrl(object $object, string $fileProperty): string {
27+
public function generateUrl(object $object, string $fileProperty, Filesystem $filesystem, string $path): string
28+
{
1529
$resourceId = $this->iriConverter->getIriFromResource($object);
1630
$converter = new CamelCaseToSnakeCaseNameConverter();
31+
1732
return $this->urlHelper->getAbsoluteUrl(sprintf('%s/download/%s', $resourceId, $converter->normalize($fileProperty)));
1833
}
1934
}

src/Factory/Uploadable/MediaObjectFactory.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@
2222
use Silverback\ApiComponentsBundle\AttributeReader\UploadableAttributeReader;
2323
use Silverback\ApiComponentsBundle\Entity\Core\FileInfo;
2424
use Silverback\ApiComponentsBundle\Entity\Utility\ImagineFiltersInterface;
25+
use Silverback\ApiComponentsBundle\Exception\InvalidArgumentException;
2526
use Silverback\ApiComponentsBundle\Flysystem\FilesystemProvider;
2627
use Silverback\ApiComponentsBundle\Helper\Uploadable\FileInfoCacheManager;
2728
use Silverback\ApiComponentsBundle\Imagine\FlysystemDataLoader;
2829
use Silverback\ApiComponentsBundle\Model\Uploadable\MediaObject;
2930
use Silverback\ApiComponentsBundle\Utility\ClassMetadataTrait;
31+
use Symfony\Component\DependencyInjection\ServiceLocator;
3032
use Symfony\Component\HttpFoundation\RequestStack;
3133

3234
/**
@@ -43,9 +45,9 @@ public function __construct(
4345
private readonly FilesystemProvider $filesystemProvider,
4446
private readonly FlysystemDataLoader $flysystemDataLoader,
4547
private readonly RequestStack $requestStack,
46-
private readonly ApiUrlGenerator $urlGenerator,
47-
private readonly ?FilterService $filterService = null)
48-
{
48+
private readonly ServiceLocator $urlGenerators,
49+
private readonly ?FilterService $filterService = null
50+
) {
4951
$this->initRegistry($managerRegistry);
5052
}
5153

@@ -69,13 +71,15 @@ public function createMediaObjects(object $object): ?ArrayCollection
6971
}
7072

7173
// todo: the content URL perhaps will just be a public URL from the source/CDN instead of via this API download action
72-
// if ($filesystem instanceof PublicUrlGenerator) {
73-
// // $filesystem->publicUrl();
74-
// }
7574
// if ($filesystem instanceof TemporaryUrlGenerator) {
7675
// // $filesystem->temporaryUrl();
7776
// }
78-
$contentUrl = $this->urlGenerator->generateUrl($object, $fileProperty);
77+
78+
$urlGenerator = $this->urlGenerators->get($fieldConfiguration->urlGenerator);
79+
if (!$urlGenerator instanceof UploadableUrlGeneratorInterface) {
80+
throw new InvalidArgumentException(sprintf('The url generator provided must implement %s', UploadableUrlGeneratorInterface::class));
81+
}
82+
$contentUrl = $urlGenerator->generateUrl($object, $fileProperty, $filesystem, $path);
7983

8084
// Populate the primary MediaObject
8185
try {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Silverback API Components Bundle Project
5+
*
6+
* (c) Daniel West <daniel@silverback.is>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Silverback\ApiComponentsBundle\Factory\Uploadable;
15+
16+
use League\Flysystem\Config;
17+
use League\Flysystem\Filesystem;
18+
use League\Flysystem\UrlGeneration\PublicUrlGenerator as FlysystemPublicUrlGenerator;
19+
use Silverback\ApiComponentsBundle\Exception\InvalidArgumentException;
20+
21+
class PublicUrlGenerator implements UploadableUrlGeneratorInterface
22+
{
23+
public function __construct(private readonly array $config = [])
24+
{
25+
}
26+
27+
public function generateUrl(object $object, string $fileProperty, Filesystem $filesystem, string $path): string
28+
{
29+
if (!$filesystem instanceof FlysystemPublicUrlGenerator) {
30+
throw new InvalidArgumentException(sprintf('The public URL generator requires a filesystem implementing %s', FlysystemPublicUrlGenerator::class));
31+
}
32+
33+
return $filesystem->publicUrl($path, new Config($this->config));
34+
}
35+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Silverback API Components Bundle Project
5+
*
6+
* (c) Daniel West <daniel@silverback.is>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Silverback\ApiComponentsBundle\Factory\Uploadable;
15+
16+
use League\Flysystem\Config;
17+
use League\Flysystem\Filesystem;
18+
use League\Flysystem\UrlGeneration\TemporaryUrlGenerator as FlysystemTemporaryUrlGenerator;
19+
use Silverback\ApiComponentsBundle\Exception\InvalidArgumentException;
20+
21+
class TemporaryUrlGenerator implements UploadableUrlGeneratorInterface
22+
{
23+
public function __construct(private readonly array $config = [], private readonly string $expires = '+3 days')
24+
{
25+
}
26+
27+
public function generateUrl(object $object, string $fileProperty, Filesystem $filesystem, string $path): string
28+
{
29+
if (!$filesystem instanceof FlysystemTemporaryUrlGenerator) {
30+
throw new InvalidArgumentException(sprintf('The public URL generator requires a filesystem implementing %s', FlysystemTemporaryUrlGenerator::class));
31+
}
32+
33+
return $filesystem->temporaryUrl($path, new \DateTime($this->expires), new Config($this->config));
34+
}
35+
}

src/Factory/Uploadable/UploadableUrlGenerator.php

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)