<?php
/*
 * $RCSfile: GalleryEntityHelper_medium.class,v $
 *
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2005 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.
 */
/**
 * @version $Revision: 1.11 $ $Date: 2005/08/23 03:49:04 $
 * @package GalleryCore
 * @author Bharat Mediratta <bharat@menalto.com>
 */

/**
 * Helper class for GalleryEntities
 *
 * @package GalleryCore
 * @subpackage Helpers
 * @abstract
 */
class GalleryEntityHelper_medium {

    /**
     * Delete the entity with the given id
     *
     * @param int the id of a GalleryEntity to delete
     * @return object GalleryStatus a status code
     * @static
     */
    function deleteEntityById($id) {
	if (empty($id)) {
	    return GalleryStatus::error(ERROR_BAD_PARAMETER, __FILE__, __LINE__);
	}
	$lockIds = array();

	/* Don't write lock it if it's already locked somewhere else */
	if (!GalleryCoreApi::isWriteLocked($id)) {
	    list ($ret, $lockIds[]) = GalleryCoreApi::acquireWriteLock($id);
	    if ($ret->isError()) {
		return $ret->wrap(__FILE__, __LINE__);
	    }
	}

	list ($ret, $entity) = GalleryEntityHelper_simple::loadEntitiesById($id);
	if ($ret->isError()) {
	    GalleryCoreApi::releaseLocks($lockIds);
	    return $ret->wrap(__FILE__, __LINE__);
	}

	if (GalleryUtilities::isA($entity, 'GalleryChildEntity')) {
	    list ($ret, $lockIds[]) = GalleryCoreApi::acquireReadLockParents($id);
	    if ($ret->isError()) {
		GalleryCoreApi::releaseLocks($lockIds);
		return $ret->wrap(__FILE__, __LINE__);
	    }
	}

	/* If this item has links to it, make one of those links the master */
	list ($ret, $linkedIds) = GalleryEntityHelper_medium::fetchEntitiesLinkedTo($id);
	if ($ret->isError()) {
	    GalleryCoreApi::releaseLocks($lockIds);
	    return $ret->wrap(__FILE__, __LINE__);
	}

	if (!empty($linkedIds)) {
	    /* Lock all of the linked items */
	    list ($ret, $lockIds[]) = GalleryCoreApi::acquireWriteLock($linkedIds);
	    if ($ret->isError()) {
		GalleryCoreApi::releaseLocks($lockIds);
		return $ret->wrap(__FILE__, __LINE__);
	    }

	    /* Make the first link the master, and point the rest at it */
	    list ($ret, $linkedEntities) = GalleryEntityHelper_simple::loadEntitiesById($linkedIds);
	    if ($ret->isError()) {
		GalleryCoreApi::releaseLocks($lockIds);
		return $ret->wrap(__FILE__, __LINE__);
	    }

	    $ret = $linkedEntities[0]->detachLink();
	    if ($ret->isError()) {
		GalleryCoreApi::releaseLocks($lockIds);
		return $ret->wrap(__FILE__, __LINE__);
	    }

	    $ret = $linkedEntities[0]->save();
	    if ($ret->isError()) {
		GalleryCoreApi::releaseLocks($lockIds);
		return $ret->wrap(__FILE__, __LINE__);
	    }
	    for ($i = 1; $i < sizeof($linkedEntities); $i++) {
		$linkedEntities[$i]->setLinkId($linkedEntities[0]->getId());
		$linkedEntities[$i]->setLinkedEntity($linkedEntities[0]);
		$ret = $linkedEntities[$i]->save();
		if ($ret->isError()) {
		    GalleryCoreApi::releaseLocks($lockIds);
		    return $ret->wrap(__FILE__, __LINE__);
		}
	    }

	    /* Remap any derivatives sourced from old-master to new-master */
	    $ret = GalleryCoreApi::remapSourceIds($id, $linkedEntities[0]->getId());
	    if ($ret->isError()) {
		GalleryCoreApi::releaseLocks($lockIds);
		return $ret->wrap(__FILE__, __LINE__);
	    }
	}

	$ret = $entity->delete();
	if ($ret->isError()) {
	    GalleryCoreApi::releaseLocks($lockIds);
	    return $ret->wrap(__FILE__, __LINE__);
	}

	$ret = GalleryCoreApi::releaseLocks($lockIds);
	if ($ret->isError()) {
	    return $ret->wrap(__FILE__, __LINE__);
	}

	return GalleryStatus::success();
    }

    /**
     * Fetch the ids of the entities linked to the target entity
     *
     * @param int the target entity id
     * @return array object GalleryStatus a status code
     *               array entity ids
     * @static
     */
    function fetchEntitiesLinkedTo($targetId) {
	global $gallery;

	$query = '
	SELECT
	  [GalleryEntity::id]
	FROM
	  [GalleryEntity]
	WHERE
	  [GalleryEntity::linkId] = ?
	ORDER BY
	  [GalleryEntity::id] ASC
	';
	$storage =& $gallery->getStorage();
	list ($ret, $searchResults) = $gallery->search($query, array($targetId));
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}

	$linkedIds = array();
	while ($result = $searchResults->nextResult()) {
	    $linkedIds[] = $result[0];
	}

	return array(GalleryStatus::success(), $linkedIds);
    }

    /**
     * Remove onLoadHandlers from all entities
     *
     * @param array of factory impl ids
     * @return object GalleryStatus a status code
     * @static
     */
    function removeOnLoadHandlers($handlerIds) {
	global $gallery;

	$query = 'SELECT [GalleryEntity::id] FROM [GalleryEntity]
		  WHERE [GalleryEntity::onLoadHandlers] LIKE ?';
	$i = 0;
	foreach ($handlerIds as $handlerId) {
	    list ($ret, $results) = $gallery->search($query, array("%|$handlerId|%"));
	    if ($ret->isError()) {
		return $ret->wrap(__FILE__, __LINE__);
	    }

	    while ($result = $results->nextResult()) {
		if ($i++ % 10 == 0) {
		    $gallery->guaranteeTimeLimit(5);
		}
		$id = (int)$result[0];
		list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($id);
		if ($ret->isError()) {
		    return $ret->wrap(__FILE__, __LINE__);
		}
		list ($ret, $entity) = GalleryCoreApi::loadEntitiesById($id);
		if ($ret->isError()) {
		    GalleryCoreApi::releaseLocks($lockId);
		    return $ret->wrap(__FILE__, __LINE__);
		}
		$entity->removeOnLoadHandler($handlerId);
		$ret = $entity->save();
		if ($ret->isError()) {
		    GalleryCoreApi::releaseLocks($lockId);
		    return $ret->wrap(__FILE__, __LINE__);
		}
		$ret = GalleryCoreApi::releaseLocks($lockId);
		if ($ret->isError()) {
		    return $ret->wrap(__FILE__, __LINE__);
		}
	    }
	}

	return GalleryStatus::success();
    }

    /**
     * Set modification timestamp for the given entity id to the current time.
     *
     * @param int the entity id
     * @return object GalleryStatus a status code
     * @static
     */
    function updateModificationTimestamp($entityId) {
	list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($entityId);
	if ($ret->isError()) {
	    return $ret->wrap(__FILE__, __LINE__);
	}
	list ($ret, $entity) = GalleryCoreApi::loadEntitiesById($entityId);
	if ($ret->isError()) {
	    GalleryCoreApi::releaseLocks($lockId);
	    return $ret->wrap(__FILE__, __LINE__);
	}
	$entity->setModificationTimestamp(time());
	$ret = $entity->save();
	if ($ret->isError()) {
	    GalleryCoreApi::releaseLocks($lockId);
	    return $ret->wrap(__FILE__, __LINE__);
	}
	$ret = GalleryCoreApi::releaseLocks($lockId);
	if ($ret->isError()) {
	    return $ret->wrap(__FILE__, __LINE__);
	}
	return GalleryStatus::success();
    }
}
?>
