-
Notifications
You must be signed in to change notification settings - Fork 379
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #227 from havvg/master
add AwsS3Resolver for new SDK version
- Loading branch information
Showing
7 changed files
with
602 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
<?php | ||
|
||
namespace Liip\ImagineBundle\Imagine\Cache\Resolver; | ||
|
||
use Aws\S3\Enum\CannedAcl; | ||
use Aws\S3\S3Client; | ||
|
||
use Liip\ImagineBundle\Imagine\Cache\CacheManagerAwareInterface; | ||
use Liip\ImagineBundle\Imagine\Cache\CacheManager; | ||
|
||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\HttpFoundation\RedirectResponse; | ||
use Symfony\Component\HttpFoundation\Response; | ||
|
||
use Symfony\Component\HttpKernel\Log\LoggerInterface; | ||
|
||
class AwsS3Resolver implements ResolverInterface, CacheManagerAwareInterface | ||
{ | ||
/** | ||
* @var S3Client | ||
*/ | ||
protected $storage; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
protected $bucket; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
protected $acl; | ||
|
||
/** | ||
* @var CacheManager | ||
*/ | ||
protected $cacheManager; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $objUrlOptions; | ||
|
||
/** | ||
* @var LoggerInterface | ||
*/ | ||
protected $logger; | ||
|
||
/** | ||
* Constructs a cache resolver storing images on Amazon S3. | ||
* | ||
* @param S3Client $storage The Amazon S3 storage API. It's required to know authentication information. | ||
* @param string $bucket The bucket name to operate on. | ||
* @param string $acl The ACL to use when storing new objects. Default: owner read/write, public read | ||
* @param array $objUrlOptions A list of options to be passed when retrieving the object url from Amazon S3. | ||
*/ | ||
public function __construct(S3Client $storage, $bucket, $acl = CannedAcl::PUBLIC_READ, array $objUrlOptions = array()) | ||
{ | ||
$this->storage = $storage; | ||
|
||
$this->bucket = $bucket; | ||
$this->acl = $acl; | ||
|
||
$this->objUrlOptions = $objUrlOptions; | ||
} | ||
|
||
/** | ||
* Sets the logger to be used. | ||
* | ||
* @param LoggerInterface $logger | ||
*/ | ||
public function setLogger(LoggerInterface $logger) | ||
{ | ||
$this->logger = $logger; | ||
} | ||
|
||
/** | ||
* @param CacheManager $cacheManager | ||
*/ | ||
public function setCacheManager(CacheManager $cacheManager) | ||
{ | ||
$this->cacheManager = $cacheManager; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function resolve(Request $request, $path, $filter) | ||
{ | ||
$objectPath = $this->getObjectPath($path, $filter); | ||
if ($this->objectExists($objectPath)) { | ||
return new RedirectResponse($this->getObjectUrl($objectPath), 301); | ||
} | ||
|
||
return $objectPath; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function store(Response $response, $targetPath, $filter) | ||
{ | ||
try { | ||
$storageResponse = $this->storage->putObject(array( | ||
'ACL' => $this->acl, | ||
'Bucket' => $this->bucket, | ||
'Key' => $targetPath, | ||
'Body' => $response->getContent(), | ||
)); | ||
} catch (\Exception $e) { | ||
if ($this->logger) { | ||
$this->logger->warn('The object could not be created on Amazon S3.', array( | ||
'targetPath' => $targetPath, | ||
'filter' => $filter, | ||
)); | ||
} | ||
|
||
return $response; | ||
} | ||
|
||
$response->setStatusCode(301); | ||
$response->headers->set('Location', $storageResponse->get('ObjectURL')); | ||
|
||
return $response; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getBrowserPath($path, $filter, $absolute = false) | ||
{ | ||
$objectPath = $this->getObjectPath($path, $filter); | ||
if ($this->objectExists($objectPath)) { | ||
return $this->getObjectUrl($objectPath); | ||
} | ||
|
||
return $this->cacheManager->generateUrl($path, $filter, $absolute); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function remove($targetPath, $filter) | ||
{ | ||
if (!$this->objectExists($targetPath)) { | ||
// A non-existing object to delete: done! | ||
return true; | ||
} | ||
|
||
try { | ||
$response = $this->storage->deleteObject(array( | ||
'Bucket' => $this->bucket, | ||
'Key' => $targetPath, | ||
)); | ||
|
||
return true; | ||
} catch (\Exception $e) { | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* Sets a single option to be passed when retrieving an objects URL. | ||
* | ||
* If the option is already set, it will be overwritten. | ||
* | ||
* @see Aws\S3\S3Client::getObjectUrl() for available options. | ||
* | ||
* @param string $key The name of the option. | ||
* @param mixed $value The value to be set. | ||
* | ||
* @return AmazonS3Resolver $this | ||
*/ | ||
public function setObjectUrlOption($key, $value) | ||
{ | ||
$this->objUrlOptions[$key] = $value; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function clear($cachePrefix) | ||
{ | ||
// TODO: implement cache clearing for Amazon S3 service | ||
} | ||
|
||
/** | ||
* Returns the object path within the bucket. | ||
* | ||
* @param string $path The base path of the resource. | ||
* @param string $filter The name of the imagine filter in effect. | ||
* | ||
* @return string The path of the object on S3. | ||
*/ | ||
protected function getObjectPath($path, $filter) | ||
{ | ||
return str_replace('//', '/', $filter.'/'.$path); | ||
} | ||
|
||
/** | ||
* Returns the URL for an object saved on Amazon S3. | ||
* | ||
* @param string $targetPath | ||
* | ||
* @return string | ||
*/ | ||
protected function getObjectUrl($targetPath) | ||
{ | ||
return $this->storage->getObjectUrl($this->bucket, $targetPath, 0, $this->objUrlOptions); | ||
} | ||
|
||
/** | ||
* Checks whether an object exists. | ||
* | ||
* @param string $objectPath | ||
* | ||
* @return bool | ||
*/ | ||
protected function objectExists($objectPath) | ||
{ | ||
return $this->storage->doesObjectExist($this->bucket, $objectPath); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# AwsS3Resolver | ||
|
||
The AwsS3Resolver requires the [aws-sdk-php](https://github.com/aws/aws-sdk-for-php). | ||
|
||
You can add the SDK by adding those lines to your `deps` file. | ||
|
||
``` ini | ||
[aws-sdk] | ||
git=git://github.com/aws/aws-sdk-php.git | ||
``` | ||
|
||
Afterwards, you only need to configure some information regarding your AWS account and the bucket. | ||
|
||
``` yaml | ||
parameters: | ||
amazon_s3.key: 'your-aws-key' | ||
amazon_s3.secret: 'your-aws-secret' | ||
amazon_s3.bucket: 'your-bucket.example.com' | ||
amazon_s3.region: 'your-bucket-region' | ||
``` | ||
Now you can set up the services required: | ||
``` yaml | ||
services: | ||
acme.amazon_s3: | ||
class: Aws\S3\S3Client | ||
factory_class: Aws\S3\S3Client | ||
factory_method: factory | ||
arguments: | ||
- | ||
key: %amazon_s3.key% | ||
secret: %amazon_s3.secret% | ||
region: %amazon_s3.region% | ||
|
||
acme.imagine.cache.resolver.amazon_s3: | ||
class: Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver | ||
arguments: | ||
- "@acme.amazon_s3" | ||
- "%amazon_s3.bucket%" | ||
tags: | ||
- { name: 'liip_imagine.cache.resolver', resolver: 'amazon_s3' } | ||
``` | ||
Now you are ready to use the `AwsS3Resolver` by configuring the bundle. | ||
The following example will configure the resolver is default. | ||
|
||
``` yaml | ||
liip_imagine: | ||
cache: 'amazon_s3' | ||
``` | ||
|
||
If you want to use other buckets for other images, simply alter the parameter names and create additional services! | ||
|
||
## Object URL Options | ||
|
||
In order to make use of the object URL options, you can simply add a call to the service, to alter those options you need. | ||
|
||
``` yaml | ||
services: | ||
acme.imagine.cache.resolver.amazon_s3: | ||
class: Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver | ||
arguments: | ||
- "@acme.amazon_s3" | ||
- "%amazon_s3.bucket%" | ||
calls: | ||
# This calls $service->setObjectUrlOption('Scheme', 'https'); | ||
- [ setObjectUrlOption, [ 'Scheme', 'https' ] ] | ||
tags: | ||
- { name: 'liip_imagine.cache.resolver', resolver: 'amazon_s3' } | ||
``` | ||
|
||
You can also use the constructor of the resolver to directly inject multiple options. | ||
|
||
``` yaml | ||
services: | ||
acme.imagine.cache.resolver.amazon_s3: | ||
class: Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver | ||
arguments: | ||
- "@acme.amazon_s3" | ||
- "%amazon_s3.bucket%" | ||
- "public-read" # Aws\S3\Enum\CannedAcl::PUBLIC_READ (default) | ||
- { Scheme: https } | ||
tags: | ||
- { name: 'liip_imagine.cache.resolver', resolver: 'amazon_s3' } | ||
``` | ||
|
||
- [Back to cache resolvers](../cache-resolvers.md) | ||
- [Back to the index](../index.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
namespace Aws\S3\Enum; | ||
|
||
class CannedAcl | ||
{ | ||
const PRIVATE_ACCESS = 'private'; | ||
const PUBLIC_READ = 'public-read'; | ||
const PUBLIC_READ_WRITE = 'public-read-write'; | ||
const AUTHENTICATED_READ = 'authenticated-read'; | ||
const BUCKET_OWNER_READ = 'bucket-owner-read'; | ||
const BUCKET_OWNER_FULL_CONTROL = 'bucket-owner-full-control'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
namespace Guzzle\Service\Resource; | ||
|
||
class Model | ||
{ | ||
public function get($key) { } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
namespace Aws\S3; | ||
|
||
class S3Client | ||
{ | ||
public function doesBucketExist($bucket, $accept403, $options = array()) { } | ||
|
||
public function doesObjectExist($bucket, $key, $options = array()) { } | ||
|
||
public function putObject($args) { } | ||
|
||
public function deleteObject($args) { } | ||
|
||
public function getObjectUrl($bucket, $key, $expires = 0, $args = array()) { } | ||
} |
Oops, something went wrong.