ThumbnailImage
* @g2 GalleryFileSystemEntity
* @g2
* @g2 1
* @g2 2
* @g2
* @g2
*
* @package Thumbnail
* @subpackage Classes
* @author Alan Harder
* @version $Revision: 15534 $
*/
class ThumbnailImage extends GalleryFileSystemEntity {
/**
* The mime type of the image.
*
* @g2
* @g2 mimeType
* @g2 STRING
* @g2 MEDIUM
* @g2 READ
* @g2
*
* @var string $mimeType
* @access public
*/
var $mimeType;
/**
* The size of the image file.
*
* @g2
* @g2 size
* @g2 INTEGER
* @g2 FULL
* @g2
*
* @var int $size
* @access public
*/
var $size;
/**
* The width of the image.
*
* @g2
* @g2 width
* @g2 INTEGER
* @g2 FULL
* @g2
*
* @var int $width
* @access public
*/
var $width;
/**
* The height of the image.
*
* @g2
* @g2 height
* @g2 INTEGER
* @g2 FULL
* @g2
*
* @var int $height
* @access public
*/
var $height;
/**
* The mime types for which this image is the default thumbnail.
*
* @g2
* @g2 itemMimeTypes
* @g2 STRING
* @g2 MEDIUM
* @g2 READ
* @g2
*
* @var string $itemMimeTypes
* @access public
*/
var $itemMimeTypes;
/**
* Get array of item mime types.
*
* @return array(string mime type)
*/
function getItemMimeTypesList() {
return explode('|', $this->getitemMimeTypes());
}
/**
* Set array of item mime types.
*
* @param array $mimeTypeList array(string mime type, ..)
*/
function setItemMimeTypesList($mimeTypeList) {
$this->setitemMimeTypes(implode('|', $mimeTypeList));
}
/**
* Create a new instance of this type in the persistent store.
*
* @param string $inputFileName the path to a data file to be contained
* @param string $mimeType the mime type of the new item
* @param string $targetName (optional) the desired name of the new item.
* @return object GalleryStatus a status code
*/
function create($inputFileName, $mimeType, $targetName=null, $parentId=null) {
GalleryCoreApi::requireOnce('modules/thumbnail/classes/ThumbnailHelper.class');
global $gallery;
$platform =& $gallery->getPlatform();
/* Validate the input file */
if (empty($inputFileName)) {
return GalleryCoreApi::error(ERROR_BAD_PARAMETER);
}
if (!$platform->file_exists($inputFileName)) {
return GalleryCoreApi::error(ERROR_BAD_PATH, __FILE__, __LINE__, $inputFileName);
}
$baseName = !empty($targetName) ? $targetName : basename($inputFileName);
list ($ret, $thumbnailContainerId) =
GalleryCoreApi::getPluginParameter('module', 'thumbnail', 'id.container');
if ($ret) {
return $ret;
}
/*
* Use the common thumbnail container for mime-type thumbs mainly for name / path
* collision checking.
*/
if (empty($parentId)) {
$parentId = (int)$thumbnailContainerId;
}
$parentLockId = null;
if (!GalleryCoreApi::isReadLocked($parentId)) {
if ($parentId == $thumbnailContainerId) {
/* For mime-type thumbs, we need a write-lock to prevent collisions. */
list ($ret, $parentLockId) = GalleryCoreApi::acquireWriteLock($parentId);
} else {
list ($ret, $parentLockId) = GalleryCoreApi::acquireReadLock($parentId);
}
if ($ret) {
return $ret;
}
}
$ret = parent::create($parentId, $baseName);
if ($ret) {
if ($parentLockId) {
GalleryCoreApi::releaseLocks($parentLockId);
}
return $ret;
}
if ($parentLockId) {
$ret = GalleryCoreApi::releaseLocks($parentLockId);
if ($ret) {
return $ret;
}
}
$this->setMimeType($mimeType);
$this->setWidth(0);
$this->setHeight(0);
$platform =& $gallery->getPlatform();
list ($ret, $path) = $this->fetchPath();
if ($ret) {
return $ret;
}
$dir = dirname($path);
list ($success) = GalleryUtilities::guaranteeDirExists($dir);
if (!$success) {
return GalleryCoreApi::error(ERROR_BAD_PATH);
}
$newFileName = $path;
if (!$platform->copy($inputFileName, $newFileName)) {
return GalleryCoreApi::error(ERROR_PLATFORM_FAILURE);
}
$this->setSize($platform->filesize($newFileName));
list ($ret, $toolkit) = GalleryCoreApi::getToolkitByProperty($mimeType, 'dimensions');
if ($ret) {
return $ret;
}
if (isset($toolkit)) {
list ($ret, $dimensions) = $toolkit->getProperty($mimeType, 'dimensions', $newFileName);
if ($ret) {
$ret->addErrorCode(ERROR_BAD_DATA_TYPE);
return $ret;
}
$this->setWidth($dimensions[0]);
$this->setHeight($dimensions[1]);
}
return null;
}
/**
* @see GalleryEntity::save
*/
function save($postEvent=true) {
return parent::save($postEvent, 0);
}
/**
* Deletes this ThumbnailImage.
*
* @see GalleryEntity::delete
*/
function delete() {
global $gallery;
list ($ret, $path) = $this->fetchPath();
if ($ret) {
return $ret;
}
/* Lock our parent to ensure that we can fetch our path. */
$parentLockId = null;
if (!GalleryCoreApi::isReadLocked($this->getParentId())) {
list ($ret, $parentLockId) = GalleryCoreApi::acquireReadLock($this->getParentId());
if ($ret) {
return $ret;
}
}
/* Delete myself */
$ret = parent::delete();
if ($ret) {
if ($parentLockId) {
GalleryCoreApi::releaseLocks($parentLockId);
}
return $ret;
}
/* Delete our source file */
$platform =& $gallery->getPlatform();
if (!$platform->unlink($path)) {
if ($parentLockId) {
GalleryCoreApi::releaseLocks($parentLockId);
}
return GalleryCoreApi::error(ERROR_BAD_PATH, __FILE__, __LINE__,
"Could not delete $path");
}
if ($parentLockId) {
$ret = GalleryCoreApi::releaseLocks($parentLockId);
if ($ret) {
return $ret;
}
}
/* Restore thumbnails of affected items. */
list ($ret, $thumbnailContainerId) =
GalleryCoreApi::getPluginParameter('module', 'thumbnail', 'id.container');
if ($ret) {
return $ret;
}
$ret = $this->_restoreItemThumbnails();
if ($ret) {
return $ret;
}
return null;
}
/**
* Ensure that items / derivatives affected by the deletion of a ThumbnailItem still have
* a thumbnail after the removal. Restore the sourceId to the original item (if there is
* toolkit support for that source mimeType). And pick a new highlight for AlbumItems.
*
* @return object GalleryStatus a status code
*/
function _restoreItemThumbnails() {
list ($ret, $derivativesTable) =
GalleryCoreApi::fetchDerivativesBySourceIds(array($this->getId()),
array(DERIVATIVE_TYPE_IMAGE_THUMBNAIL));
if ($ret) {
return $ret;
}
/*
* In theory, custom thumbnails can only be the source for a single item.
* And mime-type thumbnails are never a source for other thumbnails.
* But we make this code a little more robust.
*/
foreach ($derivativesTable as $itemId => $derivatives) {
if (empty($derivatives)) {
continue;
}
$derivative = array_shift($derivatives);
/* Don't loop in thumbnail delete event. */
$key = 'ThumbnailImage::delete';
if (GalleryDataCache::containsKey($key)
&& GalleryDataCache::get($key) == $derivative->getId()) {
continue;
}
list ($ret, $item) = GalleryCoreApi::loadEntitiesById($itemId);
if ($ret) {
return $ret;
}
if (GalleryUtilities::isA($item, 'GalleryAlbumItem')) {
list ($ret, $success) = GalleryCoreApi::guaranteeAlbumHasThumbnail($item->getId());
if ($ret) {
return $ret;
}
continue;
}
/* Make sure operations contains only thumbnail and composite */
$operations = rtrim(preg_replace('/(^|;)((?!thumbnail\||composite\|).*?(;|$))+/', '$1',
$derivative->getDerivativeOperations()), ';');
list ($ret, $source) = GalleryCoreApi::fetchPreferredSource($item);
if ($ret) {
return $ret;
}
list ($ret, $operations, $outputMimeType) =
GalleryCoreApi::makeSupportedViewableOperationSequence(
$source->getMimeType(), $operations, true);
if ($ret) {
return $ret;
}
if (empty($operations)) {
/* Operations not supported.. remove the thumbnail */
$ret = GalleryCoreApi::deleteEntityById($derivative->getId());
if ($ret) {
return $ret;
}
} else {
list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($derivative->getId());
if ($ret) {
return $ret;
}
$derivative->setMimeType($outputMimeType);
$derivative->setDerivativeOperations($operations);
$derivative->setDerivativeSourceId($source->getId());
$ret = $derivative->save();
if ($ret) {
return $ret;
}
$ret = GalleryCoreApi::releaseLocks($lockId);
if ($ret) {
return $ret;
}
}
}
return null;
}
/**
* Full path to image file
*
* @return array(object GalleryStatus a status code, string path)
*/
function fetchPath() {
global $gallery;
list ($ret, $logicalPath) = $this->fetchLogicalPath();
if ($ret) {
return array($ret, null);
}
/*
* Logical path is slash (/) delimited. Convert that to the platform's actual
* directory separator.
*/
$platform =& $gallery->getPlatform();
if ($platform->getDirectorySeparator() != '/') {
$logicalPath = str_replace('/', $platform->getDirectorySeparator(), $logicalPath);
}
return array(null, $this->getThumbnailDir() . $logicalPath);
}
function fetchLogicalPath() {
list ($ret, $thumbnailContainerId) =
GalleryCoreApi::getPluginParameter('module', 'thumbnail', 'id.container');
if ($ret) {
return array($ret, null);
}
if ($this->getParentId() != $thumbnailContainerId) {
/* Custom thumbnails are stored in a decimal tree, e.g. 7/75.jpg. */
$id = (string)$this->getId();
$path = $id{0} . '/' . $id . '.jpg';
} else {
/* Mime-type thumbnails are right under the plugin_data/modules/thumbnail/ folder. */
$path = $this->getPathComponent();
}
return array(null, $path);
}
/**
* Thumbnail directory
*
* @return string Directory where thumbnail images are stored
*/
function getThumbnailDir() {
global $gallery;
$platform =& $gallery->getPlatform();
$slash = $platform->getDirectorySeparator();
return $gallery->getConfig('data.gallery.plugins_data') .
'modules' . $slash . 'thumbnail' . $slash;
}
/** @see GalleryFileSystemEntity::move */
function move($newParentId) {
return GalleryCoreApi::error(ERROR_UNSUPPORTED_OPERATION);
}
/**
* Render image
*
* @return string content
*/
function render($format, $params) {
global $gallery;
switch($format) {
case 'HTML':
$urlGenerator =& $gallery->getUrlGenerator();
$src = $urlGenerator->generateUrl(
array('view' => 'core.DownloadItem', 'itemId' => $this->getId(),
'serialNumber' => $this->getSerialNumber()),
array('forceFullUrl' => !empty($params['forceFullUrl'])));
list ($width, $height) = array($this->getWidth(), $this->getHeight());
/* Shrink our dimensions if necessary */
if (isset($params['maxSize'])) {
list ($width, $height) =
GalleryUtilities::shrinkDimensionsToFit($width, $height, $params['maxSize']);
unset($params['maxSize']);
}
$sizeStr = ($width > 0 && $height > 0)
? sprintf(' width="%s" height="%s"', $width, $height) : '';
if (!isset($params['alt'])) {
$params['alt'] = $this->getPathComponent();
}
$html = sprintf('
$value) {
if (isset($value)) {
$html .= " $attr=\"$value\"";
}
}
return $html . '/>';
default:
return null;
}
}
/**
* So ThumbnailImage is displayable with {g->image}
*/
function getRenderer() {
return null;
}
/**
* @see GalleryEntity::getClassName
*/
function getClassName() {
return 'ThumbnailImage';
}
function getMimeType() {
return $this->mimeType;
}
function setMimeType($mimeType) {
$this->mimeType = $mimeType;
}
function getSize() {
return $this->size;
}
function setSize($size) {
$this->size = $size;
}
function getWidth() {
return $this->width;
}
function setWidth($width) {
$this->width = $width;
}
function getHeight() {
return $this->height;
}
function setHeight($height) {
$this->height = $height;
}
function getItemMimeTypes() {
return $this->itemMimeTypes;
}
function setItemMimeTypes($itemMimeTypes) {
$this->itemMimeTypes = $itemMimeTypes;
}
}
?>