Sindbad~EG File Manager

Current Path : /var/www/web3/modules/imageblock/classes/
Upload File :
Current File : /var/www/web3/modules/imageblock/classes/ImageBlockHelper.class

<?php
/*
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2008 Bharat Mediratta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
 */

/**
 * A helper class for the Image Block module.
 * @package ImageBlock
 * @subpackage Classes
 * @author Alan Harder <alan.harder@sun.com>
 * @version $Revision: 17616 $
 * @static
 */
class ImageBlockHelper /* extends GalleryEventListener */ {

    /**
     * Load image block data into template.
     *
     * @param GalleryTemplate $template
     * @param array $params (optional) image block parameters (to override module settings)
     * @return GalleryStatus a status code
     */
    function loadImageBlocks(&$template, $params) {
	global $gallery;
	list ($ret, $moduleParams) =
	    GalleryCoreApi::fetchAllPluginParameters('module', 'imageblock');
	if ($ret) {
	    return $ret;
	}
	if (!isset($params['blocks'])) {
	    $params['blocks'] = 'randomImage';
	}
	if (isset($params['repeatBlock']) && ($i = intval($params['repeatBlock'])) > 1) {
	    $params['blocks'] .= str_repeat('|' . $params['blocks'], $i - 1);
	}
	$params = array_merge($moduleParams, $params);

	if (isset($params['itemId'])) {
	    $parentId = $params['itemId'];
	} else {
	    list ($ret, $parentId) = GalleryCoreApi::getDefaultAlbumId();
	    if ($ret) {
		return $ret;
	    }
	}
	$show = array();
	foreach (explode('|', $params['show']) as $key) {
	    $show[$key] = 1;
	}
	$fullSize = isset($show['fullSize']);
	$heading = isset($show['heading']);

	list ($ret, $module) = GalleryCoreApi::loadPlugin('module', 'imageblock');
	if ($ret) {
	    return $ret;
	}

	$blocks = $blockCount = array();
	$blockList = explode('|', $params['blocks']);
	foreach ($blockList as $block) {
	    if (!isset($blockCount[$block])) {
		$blockCount[$block] = 0;
	    }
	    $blockCount[$block]++;
	}
	$maxSize = isset($params['maxSize']) ? $params['maxSize'] :
	    (isset($params['exactSize']) ? $params['exactSize'] : null);

	foreach ($blockCount as $block => $count) {
	    if (!preg_match('{^(.*?)([A-Z].*)$}', $block, $matches)) {
		continue;
	    }
	    list ($tmp, $order, $itemType) = $matches;

	    list ($ret, $blockData[$block]) = ImageBlockHelper::_getBlockData(
		$itemType, $order, $count, $parentId, $fullSize,
		isset($params['userId']) ? $params['userId'] : null,
		$maxSize, isset($params['exactSize']));
	    if ($ret) {
		return $ret;
	    }
	}

	$lastType = '';
	foreach ($blockList as $block) {
	    if (!empty($blockData[$block])) {
		$nextBlock = array_shift($blockData[$block]);
		if ($heading) {
		    /* On 2nd of same type, update first to be plural; 3rd or more, no heading */
		    $plural = ($block == $lastType)
			? (empty($blocks[count($blocks) - 1]['title']) ? 0 : 2)
			: 1;
		}
		if ($heading && $plural) {
		    switch ($block) {
		    case 'randomImage':
			$title = $module->translate(array('one' => 'Random Image',
				    'many' => 'Random Images', 'count' => $plural));
			break;
		    case 'recentImage':
			$title = $module->translate(array('one' => 'Newest Image',
				    'many' => 'Newest Images', 'count' => $plural));
			break;
		    case 'viewedImage':
			$title = $module->translate(array('one' => 'Most Viewed Image',
				    'many' => 'Most Viewed Images', 'count' => $plural));
			break;
		    case 'randomAlbum':
			$title = $module->translate(array('one' => 'Random Album',
				    'many' => 'Random Albums', 'count' => $plural));
			break;
		    case 'recentAlbum':
			$title = $module->translate(array('one' => 'Newest Album',
				    'many' => 'Newest Albums', 'count' => $plural));
			break;
		    case 'viewedAlbum':
			$title = $module->translate(array('one' => 'Most Viewed Album',
				    'many' => 'Most Viewed Albums', 'count' => $plural));
			break;
		    case 'dailyImage':
			$title = $module->translate('Picture of the Day');
			break;
		    case 'weeklyImage':
			$title = $module->translate('Picture of the Week');
			break;
		    case 'monthlyImage':
			$title = $module->translate('Picture of the Month');
			break;
		    case 'dailyAlbum':
			$title = $module->translate('Album of the Day');
			break;
		    case 'weeklyAlbum':
			$title = $module->translate('Album of the Week');
			break;
		    case 'monthlyAlbum':
			$title = $module->translate('Album of the Month');
			break;
		    default:
			$title = '';
		    }
		    if ($plural > 1) {
			$blocks[count($blocks) - 1]['title'] = $title;
		    } else {
			$nextBlock['title'] = $title;
		    }
		}
		$blocks[] = $nextBlock;
		$lastType = $block;
	    }
	}

	$ImageBlockData['show'] = $show;
	if (isset($params['maxSize']) || isset($params['exactSize'])) {
	    $ImageBlockData['maxSize'] = $maxSize;
	}
	$ImageBlockData['link'] = isset($params['link']) ? $params['link'] : '';
	if (isset($params['linkTarget'])) {
	    $ImageBlockData['linkTarget'] = $params['linkTarget'];
	}

	if (!empty($blocks)) {
	    /* Prepare image frames, if available */
	    list ($ret, $imageframe) =
		GalleryCoreApi::newFactoryInstance('ImageFrameInterface_1_1');
	    if ($ret) {
		return $ret;
	    }
	    if (isset($imageframe)) {
		$frameIds = array();
		foreach (array('albumFrame', 'itemFrame') as $key) {
		    if (!empty($params[$key])) {
			$frameIds[] = $ImageBlockData[$key] = $params[$key];
		    }
		}
	    }
	    if (!empty($frameIds)) {
		$ret = $imageframe->init($template, $frameIds);
		if ($ret) {
		    return $ret;
		}
	    }

	    $ImageBlockData['blocks'] = $blocks;
	    $ImageBlockData['forceFullUrl'] = 0;
	    $template->setVariable('ImageBlockData', $ImageBlockData);
	}

	return null;
    }

    /**
     * @access private
     */
    function _getBlockData($itemType, $order, $count, $parentId=null,
			   $fullSize=false, $userId=null, $maxSize=null, $biggerOnly=false) {
	$blocks = $data = array();
	switch ($order) {
	case 'specific':
	    if (!isset($parentId)) {
		return array(GalleryCoreApi::error(ERROR_BAD_PARAMETER), null);
	    }
	    list ($ret, $ok) = GalleryCoreApi::hasItemPermission($parentId, 'core.view', $userId);
	    if ($ret) {
		return array($ret, null);
	    }
	    if (!$ok) {
		/* Ignore permission error.. just don't add a block */
		return array(null, array());
	    }
	    list ($ret, $item) = GalleryCoreApi::loadEntitiesById($parentId, 'GalleryItem');
	    if ($ret) {
		return array($ret, null);
	    }
	    break;

	case 'daily':
	case 'weekly':
	case 'monthly':
	    $key = $order . $itemType;
	    $now = localtime();
	    switch ($order) {
	    case 'daily':
		$now = $now[7]; /* tm_yday */
		break;

	    case 'weekly':
		/* Week number; Sunday as first day of week */
		$now = ((int)(($now[7] - $now[6] + ($now[7] < $now[6] ? 7 : 0)) / 7)) % 52;
		break;

	    case 'monthly':
		$now = $now[4];
		break;
	    }
	    list ($ret, $tmp) = GalleryCoreApi::getPluginParameter('module', 'imageblock', $key);
	    if ($ret) {
		return array($ret, null);
	    }
	    if (!empty($tmp)) {
		list ($itemId, $then) = explode('|', $tmp);
		if ($now != $then) {
		    $itemId = null;
		}
	    }
	    if (isset($itemId)) {
		list ($ret, $ok) = GalleryCoreApi::hasItemPermission($itemId, 'core.view', $userId);
		if ($ret || !$ok) {
		    /* Just pick a new item if this one is inaccessible or missing */
		} else {
		    list ($ret, $item) = GalleryCoreApi::loadEntitiesById($itemId, 'GalleryItem');
		    if ($ret) {
			return array($ret, null);
		    }
		    break;
		}
	    }
	    /* Set random selection for anonymous user */
	    $order = 'random';
	    $count = 1;
	    list ($ret, $userId) = GalleryCoreApi::getAnonymousUserId();
	    if ($ret) {
		return array($ret, null);
	    }
	    /* Fall through to pick new item */

	default:
	    list ($ret, $data) =
		ImageBlockHelper::fetchViewableData($itemType, $order, $count, $parentId, $userId);
	    if ($ret) {
		return array($ret, null);
	    }
	}

	if (isset($item)) {
	    $id = $item->getId();
	    $data = array('id' => $id);
	    list ($ret, $data['viewCount']) = GalleryCoreApi::fetchItemViewCount($item->getId());
	    if ($ret) {
		return array($ret, null);
	    }
	    $data = array($data);
	} else if (isset($key) && !empty($data)) {
	    /* Record the id and time for selected item */
	    $ret = GalleryCoreApi::setPluginParameter('module', 'imageblock',
						      $key, $data[0]['id'] . '|' . $now);
	    if ($ret) {
		return array($ret, null);
	    }
	}

	foreach ($data as $itemData) {
	    $id = $itemData['id'];
	    list ($ret, $item) = GalleryCoreApi::loadEntitiesById($id, 'GalleryItem');
	    if ($ret) {
		return array($ret, null);
	    }
	    list ($ret, $owner) =
		GalleryCoreApi::loadEntitiesById($item->getOwnerId(), 'GalleryUser');
	    if ($ret) {
		return array($ret, null);
	    }
	    list ($ret, $thumbnail) = GalleryCoreApi::fetchThumbnailsByItemIds(array($id));
	    if ($ret) {
		return array($ret, null);
	    }
	    $thumbnail = isset($thumbnail[$id]) ? $thumbnail[$id] : null;
	    $image = $source = null;
	    $derivativeParentId = $id;
	    if (GalleryUtilities::isA($item, 'GalleryAlbumItem') && ($fullSize || $maxSize)) {
		/* If we may use a size larger than thumbnail, find derivative source for album */
		if (!isset($thumbnail)) {
		    /* No thumbnail, no source for larger size.. just skip this block */
		    continue;
		}
		$source = $thumbnail;
		while (GalleryUtilities::isA($source, 'GalleryDerivative')
			&& $source->getDerivativeType() != DERIVATIVE_TYPE_IMAGE_PREFERRED) {
		    list ($ret, $source) = GalleryCoreApi::loadEntitiesById(
			    $source->getDerivativeSourceId(),
			    array('GalleryFileSystemEntity', 'GalleryDerivative'));
		    if ($ret) {
			return array($ret, null);
		    }
		}

		$derivativeParentId = GalleryUtilities::isA($source, 'GalleryDerivative')
		    ? $source->getParentId() : $source->getId();

		list ($ret, $ok) = GalleryCoreApi::hasItemPermission(
			$derivativeParentId, 'core.view', $userId);
		if ($ret) {
		    return array($ret, null);
		}
		if (!$ok) {
		    if ($fullSize) {
			/* Can't view source item, so no fullsize is available */
			continue;
		    }
		    /* Can't view source item, so just stick with album thumbnail */
		    $derivativeParentId = $id;
		    $source = null;
		}
	    }
	    if ($fullSize) {
		list ($ret, $ok) = GalleryCoreApi::hasItemPermission(
			$derivativeParentId, 'core.viewSource', $userId);
		if ($ret) {
		    return array($ret, null);
		}
		if (!$ok) {
		    /* Ignore permission error.. just don't add a block */
		    continue;
		}
		if (isset($source)) {
		    /* Use full size source of album thumbnail, located above */
		    $image = $source;
		} else {
		    list ($ret, $preferred) = GalleryCoreApi::fetchPreferredsByItemIds(array($id));
		    if ($ret) {
			return array($ret, null);
		    }
		    $image = isset($preferred[$id]) ? $preferred[$id] : $item;
		}
	    } else if ($maxSize && isset($thumbnail) && ($thumbnail->getWidth() >= $maxSize
			|| $thumbnail->getHeight() >= $maxSize)) {
		/* Thumbnail is big enough */
		$image = $thumbnail;
	    } else if (!$maxSize) {
		/* Use thumbnail if there is one */
		$image = $thumbnail;
	    } else {
		/*
		 * Gather the differences in image sizes from the requested max size.
		 *
		 * We use absolute values for the differentials because they could be a negative
		 * value.  We want the closest match, so -100 is closer than +125.
		 *
		 * If $biggerOnly is set, then we don't want any negative differentials.
		 */

		/* Get the preferred item object */
		list ($ret, $ok) = GalleryCoreApi::hasItemPermission(
			$derivativeParentId, 'core.viewSource', $userId);
		if ($ret) {
		    return array($ret, null);
		}
		if ($ok) {
		    if (isset($source)) {
			/* Use full size source of album thumbnail, located above */
			$image = $source;
		    } else {
			list ($ret, $preferred) =
			    GalleryCoreApi::fetchPreferredsByItemIds(array($id));
			if ($ret) {
			    return array($ret, null);
			}
			$image = isset($preferred[$id]) ? $preferred[$id] : $item;
		    }
		}
		/*
		 * Start with an arbitrarily large differential, in case we can't view the full
		 * size or we don't have a height/width for the raw image (maybe it's not viewable?)
		 */
		$imageDifferential = $imageSize = 1000000;
		if (isset($image) && method_exists($image, 'getWidth')) {
		    $imageDifferential = abs(($image->getHeight() - $maxSize)
					     + ($image->getWidth() - $maxSize));
		    $imageSize = $image->getHeight() * $image->getWidth();
		}

		/* Get the list of resizes */
		$resizes = array();
		list ($ret, $ok) = GalleryCoreApi::hasItemPermission(
			$derivativeParentId, 'core.viewResizes', $userId);
		if ($ret) {
		    return array($ret, null);
		}
		if ($ok) {
		    list ($ret, $resizes) =
			GalleryCoreApi::fetchResizesByItemIds(array($derivativeParentId));
		    if ($ret) {
			return array($ret, null);
		    }
		    $resizes = isset($resizes[$derivativeParentId]) ? $resizes[$derivativeParentId]
								    : array();
		}
		if (isset($thumbnail)) {
		    $resizes[] = $thumbnail;
		}

		foreach ($resizes as $imageObject) {
		    $rawDifferential = ($imageObject->getHeight() - $maxSize)
				     + ($imageObject->getWidth() - $maxSize);
		    if ($biggerOnly && $rawDifferential < 0) {
			continue;
		    }
		    $resizeDifferential = abs($rawDifferential);
		    $resizeSize = $imageObject->getHeight() * $imageObject->getWidth();

		    /*
		     * If this differential is smaller than the last, update the image target and
		     * the comparison value.
		     * If two differentials are equidistant, use the larger based on image size.
		     */
		    if ($resizeDifferential < $imageDifferential
			    || $resizeDifferential == $imageDifferential
			       && $resizeSize > $imageSize) {
			$image = $imageObject;
			$imageDifferential = $resizeDifferential;
			$imageSize = $resizeSize;
		    }
		}
	    }

	    if (isset($image)) {
		$itemData['item'] = (array)$item;
		$itemData['deriv'] = (array)$image;
		$itemData['owner'] = (array)$owner;
		$itemData['thumb'] = (array)$image;
		/* {g->image} won't work with item!=image and image not a derivative */
		if ($image->getId() != $id && !GalleryUtilities::isA($image, 'GalleryDerivative')) {
		    $itemData['forceItem'] = true;
		}
		$blocks[] = $itemData;
	    }
	}
	return array(null, $blocks);
    }

    /**
     * Fetch item data for use in image block
     *
     * @param string $itemType
     * @param string $order the order type (random, recent, viewed, daily, weekly, monthly)
     * @param int $count how many items to select
     * @param int $parentId limit item selection to descendents of this item (optional)
     * @param int $userId user id for permissions check (optional; defaults to current user)
     * @return array GalleryStatus a status code
     *               array of arrays containing id, viewCount of items (empty array if none found)
     */
    function fetchViewableData($itemType, $order, $count, $parentId=null, $userId=null) {
	global $gallery;
	$storage =& $gallery->getStorage();
	$typeMap = array('Image' => 1, 'Album' => 2);
	if (!isset($userId)) {
	    $userId = $gallery->getActiveUserId();
	}

	/* Someone probably typoed a blocks parameter */
	if (empty($typeMap[$itemType])) {
	    return array(GalleryCoreApi::error(ERROR_UNIMPLEMENTED), null);
	}

	list ($ret, $orderBy) = ImageBlockHelper::_buildOrderBy($order);
	if ($ret) {
	    return array($ret, null);
	}
	
	list ($ret, $isCached) = ImageBlockHelper::_isCached($userId);
	if ($ret) {
	    return array($ret, null);
	}

	if (!$isCached) {
	    $ret = ImageBlockHelper::cacheViewableTree($userId);
	    if ($ret) {
		return array($ret, null);
	    }
	}
	
	/* Prepare the query */
	$select[] = '[ImageBlockCacheMap::itemId]';
	$from[] = '[ImageBlockCacheMap] LEFT JOIN [ImageBlockDisabledMap] ON ' .
	    '[ImageBlockCacheMap::itemId]=[ImageBlockDisabledMap::itemId]';
	$where[] = '[ImageBlockCacheMap::userId] = ?';
	$where[] = '[ImageBlockCacheMap::itemType] = ?';
	$where[] = '[ImageBlockDisabledMap::itemId] IS NULL';
	$data[] = (int)$userId;
	$data[] = $typeMap[$itemType];

	if ($order == 'viewed' || isset($parentId)) {
	    $select[] = '[GalleryItemAttributesMap::viewCount]';
	    $from[] = '[GalleryItemAttributesMap]';
	    $where[] = '[ImageBlockCacheMap::itemId] = [GalleryItemAttributesMap::itemId]';
	}

	list ($ret, $rootAlbumId) =
		GalleryCoreApi::getPluginParameter('module', 'core', 'id.rootAlbum');
	if ($ret) {
	    return array($ret, null);
	}
	/* Only use LIKE statement if necessary */
	$parentSequence = null;
	if (isset($parentId) && $parentId != $rootAlbumId) {
	    /** @todo Evaluate adding parentSequence to the ImageBlockCachedMap (and its index) */
	    $where[] = '[GalleryItemAttributesMap::parentSequence] LIKE ?';
	    list ($ret, $sequence) = GalleryCoreApi::fetchParentSequence($parentId);
	    if ($ret) {
		return array($ret, null);
	    }
	    if (!empty($sequence)) {
		$sequence = implode('/', $sequence) . '/';
	    } else {
		$sequence = '';
	    }
	    $data[] = $parentSequence = $sequence . $parentId . '/%';
	}

	if ($order == 'random') {
	    /* Prepare where clause for use in second query below */
	    $whereRequery = $where;
	    $whereRequery[] = '[ImageBlockCacheMap::random] < ?';
	    $where[] = '[ImageBlockCacheMap::random] > ?';
	    list ($ret, $minMax) = ImageBlockHelper::getRandomKeyRange(
		(int)$userId, $typeMap[$itemType], $parentSequence);
	    if ($ret) {
		return array($ret, null);
	    }
	    /* We want that the returned integer is smaller than any number in the range */
	    $data[] = ImageBlockHelper::getRandomKey($minMax[0], $minMax[1]) - 1;
	}

	/* Build the query */
	$query = 'SELECT ' . implode(', ', $select) .
		 ' FROM ' . implode(', ', $from) .
		 ' WHERE ' . implode(' AND ', $where) .
		 ' ORDER BY ' . $orderBy;

	list ($ret, $query) = $storage->getFunctionSql('LIMIT', array($count, $query));
	if ($ret) {
	    return array($ret, null);
	}

	list ($ret, $results) = ImageBlockHelper::_runQuery($query, $data);
	if ($ret) {
	    return array($ret, null);
	}

	/* Requery if necessary to fill requested count */
	$remainder = $count - count($results);
	if ($order == 'random' && $remainder > 0) {
	    /* Using exact same query as above except for where clause */
	    $query = 'SELECT ' . implode(', ', $select) .
		     ' FROM ' . implode(', ', $from) .
		     ' WHERE ' . implode(' AND ', $whereRequery) .
		     ' ORDER BY ' . $orderBy;

	    list ($ret, $query) = $storage->getFunctionSql('LIMIT', array($remainder, $query));
	    if ($ret) {
		return array($ret, null);
	    }

	    list ($ret, $resultsRequery) = ImageBlockHelper::_runQuery($query, $data);
	    if ($ret) {
		return array($ret, null);
	    }
	    
	    /* Combine results from both queries */
	    $results = array_merge($results, $resultsRequery);
	}

	foreach ($results as $i => $result) {
	    if (!isset($result['viewCount'])) {
		list ($ret, $results[$i]['viewCount']) =
		    GalleryCoreApi::fetchItemViewCount($result['id']);
		if ($ret) {
		    return array($ret, null);
		}
	    }
	}

	return array(null, $results);
    }

    /**
     * Build the 'ORDER BY' section of the fetchViewableData query
     *
     * @param string $order the order type (random, recent, viewed)
     * @return array GalleryStatus a status code
     *               string containing SQL ORDER BY statement
     */
    function _buildOrderBy($order) {
	global $gallery;
	$orderBy = null;

	switch ($order) {
	case 'random':
	    $orderBy = '[ImageBlockCacheMap::random] ASC';
	    break;
	case 'recent':
	    $orderBy = '[ImageBlockCacheMap::itemTimestamp] DESC';
	    break;
	case 'viewed':
	    $orderBy = '[GalleryItemAttributesMap::viewCount] DESC';
	    break;
	default:
	    return array(GalleryCoreApi::error(ERROR_UNIMPLEMENTED), null);
	}
	return array(null, $orderBy);
    }

    /**
     * @access private
     */
    function _runQuery($query, $data) {
	global $gallery;
	list ($ret, $searchResults) = $gallery->search($query, $data);
	if ($ret) {
	    return array($ret, null);
	}
	$results = array();
	while ($rec = $searchResults->nextResult()) {
	    $result = array('id' => (int)$rec[0]);
	    if (isset($rec[1])) {
		$result['viewCount'] = (int)$rec[1];
	    }
	    $results[] = $result;
	}
	return array(null, $results);
    }

    /**
     * @access private
     */
    function _isCached($userId) {
	global $gallery;
	list ($ret, $searchResults) = $gallery->search(
	    'SELECT COUNT(*) FROM [ImageBlockCacheMap] WHERE [ImageBlockCacheMap::userId] = ?',
	    array((int)$userId));
	if ($ret) {
	    return array($ret, null);
	}
	$isCached = ($rec = $searchResults->nextResult()) && ($rec[0] > 0);
	return array(null, $isCached);
    }

    /**
     * Cache viewable data for user
     * @param int $userId
     * @return GalleryStatus a status code
     * @todo Respect DisabledMap on INSERT such that we don't have to join the DisabledMap on SELECT
     */
    function cacheViewableTree($userId) {
	global $gallery;
	$storage =& $gallery->getStorage();

	list ($ret, $aclIds) = GalleryCoreApi::fetchAccessListIds('core.view', $userId);
	if ($ret) {
	    return $ret;
	}
	if (empty($aclIds)) {
	    return null;
	}
	$aclMarkers = GalleryUtilities::makeMarkers(count($aclIds));

	list ($ret, $randStatement) = $storage->getFunctionSql('RANDOM_INTEGER', array());
	if ($ret) {
	    return $ret;
	}

	$query = '
	INSERT INTO
	  [ImageBlockCacheMap]
	SELECT DISTINCT
	  ?, ?, [GalleryEntity::creationTimestamp], [GalleryEntity::id], ' . $randStatement . '
	FROM
	  [GalleryEntity], [%s], [GalleryAccessSubscriberMap],
	  [GalleryChildEntity], [GalleryDerivative]
	WHERE
	  [%s::id] = [GalleryEntity::id]
	  AND
	  [GalleryAccessSubscriberMap::itemId] = [GalleryEntity::id]
	  AND
	  [GalleryAccessSubscriberMap::accessListId] IN (' . $aclMarkers . ')
	  AND
	  [GalleryChildEntity::parentId] = [GalleryEntity::id]
	  AND
	  [GalleryDerivative::id] = [GalleryChildEntity::id]
	  AND
	  [GalleryDerivative::derivativeType] = ?
	';

	$data = array((int)$userId, 1);
	$data = array_merge($data, $aclIds);
	$data[] = DERIVATIVE_TYPE_IMAGE_THUMBNAIL;

	$ret = $storage->execute(sprintf($query, 'GalleryDataItem', 'GalleryDataItem'), $data);
	if ($ret) {
	    return $ret;
	}

	$data[1] = 2;
	$ret = $storage->execute(sprintf($query, 'GalleryAlbumItem', 'GalleryAlbumItem'), $data);
	if ($ret) {
	    return $ret;
	}

	return null;
    }

    /**
     * Event handler for Gallery::ViewableTreeChange, GalleryEntity::save, and GalleryEntity::delete
     *
     * @see GalleryEventListener::handleEvent
     */
    function handleEvent($event) {
	switch ($event->getEventName()) {
	case 'Gallery::ViewableTreeChange':
	    /*
	     * Invalidate image block cache for specified user, or entire cache if no user
	     * Event sends array('userId'=>id or array of ids or null,
	     *                   'itemId'=>id or array of ids or null)
	     */
	    $param = $event->getData();
	    if (!empty($param['userId'])) {
		$ret = GalleryCoreApi::removeMapEntry(
		    'ImageBlockCacheMap', array('userId' => $param['userId']));
		if ($ret) {
		    return array($ret, null);
		}
	    } else {
		$ret = GalleryCoreApi::removeAllMapEntries('ImageBlockCacheMap');
		if ($ret) {
		    return array($ret, null);
		}
	    }
	    break;

	case 'GalleryEntity::delete':
	    /*
	     * Determine if the item being deleted is listed in
	     * the ImageBlockDisabledMap and if so, remove it
	     */
	    $entity = $event->getEntity();

	    if (!GalleryUtilities::isA($entity, 'GalleryItem')) {
		break;
	    }

	    list ($ret, $disabledFlag) = ImageBlockHelper::getDisabledFlag($entity->getId());
	    if ($ret) {
		return array($ret, null);
	    }
	    if (!empty($disabledFlag)) {
		$ret = GalleryCoreApi::removeMapEntry(
		    'ImageBlockDisabledMap', array('itemId' => $entity->getId()));
		if ($ret) {
		    return array($ret, null);
		}
	    }
	    break;

	case 'GalleryEntity::save':
	    /*
	     * Determines if the item being added has a parent that is listed in the
	     * ImageBlockDisabledMap and if so, add it to the map, else remove it
	     */
	    $entity = $event->getEntity();


	    /*
	     * If the entity is a GalleryDataItem or GalleryAlbumItem and is
	     * Newly Created or the parent has changed (item moved), continue
	     * processing, otherwise break out.
	     */
	    if (!((GalleryUtilities::isA($entity, 'GalleryDataItem') ||
		       GalleryUtilities::isA($entity, 'GalleryAlbumItem')) &&
		  ($entity->testPersistentFlag(STORAGE_FLAG_NEWLY_CREATED) ||
		       $entity->isModified('parentId')))) {
		break;
	    }

	    $parentId = $entity->getParentId();

	    list ($ret, $parentDisabledFlag) = ImageBlockHelper::getDisabledFlag($parentId);
	    if ($ret) {
		return array($ret, null);
	    }

	    list ($ret, $disabledFlag) = ImageBlockHelper::getDisabledFlag($entity->getId());
	    if ($ret) {
		return array($ret, null);
	    }

	    if (GalleryUtilities::isA($entity, 'GalleryDataItem')) {
		$echo = !empty($parentDisabledFlag) ? "true" : "false";

		/* Disable flag is managed (GUI) on album level, reflect this here */
		if (!empty($parentDisabledFlag) && empty($disabledFlag)) {
		    /* New parent has disabled flag, item hasn't. Change it. */
		    $ret = GalleryCoreApi::addMapEntry(
			'ImageBlockDisabledMap', array('itemId' => $entity->getId()));
		    if ($ret) {
			return array($ret, null);
		    }
		} else if (empty($parentDisabledFlag) && !empty($disabledFlag)) {
		    /* New parent doesn't have disabled flag, remove it from the item */
		    $ret = GalleryCoreApi::removeMapEntry(
			'ImageBlockDisabledMap', array('itemId' => $entity->getId()));
		    if ($ret) {
			return array($ret, null);
		    }
		}
	    } else if (GalleryUtilities::isA($entity, 'GalleryAlbumItem')
			   && $entity->testPersistentFlag(STORAGE_FLAG_NEWLY_CREATED)
			   && !empty($parentDisabledFlag) && empty($disabledFlag)) {
		/*
		 * A new album cannot have sub items and setDisabledFlag doesn't work for items
		 * that are not yet in the persistent store (database), thus use addMapEntry()
		 */
		$ret = GalleryCoreApi::addMapEntry(
		    'ImageBlockDisabledMap', array('itemId' => $entity->getId()));
		if ($ret) {
		    return array($ret, null);
		}
	    }
	    break;
	}
	return array(null, null);
    }

    /**
     * Set the disabled flag for an album
     *
     * @param GalleryAlbumItem $parentAlbum AlbumItem which is to be flagged
     * @param boolean $recursive whether to set the disabledFlag recursively to all subalbums
     * @param boolean $disabled whether to set the disabledFlag to true or to false
     * @param boolean $useProgressBar (optional) use a progressbar during update? (default=false)
     * @return GalleryStatus a status code
     */
    function setDisabledFlag($parentAlbum, $recursive, $disabled, $useProgressBar=false) {
	global $gallery;

	$parentAlbumId = $parentAlbum->getId();
	$childIds = array();

	if ($useProgressBar) {
	    list ($ret, $module) = GalleryCoreApi::loadPlugin('module', 'imageblock');
	    if ($ret) {
		return $ret;
	    }

	    $message = $module->translate('Image Block');
	    $templateAdapter =& $gallery->getTemplateAdapter();
	    $templateAdapter->updateProgressBar($message, '', 0);
	}

	if ($recursive) {
	    /*
	     * We don't care about ERROR_MISSING_OBJECT because it's generated if
	     * the album is at the top-level
	     */
	    list ($ret, $sequence) =
	    		GalleryCoreApi::fetchParentSequence($parentAlbum->getId());
	    if ($ret && !($ret->getErrorCode() & ERROR_MISSING_OBJECT)) {
		return $ret;
	    }
	    $sequence = empty($sequence) ? '' : (implode('/', $sequence) . '/');

	    /* Build the query */
	    $query = '
	    SELECT
	      [GalleryItemAttributesMap::itemId]
	    FROM
	      [GalleryItemAttributesMap] LEFT JOIN [ImageBlockDisabledMap]
	      ON [GalleryItemAttributesMap::itemId] = [ImageBlockDisabledMap::itemId]
	    WHERE
	      ([GalleryItemAttributesMap::parentSequence] LIKE ?
	      OR
	      [GalleryItemAttributesMap::itemId] = ?)
	      AND
	      [ImageBlockDisabledMap::itemId] IS ' . ($disabled ? '' : 'NOT '). 'NULL
	    ';
	    $data = array($sequence . $parentAlbumId . '/%', (int)$parentAlbum->getId());

	    list ($ret, $searchResult) = $gallery->search($query, $data);
	    if ($ret) {
		return $ret;
	    }

	    while ($result = $searchResult->nextResult()) {
		$childIds[] = (int)$result[0];
	    }
	} else {
	    list ($ret, $childIds) = GalleryCoreApi::fetchChildDataItemIds($parentAlbum);
	    $childIds[] = (int)$parentAlbum->getId();
	    if ($ret) {
		return $ret;
	    }
	}

	$i = 0;
	$total = count($childIds);
	foreach ($childIds as $itemId) {
	    $gallery->guaranteeTimeLimit(30);
	    if ($disabled) {
		$ret = GalleryCoreApi::addMapEntry(
		    'ImageBlockDisabledMap', array('itemId' => $itemId));
		if ($ret) {
		    return $ret;
		}
	    } else {
		$ret = GalleryCoreApi::removeMapEntry(
		    'ImageBlockDisabledMap', array('itemId' => $itemId));
		if ($ret) {
		    return $ret;
		}
	    }
	    if ($useProgressBar && (!(++$i % 30) || $i == $total)) {
		$templateAdapter->updateProgressBar($message, '', $i / $total);
	    }
	}
	return null;
    }

    /**
     * Get the disabled flag for an item
     *
     * @param int $itemId entityId of a GalleryItem for which the flag is to be retrieved
     * @return array GalleryStatus a status code
     *               boolean disabledFlag for the GalleryDataItem
     */
    function getDisabledFlag($itemId) {
	list ($ret, $searchResults) = GalleryCoreApi::getMapEntry('ImageBlockDisabledMap',
	    array('itemId'), array('itemId' => (int)$itemId));
	if ($ret) {
	    return array($ret, null);
	}

	$result = false;
	if ($rec = $searchResults->nextResult()) {
	    $result = (bool)$rec[0];
	}
	return array(null, $result);
    }

    /**
     * Get a random number that can be used to search later
     * @param  int $min(optional) the minimum number to generate (default: 0)
     * @param  int $max(optional) the maximim number to generate (default: 2147483647)
     * @return int a number between 0 and 2147483647.
     */
    function getRandomKey($min=0, $max=2147483647) {
    	global $gallery;
    	$phpVm = $gallery->getPhpVm();
	static $initialized = false;

	if (!$initialized) {
	    list($usec, $sec) = explode(' ', microtime());
	    srand($sec + $usec * 100000);
	    $initialized = true;
	}
	return $phpVm->rand($min, $max);
    }

    /**
     * Determine the highest and lowest numbers currently in the random index.
     *
     * @param int $userId User id
     * @param int $itemType ImageBlock itemType
     * @param string $parentSequence (optional) Optional parent sequence condition
     * @return array GalleryStatus a status code
     *		     array int Minimum value of the random number to be genereated
     *			   int Maximum value of the random number to be generated
     */
    function getRandomKeyRange($userId, $itemType, $parentSequence=null) {
	global $gallery;
	$storage = $gallery->getStorage();

	$from[] = '[ImageBlockCacheMap] LEFT JOIN [ImageBlockDisabledMap] ON '
		. '[ImageBlockCacheMap::itemId]=[ImageBlockDisabledMap::itemId]';
	$where[] = '[ImageBlockCacheMap::userId] = ?';
	$where[] = '[ImageBlockCacheMap::itemType] = ?';
	$where[] = '[ImageBlockCacheMap::random] IS NOT NULL';
	$where[] = '[ImageBlockDisabledMap::itemId] IS NULL';
	$data = array($userId, $itemType);
	if (!empty($parentSequence)) {
	    $from[] = '[GalleryItemAttributesMap]';
	    $where[] = '[ImageBlockCacheMap::itemId] = [GalleryItemAttributesMap::itemId]';
	    $where[] = '[GalleryItemAttributesMap::parentSequence] LIKE ?';
	    $data[] = $parentSequence;
	}

	$query = '
	SELECT MIN([ImageBlockCacheMap::random]), MAX([ImageBlockCacheMap::random])
	FROM ' . implode(', ', $from) . '
	WHERE ' . implode(' AND ', $where);

	list ($ret, $results) = $storage->search($query, $data);
	if ($ret) {
	    return array($ret, null);
	}

	if ($row = $results->nextResult()) {
	    $min = $row[0];
	    $max = $row[1];
	}
	return array(null, array($min, $max));
    }
}
?>

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists