<?php
/**
 * Copyright 2008-2016 Horde LLC (http://www.horde.org/)
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 *
 * @author   Duck <duck@obala.net>
 * @category Horde
 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 * @package  Group
 */

/**
 * This class provides a mock driver for the Horde group system.
 *
 * @author   Duck <duck@obala.net>
 * @category Horde
 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 * @package  Group
 */
class Horde_Group_Mock extends Horde_Group_Base
{
    /**
     * List of groups.
     *
     * @var array
     */
    protected $_groups = array();

    /**
     * Access log.
     *
     * @var array
     */
    protected $_log = array();

    /**
     * Returns the current method call log.
     *
     * @return array  The current call log.
     */
    public function getLog()
    {
        return $this->_log;
    }

    /**
     * Resets the current method call log.
     */
    public function clearLog()
    {
        $this->_log = array();
    }

    /**
     * Logs a method call.
     *
     * Add the currently called class method to the call log.
     */
    protected function _log()
    {
        $trace = debug_backtrace();
        $this->_log[] = $trace[1]['function'];
    }

    /**
     * Creates a new group.
     *
     * @param string $name   A group name.
     * @param string $email  The group's email address.
     *
     * @return mixed  The ID of the created group.
     * @throws Horde_Group_Exception
     */
    protected function _create($name, $email = null)
    {
        $this->_log();
        $id = 'group_' . count($this->_groups);
        $this->_groups[$id] = array('name'  => $name,
                                    'email' => $email,
                                    'users' => array());
        return $id;
    }

    /**
     * Renames a group.
     *
     * @param mixed $gid    A group ID.
     * @param string $name  The new name.
     *
     * @throws Horde_Group_Exception
     */
    protected function _rename($gid, $name)
    {
        $this->_log();
        if (!isset($this->_groups[$gid])) {
            throw new Horde_Exception_NotFound('Group "' . $gid . '" not found');
        }
        $this->_groups[$gid]['name'] = $name;
    }

    /**
     * Removes a group.
     *
     * @param mixed $gid  A group ID.
     *
     * @throws Horde_Group_Exception
     */
    protected function _remove($gid)
    {
        $this->_log();
        unset($this->_groups[$gid]);
    }

    /**
     * Checks if a group exists.
     *
     * @param mixed $gid  A group ID.
     *
     * @return boolean  True if the group exists.
     * @throws Horde_Group_Exception
     */
    protected function _exists($gid)
    {
        $this->_log();
        return isset($this->_groups[$gid]);
    }

    /**
     * Returns a group name.
     *
     * @param mixed $gid  A group ID.
     *
     * @return string  The group's name.
     * @throws Horde_Group_Exception
     */
    protected function _getName($gid)
    {
        $this->_log();
        if (!isset($this->_groups[$gid])) {
            throw new Horde_Exception_NotFound('Group ' . $gid . ' not found');
        }
        return $this->_groups[$gid]['name'];
    }

    /**
     * Returns all available attributes of a group.
     *
     * @param mixed $gid  A group ID.
     *
     * @return array  The group's date.
     * @throws Horde_Group_Exception
     * @throws Horde_Exception_NotFound
     */
    protected function _getData($gid)
    {
        $this->_log();
        if (!isset($this->_groups[$gid])) {
            throw new Horde_Exception_NotFound('Group ' . $gid . ' not found');
        }
        return $this->_groups[$gid];
    }

    /**
     * Sets one or more attributes of a group.
     *
     * @param mixed $gid               A group ID.
     * @param array|string $attribute  An attribute name or a hash of
     *                                 attributes.
     * @param string $value            An attribute value if $attribute is a
     *                                 string.
     *
     * @throws Horde_Group_Exception
     * @throws Horde_Exception_NotFound
     */
    protected function _setData($gid, $attribute, $value = null)
    {
        $this->_log();
        if (!isset($this->_groups[$gid])) {
            throw new Horde_Exception_NotFound('Group ' . $gid . ' not found');
        }
        if (is_array($attribute)) {
            $this->_groups[$gid] = array_merge($this->_groups[$gid], $attribute);
        } else {
            $this->_groups[$gid][$attribute] = $value;
        }
    }

    /**
     * Returns a list of all groups a user may see, with IDs as keys and names
     * as values.
     *
     * @return array  All existing groups.
     * @throws Horde_Group_Exception
     */
    protected function _listAll()
    {
        $this->_log();
        $groups = array();
        foreach ($this->_groups as $gid => $group) {
            $groups[$gid] = $group['name'];
        }
        asort($groups);
        return $groups;
    }

    /**
     * Returns a list of users in a group.
     *
     * @param mixed $gid  A group ID.
     *
     * @return array  List of group users.
     * @throws Horde_Group_Exception
     */
    protected function _listUsers($gid)
    {
        $this->_log();
        if (!isset($this->_groups[$gid])) {
            throw new Horde_Exception_NotFound('Group ' . $gid . ' not found');
        }
        return $this->_groups[$gid]['users'];
    }

    /**
     * Returns a list of groups a user belongs to.
     *
     * @param string $user  A user name.
     *
     * @return array  A list of groups, with IDs as keys and names as values.
     * @throws Horde_Group_Exception
     */
    protected function _listGroups($user)
    {
        $this->_log();
        $groups = array();
        foreach ($this->_groups as $gid => $group) {
            if (in_array($user, $group['users'])) {
                $groups[$gid] = $group['name'];
            }
        }
        asort($groups);
        return $groups;
    }

    /**
     * Add a user to a group.
     *
     * @param mixed $gid    A group ID.
     * @param string $user  A user name.
     *
     * @throws Horde_Group_Exception
     */
    protected function _addUser($gid, $user)
    {
        $this->_log();
        if (!isset($this->_groups[$gid])) {
            throw new Horde_Exception_NotFound('Group ' . $gid . ' not found');
        }
        $this->_groups[$gid]['users'][] = $user;
    }

    /**
     * Removes a user from a group.
     *
     * @param mixed $gid    A group ID.
     * @param string $user  A user name.
     *
     * @throws Horde_Group_Exception
     */
    protected function _removeUser($gid, $user)
    {
        $this->_log();
        if (!isset($this->_groups[$gid])) {
            throw new Horde_Exception_NotFound('Group ' . $gid . ' not found');
        }
        $key = array_search($user, $this->_groups[$gid]['users']);
        if ($key !== false) {
            unset($this->_groups[$gid]['users'][$key]);
        }
    }

    /**
     * Searches for group names.
     *
     * @param string $name  A search string.
     *
     * @return array  A list of matching groups, with IDs as keys and names as
     *                values.
     * @throws Horde_Group_Exception
     */
    protected function _search($name)
    {
        $this->_log();
        $groups = array();
        foreach ($this->_groups as $gid => $group) {
            if (strpos($group['name'], $name) !== false) {
                $groups[$gid] = $group['name'];
            }
        }
        asort($groups);
        return $groups;
    }
}
