Skip to content

Commit

Permalink
Merge branch 'aliasaria-develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
christeredvartsen committed Mar 17, 2016
2 parents 1da4a2c + 6b7f4f3 commit e1d2309
Show file tree
Hide file tree
Showing 3 changed files with 264 additions and 0 deletions.
197 changes: 197 additions & 0 deletions library/Imbo/EventListener/ImageVariations/Storage/S3.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
<?php
/**
* This file is part of the Imbo package
*
* (c) Christer Edvartsen <cogo@starzinger.net>
*
* For the full copyright and license information, please view the LICENSE file that was
* distributed with this source code.
*/

namespace Imbo\EventListener\ImageVariations\Storage;

use Imbo\Exception\StorageException,
Aws\S3\S3Client,
Aws\S3\Exception\NoSuchKeyException,
Aws\S3\Exception\S3Exception,
DateTime,
DateTimeZone;

/**
* S3 storage driver for the image variations
*
* Configuration options supported by this driver:
* Parameters for this adapter:
*
* - (string) key Your AWS access key
* - (string) secret Your AWS secret key
* - (string) bucket The name of the bucket to store the files in. The bucket should exist prior
* to using this client. Imbo will not try to automatically add the bucket for
* you.
*
* @package Storage
*/
class S3 implements StorageInterface {
/**
* S3 client
*
* @var S3Client
*/
private $client;

/**
* Parameters for the driver
*
* @var array
*/
private $params = [
// Access key
'key' => null,

// Secret key
'secret' => null,

// Name of the bucket to store the files in
'bucket' => null,

// Region
'region' => null,
];

/**
* Class constructor
*
* @param array $params Parameters for the adapter
* @param S3Client $client Configured S3Client instance
*/
public function __construct(array $params = null, S3Client $client = null) {
if ($params !== null) {
$this->params = array_replace_recursive($this->params, $params);
}

if ($client !== null) {
$this->client = $client;
}
}

/**
* {@inheritdoc}
*/
public function storeImageVariation($user, $imageIdentifier, $imageData, $width) {
try {
$this->getClient()->putObject([
'Bucket' => $this->params['bucket'],
'Key' => $this->getImagePath($user, $imageIdentifier, $width),
'Body' => $imageData,
]);
} catch (S3Exception $e) {
throw new StorageException('Could not store image', 500);
}

return true;
}

/**
* {@inheritdoc}
*/
public function getImageVariation($user, $imageIdentifier, $width) {
try {
$model = $this->getClient()->getObject([
'Bucket' => $this->params['bucket'],
'Key' => $this->getImagePath($user, $imageIdentifier, $width),
]);
} catch (NoSuchKeyException $e) {
return null;
}

return (string) $model->get('Body');
}

/**
* {@inheritdoc}
*/
public function deleteImageVariations($user, $imageIdentifier, $width = null) {
// If width is specified, delete only the specific image
if ($width !== null) {
$this->getClient()->deleteObject([
'Bucket' => $this->params['bucket'],
'Key' => $this->getImagePath($user, $imageIdentifier, $width)
]);

return true;
}

// If width is not specified, delete every variation. Ask S3 to list all files in the
// directory.
$variationsPath = $this->getImagePath($user, $imageIdentifier);

$varations = $this->getClient()->getIterator('ListObjects', [
'Bucket' => $this->params['bucket'],
'Prefix' => $variationsPath
]);

// Note: could also use AWS's deleteMatchingObjects instead of deleting items one by one
foreach ($varations as $variation) {
$this->getClient()->deleteObject([
'Bucket' => $this->params['bucket'],
'Key' => $variation['Key']
]);
}

return true;
}

/**
* Get the path to an image
*
* @param string $user The user which the image belongs to
* @param string $imageIdentifier Image identifier
* @param int $width Width of the image, in pixels
* @param boolean $includeFilename Whether or not to include the last part of the path
* (the filename itself)
* @return string
*/
private function getImagePath($user, $imageIdentifier, $width = null, $includeFilename = true) {
$userPath = str_pad($user, 3, '0', STR_PAD_LEFT);
$parts = [
'imageVariation',
$userPath[0],
$userPath[1],
$userPath[2],
$user,
$imageIdentifier[0],
$imageIdentifier[1],
$imageIdentifier[2],
$imageIdentifier,
];

if ($includeFilename) {
$parts[] = $width;
}

return implode('/', $parts);
}


/**
* Get the S3Client instance
*
* @return S3Client
*/
private function getClient() {
if ($this->client === null) {
$params = [
'key' => $this->params['key'],
'secret' => $this->params['secret'],
];

if ($this->params['region']) {
$params['region'] = $this->params['region'];
}

$this->client = S3Client::factory($params);
}

return $this->client;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* This file is part of the Imbo package
*
* (c) Christer Edvartsen <cogo@starzinger.net>
*
* For the full copyright and license information, please view the LICENSE file that was
* distributed with this source code.
*/

namespace ImboIntegrationTest\EventListener\ImageVariations\Storage;

use Imbo\EventListener\ImageVariations\Storage\S3,
Aws\S3\S3Client;

/**
* @covers Imbo\EventListener\ImageVariations\Storage\S3
* @group integration
* @group storage
* @group aws
*/
class S3Test extends StorageTests {
/**
* @see ImboIntegrationTest\Storage\StorageTests::getDriver()
*/
protected function getAdapter() {
return new S3([
'key' => $GLOBALS['AWS_S3_KEY'],
'secret' => $GLOBALS['AWS_S3_SECRET'],
'bucket' => $GLOBALS['AWS_S3_BUCKET'],
]);
}

/**
* Make sure we have the correct config available
*/
public function setUp() {
foreach (['AWS_S3_KEY', 'AWS_S3_SECRET', 'AWS_S3_BUCKET'] as $key) {
if (empty($GLOBALS[$key])) {
$this->markTestSkipped('This test needs the ' . $key . ' value to be set in phpunit.xml');
}
}

$client = S3Client::factory([
'key' => $GLOBALS['AWS_S3_KEY'],
'secret' => $GLOBALS['AWS_S3_SECRET'],
]);
$client->clearBucket($GLOBALS['AWS_S3_BUCKET']);

parent::setUp();
}
}
15 changes: 15 additions & 0 deletions tests/phpunit/ImboIntegrationTest/Storage/S3Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,19 @@ public function setUp() {

parent::setUp();
}

/**
* @covers Imbo\Storage\S3::getStatus
*/
public function testGetStatus() {
$this->assertTrue($this->getDriver()->getStatus());

$driver = new S3([
'key' => $GLOBALS['AWS_S3_KEY'],
'secret' => $GLOBALS['AWS_S3_SECRET'],
'bucket' => uniqid(),
]);

$this->assertFalse($driver->getStatus());
}
}

0 comments on commit e1d2309

Please sign in to comment.