Skip to content

Instantly share code, notes, and snippets.

@sameg14
Created April 29, 2016 20:03
Show Gist options
  • Save sameg14/85ccf0332800d115521dd40612495d9a to your computer and use it in GitHub Desktop.
Save sameg14/85ccf0332800d115521dd40612495d9a to your computer and use it in GitHub Desktop.
An example service that contains business logic
<?php
namespace Tib\CoreBundle\Service;
use Aws\S3\S3Client;
use Tib\CoreBundle\Model\User;
use Aws\S3\Iterator\ListObjectsIterator;
use Tib\CoreBundle\Exception\UploadException;
use Aws\Common\Credentials\CredentialsInterface;
use Tib\CoreBundle\Exception\InvalidDataException;
use Tib\CoreBundle\Exception\MissingDataException;
use Symfony\Component\HttpFoundation\Session\Session;
use Tib\CoreBundle\Exception\InvalidCredentialsException;
/**
* Class S3Service handles all interactions with S3 for mixes and images
*
* @package Tib\CoreBundle\Service
*/
class S3Service extends AbstractService
{
const BASE_MIX_BUCKET = 'theillbeat/mixes/';
const BASE_IMAGE_BUCKET = 'theillbeat/images/mixes/';
/**
* @var S3Client
*/
protected $client;
/**
* Hydrated AWS credentials object
* @var CredentialsInterface
*/
protected $credentials;
public function __construct(CredentialsInterface $credentials, Session $session, $rootDirectory)
{
$this->credentials = $credentials;
$this->client = S3Client::factory(['credentials' => $credentials]);
$this->setSession($session);
$this->setRootDir($rootDirectory);
}
/**
* Ensure that the user image and mix buckets exist
*
* @param string $username SEF username
*
* @return bool
*/
public function ensureUserBuckets($username)
{
$didCreateMix = $didCreateImage = false;
$userMixBucket = self::BASE_MIX_BUCKET . $username . '/';
$userImageBucket = self::BASE_IMAGE_BUCKET . $username . '/';
// User's mix bucket
if (!$this->ensureBucket($userMixBucket)) {
$didCreateMix = $this->createBucket($userMixBucket);
}
// User's image bucket
if (!$this->ensureBucket($userImageBucket)) {
$didCreateImage = $this->createBucket($userImageBucket);
}
return $didCreateMix && $didCreateImage;
}
/**
* Upload a mix to S3
*
* @param string $usernameSlug Username of this user
* @param string $mixSlug Slug for this mix
* @param string $mixAbsPath Where is the file located on the current server
*
* @throws InvalidDataException
* @throws UploadException
* @throws MissingDataException
* @return string Publicly accessible URL for the mix
*/
public function uploadMix($usernameSlug, $mixSlug, $mixAbsPath)
{
if (empty($mixAbsPath)) {
throw new InvalidDataException('Absolute path of mix cannot be empty');
}
if (empty($usernameSlug)) {
throw new InvalidDataException('Username slug cannot be empty');
}
if (empty($mixSlug)) {
throw new InvalidDataException('Mix slug cannot be empty');
}
// if (!file_exists($mixAbsPath)) {
// throw new MissingDataException('Cannot locate mix locally');
// }
$mixName = $mixSlug . '.mp3';
$streamPutObject = $this->getClient()->putObject(
array(
'Bucket' => S3Service::BASE_MIX_BUCKET . $usernameSlug,
'Key' => $mixName,
'Body' => fopen($mixAbsPath, 'r+'),
'ACL' => 'public-read'
)
);
if (!$streamPutObject) {
throw new UploadException('Cannot upload mix to the cloud');
}
$data = $streamPutObject->toArray();
if (!$data) {
throw new UploadException('Invalid data received after uploading to S3');
}
if (!array_key_exists('ObjectURL', $data)) {
throw new UploadException('Could not get newly saved mix URL');
}
unlink($mixAbsPath);
return $data['ObjectURL'];
}
/**
* Upload mix images to S3
*
* @param string $usernameSlug Username slug of this person
* @param string $largeRelPath Large image relative location on this server
* @param string $thumbRelPath Thumb image relative location on this server
* @param string $imageAbsPath Absolute location for the big images folder on the server
* @param string $thumbAbsPath Absolute location for the thumbnail images folder on the server
*
* @throws InvalidDataException
* @throws MissingDataException
* @throws UploadException
* @return array containing URLS of both images array('large' => 's3/img.jpg', 'thumb' => 's3/tn_img.jpg')
*/
public function uploadMixImages($usernameSlug, $largeRelPath, $thumbRelPath, $imageAbsPath = null, $thumbAbsPath = null)
{
if (empty($usernameSlug)) {
throw new MissingDataException('Login again, your session may have expired');
}
if (empty($largeRelPath)) {
throw new MissingDataException('No large image found');
}
if (empty($thumbRelPath)) {
throw new MissingDataException('No thumbnail found');
}
$largeRelName = basename($largeRelPath);
$thumbRelName = basename($thumbRelPath);
if (empty($imageAbsPath)) {
$imageAbsPath = $this->rootDir . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'mixes' . DIRECTORY_SEPARATOR;
}
$largeBodyPath = $imageAbsPath . $largeRelPath;
$largeBodyPath = str_replace('//', '/', $largeBodyPath);
if (!file_exists($largeBodyPath)) {
return false;
}
$largeStreamPutObject = $this->getClient()->putObject(
array(
'Bucket' => S3Service::BASE_IMAGE_BUCKET . $usernameSlug,
'Key' => $largeRelName,
'Body' => fopen($largeBodyPath, 'r+'),
'ACL' => 'public-read'
)
);
$largeData = $largeStreamPutObject->toArray();
if (empty($thumbAbsPath)) {
$thumbAbsPath = $this->rootDir . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'thumbs' . DIRECTORY_SEPARATOR;
}
$thumbBodyPath = $thumbAbsPath . DIRECTORY_SEPARATOR . $thumbRelPath;
$thumbBodyPath = str_replace('//', '/', $thumbBodyPath);
if (!file_exists($thumbBodyPath)) {
return false;
}
$thumbStreamPutObject = $this->getClient()->putObject(
array(
'Bucket' => S3Service::BASE_IMAGE_BUCKET . $usernameSlug,
'Key' => $thumbRelName,
'Body' => fopen($thumbBodyPath, 'r+'),
'ACL' => 'public-read'
)
);
$thumbData = $thumbStreamPutObject->toArray();
if (!empty($largeData) && !empty($thumbData)) {
return array(
'large' => $largeData['ObjectURL'],
'thumb' => $thumbData['ObjectURL'],
'largeLocalAbs' => $largeBodyPath,
'thumbLocalAbs' => $thumbBodyPath
);
}
throw new UploadException('An unknown error occurred when trying to upload mix images to S3');
}
/**
* Remove a mix from S3
*
* @param string $usernameSlug Slug for this user's username
* @param string $mixSlug Slug for this mix, with no extension
*
* @throws InvalidDataException
* @return bool
*/
public function removeMix($usernameSlug, $mixSlug)
{
if (empty($usernameSlug)) {
throw new InvalidDataException('Username slug cannot be empty');
}
if (empty($mixSlug)) {
throw new InvalidDataException('Mix slug cannot be empty');
}
$mixName = $mixSlug . '.mp3';
$didRemove = $this->getClient()->deleteObject(
array(
'Bucket' => self::BASE_MIX_BUCKET . $usernameSlug,
'Key' => $mixName
)
);
return (bool)$didRemove;
}
/**
* Remove all user buckets
* @param string $usernameSlug
* @throws InvalidDataException
* @return bool
*/
public function removeAllUserBuckets($usernameSlug)
{
if (empty($usernameSlug)) {
throw new InvalidDataException('Username slug cannot be empty');
}
$didRemoveMix = $this->getClient()->deleteBucket(
array(
'Bucket' => self::BASE_MIX_BUCKET . $usernameSlug
)
);
$didRemoveImage = $this->getClient()->deleteBucket(
array(
'Bucket' => self::BASE_IMAGE_BUCKET . $usernameSlug
)
);
return (bool)$didRemoveMix && (bool)$didRemoveImage;
}
/**
* Ensure that a mix exists on S3
*
* @param string $usernameSlug just the username slug
* @param string $mixFileName Just the mix filename, with extension
*
* @return bool
*/
public function ensureMix($usernameSlug, $mixFileName)
{
return $this->getClient()->doesObjectExist(self::BASE_MIX_BUCKET . $usernameSlug, $mixFileName);
}
/**
* Delete a mix from this user's bucket
* @param string $usernameSlug Slug for this user
* @param string $mixFileName With extension
* @return bool
*/
public function deleteMix($usernameSlug, $mixFileName)
{
$result = $this->getClient()->deleteObject(
array(
'Bucket' => self::BASE_MIX_BUCKET . $usernameSlug,
'Key' => $mixFileName
)
);
$resultArray = $result->toArray();
return isset($resultArray['DeleteMarker']) && !empty($resultArray['RequestId']) ? true : false;
}
/**
* @param string $usernameSlug Slug for this user
* @param string $imageFilename main image
* @param string $thumbFilename thumb
* @return bool
*/
public function deleteMixImages($usernameSlug, $imageFilename, $thumbFilename)
{
$imageResult = $this->getClient()->deleteObject(
array(
'Bucket' => self::BASE_IMAGE_BUCKET . $usernameSlug,
'Key' => $imageFilename
)
);
$imageResultArray = $imageResult->toArray();
$didImageDelete = isset($imageResultArray['DeleteMarker']) && !empty($imageResultArray['RequestId']) ? true : false;
$thumbResult = $this->getClient()->deleteObject(
array(
'Bucket' => self::BASE_IMAGE_BUCKET . $usernameSlug,
'Key' => $thumbFilename
)
);
$thumbResultArray = $thumbResult->toArray();
$didThumbDelete = isset($thumbResultArray['DeleteMarker']) && !empty($thumbResultArray['RequestId']) ? true : false;
return $didImageDelete && $didThumbDelete;
}
/**
* Ensure that this bucket exists
*
* @param string $bucket Absolute path of bucket
*
* @return bool
*/
public function ensureBucket($bucket)
{
return (bool)$this->client->doesBucketExist($bucket);
}
/**
* Get all mixes from this user's bucket
*
* @param string $usernameSlug just the username slug
*
* @return ListObjectsIterator|null
*/
public function getMixes($usernameSlug)
{
return $this->getClient()->getIterator('ListObjects', array(
'Bucket' => 'theillbeat/',
"Prefix" => 'mixes/' . $usernameSlug . '/'
));
}
/**
* Get all mixes from this user's bucket
*
* @param string $usernameSlug just the username slug
* @param string $mixFileName Just the mix filename, with extension
*
* @return ListObjectsIterator|null
*/
public function getMix($usernameSlug, $mixFileName)
{
$mixes = $this->getMixes($usernameSlug);
$key = 'mixes/' . $usernameSlug . '/' . $mixFileName;
foreach ($mixes as $mix) {
if ($mix['Key'] == $key) {
return $mix;
}
}
return null;
}
/**
* Create a new bucket
*
* @param string $bucket Full folder path of the bucket from the root ending in a slash
*
* @return bool
*/
public function createBucket($bucket)
{
return (bool)$this->client->createBucket(
array(
'Bucket' => $bucket
)
);
}
/**
* Get the client ( test and dev only )
*
* @return S3Client
*/
public function getClient()
{
return $this->client;
}
/**
* @param S3Client $s3Client
*/
public function setS3Client($s3Client)
{
$this->client = $s3Client;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment