Skip to content

Commit

Permalink
Merge pull request #1 from Gaufrette/feature/resolvable-fs
Browse files Browse the repository at this point in the history
Resolvable Filesystem
  • Loading branch information
Albin Kerouanton authored May 31, 2017
2 parents 1446145 + 7970dfb commit 3a2d63a
Show file tree
Hide file tree
Showing 20 changed files with 781 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ cache:
directories:
- $HOME/.composer/cache/files

env:
global:
- AWS_KEY:
- AWS_SECRET:

php:
- 5.6
- 7.0
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,26 @@


Provides extras functionality around Gaufrette like Resolvable filesystem.

### Resolvable filesystem

`ResolvableFilesystem` is a decorator permitting to resolve objects paths into URLs.

In order to use it, you have to pass the decorated Filesystem and a Resolver:

$client = // AwsS3 client instantiation
$decorated = new Filesystem(new AwsS3($client, 'my_bucket', ['directory' => 'root/dir']));
$filesystem = new ResolvableFilesystem(
$decorated,
new AwsS3PresignedUrlResolver($client, 'my_bucket', 'root/dir')
);

Then you can call `resolve($key)`:

$filesystem->resolve('/foo.png'); // = 'https://...

Currently these resolvers are supported:

* AwsS3PublicUrlResolver
* AwsS3PresignedUrlResolver
* StaticUrlResolver
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
},
"require-dev": {
"phpspec/phpspec": "^3.4",
"phpunit/phpunit": "^5"
"phpunit/phpunit": "^5",
"aws/aws-sdk-php": "~3"
},
"license": "MIT",
"authors": [
Expand All @@ -32,5 +33,10 @@
"psr-4": {
"Gaufrette\\Extras\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Gaufrette\\Extras\\Tests\\": "tests/"
}
}
}
4 changes: 4 additions & 0 deletions phpspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
suites:
default:
namespace: Gaufrette\Extras
psr4_prefix: Gaufrette\Extras
142 changes: 142 additions & 0 deletions spec/Resolvable/ResolvableFilesystemSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

namespace spec\Gaufrette\Extras\Resolvable;

use Gaufrette\Extras\Resolvable\ResolvableFilesystem;
use Gaufrette\Extras\Resolvable\ResolverInterface;
use Gaufrette\Extras\Resolvable\UnresolvableObjectException;
use Gaufrette\File;
use Gaufrette\FilesystemInterface;
use Gaufrette\Stream;
use PhpSpec\ObjectBehavior;

class ResolvableFilesystemSpec extends ObjectBehavior
{
function let(MockedFilesystem $decorated, ResolverInterface $resolver)
{
$this->beConstructedWith($decorated, $resolver);
}

function it_is_initializable()
{
$this->shouldHaveType(ResolvableFilesystem::class);
}

function it_is_a_filesystem()
{
$this->shouldImplement(FilesystemInterface::class);
}

function it_resolves_object_path_into_uri($resolver)
{
$resolver->resolve('foo')->willReturn('https://yolo.com/my_image.png');
$this->resolve('foo')->shouldReturn('https://yolo.com/my_image.png');
}

function it_throws_unresolvable_object_exception_if_any_error_happen_during_resolution($resolver)
{
$resolver->resolve('foo')->willThrow(\Exception::class);
$this->shouldThrow(UnresolvableObjectException::class)->duringResolve('foo');
}

function it_delegates_has_to_decorated_filesystem($decorated)
{
$decorated->has('foo')->willReturn(true);
$this->has('foo')->shouldReturn(true);
}

function it_delegates_rename_to_decorated_filesystem($decorated)
{
$decorated->rename('foo', 'bar')->willReturn(true);
$this->rename('foo', 'bar')->shouldReturn(true);
}

function it_delegates_get_to_decorated_filesystem($decorated, File $file)
{
$decorated->get('foo', true)->willReturn($file);
$this->get('foo', true)->shouldReturn($file);
}

function it_delegates_write_to_decorated_filesystem($decorated)
{
$decorated->write('foo', 'content', true)->willReturn(7);
$this->write('foo', 'content', true)->shouldReturn(7);
}

function it_delegates_read_to_decorated_filesystem($decorated)
{
$decorated->read('foo')->willReturn('content');
$this->read('foo')->shouldReturn('content');
}

function it_delegates_delete_to_decorated_filesystem($decorated)
{
$decorated->delete('foo')->willReturn(true);
$this->delete('foo')->shouldReturn(true);
}

function it_delegates_keys_to_decorated_filesystem($decorated)
{
$decorated->keys()->willReturn(['foo', 'bar']);
$this->keys()->shouldReturn(['foo', 'bar']);
}

function it_delegates_list_keys_to_decorated_filesystem($decorated)
{
$decorated->listKeys('aze/*')->willReturn(['keys' => ['foo', 'bar']]);
$this->listKeys('aze/*')->shouldReturn(['keys' => ['foo', 'bar']]);
}

function it_delegates_mime_type_retrieval_to_decorated_filesystem($decorated)
{
$decorated->mtime('foo')->willReturn(123);
$this->mtime('foo')->shouldReturn(123);
}

function it_delegates_checksum_computation_to_decorated_filesystem($decorated)
{
$decorated->checksum('foo')->willReturn('abcdef');
$this->checksum('foo')->shouldReturn('abcdef');
}

function it_delegates_size_computation_to_decorated_filesystem($decorated)
{
$decorated->size('foo')->willReturn(123);
$this->size('foo')->shouldReturn(123);
}

function it_delegates_stream_creation_to_decorated_filesystem($decorated, Stream $stream)
{
$decorated->createStream('foo')->willReturn($stream);
$this->createStream('foo')->shouldReturn($stream);
}

function it_delegates_file_creation_to_decorated_filesystem($decorated, File $file)
{
$decorated->createFile('foo')->willReturn($file);
$this->createFile('foo')->shouldReturn($file);
}

function it_delegates_mime_type_guessing_to_decorated_filesystem($decorated)
{
$decorated->mimeType('foo')->willReturn('application/json');
$this->mimeType('foo')->shouldReturn('application/json');
}

function it_delegates_is_directory_to_delegated_filesystem($decorated)
{
$decorated->isDirectory('foo')->willReturn(false);
$this->isDirectory('foo')->shouldReturn(false);
}

function it_delegates_any_other_method_call_to_decorated_filesystem($decorated)
{
$decorated->otherMethod()->shouldBeCalled();

$this->otherMethod();
}
}

interface MockedFilesystem extends FilesystemInterface {
public function otherMethod();
}
41 changes: 41 additions & 0 deletions spec/Resolvable/Resolver/AwsS3PresignedUrlResolverSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace spec\Gaufrette\Extras\Resolvable\Resolver;

use Aws\CommandInterface;
use Aws\S3\S3Client;
use Gaufrette\Extras\Resolvable\Resolver\AwsS3PresignedUrlResolver;
use Gaufrette\Extras\Resolvable\ResolverInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Psr\Http\Message\RequestInterface;

class AwsS3PresignedUrlResolverSpec extends ObjectBehavior
{
function let(S3Client $client)
{
$this->beConstructedWith($client, 'bucket', '/base/dir/', new \DateTime('+12 hour'));
}

function it_is_initializable()
{
$this->shouldHaveType(AwsS3PresignedUrlResolver::class);
}

function it_is_a_resolver()
{
$this->shouldImplement(ResolverInterface::class);
}

function it_resolves_object_path_into_presigned_url(
$client,
CommandInterface $command,
RequestInterface $presignedRequest
) {
$client->getCommand('GetObject', ['Bucket' => 'bucket', 'Key' => 'base/dir/foo.png'])->willReturn($command);
$client->createPresignedRequest($command, Argument::type(\DateTime::class))->willReturn($presignedRequest);
$presignedRequest->getUri()->willReturn('https://amazon');

$this->resolve('/foo.png')->shouldReturn('https://amazon');
}
}
33 changes: 33 additions & 0 deletions spec/Resolvable/Resolver/AwsS3PublicUrlResolverSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace spec\Gaufrette\Extras\Resolvable\Resolver;

use Aws\S3\S3Client;
use Gaufrette\Extras\Resolvable\Resolver\AwsS3PublicUrlResolver;
use Gaufrette\Extras\Resolvable\ResolverInterface;
use PhpSpec\ObjectBehavior;

class AwsS3PublicUrlResolverSpec extends ObjectBehavior
{
function let(S3Client $service)
{
$this->beConstructedWith($service, 'bucket', 'base/dir/');
}

function it_is_initializable()
{
$this->shouldHaveType(AwsS3PublicUrlResolver::class);
}

function it_is_a_resolver()
{
$this->shouldImplement(ResolverInterface::class);
}

function it_resolves_object_path_to_public_url($service)
{
$service->getObjectUrl('bucket', 'base/dir/foo.png')->willReturn('https://amazon');

$this->resolve('/foo.png')->shouldReturn('https://amazon');
}
}
30 changes: 30 additions & 0 deletions spec/Resolvable/Resolver/StaticUrlResolverSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace spec\Gaufrette\Extras\Resolvable\Resolver;

use Gaufrette\Extras\Resolvable\Resolver\StaticUrlResolver;
use Gaufrette\Extras\Resolvable\ResolverInterface;
use PhpSpec\ObjectBehavior;

class StaticUrlResolverSpec extends ObjectBehavior
{
function let()
{
$this->beConstructedWith('https://google.com/');
}

function it_is_initializable()
{
$this->shouldHaveType(StaticUrlResolver::class);
}

function it_is_a_resolver()
{
$this->shouldImplement(ResolverInterface::class);
}

function it_resolves_url_by_prepending_static_prefix_to_path()
{
$this->resolve('/foo.png')->shouldReturn('https://google.com/foo.png');
}
}
Loading

0 comments on commit 3a2d63a

Please sign in to comment.