blue-twilight/app/AlbumSources/OpenStackSource.php

185 lines
5.6 KiB
PHP

<?php
namespace App\AlbumSources;
use App\Photo;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Stream;
use Illuminate\Support\Facades\Log;
use OpenStack\Common\Error\BadResponseError;
use OpenStack\Common\Transport\Utils as TransportUtils;
use OpenStack\Identity\v2\Service as IdentityV2Service;
use OpenStack\OpenStack;
use function GuzzleHttp\Psr7\stream_for;
/**
* Driver for managing files on an OpenStack Keystone+Swift compatible platform.
* @package App\AlbumSources
*/
class OpenStackSource extends AlbumSourceBase implements IAlbumSource
{
/**
* Deletes an entire album's media contents.
* @return void
*/
public function deleteAlbumContents()
{
// Because all photos live in a single container, 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->getContainer()->getObject($photoPath)->delete();
}
catch (GuzzleException $ex)
{
// Don't worry if the file no longer exists
Log::warning('Failed deleting image from OpenStack.', ['error' => $ex->getMessage(), 'path' => $photoPath]);
}
catch (BadResponseError $ex)
{
// Don't worry if the file no longer exists
Log::warning('Failed deleting image from OpenStack.', ['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 Stream
*/
public function fetchPhotoContent(Photo $photo, $thumbnail = null)
{
$object = $this->getContainer()->getObject($this->getPathToPhoto($photo, $thumbnail));
return stream_for($object->download());
}
/**
* Gets the name of this album source.
* @return string
*/
public function getName()
{
return 'global.album_sources.openstack';
}
/**
* 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)
{
$cdnUrl = $this->configuration->cdn_url;
if (strlen($cdnUrl) > 0)
{
if (substr($cdnUrl, strlen($cdnUrl) - 1, 1) == '/')
{
$cdnUrl = substr($cdnUrl, 0, strlen($cdnUrl) - 1);
}
return sprintf('%s/%s', $cdnUrl, $this->getPathToPhoto($photo, $thumbnail));
}
// Not using a CDN - use the standard download controller
$photoUrl = route('downloadPhoto', [
'albumUrlAlias' => $this->album->url_alias,
'photoFilename' => $photo->storage_file_name
]);
if (!is_null($thumbnail))
{
$photoUrl .= sprintf('?t=%s', urlencode($thumbnail));
}
return $photoUrl;
}
/**
* 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);
$createOptions = [
'name' => $photoPath,
'content' => file_get_contents($tempFilename)
];
$this->getContainer()->createObject($createOptions);
}
protected function getClient()
{
$authURL = $this->configuration->auth_url;
$options = [
'authUrl' => $authURL,
'username' => $this->configuration->username,
'password' => decrypt($this->configuration->password),
'tenantName' => $this->configuration->tenant_name,
'region' => $this->configuration->service_region,
'identityService' => IdentityV2Service::factory(
new Client([
'base_uri' => TransportUtils::normalizeUrl($authURL),
'handler' => HandlerStack::create(),
])
)
];
return new OpenStack($options);
}
protected function getContainer()
{
return $this->getStorageService()->getContainer($this->configuration->container_name);
}
protected function getStorageService()
{
return $this->getClient()->objectStoreV1([
'catalogName' => $this->getStorageServiceCatalogName()
]);
}
protected function getStorageServiceCatalogName()
{
return $this->configuration->service_name;
}
protected function getOriginalsFolder()
{
return '_originals';
}
protected 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
);
}
}