Files
server/usr/share/psa-pear/pear/php/Horde/Perms/Sql.php
2026-01-07 20:52:11 +01:00

424 lines
13 KiB
PHP

<?php
/**
* The Horde_Perms_Sql:: class provides a SQL driver for the Horde
* permissions system.
*
* Copyright 2008-2017 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
* @package Perms
*/
class Horde_Perms_Sql extends Horde_Perms_Base
{
/**
* Configuration parameters.
*
* @var array
*/
protected $_params = array();
/**
* Handle for the current database connection.
*
* @var Horde_Db_Adapter
*/
protected $_db;
/**
* Incrementing version number if cached classes change.
*
* @var integer
*/
private $_cacheVersion = 2;
/**
* Cache of previously retrieved permissions.
*
* @var array
*/
protected $_permsCache = array();
/**
* Constructor.
*
* @param array $params Configuration parameters (in addition to base
* Horde_Perms parameters):
* <pre>
* 'db' - (Horde_Db_Adapter) [REQUIRED] The DB instance.
* 'table' - (string) The name of the perms table.
* DEFAULT: 'horde_perms'
* </pre>
*
* @throws Horde_Perms_Exception
*/
public function __construct($params = array())
{
if (!isset($params['db'])) {
throw new Horde_Perms_Exception('Missing db parameter.');
}
$this->_db = $params['db'];
unset($params['db']);
$this->_params = array_merge(array(
'table' => 'horde_perms'
), $this->_params, $params);
parent::__construct($params);
}
/**
* Returns a new permissions object.
*
* @param string $name The permission's name.
* @param string $type The permission type.
* @param array $params The permission parameters.
*
* @return Horde_Perms_Permission_Sql A new permissions object.
*/
public function newPermission($name, $type = 'matrix', $params = null)
{
$ob = new Horde_Perms_Permission_Sql($name, $this->_cacheVersion, $type, $params);
$ob->setObs($this->_cache, $this->_db);
return $ob;
}
/**
* Returns an object corresponding to the named permission, with the
* users and other data retrieved appropriately.
*
* @param string $name The name of the permission to retrieve.
*
* @return Horde_Perms_Permission_Sql TODO
* @throw Horde_Perms_Exception
*/
public function getPermission($name)
{
if (isset($this->_permsCache[$name])) {
return $this->_permsCache[$name];
}
$perm = $this->_cache->get('perm_sql_' . $this->_cacheVersion . $name, $GLOBALS['conf']['cache']['default_lifetime']);
if (!empty($perm)) {
$this->_permsCache[$name] = unserialize($perm);
}
if (empty($this->_permsCache[$name])) {
$query = 'SELECT perm_id, perm_data FROM ' .
$this->_params['table'] . ' WHERE perm_name = ?';
try {
$result = $this->_db->selectOne($query, array($name));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
if (empty($result)) {
throw new Horde_Perms_Exception('Does not exist', Horde_Perms_Exception::NOT_EXIST);
}
$object = new Horde_Perms_Permission_Sql($name, $this->_cacheVersion);
$object->setId($result['perm_id']);
$object->setData(unserialize($result['perm_data']));
$this->_cache->set('perm_sql_' . $this->_cacheVersion . $name, serialize($object));
$this->_permsCache[$name] = $object;
}
$this->_permsCache[$name]->setObs($this->_cache, $this->_db);
return $this->_permsCache[$name];
}
/**
* Returns a permission object corresponding to the given unique ID,
* with the users and other data retrieved appropriately.
*
* @param integer $id The unique ID of the permission to retrieve.
*
* @return Horde_Perms_Permission_Sql TODO
* @throws Horde_Perms_Exception
*/
public function getPermissionById($id)
{
if ($id == Horde_Perms::ROOT || empty($id)) {
$object = $this->newPermission(Horde_Perms::ROOT);
} else {
$query = 'SELECT perm_name, perm_data FROM ' .
$this->_params['table'] . ' WHERE perm_id = ?';
try {
$result = $this->_db->selectOne($query, array($id));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
if (empty($result)) {
throw new Horde_Perms_Exception('Does not exist', Horde_Perms_Exception::NOT_EXIST);
}
$object = new Horde_Perms_Permission_Sql($result['perm_name'], $this->_cacheVersion);
$object->setId($id);
$object->setData(unserialize($result['perm_data']));
$object->setObs($this->_cache, $this->_db);
}
return $object;
}
/**
* Adds a permission to the permissions system. The permission must first
* be created with newPermission(), and have any initial users added to
* it, before this function is called.
*
* @param Horde_Perms_Permission_Sql $perm The perm object.
*
* @return integer Permission ID in the database.
* @throws Horde_Perms_Exception
*/
public function addPermission(Horde_Perms_Permission $perm)
{
$name = $perm->getName();
if (empty($name)) {
throw new Horde_Perms_Exception('Permission name must be non-empty.');
}
$this->_cache->expire('perm_sql_' . $this->_cacheVersion . $name);
$this->_cache->expire('perm_sql_exists_' . $this->_cacheVersion . $name);
// remove root from the name
$root = Horde_Perms::ROOT . ':';
if (substr($name, 0, strlen($root)) == ($root)) {
$name = substr($name, strlen($root));
}
// build parents
$parents = null;
if (($pos = strrpos($name, ':')) !== false) {
$parent_name = substr($name, 0, $pos);
$query = 'SELECT perm_id, perm_parents FROM ' .
$this->_params['table'] . ' WHERE perm_name = ?';
$result = $this->_db->selectOne($query, array($parent_name));
if (empty($result)) {
throw new Horde_Perms_Exception(Horde_Perms_Translation::t("Trying to create sub permission of non-existent parent permission. Create parent permission(s) first."));
}
$parents = $result['perm_parents'] . ':' . $result['perm_id'];
}
$query = 'INSERT INTO ' . $this->_params['table'] .
' (perm_name, perm_parents) VALUES (?, ?)';
try {
$id = $this->_db->insert($query, array($name, $parents));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
$perm->setId($id);
$perm->save();
return $id;
}
/**
* Removes a permission from the permissions system permanently.
*
* @param Horde_Perms_Permission_Sql $perm The permission to
* remove.
* @param boolean $force Force to remove every
* child.
*
* @return boolean True if permission was deleted.
* @throws Horde_Perms_Exception
*/
public function removePermission(Horde_Perms_Permission $perm,
$force = false)
{
$name = $perm->getName();
$this->_cache->expire('perm_sql_' . $this->_cacheVersion . $name);
$this->_cache->expire('perm_sql_exists_' . $this->_cacheVersion . $name);
$query = 'DELETE FROM ' . $this->_params['table'] .
' WHERE perm_name = ?';
try {
$result = $this->_db->delete($query, array($name));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
if (!$force) {
return (bool)$result;
}
/* Need to expire cache for all sub-permissions. */
try {
$sub = $this->_db->selectValues(
'SELECT perm_name FROM ' . $this->_params['table'] . ' WHERE perm_name LIKE ?',
array($name . ':%')
);
foreach ($sub as $val) {
$this->_cache->expire('perm_sql_' . $this->_cacheVersion . $val);
$this->_cache->expire('perm_sql_exists_' . $this->_cacheVersion . $val);
}
} catch (Horde_Db_Exception $e) {}
$query = 'DELETE FROM ' . $this->_params['table'] .
' WHERE perm_name LIKE ?';
try {
return (bool)$this->_db->delete($query, array($name . ':%'));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
}
/**
* Returns the unique identifier of this permission.
*
* @param Horde_Perms_Permission_Sql $perm The permission object to
* get the ID of.
*
* @return integer The unique id.
* @throws Horde_Perms_Exception
*/
public function getPermissionId($permission)
{
if ($permission->getName() == Horde_Perms::ROOT) {
return Horde_Perms::ROOT;
}
$query = 'SELECT perm_id FROM ' . $this->_params['table'] .
' WHERE perm_name = ?';
try {
return $this->_db->selectValue($query, array($permission->getName()));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
}
/**
* Checks if a permission exists in the system.
*
* @param string $permission The permission to check.
*
* @return boolean True if the permission exists.
* @throws Horde_Perms_Exception
*/
public function exists($permission)
{
$key = 'perm_sql_exists_' . $this->_cacheVersion . $permission;
$exists = $this->_cache->get($key, $GLOBALS['conf']['cache']['default_lifetime']);
if ($exists === false) {
$query = 'SELECT COUNT(*) FROM ' . $this->_params['table'] .
' WHERE perm_name = ?';
try {
$exists = $this->_db->selectValue($query, array($permission));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
$this->_cache->set($key, (string)$exists);
}
return (bool)$exists;
}
/**
* Returns a child's direct parent ID.
*
* @param mixed $child The object name for which to look up the parent's
* ID.
*
* @return integer The unique ID of the parent.
* @throws Horde_Perms_Exception
*/
public function getParent($child)
{
$query = 'SELECT perm_parents FROM ' . $this->_params['table'] .
' WHERE perm_name = ?';
try {
$parents = $this->_db->selectValue($query, array($child));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
if (empty($parents)) {
return Horde_Perms::ROOT;
}
$parents = explode(':', $parents);
return array_pop($parents);
}
/**
* Returns a list of parent permissions.
*
* @param string $child The name of the child to retrieve parents for.
*
* @return array A hash with all parents in a tree format.
* @throws Horde_Perms_Exception
*/
public function getParents($child)
{
$query = 'SELECT perm_parents FROM ' . $this->_params['table'] .
' WHERE perm_name = ?';
try {
$result = $this->_db->selectValue($query, array($child));
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
if (empty($result)) {
throw new Horde_Perms_Exception('Does not exist', Horde_Perms_Exception::NOT_EXIST);
}
return $this->_getParents($result);
}
/**
* TODO
*/
protected function _getParents($parents)
{
if (empty($parents)) {
return array(Horde_Perms::ROOT => true);
}
$pname = $parents;
$parents = substr($parents, 0, strrpos($parents, ':'));
return array($pname => $this->_getParents($parents));
}
/**
* Returns all permissions of the system in a tree format.
*
* @return array A hash with all permissions in a tree format.
* @throws Horde_Perms_Exception
*/
public function getTree()
{
$query = 'SELECT perm_id, perm_name FROM ' . $this->_params['table'] .
' ORDER BY perm_name ASC';
try {
$tree = $this->_db->selectAssoc($query);
} catch (Horde_Db_Exception $e) {
throw new Horde_Perms_Exception($e);
}
$tree[Horde_Perms::ROOT] = Horde_Perms::ROOT;
return $tree;
}
}