You've already forked joomla_test
							
							
		
			
	
	
		
			571 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			571 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
|   | <?php | ||
|  | /** | ||
|  |  * @package     Joomla.Platform | ||
|  |  * @subpackage  Access | ||
|  |  * | ||
|  |  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved. | ||
|  |  * @license     GNU General Public License version 2 or later; see LICENSE | ||
|  |  */ | ||
|  | 
 | ||
|  | defined('JPATH_PLATFORM') or die; | ||
|  | 
 | ||
|  | jimport('joomla.utilities.arrayhelper'); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Class that handles all access authorisation routines. | ||
|  |  * | ||
|  |  * @package     Joomla.Platform | ||
|  |  * @subpackage  Access | ||
|  |  * @since       11.1 | ||
|  |  */ | ||
|  | class JAccess | ||
|  | { | ||
|  | 	/** | ||
|  | 	 * Array of view levels | ||
|  | 	 * | ||
|  | 	 * @var    array | ||
|  | 	 * @since  11.1 | ||
|  | 	 */ | ||
|  | 	protected static $viewLevels = array(); | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Array of rules for the asset | ||
|  | 	 * | ||
|  | 	 * @var    array | ||
|  | 	 * @since  11.1 | ||
|  | 	 */ | ||
|  | 	protected static $assetRules = array(); | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Array of user groups. | ||
|  | 	 * | ||
|  | 	 * @var    array | ||
|  | 	 * @since  11.1 | ||
|  | 	 */ | ||
|  | 	protected static $userGroups = array(); | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Array of user group paths. | ||
|  | 	 * | ||
|  | 	 * @var    array | ||
|  | 	 * @since  11.1 | ||
|  | 	 */ | ||
|  | 	protected static $userGroupPaths = array(); | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Array of cached groups by user. | ||
|  | 	 * | ||
|  | 	 * @var    array | ||
|  | 	 * @since  11.1 | ||
|  | 	 */ | ||
|  | 	protected static $groupsByUser = array(); | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method for clearing static caches. | ||
|  | 	 * | ||
|  | 	 * @return  void | ||
|  | 	 * | ||
|  | 	 * @since   11.3 | ||
|  | 	 */ | ||
|  | 	public static function clearStatics() | ||
|  | 	{ | ||
|  | 		self::$viewLevels = array(); | ||
|  | 		self::$assetRules = array(); | ||
|  | 		self::$userGroups = array(); | ||
|  | 		self::$userGroupPaths = array(); | ||
|  | 		self::$groupsByUser = array(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to check if a user is authorised to perform an action, optionally on an asset. | ||
|  | 	 * | ||
|  | 	 * @param   integer  $userId  Id of the user for which to check authorisation. | ||
|  | 	 * @param   string   $action  The name of the action to authorise. | ||
|  | 	 * @param   mixed    $asset   Integer asset id or the name of the asset as a string.  Defaults to the global asset node. | ||
|  | 	 * | ||
|  | 	 * @return  boolean  True if authorised. | ||
|  | 	 * | ||
|  | 	 * @since   11.1 | ||
|  | 	 */ | ||
|  | 	public static function check($userId, $action, $asset = null) | ||
|  | 	{ | ||
|  | 		// Sanitise inputs.
 | ||
|  | 		$userId = (int) $userId; | ||
|  | 
 | ||
|  | 		$action = strtolower(preg_replace('#[\s\-]+#', '.', trim($action))); | ||
|  | 		$asset = strtolower(preg_replace('#[\s\-]+#', '.', trim($asset))); | ||
|  | 
 | ||
|  | 		// Default to the root asset node.
 | ||
|  | 		if (empty($asset)) | ||
|  | 		{ | ||
|  | 			$db = JFactory::getDbo(); | ||
|  | 			$assets = JTable::getInstance('Asset', 'JTable', array('dbo' => $db)); | ||
|  | 			$rootId = $assets->getRootId(); | ||
|  | 			$asset = $rootId; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Get the rules for the asset recursively to root if not already retrieved.
 | ||
|  | 		if (empty(self::$assetRules[$asset])) | ||
|  | 		{ | ||
|  | 			self::$assetRules[$asset] = self::getAssetRules($asset, true); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Get all groups against which the user is mapped.
 | ||
|  | 		$identities = self::getGroupsByUser($userId); | ||
|  | 		array_unshift($identities, $userId * -1); | ||
|  | 
 | ||
|  | 		return self::$assetRules[$asset]->allow($action, $identities); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to check if a group is authorised to perform an action, optionally on an asset. | ||
|  | 	 * | ||
|  | 	 * @param   integer  $groupId  The path to the group for which to check authorisation. | ||
|  | 	 * @param   string   $action   The name of the action to authorise. | ||
|  | 	 * @param   mixed    $asset    Integer asset id or the name of the asset as a string.  Defaults to the global asset node. | ||
|  | 	 * | ||
|  | 	 * @return  boolean  True if authorised. | ||
|  | 	 * | ||
|  | 	 * @since   11.1 | ||
|  | 	 */ | ||
|  | 	public static function checkGroup($groupId, $action, $asset = null) | ||
|  | 	{ | ||
|  | 		// Sanitize inputs.
 | ||
|  | 		$groupId = (int) $groupId; | ||
|  | 		$action = strtolower(preg_replace('#[\s\-]+#', '.', trim($action))); | ||
|  | 		$asset = strtolower(preg_replace('#[\s\-]+#', '.', trim($asset))); | ||
|  | 
 | ||
|  | 		// Get group path for group
 | ||
|  | 		$groupPath = self::getGroupPath($groupId); | ||
|  | 
 | ||
|  | 		// Default to the root asset node.
 | ||
|  | 		if (empty($asset)) | ||
|  | 		{ | ||
|  | 			// TODO: $rootId doesn't seem to be used!
 | ||
|  | 			$db = JFactory::getDbo(); | ||
|  | 			$assets = JTable::getInstance('Asset', 'JTable', array('dbo' => $db)); | ||
|  | 			$rootId = $assets->getRootId(); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Get the rules for the asset recursively to root if not already retrieved.
 | ||
|  | 		if (empty(self::$assetRules[$asset])) | ||
|  | 		{ | ||
|  | 			self::$assetRules[$asset] = self::getAssetRules($asset, true); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return self::$assetRules[$asset]->allow($action, $groupPath); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Gets the parent groups that a leaf group belongs to in its branch back to the root of the tree | ||
|  | 	 * (including the leaf group id). | ||
|  | 	 * | ||
|  | 	 * @param   mixed  $groupId  An integer or array of integers representing the identities to check. | ||
|  | 	 * | ||
|  | 	 * @return  mixed  True if allowed, false for an explicit deny, null for an implicit deny. | ||
|  | 	 * | ||
|  | 	 * @since   11.1 | ||
|  | 	 */ | ||
|  | 	protected static function getGroupPath($groupId) | ||
|  | 	{ | ||
|  | 		// Preload all groups
 | ||
|  | 		if (empty(self::$userGroups)) | ||
|  | 		{ | ||
|  | 			$db = JFactory::getDbo(); | ||
|  | 			$query = $db->getQuery(true) | ||
|  | 				->select('parent.id, parent.lft, parent.rgt') | ||
|  | 				->from('#__usergroups AS parent') | ||
|  | 				->order('parent.lft'); | ||
|  | 			$db->setQuery($query); | ||
|  | 			self::$userGroups = $db->loadObjectList('id'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Make sure groupId is valid
 | ||
|  | 		if (!array_key_exists($groupId, self::$userGroups)) | ||
|  | 		{ | ||
|  | 			return array(); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Get parent groups and leaf group
 | ||
|  | 		if (!isset(self::$userGroupPaths[$groupId])) | ||
|  | 		{ | ||
|  | 			self::$userGroupPaths[$groupId] = array(); | ||
|  | 
 | ||
|  | 			foreach (self::$userGroups as $group) | ||
|  | 			{ | ||
|  | 				if ($group->lft <= self::$userGroups[$groupId]->lft && $group->rgt >= self::$userGroups[$groupId]->rgt) | ||
|  | 				{ | ||
|  | 					self::$userGroupPaths[$groupId][] = $group->id; | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return self::$userGroupPaths[$groupId]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to return the JAccessRules object for an asset.  The returned object can optionally hold | ||
|  | 	 * only the rules explicitly set for the asset or the summation of all inherited rules from | ||
|  | 	 * parent assets and explicit rules. | ||
|  | 	 * | ||
|  | 	 * @param   mixed    $asset      Integer asset id or the name of the asset as a string. | ||
|  | 	 * @param   boolean  $recursive  True to return the rules object with inherited rules. | ||
|  | 	 * | ||
|  | 	 * @return  JAccessRules   JAccessRules object for the asset. | ||
|  | 	 * | ||
|  | 	 * @since   11.1 | ||
|  | 	 */ | ||
|  | 	public static function getAssetRules($asset, $recursive = false) | ||
|  | 	{ | ||
|  | 		// Get the database connection object.
 | ||
|  | 		$db = JFactory::getDbo(); | ||
|  | 
 | ||
|  | 		// Build the database query to get the rules for the asset.
 | ||
|  | 		$query = $db->getQuery(true) | ||
|  | 			->select($recursive ? 'b.rules' : 'a.rules') | ||
|  | 			->from('#__assets AS a'); | ||
|  | 
 | ||
|  | 		// SQLsrv change
 | ||
|  | 		$query->group($recursive ? 'b.id, b.rules, b.lft' : 'a.id, a.rules, a.lft'); | ||
|  | 
 | ||
|  | 		// If the asset identifier is numeric assume it is a primary key, else lookup by name.
 | ||
|  | 		if (is_numeric($asset)) | ||
|  | 		{ | ||
|  | 			$query->where('(a.id = ' . (int) $asset . ')'); | ||
|  | 		} | ||
|  | 		else | ||
|  | 		{ | ||
|  | 			$query->where('(a.name = ' . $db->quote($asset) . ')'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// If we want the rules cascading up to the global asset node we need a self-join.
 | ||
|  | 		if ($recursive) | ||
|  | 		{ | ||
|  | 			$query->join('LEFT', '#__assets AS b ON b.lft <= a.lft AND b.rgt >= a.rgt') | ||
|  | 				->order('b.lft'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Execute the query and load the rules from the result.
 | ||
|  | 		$db->setQuery($query); | ||
|  | 		$result = $db->loadColumn(); | ||
|  | 
 | ||
|  | 		// Get the root even if the asset is not found and in recursive mode
 | ||
|  | 		if (empty($result)) | ||
|  | 		{ | ||
|  | 			$db = JFactory::getDbo(); | ||
|  | 			$assets = JTable::getInstance('Asset', 'JTable', array('dbo' => $db)); | ||
|  | 			$rootId = $assets->getRootId(); | ||
|  | 			$query->clear() | ||
|  | 				->select('rules') | ||
|  | 				->from('#__assets') | ||
|  | 				->where('id = ' . $db->quote($rootId)); | ||
|  | 			$db->setQuery($query); | ||
|  | 			$result = $db->loadResult(); | ||
|  | 			$result = array($result); | ||
|  | 		} | ||
|  | 		// Instantiate and return the JAccessRules object for the asset rules.
 | ||
|  | 		$rules = new JAccessRules; | ||
|  | 		$rules->mergeCollection($result); | ||
|  | 
 | ||
|  | 		return $rules; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to return a list of user groups mapped to a user. The returned list can optionally hold | ||
|  | 	 * only the groups explicitly mapped to the user or all groups both explicitly mapped and inherited | ||
|  | 	 * by the user. | ||
|  | 	 * | ||
|  | 	 * @param   integer  $userId     Id of the user for which to get the list of groups. | ||
|  | 	 * @param   boolean  $recursive  True to include inherited user groups. | ||
|  | 	 * | ||
|  | 	 * @return  array    List of user group ids to which the user is mapped. | ||
|  | 	 * | ||
|  | 	 * @since   11.1 | ||
|  | 	 */ | ||
|  | 	public static function getGroupsByUser($userId, $recursive = true) | ||
|  | 	{ | ||
|  | 		// Creates a simple unique string for each parameter combination:
 | ||
|  | 		$storeId = $userId . ':' . (int) $recursive; | ||
|  | 
 | ||
|  | 		if (!isset(self::$groupsByUser[$storeId])) | ||
|  | 		{ | ||
|  | 			// TODO: Uncouple this from JComponentHelper and allow for a configuration setting or value injection.
 | ||
|  | 			if (class_exists('JComponentHelper')) | ||
|  | 			{ | ||
|  | 				$guestUsergroup = JComponentHelper::getParams('com_users')->get('guest_usergroup', 1); | ||
|  | 			} | ||
|  | 			else | ||
|  | 			{ | ||
|  | 				$guestUsergroup = 1; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			// Guest user (if only the actually assigned group is requested)
 | ||
|  | 			if (empty($userId) && !$recursive) | ||
|  | 			{ | ||
|  | 				$result = array($guestUsergroup); | ||
|  | 			} | ||
|  | 			// Registered user and guest if all groups are requested
 | ||
|  | 			else | ||
|  | 			{ | ||
|  | 				$db = JFactory::getDbo(); | ||
|  | 
 | ||
|  | 				// Build the database query to get the rules for the asset.
 | ||
|  | 				$query = $db->getQuery(true) | ||
|  | 					->select($recursive ? 'b.id' : 'a.id'); | ||
|  | 
 | ||
|  | 				if (empty($userId)) | ||
|  | 				{ | ||
|  | 					$query->from('#__usergroups AS a') | ||
|  | 						->where('a.id = ' . (int) $guestUsergroup); | ||
|  | 				} | ||
|  | 				else | ||
|  | 				{ | ||
|  | 					$query->from('#__user_usergroup_map AS map') | ||
|  | 						->where('map.user_id = ' . (int) $userId) | ||
|  | 						->join('LEFT', '#__usergroups AS a ON a.id = map.group_id'); | ||
|  | 				} | ||
|  | 
 | ||
|  | 				// If we want the rules cascading up to the global asset node we need a self-join.
 | ||
|  | 				if ($recursive) | ||
|  | 				{ | ||
|  | 					$query->join('LEFT', '#__usergroups AS b ON b.lft <= a.lft AND b.rgt >= a.rgt'); | ||
|  | 				} | ||
|  | 
 | ||
|  | 				// Execute the query and load the rules from the result.
 | ||
|  | 				$db->setQuery($query); | ||
|  | 				$result = $db->loadColumn(); | ||
|  | 
 | ||
|  | 				// Clean up any NULL or duplicate values, just in case
 | ||
|  | 				JArrayHelper::toInteger($result); | ||
|  | 
 | ||
|  | 				if (empty($result)) | ||
|  | 				{ | ||
|  | 					$result = array('1'); | ||
|  | 				} | ||
|  | 				else | ||
|  | 				{ | ||
|  | 					$result = array_unique($result); | ||
|  | 				} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			self::$groupsByUser[$storeId] = $result; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return self::$groupsByUser[$storeId]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to return a list of user Ids contained in a Group | ||
|  | 	 * | ||
|  | 	 * @param   integer  $groupId    The group Id | ||
|  | 	 * @param   boolean  $recursive  Recursively include all child groups (optional) | ||
|  | 	 * | ||
|  | 	 * @return  array | ||
|  | 	 * | ||
|  | 	 * @since   11.1 | ||
|  | 	 * @todo    This method should move somewhere else | ||
|  | 	 */ | ||
|  | 	public static function getUsersByGroup($groupId, $recursive = false) | ||
|  | 	{ | ||
|  | 		// Get a database object.
 | ||
|  | 		$db = JFactory::getDbo(); | ||
|  | 
 | ||
|  | 		$test = $recursive ? '>=' : '='; | ||
|  | 
 | ||
|  | 		// First find the users contained in the group
 | ||
|  | 		$query = $db->getQuery(true) | ||
|  | 			->select('DISTINCT(user_id)') | ||
|  | 			->from('#__usergroups as ug1') | ||
|  | 			->join('INNER', '#__usergroups AS ug2 ON ug2.lft' . $test . 'ug1.lft AND ug1.rgt' . $test . 'ug2.rgt') | ||
|  | 			->join('INNER', '#__user_usergroup_map AS m ON ug2.id=m.group_id') | ||
|  | 			->where('ug1.id=' . $db->quote($groupId)); | ||
|  | 
 | ||
|  | 		$db->setQuery($query); | ||
|  | 
 | ||
|  | 		$result = $db->loadColumn(); | ||
|  | 
 | ||
|  | 		// Clean up any NULL values, just in case
 | ||
|  | 		JArrayHelper::toInteger($result); | ||
|  | 
 | ||
|  | 		return $result; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to return a list of view levels for which the user is authorised. | ||
|  | 	 * | ||
|  | 	 * @param   integer  $userId  Id of the user for which to get the list of authorised view levels. | ||
|  | 	 * | ||
|  | 	 * @return  array    List of view levels for which the user is authorised. | ||
|  | 	 * | ||
|  | 	 * @since   11.1 | ||
|  | 	 */ | ||
|  | 	public static function getAuthorisedViewLevels($userId) | ||
|  | 	{ | ||
|  | 		// Get all groups that the user is mapped to recursively.
 | ||
|  | 		$groups = self::getGroupsByUser($userId); | ||
|  | 
 | ||
|  | 		// Only load the view levels once.
 | ||
|  | 		if (empty(self::$viewLevels)) | ||
|  | 		{ | ||
|  | 			// Get a database object.
 | ||
|  | 			$db = JFactory::getDbo(); | ||
|  | 
 | ||
|  | 			// Build the base query.
 | ||
|  | 			$query = $db->getQuery(true) | ||
|  | 				->select('id, rules') | ||
|  | 				->from($db->quoteName('#__viewlevels')); | ||
|  | 
 | ||
|  | 			// Set the query for execution.
 | ||
|  | 			$db->setQuery($query); | ||
|  | 
 | ||
|  | 			// Build the view levels array.
 | ||
|  | 			foreach ($db->loadAssocList() as $level) | ||
|  | 			{ | ||
|  | 				self::$viewLevels[$level['id']] = (array) json_decode($level['rules']); | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Initialise the authorised array.
 | ||
|  | 		$authorised = array(1); | ||
|  | 
 | ||
|  | 		// Find the authorised levels.
 | ||
|  | 		foreach (self::$viewLevels as $level => $rule) | ||
|  | 		{ | ||
|  | 			foreach ($rule as $id) | ||
|  | 			{ | ||
|  | 				if (($id < 0) && (($id * -1) == $userId)) | ||
|  | 				{ | ||
|  | 					$authorised[] = $level; | ||
|  | 					break; | ||
|  | 				} | ||
|  | 				// Check to see if the group is mapped to the level.
 | ||
|  | 				elseif (($id >= 0) && in_array($id, $groups)) | ||
|  | 				{ | ||
|  | 					$authorised[] = $level; | ||
|  | 					break; | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return $authorised; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to return a list of actions for which permissions can be set given a component and section. | ||
|  | 	 * | ||
|  | 	 * @param   string  $component  The component from which to retrieve the actions. | ||
|  | 	 * @param   string  $section    The name of the section within the component from which to retrieve the actions. | ||
|  | 	 * | ||
|  | 	 * @return  array  List of actions available for the given component and section. | ||
|  | 	 * | ||
|  | 	 * @since       11.1 | ||
|  | 	 * @deprecated  12.3 (Platform) & 4.0 (CMS)  Use JAccess::getActionsFromFile or JAccess::getActionsFromData instead. | ||
|  | 	 * @codeCoverageIgnore | ||
|  | 	 */ | ||
|  | 	public static function getActions($component, $section = 'component') | ||
|  | 	{ | ||
|  | 		JLog::add(__METHOD__ . ' is deprecated. Use JAccess::getActionsFromFile or JAccess::getActionsFromData instead.', JLog::WARNING, 'deprecated'); | ||
|  | 
 | ||
|  | 		$actions = self::getActionsFromFile( | ||
|  | 			JPATH_ADMINISTRATOR . '/components/' . $component . '/access.xml', | ||
|  | 			"/access/section[@name='" . $section . "']/" | ||
|  | 		); | ||
|  | 
 | ||
|  | 		if (empty($actions)) | ||
|  | 		{ | ||
|  | 			return array(); | ||
|  | 		} | ||
|  | 		else | ||
|  | 		{ | ||
|  | 			return $actions; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to return a list of actions from a file for which permissions can be set. | ||
|  | 	 * | ||
|  | 	 * @param   string  $file   The path to the XML file. | ||
|  | 	 * @param   string  $xpath  An optional xpath to search for the fields. | ||
|  | 	 * | ||
|  | 	 * @return  boolean|array   False if case of error or the list of actions available. | ||
|  | 	 * | ||
|  | 	 * @since   12.1 | ||
|  | 	 */ | ||
|  | 	public static function getActionsFromFile($file, $xpath = "/access/section[@name='component']/") | ||
|  | 	{ | ||
|  | 		if (!is_file($file) || !is_readable($file)) | ||
|  | 		{ | ||
|  | 			// If unable to find the file return false.
 | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 		else | ||
|  | 		{ | ||
|  | 			// Else return the actions from the xml.
 | ||
|  | 			$xml = simplexml_load_file($file); | ||
|  | 
 | ||
|  | 			return self::getActionsFromData($xml, $xpath); | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * Method to return a list of actions from a string or from an xml for which permissions can be set. | ||
|  | 	 * | ||
|  | 	 * @param   string|SimpleXMLElement  $data   The XML string or an XML element. | ||
|  | 	 * @param   string                   $xpath  An optional xpath to search for the fields. | ||
|  | 	 * | ||
|  | 	 * @return  boolean|array   False if case of error or the list of actions available. | ||
|  | 	 * | ||
|  | 	 * @since   12.1 | ||
|  | 	 */ | ||
|  | 	public static function getActionsFromData($data, $xpath = "/access/section[@name='component']/") | ||
|  | 	{ | ||
|  | 		// If the data to load isn't already an XML element or string return false.
 | ||
|  | 		if ((!($data instanceof SimpleXMLElement)) && (!is_string($data))) | ||
|  | 		{ | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Attempt to load the XML if a string.
 | ||
|  | 		if (is_string($data)) | ||
|  | 		{ | ||
|  | 			try | ||
|  | 			{ | ||
|  | 				$data = new SimpleXMLElement($data); | ||
|  | 			} | ||
|  | 			catch (Exception $e) | ||
|  | 			{ | ||
|  | 				return false; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			// Make sure the XML loaded correctly.
 | ||
|  | 			if (!$data) | ||
|  | 			{ | ||
|  | 				return false; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Initialise the actions array
 | ||
|  | 		$actions = array(); | ||
|  | 
 | ||
|  | 		// Get the elements from the xpath
 | ||
|  | 		$elements = $data->xpath($xpath . 'action[@name][@title][@description]'); | ||
|  | 
 | ||
|  | 		// If there some elements, analyse them
 | ||
|  | 		if (!empty($elements)) | ||
|  | 		{ | ||
|  | 			foreach ($elements as $action) | ||
|  | 			{ | ||
|  | 				// Add the action to the actions array
 | ||
|  | 				$actions[] = (object) array( | ||
|  | 					'name' => (string) $action['name'], | ||
|  | 					'title' => (string) $action['title'], | ||
|  | 					'description' => (string) $action['description'] | ||
|  | 				); | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// Finally return the actions array
 | ||
|  | 		return $actions; | ||
|  | 	} | ||
|  | } |