Index: src/gambio_updater/classes/DatabaseModel.inc.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/gambio_updater/classes/DatabaseModel.inc.php	(revision 57f58b0cdb7c34863c4b98a4b99a21259aba5d04)
+++ src/gambio_updater/classes/DatabaseModel.inc.php	(date 1578925615570)
@@ -698,760 +698,792 @@
 	{
 		return $this->coo_mysqli;
 	}
-	
-	
-	/**
-	 * Adds a new Admin Access Group into the database.
-	 *
-	 * @param array $names        Array which contains the names for this group. Keys must be the language id.
-	 * @param array $descriptions Array which contains the descriptions for this group. Keys must be the language id.
-	 * @param int   $sortOrder    Sort order.
-	 * @param int   $parentId     Parent group id.
-	 *
-	 * @return int|bool Returns the group id on success or false on failure.
-	 */
-	public function addAdminAccessGroup($names, $descriptions = array(), $sortOrder = 0, $parentId = 0, $protected = true)
-	{
-		$query   = sprintf('INSERT INTO `admin_access_groups` (`parent_id`, `sort_order`, `protected`) VALUES (%d, %d, %d);',
-		                   (int)$parentId, (int)$sortOrder, (int)$protected);
-		$groupId = $this->query($query);
-		if($groupId === false)
-		{
-			return false;
-		}
-		
-		$query = 'INSERT INTO `admin_access_group_descriptions` (`admin_access_group_id`, `language_id`, `name`, `description`) VALUES ';
-		foreach($names as $languageId => $name)
-		{
-			$query .= sprintf('(%d, %d, "%s", "%s"), ', (int)$groupId, (int)$languageId,
-			                  $this->real_escape_string($name),
-				(isset($descriptions[$languageId]) ? $this->real_escape_string($descriptions[$languageId]) : ''));
-		}
-		
-		if($this->query(substr($query, 0, -2) . ';') !== false)
-		{
-			return $groupId;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Adds a Group Item to an existing Admin Access Group.
-	 *
-	 * @param int          $groupId     Group ID.
-	 * @param string|array $types       Type of this item. Should be "CONTROLLER", "PAGE" or "AJAX_HANDLER".
-	 * @param string|array $identifiers Identifier of this item. Must be the name of the controller or page.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function addAdminAccessGroupItem($groupId, $types, $identifiers)
-	{
-		$query = 'REPLACE INTO `admin_access_group_items` (`admin_access_group_id`, `identifier`, `type`) VALUES ';
-		
-		if(is_array($identifiers))
-		{
-			foreach($identifiers as $index => $identifier)
-			{
-				$query .= sprintf('(%d, "%s", "%s"), ', (int)$groupId, $this->real_escape_string($identifier),
-				                  $this->real_escape_string(is_array($types) ? $types[$index] : $types));
-			}
-		}
-		else
-		{
-			$query .= sprintf('(%d, "%s", "%s"), ', (int)$groupId, $this->real_escape_string($identifiers),
-			                  $this->real_escape_string($types));
-		}
-		
-		return $this->query(substr($query, 0, -2) . ';') !== false;
-	}
-	
-	
-	/**
-	 * Adds a new Admin Access Role into the database.
-	 *
-	 * @param array $names        Array which contains the names for this role. Keys must be the language id.
-	 * @param array $descriptions Array which contains the descriptions for this role. Keys must be the language id.
-	 * @param int   $sortOrder    Sort order.
-	 *
-	 * @return int|bool Returns the role id on success or false on failure.
-	 */
-	public function addAdminAccessRole($names, $descriptions = array(), $sortOrder = 0, $protected = true)
-	{
-		$query  = sprintf('INSERT INTO `admin_access_roles` (`sort_order`, `protected`) VALUES (%d, %d);', (int)$sortOrder, (int)$protected);
-		$roleId = $this->query($query);
-		if($roleId === false)
-		{
-			return false;
-		}
-		
-		$query = 'INSERT INTO `admin_access_role_descriptions` (`admin_access_role_id`, `language_id`, `name`, `description`) VALUES ';
-		foreach($names as $languageId => $name)
-		{
-			$query .= sprintf('(%d, %d, "%s", "%s"), ', (int)$roleId, (int)$languageId,
-			                  $this->real_escape_string($name),
-				(isset($descriptions[$languageId]) ? $this->real_escape_string($descriptions[$languageId]) : ''));
-		}
-		
-		if($this->query(substr($query, 0, -2) . ';') !== false)
-		{
-			return $roleId;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Grants permission for an existing Admin Access Permission.
-	 * The permission will be identified by the ID of the Admin Access Role and Group.
-	 *
-	 * @param int  $roleId        Role id.
-	 * @param int  $groupId       Group id.
-	 * @param bool $grantReading  True if reading permission should be granted, otherwise false.
-	 * @param bool $grantWriting  True if writing permission should be granted, otherwise false.
-	 * @param bool $grantDeleting True if deleting permission should be granted, otherwise false.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function grantAdminAccessPermission($roleId,
-	                                           $groupId,
-	                                           $grantReading = true,
-	                                           $grantWriting = true,
-	                                           $grantDeleting = true)
-	{
-		$query = sprintf('REPLACE INTO `admin_access_permissions` (`admin_access_role_id`, `admin_access_group_id`, `reading_granted`, `writing_granted`, `deleting_granted`) VALUES (%d, %d, %d, %d, %d);',
-		                 (int)$roleId, (int)$groupId, (int)$grantReading, (int)$grantWriting, (int)$grantDeleting);
-		$error = $this->query($query) !== false;
-		
-		$parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
-		                            (int)$groupId);
-		$parentGroupQuery = $this->query($parentGroupSql, true);
-		if($parentGroupQuery->num_rows > 0)
-		{
-			$parentGroup = $parentGroupQuery->fetch_assoc();
-			
-			if((int)($parentGroup['admin_access_group_id']) > 0)
-			{
-				$error &= $this->grantAdminAccessPermission($roleId, (int)$parentGroup['admin_access_group_id'],
-				                                            $grantReading ? : $parentGroup['reading_granted'] === '1',
-				                                            $grantWriting ? : $parentGroup['writing_granted'] === '1',
-				                                            $grantDeleting ? : $parentGroup['deleting_granted']
-				                                                               === '1');
-			}
-		}
-		
-		return $error;
-	}
-	
-	
-	/**
-	 * Adds an existing Admin Access Role to an existing Customer/Admin.
-	 *
-	 * @param int $roleId     Role id.
-	 * @param int $customerId Customer id.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function addAdminAccessRoleToUserByCustomerId($roleId, $customerId)
-	{
-		$query = sprintf('REPLACE INTO `admin_access_users` (`customer_id`, `admin_access_role_id`) VALUES (%d, %d);',
-		                 (int)$customerId, (int)$roleId);
-		
-		return $this->query($query) !== false;
-	}
-	
-	
-	/**
-	 * Removes an existing Admin Access Role to an existing Customer/Admin.
-	 *
-	 * @param int $roleId     Role id.
-	 * @param int $customerId Customer id.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function removeAdminAccessRoleFromUserByCustomerId($roleId, $customerId)
-	{
-		$query = sprintf('DELETE FROM `admin_access_users` WHERE `customer_id` = %d AND `admin_access_role_id` = %d;',
-		                 (int)$customerId, (int)$roleId);
-		
-		return $this->query($query) !== false;
-	}
-	
-	
-	/**
-	 * Returns the id of an existing Admin Access Group identified by a type and the identifier.
-	 *
-	 * @param string $type       Type of this identifier. Should be "PAGE", "CONTROLLER" or "AJAX_HANDLER".
-	 * @param string $identifier Identifier you are looking for. Should be the name of a controller or page.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function getAdminAccessGroupIdByIdentifier($type, $identifier)
-	{
-		$query = sprintf('SELECT * FROM  `admin_access_group_items` WHERE `type` = "%s" AND `identifier` = "%s" LIMIT 1;',
-		                 $this->real_escape_string($type), $this->real_escape_string($identifier));
-		
-		$group = $this->query($query, true);
-		
-		if($group !== false)
-		{
-			$group = $group->fetch_assoc();
-			
-			return $group['admin_access_group_id'];
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Returns the id of an existing Admin Access Group identified by a type and the identifier.
-	 *
-	 * @param string $type       Type of this identifier. Should be "PAGE", "CONTROLLER" or "AJAX_HANDLER".
-	 * @param string $identifier Identifier you are looking for. Should be the name of a controller or page.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function getAdminAccessGroupIdByName($name, $languageId = 2)
-	{
-		$query = sprintf('SELECT * FROM  `admin_access_group_descriptions` WHERE `name` = "%s" AND `language_id` = %s LIMIT 1;',
-		                 $this->real_escape_string($name), (int)$languageId);
-		
-		$group = $this->query($query, true);
-		
-		if($group !== false)
-		{
-			$group = $group->fetch_assoc();
-			
-			return $group['admin_access_group_id'];
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the deleting permission for a controller.
-	 *
-	 * @param string $identifier The name of a controller to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check the permission for.
-	 *
-	 * @return bool True if customer has a deleting permission for the controller, false otherwise.
-	 */
-	public function checkAdminAccessDeletingPermissionForController($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'CONTROLLER', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['deleting_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the deleting permission for a page.
-	 *
-	 * @param string $identifier The name of a page to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check permission for.
-	 *
-	 * @return bool True if customer has a deleting permission for the page, false otherwise.
-	 */
-	public function checkAdminAccessDeletingPermissionForPage($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'PAGE', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['deleting_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the deleting permission for an ajax handler.
-	 *
-	 * @param string $identifier The name of an ajax handler to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check permission for.
-	 *
-	 * @return bool True if customer has a deleting permission for the ajax handler, false otherwise.
-	 */
-	public function checkAdminAccessDeletingPermissionForAjaxHandler($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'AJAX_HANDLER', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['deleting_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the reading permission for a controller.
-	 *
-	 * @param string $identifier The name of a controller to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check the permission for.
-	 *
-	 * @return bool True if customer has a reading permission for the controller, false otherwise.
-	 */
-	public function checkAdminAccessReadingPermissionForController($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'CONTROLLER', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['reading_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the reading permission for a page.
-	 *
-	 * @param string $identifier The name of a page to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check permission for.
-	 *
-	 * @return bool True if customer has a reading permission for the page, false otherwise.
-	 */
-	public function checkAdminAccessReadingPermissionForPage($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'PAGE', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['reading_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the reading permission for an ajax handler.
-	 *
-	 * @param string $identifier The name of an ajax handler to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check permission for.
-	 *
-	 * @return bool True if customer has a reading permission for the ajax handler, false otherwise.
-	 */
-	public function checkAdminAccessReadingPermissionForAjaxHandler($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'AJAX_HANDLER', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['reading_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the writing permission for a controller.
-	 *
-	 * @param string $identifier The name of a controller to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check the permission for.
-	 *
-	 * @return bool True if customer has a writing permission for the controller, false otherwise.
-	 */
-	public function checkAdminAccessWritingPermissionForController($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'CONTROLLER', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['writing_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the writing permission for a page.
-	 *
-	 * @param string $identifier The name of a page to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check permission for.
-	 *
-	 * @return bool True if customer has a writing permission for the page, false otherwise.
-	 */
-	public function checkAdminAccessWritingPermissionForPage($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'PAGE', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['writing_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Checks the writing permission for an ajax handler.
-	 *
-	 * @param string $identifier The name of an ajax handler to identify an admin access group.
-	 * @param int    $customerId ID of a customer to check permission for.
-	 *
-	 * @return bool True if customer has a writing permission for the ajax handler, false otherwise.
-	 */
-	public function checkAdminAccessWritingPermissionForAjaxHandler($identifier, $customerId)
-	{
-		$query      = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
-		                      $this->real_escape_string($identifier), 'AJAX_HANDLER', (int)$customerId);
-		$permission = $this->query($query, true);
-		
-		if($permission !== false)
-		{
-			$permission = $permission->fetch_assoc();
-			
-			return (int)$permission['writing_granted'] === 1;
-		}
-		
-		return false;
-	}
-	
-	
-	/**
-	 * Returns a collection of all permissions by a given role ID.
-	 *
-	 * @param int $roleId Role ID.
-	 *
-	 * @return mysqli_result
-	 */
-	public function getAdminAccessPermissionsByRoleId($roleId)
-	{
-		$query = sprintf('SELECT `permissions`.* FROM `admin_access_permissions` `permissions` WHERE `permissions`.`admin_access_role_id` = %d;',
-		                 (int)$roleId);
-		
-		return $this->query($query, true);
-	}
-	
-	
-	/**
-	 * Returns all roles of certain user by a given user ID.
-	 *
-	 * @param int $id User ID.
-	 *
-	 * @return mysqli_result
-	 */
-	public function getAdminAccessRolesByCustomerId($customerId)
-	{
-		$query = sprintf('SELECT `roles`.* FROM `admin_access_users` `users` LEFT JOIN `admin_access_roles` `roles` ON `users`.`admin_access_role_id` = `roles`.`admin_access_role_id` WHERE `users`.`customer_id` = %d;',
-		                 (int)$customerId);
-		
-		return $this->query($query, true);
-	}
-	
-	
-	/**
-	 * Grants deleting permission to a role for a given group id.
-	 *
-	 * @param int $groupId Group ID to grant permission for.
-	 * @param int $roleId  Role ID to grant permission for.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function grantAdminAccessDeletingPermissionToRole($groupId, $roleId)
-	{
-		$query = sprintf('UPDATE `admin_access_permissions` SET `deleting_granted` = "1" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
-		                 (int)$roleId, (int)$groupId);
-		$error = $this->query($query) !== false;
-		
-		$parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
-		                            (int)$groupId);
-		$parentGroupQuery = $this->query($parentGroupSql, true);
-		if($parentGroupQuery->num_rows > 0)
-		{
-			$parentGroup = $parentGroupQuery->fetch_assoc();
-			if((int)$parentGroup['admin_access_group_id'] > 0)
-			{
-				$error &= $this->grantAdminAccessDeletingPermissionToRole((int)$parentGroup['admin_access_group_id'],
-				                                                          $roleId);
-			}
-		}
-		
-		return $error;
-	}
-	
-	
-	/**
-	 * Removes deleting permission from role for a given group id.
-	 *
-	 * @param int $groupId Group ID to remove permission for.
-	 * @param int $roleId  Role ID to remove permission from.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function removeAdminAccessDeletingPermissionFromRole($groupId, $roleId)
-	{
-		$query = sprintf('UPDATE `admin_access_permissions` SET `deleting_granted` = "0" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
-		                 (int)$roleId, (int)$groupId);
-		
-		return $this->query($query) !== false;
-	}
-	
-	
-	/**
-	 * Grants reading permission to a role for a given group id.
-	 *
-	 * @param int $groupId Group ID to grant permission for.
-	 * @param int $roleId  Role ID to grant permission for.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function grantAdminAccessReadingPermissionToRole($groupId, $roleId)
-	{
-		$query = sprintf('UPDATE `admin_access_permissions` SET `reading_granted` = "1" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
-		                 (int)$roleId, (int)$groupId);
-		$error = $this->query($query) !== false;
-		
-		$parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
-		                            (int)$groupId);
-		$parentGroupQuery = $this->query($parentGroupSql, true);
-		if($parentGroupQuery->num_rows > 0)
-		{
-			$parentGroup = $parentGroupQuery->fetch_assoc();
-			if((int)$parentGroup['admin_access_group_id'] > 0)
-			{
-				$error &= $this->grantAdminAccessReadingPermissionToRole((int)$parentGroup['admin_access_group_id'],
-				                                                         $roleId);
-			}
-		}
-		
-		return $error;
-	}
-	
-	
-	/**
-	 * Removes reading permission from role for a given group id.
-	 *
-	 * @param int $groupId Group ID to remove permission for.
-	 * @param int $roleId  Role ID to remove permission from.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function removeAdminAccessReadingPermissionFromRole($groupId, $roleId)
-	{
-		$query = sprintf('UPDATE `admin_access_permissions` SET `reading_granted` = "0" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
-		                 (int)$roleId, (int)$groupId);
-		
-		return $this->query($query) !== false;
-	}
-	
-	
-	/**
-	 * Grants writing permission to a role for a given group id.
-	 *
-	 * @param int $groupId Group ID to grant permission for.
-	 * @param int $roleId  Role ID to grant permission for.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function grantAdminAccessWritingPermissionToRole($groupId, $roleId)
-	{
-		$query = sprintf('UPDATE `admin_access_permissions` SET `writing_granted` = "1" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
-		                 (int)$roleId, (int)$groupId);
-		$error = $this->query($query) !== false;
-		
-		$parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
-		                            (int)$groupId);
-		$parentGroupQuery = $this->query($parentGroupSql, true);
-		if($parentGroupQuery->num_rows > 0)
-		{
-			$parentGroup = $parentGroupQuery->fetch_assoc();
-			if((int)$parentGroup['admin_access_group_id'] > 0)
-			{
-				$error &= $this->grantAdminAccessWritingPermissionToRole((int)$parentGroup['admin_access_group_id'],
-				                                                         $roleId);
-			}
-		}
-		
-		return $error;
-	}
-	
-	
-	/**
-	 * Removes writing permission from role for a given group id.
-	 *
-	 * @param int $groupId Group ID to remove permission for.
-	 * @param int $roleId  Role ID to remove permission from.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function removeAdminAccessWritingPermissionFromRole($groupId, $roleId)
-	{
-		$query = sprintf('UPDATE `admin_access_permissions` SET `writing_granted` = "0" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
-		                 (int)$roleId, (int)$groupId);
-		
-		return $this->query($query) !== false;
-	}
-	
-	
-	/**
-	 * Deletes role by a given role ID.
-	 *
-	 * @param int $roleId ID of the role that should be deleted.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function deleteAdminAccessRoleById($roleId)
-	{
-		$query = sprintf('DELETE FROM `admin_access_roles` WHERE `admin_access_role_id` = %d;', (int)$roleId);
-		$error = $this->query($query) !== false;
-		
-		$query = sprintf('DELETE FROM `admin_access_role_descriptions` WHERE `admin_access_role_id` = %d;',
-		                 (int)$roleId);
-		$error &= $this->query($query) !== false;
-		
-		$query = sprintf('DELETE FROM `admin_access_users` WHERE `admin_access_role_id` = %d;', (int)$roleId);
-		$error &= $this->query($query) !== false;
-		
-		$query = sprintf('DELETE FROM `admin_access_permissions` WHERE `admin_access_role_id` = %d;', (int)$roleId);
-		$error &= $this->query($query) !== false;
-		
-		return $error;
-	}
-	
-	
-	/**
-	 * Returns a collection of all roles.
-	 *
-	 * @return mysqli_result
-	 */
-	public function getAllAdminAccessRoles()
-	{
-		return $this->query('SELECT `roles`.* FROM `admin_access_roles` `roles`;', true);
-	}
-	
-	
-	/**
-	 * Deletes an admin access user by a given customer ID.
-	 *
-	 * @param int $customerId ID of the user that should be deleted.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function deleteAdminAccessUserByCustomerId($customerId)
-	{
-		$query = sprintf('DELETE FROM `admin_access_users` WHERE `customer_id` = %d;', (int)$customerId);
-		
-		return $this->query($query) !== false;
-	}
-	
-	
-	/**
-	 * Returns a role by a given role ID.
-	 *
-	 * @param int $roleId ID of the requested role.
-	 *
-	 * @return mysqli_result
-	 */
-	public function getAdminAccessRoleById($roleId)
-	{
-		$query = sprintf('SELECT `roles`.* FROM `admin_access_roles` `roles` WHERE `roles`.`admin_access_role_id` = %d;',
-		                 (int)$roleId);
-		
-		return $this->query($query, true);
-	}
-	
-	
-	/**
-	 * Returns a collection of all groups.
-	 *
-	 * @return mysqli_result
-	 */
-	public function getAllAdminAccessGroups()
-	{
-		return $this->query('SELECT `groups`.* FROM `admin_access_groups` `groups`;', true);
-	}
-	
-	
-	/**
-	 * Returns a group by a given group id.
-	 *
-	 * @param int $id Group id.
-	 *
-	 * @return mysqli_result
-	 */
-	public function getAdminAccessGroupById($groupId)
-	{
-		$query = sprintf('SELECT `groups`.* FROM `admin_access_groups` `groups` WHERE `groups`.`admin_access_group_id` = %d;',
-		                 (int)$groupId);
-		
-		return $this->query($query, true);
-	}
-	
-	
-	/**
-	 * Deletes a group by a given group ID.
-	 *
-	 * @param int $id ID of the group that should be deleted.
-	 *
-	 * @return bool Return true on success and false on failure.
-	 */
-	public function deleteAdminAccessGroupById($groupId)
-	{
-		$query = sprintf('DELETE FROM `admin_access_groups` WHERE `admin_access_group_id` = %d;', (int)$groupId);
-		$error = $this->query($query) !== false;
-		
-		$query = sprintf('DELETE FROM `admin_access_group_items` WHERE `admin_access_group_id` = %d;', (int)$groupId);
-		$error &= $this->query($query) !== false;
-		
-		$query = sprintf('DELETE FROM `admin_access_group_descriptions` WHERE `admin_access_group_id` = %d;',
-		                 (int)$groupId);
-		$error &= $this->query($query) !== false;
-		
-		$query = sprintf('DELETE FROM `admin_access_permissions` WHERE `admin_access_group_id` = %d;', (int)$groupId);
-		$error &= $this->query($query) !== false;
-		
-		return $error;
-	}
+    
+    
+    /**
+     * Adds a new Admin Access Group into the database.
+     *
+     * @param array $names        Array which contains the names for this group. Keys must be the language id.
+     * @param array $descriptions Array which contains the descriptions for this group. Keys must be the language id.
+     * @param int   $sortOrder    Sort order.
+     * @param int   $parentId     Parent group id.
+     *
+     * @return int|bool Returns the group id on success or false on failure.
+     */
+    public function addAdminAccessGroup($names, $descriptions = [], $sortOrder = 0, $parentId = 0, $protected = true)
+    {
+        $query   = sprintf('INSERT INTO `admin_access_groups` (`parent_id`, `sort_order`, `protected`) VALUES (%d, %d, %d);',
+                           (int)$parentId,
+                           (int)$sortOrder,
+                           (int)$protected);
+        $groupId = $this->query($query);
+        if ($groupId === false) {
+            return false;
+        }
+        
+        $query = 'INSERT INTO `admin_access_group_descriptions` (`admin_access_group_id`, `language_id`, `name`, `description`) VALUES ';
+        foreach ($names as $languageId => $name) {
+            $query .= sprintf('(%d, %d, "%s", "%s"), ',
+                              (int)$groupId,
+                              (int)$languageId,
+                              $this->real_escape_string($name),
+                (isset($descriptions[$languageId]) ? $this->real_escape_string($descriptions[$languageId]) : ''));
+        }
+        
+        $result = $this->query(substr($query, 0, -2) . ';');
+        if ($result !== false && $result !== null) {
+            return $groupId;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Adds a Group Item to an existing Admin Access Group.
+     *
+     * @param int          $groupId     Group ID.
+     * @param string|array $types       Type of this item. Should be "CONTROLLER", "PAGE" or "AJAX_HANDLER".
+     * @param string|array $identifiers Identifier of this item. Must be the name of the controller or page.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function addAdminAccessGroupItem($groupId, $types, $identifiers)
+    {
+        $query = 'REPLACE INTO `admin_access_group_items` (`admin_access_group_id`, `identifier`, `type`) VALUES ';
+        
+        if (is_array($identifiers)) {
+            foreach ($identifiers as $index => $identifier) {
+                $query .= sprintf('(%d, "%s", "%s"), ',
+                                  (int)$groupId,
+                                  $this->real_escape_string($identifier),
+                                  $this->real_escape_string(is_array($types) ? $types[$index] : $types));
+            }
+        } else {
+            $query .= sprintf('(%d, "%s", "%s"), ',
+                              (int)$groupId,
+                              $this->real_escape_string($identifiers),
+                              $this->real_escape_string($types));
+        }
+        
+        $result = $this->query(substr($query, 0, -2) . ';');
+        
+        return $result !== null && $result !== false;
+    }
+    
+    
+    /**
+     * Adds a new Admin Access Role into the database.
+     *
+     * @param array $names        Array which contains the names for this role. Keys must be the language id.
+     * @param array $descriptions Array which contains the descriptions for this role. Keys must be the language id.
+     * @param int   $sortOrder    Sort order.
+     *
+     * @return int|bool Returns the role id on success or false on failure.
+     */
+    public function addAdminAccessRole($names, $descriptions = [], $sortOrder = 0, $protected = true)
+    {
+        $query  = sprintf('INSERT INTO `admin_access_roles` (`sort_order`, `protected`) VALUES (%d, %d);',
+                          (int)$sortOrder,
+                          (int)$protected);
+        $roleId = $this->query($query);
+        if ($roleId === null || $roleId === false) {
+            return false;
+        }
+        
+        $query = 'INSERT INTO `admin_access_role_descriptions` (`admin_access_role_id`, `language_id`, `name`, `description`) VALUES ';
+        foreach ($names as $languageId => $name) {
+            $query .= sprintf('(%d, %d, "%s", "%s"), ',
+                              (int)$roleId,
+                              (int)$languageId,
+                              $this->real_escape_string($name),
+                (isset($descriptions[$languageId]) ? $this->real_escape_string($descriptions[$languageId]) : ''));
+        }
+        $result = $this->query(substr($query, 0, -2) . ';');
+        if ($result !== null && $result !== false) {
+            return $roleId;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Grants permission for an existing Admin Access Permission.
+     * The permission will be identified by the ID of the Admin Access Role and Group.
+     *
+     * @param int  $roleId        Role id.
+     * @param int  $groupId       Group id.
+     * @param bool $grantReading  True if reading permission should be granted, otherwise false.
+     * @param bool $grantWriting  True if writing permission should be granted, otherwise false.
+     * @param bool $grantDeleting True if deleting permission should be granted, otherwise false.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function grantAdminAccessPermission(
+        $roleId,
+        $groupId,
+        $grantReading = true,
+        $grantWriting = true,
+        $grantDeleting = true
+    ) {
+        $query  = sprintf('REPLACE INTO `admin_access_permissions` (`admin_access_role_id`, `admin_access_group_id`, `reading_granted`, `writing_granted`, `deleting_granted`) VALUES (%d, %d, %d, %d, %d);',
+                          (int)$roleId,
+                          (int)$groupId,
+                          (int)$grantReading,
+                          (int)$grantWriting,
+                          (int)$grantDeleting);
+        $result = $this->query($query, true);
+        $error  = $result !== null && $result !== false;
+        
+        $parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
+                                    (int)$groupId);
+        $parentGroupQuery = $this->query($parentGroupSql, true);
+        if ($parentGroupSql !== null && $parentGroupQuery->num_rows > 0) {
+            $parentGroup = $parentGroupQuery->fetch_assoc();
+            
+            if ((int)($parentGroup['admin_access_group_id']) > 0) {
+                $error &= $this->grantAdminAccessPermission($roleId,
+                                                            (int)$parentGroup['admin_access_group_id'],
+                                                            $grantReading ? : $parentGroup['reading_granted'] === '1',
+                                                            $grantWriting ? : $parentGroup['writing_granted'] === '1',
+                                                            $grantDeleting ? : $parentGroup['deleting_granted']
+                                                                               === '1');
+            }
+        }
+        
+        return $error;
+    }
+    
+    
+    /**
+     * Adds an existing Admin Access Role to an existing Customer/Admin.
+     *
+     * @param int $roleId     Role id.
+     * @param int $customerId Customer id.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function addAdminAccessRoleToUserByCustomerId($roleId, $customerId)
+    {
+        $query  = sprintf('REPLACE INTO `admin_access_users` (`customer_id`, `admin_access_role_id`) VALUES (%d, %d);',
+                          (int)$customerId,
+                          (int)$roleId);
+        $result = $this->query($query, true);
+        
+        return $result !== null && $result !== false;
+    }
+    
+    
+    /**
+     * Removes an existing Admin Access Role to an existing Customer/Admin.
+     *
+     * @param int $roleId     Role id.
+     * @param int $customerId Customer id.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function removeAdminAccessRoleFromUserByCustomerId($roleId, $customerId)
+    {
+        $query  = sprintf('DELETE FROM `admin_access_users` WHERE `customer_id` = %d AND `admin_access_role_id` = %d;',
+                          (int)$customerId,
+                          (int)$roleId);
+        $result = $this->query($query, true);
+        
+        return $result !== null && $result !== false;
+    }
+    
+    
+    /**
+     * Returns the id of an existing Admin Access Group identified by a type and the identifier.
+     *
+     * @param string $type       Type of this identifier. Should be "PAGE", "CONTROLLER" or "AJAX_HANDLER".
+     * @param string $identifier Identifier you are looking for. Should be the name of a controller or page.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function getAdminAccessGroupIdByIdentifier($type, $identifier)
+    {
+        $query = sprintf('SELECT * FROM  `admin_access_group_items` WHERE `type` = "%s" AND `identifier` = "%s" LIMIT 1;',
+                         $this->real_escape_string($type),
+                         $this->real_escape_string($identifier));
+        
+        $group = $this->query($query, true);
+        if ($group !== null && $group->num_rows > 0) {
+            $group = $group->fetch_assoc();
+            
+            return $group['admin_access_group_id'];
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Returns the id of an existing Admin Access Group identified by a type and the identifier.
+     *
+     * @param string $type       Type of this identifier. Should be "PAGE", "CONTROLLER" or "AJAX_HANDLER".
+     * @param string $identifier Identifier you are looking for. Should be the name of a controller or page.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function getAdminAccessGroupIdByName($name, $languageId = 2)
+    {
+        $query = sprintf('SELECT * FROM  `admin_access_group_descriptions` WHERE `name` = "%s" AND `language_id` = %s LIMIT 1;',
+                         $this->real_escape_string($name),
+                         (int)$languageId);
+        
+        $group = $this->query($query, true);
+        if ($group !== null && $group->num_rows > 0) {
+            $group = $group->fetch_assoc();
+            
+            return $group['admin_access_group_id'];
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the deleting permission for a controller.
+     *
+     * @param string $identifier The name of a controller to identify an admin access group.
+     * @param int    $customerId ID of a customer to check the permission for.
+     *
+     * @return bool True if customer has a deleting permission for the controller, false otherwise.
+     */
+    public function checkAdminAccessDeletingPermissionForController($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'CONTROLLER',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['deleting_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the deleting permission for a page.
+     *
+     * @param string $identifier The name of a page to identify an admin access group.
+     * @param int    $customerId ID of a customer to check permission for.
+     *
+     * @return bool True if customer has a deleting permission for the page, false otherwise.
+     */
+    public function checkAdminAccessDeletingPermissionForPage($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'PAGE',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['deleting_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the deleting permission for an ajax handler.
+     *
+     * @param string $identifier The name of an ajax handler to identify an admin access group.
+     * @param int    $customerId ID of a customer to check permission for.
+     *
+     * @return bool True if customer has a deleting permission for the ajax handler, false otherwise.
+     */
+    public function checkAdminAccessDeletingPermissionForAjaxHandler($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'AJAX_HANDLER',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['deleting_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the reading permission for a controller.
+     *
+     * @param string $identifier The name of a controller to identify an admin access group.
+     * @param int    $customerId ID of a customer to check the permission for.
+     *
+     * @return bool True if customer has a reading permission for the controller, false otherwise.
+     */
+    public function checkAdminAccessReadingPermissionForController($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'CONTROLLER',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['reading_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the reading permission for a page.
+     *
+     * @param string $identifier The name of a page to identify an admin access group.
+     * @param int    $customerId ID of a customer to check permission for.
+     *
+     * @return bool True if customer has a reading permission for the page, false otherwise.
+     */
+    public function checkAdminAccessReadingPermissionForPage($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'PAGE',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['reading_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the reading permission for an ajax handler.
+     *
+     * @param string $identifier The name of an ajax handler to identify an admin access group.
+     * @param int    $customerId ID of a customer to check permission for.
+     *
+     * @return bool True if customer has a reading permission for the ajax handler, false otherwise.
+     */
+    public function checkAdminAccessReadingPermissionForAjaxHandler($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'AJAX_HANDLER',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['reading_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the writing permission for a controller.
+     *
+     * @param string $identifier The name of a controller to identify an admin access group.
+     * @param int    $customerId ID of a customer to check the permission for.
+     *
+     * @return bool True if customer has a writing permission for the controller, false otherwise.
+     */
+    public function checkAdminAccessWritingPermissionForController($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'CONTROLLER',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['writing_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the writing permission for a page.
+     *
+     * @param string $identifier The name of a page to identify an admin access group.
+     * @param int    $customerId ID of a customer to check permission for.
+     *
+     * @return bool True if customer has a writing permission for the page, false otherwise.
+     */
+    public function checkAdminAccessWritingPermissionForPage($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'PAGE',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['writing_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Checks the writing permission for an ajax handler.
+     *
+     * @param string $identifier The name of an ajax handler to identify an admin access group.
+     * @param int    $customerId ID of a customer to check permission for.
+     *
+     * @return bool True if customer has a writing permission for the ajax handler, false otherwise.
+     */
+    public function checkAdminAccessWritingPermissionForAjaxHandler($identifier, $customerId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_group_items` `items` LEFT JOIN `admin_access_permissions` `permissions` ON `admin_access_group_id` = `permissions`.`admin_access_group_id` LEFT JOIN `admin_access_users` `users` ON `permissions`.`admin_access_role_id` = `users`.`admin_access_role_id` WHERE `items`.`identifier` = "%s" AND `items`.`type` = "%s" AND `users`.`customer_id` = %d;',
+                         $this->real_escape_string($identifier),
+                         'AJAX_HANDLER',
+                         (int)$customerId);
+        
+        $permission = $this->query($query, true);
+        if ($permission !== null && $permission->num_rows > 0) {
+            $permission = $permission->fetch_assoc();
+            
+            return (int)$permission['writing_granted'] === 1;
+        }
+        
+        return false;
+    }
+    
+    
+    /**
+     * Returns a collection of all permissions by a given role ID.
+     *
+     * @param int $roleId Role ID.
+     *
+     * @return mysqli_result
+     */
+    public function getAdminAccessPermissionsByRoleId($roleId)
+    {
+        $query = sprintf('SELECT `permissions`.* FROM `admin_access_permissions` `permissions` WHERE `permissions`.`admin_access_role_id` = %d;',
+                         (int)$roleId);
+        
+        return $this->query($query, true);
+    }
+    
+    
+    /**
+     * Returns all roles of certain user by a given user ID.
+     *
+     * @param int $id User ID.
+     *
+     * @return mysqli_result
+     */
+    public function getAdminAccessRolesByCustomerId($customerId)
+    {
+        $query = sprintf('SELECT `roles`.* FROM `admin_access_users` `users` LEFT JOIN `admin_access_roles` `roles` ON `users`.`admin_access_role_id` = `roles`.`admin_access_role_id` WHERE `users`.`customer_id` = %d;',
+                         (int)$customerId);
+        
+        return $this->query($query, true);
+    }
+    
+    
+    /**
+     * Grants deleting permission to a role for a given group id.
+     *
+     * @param int $groupId Group ID to grant permission for.
+     * @param int $roleId  Role ID to grant permission for.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function grantAdminAccessDeletingPermissionToRole($groupId, $roleId)
+    {
+        $query  = sprintf('UPDATE `admin_access_permissions` SET `deleting_granted` = "1" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
+                          (int)$roleId,
+                          (int)$groupId);
+        $result = $this->query($query, true);
+        $error  = $result !== null && $result !== false;
+        
+        $parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
+                                    (int)$groupId);
+        $parentGroupQuery = $this->query($parentGroupSql, true);
+        if ($parentGroupQuery !== null && $parentGroupQuery->num_rows > 0) {
+            $parentGroup = $parentGroupQuery->fetch_assoc();
+            if ((int)$parentGroup['admin_access_group_id'] > 0) {
+                $error &= $this->grantAdminAccessDeletingPermissionToRole((int)$parentGroup['admin_access_group_id'],
+                                                                          $roleId);
+            }
+        }
+        
+        return $error;
+    }
+    
+    
+    /**
+     * Removes deleting permission from role for a given group id.
+     *
+     * @param int $groupId Group ID to remove permission for.
+     * @param int $roleId  Role ID to remove permission from.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function removeAdminAccessDeletingPermissionFromRole($groupId, $roleId)
+    {
+        $query  = sprintf('UPDATE `admin_access_permissions` SET `deleting_granted` = "0" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
+                          (int)$roleId,
+                          (int)$groupId);
+        $result = $this->query($query, true);
+        
+        return $result !== null && $result !== false;
+    }
+    
+    
+    /**
+     * Grants reading permission to a role for a given group id.
+     *
+     * @param int $groupId Group ID to grant permission for.
+     * @param int $roleId  Role ID to grant permission for.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function grantAdminAccessReadingPermissionToRole($groupId, $roleId)
+    {
+        $query  = sprintf('UPDATE `admin_access_permissions` SET `reading_granted` = "1" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
+                          (int)$roleId,
+                          (int)$groupId);
+        $result = $this->query($query, true);
+        $error  = $result !== null && $result !== false;
+        
+        $parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
+                                    (int)$groupId);
+        $parentGroupQuery = $this->query($parentGroupSql, true);
+        if ($parentGroupQuery !== null && $parentGroupQuery->num_rows > 0) {
+            $parentGroup = $parentGroupQuery->fetch_assoc();
+            if ((int)$parentGroup['admin_access_group_id'] > 0) {
+                $error &= $this->grantAdminAccessReadingPermissionToRole((int)$parentGroup['admin_access_group_id'],
+                                                                         $roleId);
+            }
+        }
+        
+        return $error;
+    }
+    
+    
+    /**
+     * Removes reading permission from role for a given group id.
+     *
+     * @param int $groupId Group ID to remove permission for.
+     * @param int $roleId  Role ID to remove permission from.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function removeAdminAccessReadingPermissionFromRole($groupId, $roleId)
+    {
+        $query  = sprintf('UPDATE `admin_access_permissions` SET `reading_granted` = "0" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
+                          (int)$roleId,
+                          (int)$groupId);
+        $result = $this->query($query, true);
+        
+        return $result !== null && $result !== false;
+    }
+    
+    
+    /**
+     * Grants writing permission to a role for a given group id.
+     *
+     * @param int $groupId Group ID to grant permission for.
+     * @param int $roleId  Role ID to grant permission for.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function grantAdminAccessWritingPermissionToRole($groupId, $roleId)
+    {
+        $query  = sprintf('UPDATE `admin_access_permissions` SET `writing_granted` = "1" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
+                          (int)$roleId,
+                          (int)$groupId);
+        $result = $this->query($query, true);
+        $error  = $result !== null && $result !== false;
+        
+        $parentGroupSql   = sprintf('SELECT * FROM `admin_access_groups` WHERE `admin_access_group_id` = (SELECT `parent_id` FROM `admin_access_groups` WHERE `admin_access_group_id` = %d);',
+                                    (int)$groupId);
+        $parentGroupQuery = $this->query($parentGroupSql, true);
+        if ($parentGroupQuery !== null && $parentGroupQuery->num_rows > 0) {
+            $parentGroup = $parentGroupQuery->fetch_assoc();
+            if ((int)$parentGroup['admin_access_group_id'] > 0) {
+                $error &= $this->grantAdminAccessWritingPermissionToRole((int)$parentGroup['admin_access_group_id'],
+                                                                         $roleId);
+            }
+        }
+        
+        return $error;
+    }
+    
+    
+    /**
+     * Removes writing permission from role for a given group id.
+     *
+     * @param int $groupId Group ID to remove permission for.
+     * @param int $roleId  Role ID to remove permission from.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function removeAdminAccessWritingPermissionFromRole($groupId, $roleId)
+    {
+        $query  = sprintf('UPDATE `admin_access_permissions` SET `writing_granted` = "0" WHERE `admin_access_role_id` = %d AND `admin_access_group_id` = %d;',
+                          (int)$roleId,
+                          (int)$groupId);
+        $result = $this->query($query, true);
+        
+        return $result !== null && $result !== false;
+    }
+    
+    
+    /**
+     * Deletes role by a given role ID.
+     *
+     * @param int $roleId ID of the role that should be deleted.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function deleteAdminAccessRoleById($roleId)
+    {
+        $query  = sprintf('DELETE FROM `admin_access_roles` WHERE `admin_access_role_id` = %d;', (int)$roleId);
+        $result = $this->query($query, true);
+        $error  = $result !== null && $result !== false;
+        
+        $query  = sprintf('DELETE FROM `admin_access_role_descriptions` WHERE `admin_access_role_id` = %d;',
+                          (int)$roleId);
+        $result = $this->query($query, true);
+        $error  &= $result !== null && $result !== false;
+        
+        $query  = sprintf('DELETE FROM `admin_access_users` WHERE `admin_access_role_id` = %d;', (int)$roleId);
+        $result = $this->query($query, true);
+        $error  &= $result !== null && $result !== false;
+        
+        $query  = sprintf('DELETE FROM `admin_access_permissions` WHERE `admin_access_role_id` = %d;', (int)$roleId);
+        $result = $this->query($query, true);
+        $error  &= $result !== null && $result !== false;
+        
+        return $error;
+    }
+    
+    
+    /**
+     * Returns a collection of all roles.
+     *
+     * @return mysqli_result
+     */
+    public function getAllAdminAccessRoles()
+    {
+        return $this->query('SELECT `roles`.* FROM `admin_access_roles` `roles`;', true);
+    }
+    
+    
+    /**
+     * Deletes an admin access user by a given customer ID.
+     *
+     * @param int $customerId ID of the user that should be deleted.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function deleteAdminAccessUserByCustomerId($customerId)
+    {
+        $query  = sprintf('DELETE FROM `admin_access_users` WHERE `customer_id` = %d;', (int)$customerId);
+        $result = $this->query($query, true);
+        
+        return $result !== null && $result !== false;
+    }
+    
+    
+    /**
+     * Returns a role by a given role ID.
+     *
+     * @param int $roleId ID of the requested role.
+     *
+     * @return mysqli_result
+     */
+    public function getAdminAccessRoleById($roleId)
+    {
+        $query = sprintf('SELECT `roles`.* FROM `admin_access_roles` `roles` WHERE `roles`.`admin_access_role_id` = %d;',
+                         (int)$roleId);
+        
+        return $this->query($query, true);
+    }
+    
+    
+    /**
+     * Returns a collection of all groups.
+     *
+     * @return mysqli_result
+     */
+    public function getAllAdminAccessGroups()
+    {
+        return $this->query('SELECT `groups`.* FROM `admin_access_groups` `groups`;', true);
+    }
+    
+    
+    /**
+     * Returns a group by a given group id.
+     *
+     * @param int $id Group id.
+     *
+     * @return mysqli_result
+     */
+    public function getAdminAccessGroupById($groupId)
+    {
+        $query = sprintf('SELECT `groups`.* FROM `admin_access_groups` `groups` WHERE `groups`.`admin_access_group_id` = %d;',
+                         (int)$groupId);
+        
+        return $this->query($query, true);
+    }
+    
+    
+    /**
+     * Deletes a group by a given group ID.
+     *
+     * @param int $id ID of the group that should be deleted.
+     *
+     * @return bool Return true on success and false on failure.
+     */
+    public function deleteAdminAccessGroupById($groupId)
+    {
+        $query = sprintf('DELETE FROM `admin_access_groups` WHERE `admin_access_group_id` = %d;', (int)$groupId);
+        $error = $this->query($query) !== false;
+        
+        $query = sprintf('DELETE FROM `admin_access_group_items` WHERE `admin_access_group_id` = %d;', (int)$groupId);
+        $error &= $this->query($query) !== false;
+        
+        $query = sprintf('DELETE FROM `admin_access_group_descriptions` WHERE `admin_access_group_id` = %d;',
+                         (int)$groupId);
+        $error &= $this->query($query) !== false;
+        
+        $query = sprintf('DELETE FROM `admin_access_permissions` WHERE `admin_access_group_id` = %d;', (int)$groupId);
+        $error &= $this->query($query) !== false;
+        
+        return $error;
+    }
 	
 	
 	/**
