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

Abstract Storages #7319

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ ENABLE_ASSESSOR_SPACE=1
ENABLE_MUNICIPAL_SPACE=1

GCLOUD_BUCKET=
GCLOUD_PUBLIC_BUCKET=
GCLOUD_PRIVATE_BUCKET=
GCLOUD_LB_IP=

PAYBOX_SITE=
Expand Down
54 changes: 54 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ services:
$dynamicLinksHost: '%env(DYNAMIC_LINKS_HOST)%'
$jemengageAppPackageId: '%env(JEMENGAGE_APP_PACKAGE_ID)%'
$invalidEmailHashKey: '%env(INVALID_EMAIL_HASH_KEY)%'
$publicStorage: '@app.storage.public'
$privateStorage: '@app.storage.private'

_instanceof:
App\Adherent\Unregistration\Handlers\UnregistrationAdherentHandlerInterface:
Expand Down Expand Up @@ -375,3 +377,55 @@ services:
logger:
alias: 'monolog.logger'
public: true

app.storage.public_filesystem:
class: 'League\Flysystem\Filesystem'
factory: 'App\Storage\FilesystemFactory::createLocal'
arguments:
- '%kernel.project_dir%/app/storage/public'

app.storage.private_filesystem:
class: 'League\Flysystem\Filesystem'
factory: 'App\Storage\FilesystemFactory::createLocal'
arguments:
- '%kernel.project_dir%/app/storage/private'

app.storage.cache.adapter:
class: 'Danhunsaker\Flysystem\Redis\RedisAdapter'
arguments: ['@snc_redis.default']

app.storage.cache.filesystem:
class: 'League\Flysystem\Filesystem'
arguments: ['@app.storage.cache.adapter']

app.storage.cache.public:
class: 'League\Glide\Server'
factory: 'League\Glide\ServerFactory::create'
arguments:
- {
source: '@app.storage.public_filesystem',
cache: '@app.storage.cache.filesystem',
cache_path_prefix: '.cache.public'
}

app.storage.cache.private:
class: 'League\Glide\Server'
factory: 'League\Glide\ServerFactory::create'
arguments:
- {
source: '@app.storage.private_filesystem',
cache: '@app.storage.cache.filesystem',
cache_path_prefix: '.cache.private'
}

app.storage.public:
class: 'App\Storage\Storage'
arguments:
- '@app.storage.public_filesystem'
- '@app.storage.cache.public'

app.storage.private:
class: 'App\Storage\Storage'
arguments:
- '@app.storage.private_filesystem'
- '@app.storage.cache.private'
16 changes: 16 additions & 0 deletions config/services_dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,19 @@ services:

kreait_firebase.jemarche_app.dynamic_links: '@Tests\App\Test\Firebase\DummyDynamicLinks'
kreait_firebase.jemarche_app.messaging: '@Tests\App\Test\Firebase\DummyMessaging'

app.storage.public:
class: 'App\Storage\Storage'
arguments:
- !service
factory: 'App\Storage\AdapterFactory::createLocal'
arguments:
- '%kernel.project_dir%/app/storage/public'

app.storage.private:
class: 'App\Storage\Storage'
arguments:
- !service
factory: 'App\Storage\AdapterFactory::createLocal'
arguments:
- '%kernel.project_dir%/app/storage/private'
12 changes: 12 additions & 0 deletions config/services_prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,15 @@ services:
App\Monolog\SentryHandler:
decorates: 'monolog.handler.sentry'
arguments: [ '@App\Monolog\SentryHandler.inner' ]

app.storage.public_filesystem:
class: 'League\Flysystem\Filesystem'
factory: 'App\Storage\FilesystemFactory::createGoogleStorage'
arguments:
- '%env(GCLOUD_PUBLIC_BUCKET)%'

app.storage.private_filesystem:
class: 'League\Flysystem\Filesystem'
factory: 'App\Storage\FilesystemFactory::createLocal'
arguments:
- '%env(GCLOUD_PRIVATE_BUCKET)%'
3 changes: 3 additions & 0 deletions config/services_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ services:
app.glide.cache_adapter:
class: 'League\Flysystem\Memory\MemoryAdapter'

app.storage.cache.adapter:
class: 'League\Flysystem\Memory\MemoryAdapter'

old_sound_rabbit_mq.mailer_campaign_producer:
class: 'Tests\App\Test\Producer\MailerNullProducer'
public: false
Expand Down
32 changes: 32 additions & 0 deletions src/Storage/Cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Storage;

use League\Glide\Responses\ResponseFactoryInterface;
use League\Glide\Server;
use Symfony\Contracts\HttpClient\ResponseInterface;

class Cache implements CacheInterface
{
private Server $glide;

public function __construct(Server $glide)
{
$this->glide = $glide;
}

public function deleteCache(string $path): bool
{
return $this->glide->deleteCache($path);
}

public function setResponseFactory(ResponseFactoryInterface $responseFactory): void
{
$this->glide->setResponseFactory($responseFactory);
}

public function getImageResponse(string $path, array $params): ResponseInterface
{
return $this->glide->getImageResponse($path, $params);
}
}
12 changes: 12 additions & 0 deletions src/Storage/CacheInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace App\Storage;

use Symfony\Contracts\HttpClient\ResponseInterface;

interface CacheInterface
{
public function deleteCache(string $path): bool;

public function getImageResponse(string $path, array $params): ResponseInterface;
}
21 changes: 21 additions & 0 deletions src/Storage/DummyService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\Storage;

/**
* This service is here so that the injected services
* are not removed from the container after compilation.
*
* To be removed.
*/
class DummyService
{
private StorageInterface $publicStorage;
private StorageInterface $privateStorage;

public function __construct(StorageInterface $publicStorage, StorageInterface $privateStorage)
{
$this->publicStorage = $publicStorage;
$this->privateStorage = $privateStorage;
}
}
9 changes: 9 additions & 0 deletions src/Storage/Exception/FileExistsException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace App\Storage\Exception;

use League\Flysystem\FileExistsException as BaseFileExistsException;

class FileExistsException extends BaseFileExistsException
{
}
9 changes: 9 additions & 0 deletions src/Storage/Exception/FileNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace App\Storage\Exception;

use League\Flysystem\FileNotFoundException as BaseFileNotFoundException;

class FileNotFoundException extends BaseFileNotFoundException
{
}
34 changes: 34 additions & 0 deletions src/Storage/FilesystemFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\Storage;

use Google\Cloud\Storage\StorageClient;
use League\Flysystem\Adapter\Local;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Cached\CachedAdapter;
use League\Flysystem\Cached\Storage\Memory;
use League\Flysystem\Filesystem;
use Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter;

class FilesystemFactory
{
public static function createLocal(string $localPath): Filesystem
{
return self::create(new Local($localPath));
}

public static function createGoogleStorage(string $gcloudBucket, string $pathPrefix = null): Filesystem
{
$storage = new StorageClient();

return self::create(new CachedAdapter(
new GoogleStorageAdapter($storage, $storage->bucket($gcloudBucket), $pathPrefix),
new Memory(),
));
}

private static function create(AdapterInterface $adapter): Filesystem
{
return new Filesystem($adapter);
}
}
91 changes: 91 additions & 0 deletions src/Storage/Storage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace App\Storage;

use App\Storage\Exception\FileExistsException;
use App\Storage\Exception\FileNotFoundException;
use League\Flysystem\FileExistsException as LeagueFileExistsException;
use League\Flysystem\FileNotFoundException as LeagueFileNotFoundException;
use League\Flysystem\FilesystemInterface;

class Storage implements StorageInterface
{
private FilesystemInterface $filesystem;

public function __construct(FilesystemInterface $filesystem)
{
$this->filesystem = $filesystem;
}

public function has(string $path): bool
{
return $this->filesystem->has($path);
}

public function getMimetype(string $path): string
{
try {
return $this->filesystem->getMimetype($path);
} catch (LeagueFileNotFoundException $exception) {
throw $this->createFileNotFoundException($path);
}
}

public function read(string $path): string
{
try {
return $this->filesystem->read($path);
} catch (LeagueFileNotFoundException $exception) {
throw $this->createFileNotFoundException($path);
}
}

public function readStream(string $path)
{
try {
return $this->filesystem->readStream($path);
} catch (LeagueFileNotFoundException $exception) {
throw $this->createFileNotFoundException($path);
}
}

public function put(string $path, string $contents, array $config = []): bool
{
return $this->filesystem->put($path, $contents, $config);
}

public function copy(string $path, string $newPath): bool
{
try {
return $this->filesystem->copy($path, $newPath);
} catch (LeagueFileNotFoundException $exception) {
throw $this->createFileNotFoundException($path);
} catch (LeagueFileExistsException $exception) {
throw $this->createFileExistsException($newPath);
}
}

public function delete(string $path): bool
{
try {
return $this->filesystem->delete($path);
} catch (LeagueFileNotFoundException $exception) {
throw $this->createFileNotFoundException($path);
}
}

public function listContents(string $directory, bool $recursive = false): array
{
return $this->filesystem->listContents($directory, $recursive);
}

private function createFileNotFoundException(string $path): FileNotFoundException
{
return new FileNotFoundException($path);
}

private function createFileExistsException(string $path): FileExistsException
{
return new FileExistsException($path);
}
}
43 changes: 43 additions & 0 deletions src/Storage/StorageInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace App\Storage;

use App\Storage\Exception\FileExistsException;
use App\Storage\Exception\FileNotFoundException;

interface StorageInterface
{
public function has(string $path): bool;

/**
* @throws FileNotFoundException
*/
public function getMimetype(string $path): string;

/**
* @throws FileNotFoundException Thrown if $path does not exist
*/
public function read(string $path): string;

/**
* @throws FileNotFoundException Thrown if $path does not exist
*
* @return resource
*/
public function readStream(string $path);

public function put(string $path, string $contents, array $config = []): bool;

/**
* @throws FileExistsException Thrown if $newpath exists
* @throws FileNotFoundException Thrown if $path does not exist
*/
public function copy(string $path, string $newpath): bool;

/**
* @throws FileNotFoundException
*/
public function delete(string $path): bool;

public function listContents(string $directory, bool $recursive = false): array;
}
Loading