<?php
/*
 * $RCSfile: GalleryQuotasHelper.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.
 */

/**
 * @package Quotas
 * @version $Revision: 1.2 $ $Date: 2005/08/23 03:49:49 $
 * @author Robert Balousek <volksport@users.sf.net>
 */

/**
 * A helper class for Quotas
 *
 * Utility functions useful in managing Quotas
 *
 * @package Quotas
 * @subpackage Classes
 */
class GalleryQuotasHelper {

    /**
     * Get the total size of all the user's current files, excluding the files in the
     * excludeIds param array.
     *
     * @return array object GalleryStatus a status code
     * 		     integer user's disk usage in bytes
     *
     * @static
     */
    function getUserDiskUsage($userId, $excludeIds=array()) {
	global $gallery;
	
        $storage =& $gallery->getStorage();

        $query = '
        SELECT
          SUM([GalleryDataItem::size])
        FROM
          [GalleryItem], [GalleryDataItem]
        WHERE
          [GalleryItem::id] = [GalleryDataItem::id]
	  AND
	  [GalleryItem::ownerId] = ?
	';

	$data = array($userId);
	if (!empty($excludeIds)) {
	    $data = array_merge($data, $excludeIds);
	    $itemIdMarkers = GalleryUtilities::makeMarkers(count($excludeIds));
	    $query .= '  AND
	    		 [GalleryItem::id] NOT IN (' . $itemIdMarkers . ')';
	}

        list ($ret, $searchResults) = $gallery->search($query, $data);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null);
        }

        /* Get our user's total disk usage */
        $result = $searchResults->nextResult();
        if (!empty($result[0])) {
            $userDiskUsage = $result[0];
	} else {
	    $userDiskUsage = 0;
	}

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

    /**
     * Get the user's quota if one exists. This is achieved by checking for a direct user quota,
     * if one does not exist, then quotas for groups the user belongs to is checked. 
     * If the user belongs to one or more groups with quotas, the group with the highest quota
     * is used as their quota.
     *
     * @return array object GalleryStatus a status code
     * 		     bool does a quota exists for this user
     * 		     integer user's disk quota in Kilobytes
     *
     * @static
     */
    function getUserDiskQuota($userId) {
	global $gallery;
	$userDiskQuota = null;
	list ($ret, $userQuotaExists, $userQuotaInfo) = 
	    GalleryQuotasHelper::fetchUserQuota($userId);
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null, null);
	}
	if (!$userQuotaExists) {
	    list ($ret, $groupQuotaExists, $groupQuotaInfo) = 
	        GalleryQuotasHelper::fetchHighestGroupQuota($userId);
	    if ($ret->isError()) {
		return array($ret->wrap(__FILE__, __LINE__), null, null);
	    }
	    if ($groupQuotaExists) {
	        $userDiskQuota = $groupQuotaInfo['quota']; 
	    }
	} else {
	    $userDiskQuota = $userQuotaInfo['quota'];
	    $groupQuotaExists = false;
	}

	return array(GalleryStatus::success(), $userQuotaExists | $groupQuotaExists, 
		     $userDiskQuota);
    }

    /**
     * Get the users highest group quota, if they have multiple (or one), or return no
     * quota if they have no group quotas assigned.
     *
     * @return array object GalleryStatus a status code
     * 		     boolean: does a quota exists for this user
     * 		     array('quota' => integer user's disk quota in Kilobytes,
     *			   'name' => string group's name
     * 			  )
     *
     * @static
     */
    function fetchHighestGroupQuota($userId) {
	global $gallery;

	list ($ret, $groupQuotaIds) = GalleryCoreApi::fetchGroupsForUser($userId);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null, null);
        }
        $storage =& $gallery->getStorage();
        $groupQuotaIds = array_keys($groupQuotaIds);
        $groupQuotaIdMarkers = GalleryUtilities::makeMarkers(count($groupQuotaIds));

        $query = '
        SELECT
          [GalleryQuotasMap::quotaSize], [GalleryGroup::groupName]
        FROM
          [GalleryQuotasMap], [GalleryGroup]
        WHERE
          [GalleryQuotasMap::userOrGroupId] IN (' . $groupQuotaIdMarkers . ')
          AND
          [GalleryQuotasMap::userOrGroupId] = [GalleryGroup::id]
	ORDER BY
	  [GalleryQuotasMap::quotaSize] DESC
        ';

        $data = $groupQuotaIds;
        $options = array();
        $options['limit'] = array('count' => 1);

        list ($ret, $searchResults) = $gallery->search($query, $data, $options);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null, null);
        }

        /* Get our group's quota size and name */
        $result = $searchResults->nextResult();
        if (!empty($result)) {
            $groupQuotaExists = true;
            $groupQuotaInfo = array('quota' => $result[0], 'name' => $result[1]);
        } else {
            $groupQuotaExists = false;
            $groupQuotaInfo = array();
        }

	return array(GalleryStatus::success(), $groupQuotaExists, $groupQuotaInfo);
    }

    /**
     * Convert Kilobytes to a human readable format (ie: KB, MB, GB)
     *
     * @return array object GalleryStatus a status code
     * 		     string user's quota in human readable format
     * 		     string the unit of measurement for the user's quota (ie: KB, MB, GB)
     *
     * @static
     */
    function humanReadableFromKilobytes($kilobytes) {
	$suffixes = array('KB', 'MB', 'GB');	
	$base = 1024;
	$useSuffix = 0;
	$kilobytes = (float)$kilobytes;
	while($kilobytes >= $base && $useSuffix < count($suffixes)-1) {
	    $kilobytes /= (float)$base;
	    $useSuffix++;
	}
	$humanReadable = (string)round($kilobytes, 2);
	$unit = $suffixes[$useSuffix];
	return array(GalleryStatus::success(), $humanReadable, $unit);
    }

    /**
     * Get list of groups who have quotas
     *
     * @return array object GalleryStatus a status code
     * 		     array(groupId => array('quota' => group's disk quota,
     *					    'name' => group's groupname
     *					   )
     * 			  )
     *
     * @static
     */
    function fetchQuotaGroupIdList($count, $offset=0) {
	global $gallery;

        $storage =& $gallery->getStorage();

        $query = '
        SELECT
          [GalleryQuotasMap::userOrGroupId], [GalleryQuotasMap::quotaSize], 
          [GalleryGroup::groupName]
        FROM
          [GalleryQuotasMap], [GalleryGroup]
        WHERE
          [GalleryQuotasMap::userOrGroupId] = [GalleryGroup::id]
        ORDER BY
          [GalleryQuotasMap::userOrGroupId] ASC
        ';

	$data = array();
        $options = array();
        $options['limit'] = array('count' => $count, 'offset' => $offset);

        list ($ret, $searchResults) = $gallery->search($query, $data, $options);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null);
        }

        /* Get our groups' id, quota size, and name */
	$groupQuotasList = array();
	while($result = $searchResults->nextResult()) {
	    $groupQuotasList[$result[0]] = array('quota' => $result[1], 'name' => $result[2]);
	}
        return array(GalleryStatus::success(), $groupQuotasList);
    }

    /**
     * Get the users highest group quota, if they have multiple (or one), or return no
     * quota if they have no group quotas assigned.
     *
     * @return array object GalleryStatus a status code
     * 		     integer the number of groups that have quotas assigned
     *
     * @static
     */
    function fetchQuotaGroupCount() {
	global $gallery;

        $storage =& $gallery->getStorage();

        $query = '
        SELECT
          COUNT([GalleryQuotasMap::userOrGroupId])
        FROM
          [GalleryQuotasMap], [GalleryGroup]
        WHERE
          [GalleryQuotasMap::userOrGroupId] = [GalleryGroup::id]
        ';

        list ($ret, $searchResults) = $gallery->search($query);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null);
        }

        /* Get the number of groups that have quotas assigned */
        $result = $searchResults->nextResult();
	$groupCount = $result[0];

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

    /**
     * Get list of user's who have quotas
     *
     * @return array object GalleryStatus a status code
     * 		     array(groupId => array('quota' => user's disk quota,
     * 					    'name' => user's username
     *					   )
     *			  )
     *
     * @static
     */
    function fetchQuotaUserIdList($count, $offset=0) {
        global $gallery;

        $storage =& $gallery->getStorage();

        $query = '
        SELECT
          [GalleryQuotasMap::userOrGroupId], [GalleryQuotasMap::quotaSize], [GalleryUser::userName]
        FROM
          [GalleryQuotasMap], [GalleryUser]
        WHERE
          [GalleryQuotasMap::userOrGroupId] = [GalleryUser::id]
        ORDER BY
          [GalleryQuotasMap::userOrGroupId] ASC
        ';

        $data = array();
        $options = array();
        $options['limit'] = array('count' => $count, 'offset' => $offset);

        list ($ret, $searchResults) = $gallery->search($query, $data, $options);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null);
        }

        /* Get our users' id, quota size, and name */
        $userQuotasList = array();
        while($result = $searchResults->nextResult()) {
            $userQuotasList[$result[0]] = array('quota' => $result[1], 'name' => $result[2]);
        }
        return array(GalleryStatus::success(), $userQuotasList);

    }

    /**
     * Get the number of users that have a quota assigned directly to them
     *
     * @return array object GalleryStatus a status code
     * 		     integer the number of users that have quotas assigned
     *
     * @static
     */
    function fetchQuotaUserCount() {
	global $gallery;

        $storage =& $gallery->getStorage();

        $query = '
        SELECT
          COUNT([GalleryQuotasMap::userOrGroupId])
        FROM
          [GalleryQuotasMap], [GalleryUser]
        WHERE
          [GalleryQuotasMap::userOrGroupId] = [GalleryUser::id]
        ';

        list ($ret, $searchResults) = $gallery->search($query);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null);
        }

        /* Get the number of users that have quotas assigned */
        $result = $searchResults->nextResult();
        $userCount = $result[0];

        return array(GalleryStatus::success(), $userCount);
    }
    
    /**
     * get the quota assigned to a group
     *
     * @return array object GalleryStatus a status code
     * 		     boolean does a quota exist
     * 		     array('id' => group's groupId
     * 			   'quota' => group's disk quota,
     * 			   'name' => group's groupname
     * 			  )
     *
     * @static
     */
    function fetchGroupQuota($groupId) {
	global $gallery;
        $storage =& $gallery->getStorage();
        $query = '
        SELECT
          [GalleryQuotasMap::userOrGroupId], [GalleryQuotasMap::quotaSize], 
          [GalleryGroup::groupName] 
        FROM
          [GalleryQuotasMap], [GalleryGroup]
        WHERE
          [GalleryQuotasMap::userOrGroupId] = ?
	  AND
	  [GalleryQuotasMap::userOrGroupId] = [GalleryGroup::id]	
        ';

        $data = array($groupId);

        list ($ret, $searchResults) = $gallery->search($query, $data);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null, null);
        }

        /* Get our group's quota size and name */
        $result = $searchResults->nextResult();
	if (!empty($result)) {
	    $quotaExists = true;
	    $groupQuotaInfo = array('id' => $result[0], 'quota' => $result[1], 
	    			    'name' => $result[2]);
	} else {
	    $quotaExists = false;
	    $groupQuotaInfo = array();
	}
	return array(GalleryStatus::success(), $quotaExists, $groupQuotaInfo);
	
    }

    /**
     * get the quota assigned to a user
     *
     * @return array object GalleryStatus a status code
     *		     boolean does a quota exist
     * 		     array('id' => user's userId
     *			   'quota' => user's disk quota,
     *			   'name' => user's username
     *			  )
     *
     * @static
     */
    function fetchUserQuota($userId) {
        global $gallery;
        
        $storage =& $gallery->getStorage();

        $query = '
        SELECT
          [GalleryQuotasMap::userOrGroupId], [GalleryQuotasMap::quotaSize], [GalleryUser::userName]
        FROM
          [GalleryQuotasMap], [GalleryUser]
        WHERE
          [GalleryQuotasMap::userOrGroupId] = ?
          AND
          [GalleryQuotasMap::userOrGroupId] = [GalleryUser::id]
        ';

        $data = array($userId);

        list ($ret, $searchResults) = $gallery->search($query, $data);
        if ($ret->isError()) {
            return array($ret->wrap(__FILE__, __LINE__), null, null);
        }

        /* Get our users' quota size and name */
        $result = $searchResults->nextResult();
        if (!empty($result)) {
            $quotaExists = true;
	    $userQuotaInfo = array('id' => $result[0], 'quota' => $result[1], 
	    			   'name' => $result[2]);
	} else {
	    $quotaExists = false;
	    $userQuotaInfo = array();
	}
        return array(GalleryStatus::success(), $quotaExists, $userQuotaInfo);
    }
}
?>
