<?php namespace App\AlbumSources; use App\Photo; use Guzzle\Http\EntityBody; use Guzzle\Http\Exception\ClientErrorResponseException; use Illuminate\Support\Facades\Log; class AmazonS3Source extends AlbumSourceBase implements IAlbumSource { /** * Deletes an entire album's media contents. * @return void */ public function deleteAlbumContents() { // Because all photos live in a single bucket, there is nothing "global" to delete for the entire album // The delete routine will have already removed all photos } /** * Deletes a thumbnail file for a photo. * @param Photo $photo Photo to delete the thumbnail from. * @param string $thumbnail Thumbnail to delete (or null to delete the original.) * @return void */ public function deleteThumbnail(Photo $photo, $thumbnail = null) { $photoPath = $this->getPathToPhoto($photo, $thumbnail); try { $this->getClient()->deleteObject([ 'Bucket' => $this->configuration->container_name, 'Key' => $this->getPathToPhoto($photo, $thumbnail) ]); } catch (ClientErrorResponseException $ex) { // Don't worry if the file no longer exists Log::warning('Failed deleting image from S3.', ['error' => $ex->getMessage(), 'path' => $photoPath]); } } /** * Fetches the contents of a thumbnail for a photo. * @param Photo $photo Photo to fetch the thumbnail for. * @param string $thumbnail Thumbnail to fetch (or null to fetch the original.) * @return EntityBody */ public function fetchPhotoContent(Photo $photo, $thumbnail = null) { $tempFile = tempnam(sys_get_temp_dir(), 'BlueTwilight_'); try { $this->getClient()->getObject([ 'Bucket' => $this->configuration->container_name, 'Key' => $this->getPathToPhoto($photo, $thumbnail), 'SaveAs' => $tempFile ]); return EntityBody::factory(fopen($tempFile, 'r+')); } finally { @unlink($tempFile); } } /** * Gets the name of this album source. * @return string */ public function getName() { return 'global.album_sources.amazon_s3'; } /** * Gets the absolute URL to the given photo file. * @param Photo $photo Photo to get the URL to. * @param string $thumbnail Thumbnail to get the image to. * @return string */ public function getUrlToPhoto(Photo $photo, $thumbnail = null) { return $this->getClient()->getObjectUrl($this->configuration->container_name, $this->getPathToPhoto($photo, $thumbnail)); } /** * Saves a generated thumbnail to its permanent location. * @param Photo $photo Photo the image relates to. * @param string $tempFilename Filename containing the image. * @param string $thumbnail Name of the thumbnail (or null for the original.) * @return mixed */ public function saveThumbnail(Photo $photo, $tempFilename, $thumbnail = null) { $photoPath = $this->getPathToPhoto($photo, $thumbnail); $this->getClient()->upload($this->configuration->container_name, $photoPath, fopen($tempFilename, 'r+'), 'public-read'); } private function getClient() { $config = [ 'credentials' => new \Aws\Credentials\Credentials( decrypt($this->configuration->access_key), decrypt($this->configuration->secret_key) ), 'version' => 'latest', 'region' => $this->configuration->service_region ]; if (!empty($this->configuration->auth_url) && parse_url($this->configuration->auth_url) !== false) { $config['endpoint'] = $this->configuration->auth_url; } return new \Aws\S3\S3Client($config); } private function getOriginalsFolder() { return '_originals'; } private function getPathToPhoto(Photo $photo, $thumbnail = null) { return sprintf( '%s/%s/%s', $this->album->url_alias, is_null($thumbnail) ? $this->getOriginalsFolder() : $thumbnail, $photo->storage_file_name ); } }