Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #898 from chdemko/access

Implement JAccess::getActionsFromFile and JAccess::getActionsFromData method
  • Loading branch information...
commit 6a85bab4f932513830ba78854dd70b5d17930771 2 parents 70475d8 + 2456b71
@eddieajau eddieajau authored
View
105 libraries/joomla/access/access.php
@@ -226,12 +226,12 @@ public static function getAssetRules($asset, $recursive = false)
if (is_numeric($asset))
{
// Get the root even if the asset is not found
- $query->where('(a.id = ' . (int) $asset . ($recursive ? ' OR a.parent_id=0' : '') . ')');
+ $query->where('(a.id = ' . (int) $asset . ')');
}
else
{
// Get the root even if the asset is not found
- $query->where('(a.name = ' . $db->quote($asset) . ($recursive ? ' OR a.parent_id=0' : '') . ')');
+ $query->where('(a.name = ' . $db->quote($asset) . ')');
}
// If we want the rules cascading up to the global asset node we need a self-join.
@@ -434,34 +434,105 @@ public static function getAuthorisedViewLevels($userId)
*
* @since 11.1
*
+ * @deprecated 12.3 Use JAccess::getActionsFromFile or JAccess::getActionsFromData instead.
+ *
+ * @codeCoverageIgnore
+ *
* @todo Need to decouple this method from the CMS. Maybe check if $component is a
* valid file (or create a getActionsFromFile method).
*/
public static function getActions($component, $section = 'component')
{
- $actions = array();
+ JLog::add(__METHOD__ . ' is deprecated. Use JAccess::getActionsFromFile or JAcces::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))
+ {
+ // If unable to find the file return false.
+ return false;
+ }
+ else
+ {
+ // Else return the actions from the xml.
+ return self::getActionsFromData(JFactory::getXML($file, true), $xpath);
+ }
+ }
+
+ /**
+ * Method to return a list of actions from a string or from an xml for which permissions can be set.
+ *
+ * @param string|JXMLElement $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 JXMLElement)) && (!is_string($data)))
+ {
+ return false;
+ }
- if (defined('JPATH_ADMINISTRATOR') && is_file(JPATH_ADMINISTRATOR . '/components/' . $component . '/access.xml'))
+ // Attempt to load the XML if a string.
+ if (is_string($data))
{
- $xml = simplexml_load_file(JPATH_ADMINISTRATOR . '/components/' . $component . '/access.xml');
+ $data = JFactory::getXML($data, false);
- foreach ($xml->children() as $child)
+ // Make sure the XML loaded correctly.
+ if (!$data)
{
- if ($section == (string) $child['name'])
- {
- foreach ($child->children() as $action)
- {
- $actions[] = (object) array(
- 'name' => (string) $action['name'],
- 'title' => (string) $action['title'],
- 'description' => (string) $action['description']);
- }
+ return false;
+ }
+ }
- break;
- }
+ // 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;
}
}
View
261 tests/suite/joomla/access/JAccessTest.php
@@ -8,6 +8,7 @@
*/
require_once JPATH_PLATFORM.'/joomla/access/access.php';
+require_once JPATH_PLATFORM.'/joomla/filesystem/path.php';
/**
* Test class for JAccess.
@@ -35,6 +36,61 @@ protected function setUp()
JAccess::clearStatics();
$this->object = new JAccess;
+
+ // Make sure previous test files are cleaned up
+ $this->_cleanupTestFiles();
+
+ // Make some test files and folders
+ mkdir(JPath::clean(JPATH_TESTS . '/tmp/access'), 0777, true);
+ }
+
+ /**
+ * Remove created files
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ protected function tearDown()
+ {
+ $this->_cleanupTestFiles();
+ }
+
+ /**
+ * Convenience method to cleanup before and after test
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ private function _cleanupTestFiles()
+ {
+ $this->_cleanupFile(JPath::clean(JPATH_TESTS . '/tmp/access/access.xml'));
+ $this->_cleanupFile(JPath::clean(JPATH_TESTS . '/tmp/access'));
+ }
+
+ /**
+ * Convenience method to clean up for files test
+ *
+ * @param string $path The path to clean
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ private function _cleanupFile($path)
+ {
+ if (file_exists($path))
+ {
+ if (is_file($path))
+ {
+ unlink($path);
+ }
+ elseif (is_dir($path))
+ {
+ rmdir($path);
+ }
+ }
}
/**
@@ -326,6 +382,14 @@ public function testGetAssetRules()
$this->equalTo($string1),
'Line: ' . __LINE__
);
+
+ $ObjArrayJrules = $access->getAssetRules('testasset', true);
+ $string1 = '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1,"10":1},"core.create":{"6":1},"core.delete":{"6":1},"core.edit":{"6":1},"core.edit.state":{"6":1}}';
+ $this->assertThat(
+ (string)$ObjArrayJrules,
+ $this->equalTo($string1),
+ 'Line: ' . __LINE__
+ );
}
/**
@@ -404,94 +468,141 @@ public function testGetGroupsByUser()
}
/**
- * Tests the JAccess::getActions method.
+ * Data provider for the JAccess::getActionsFromData method.
*
- * Note, JAccess::getActions need to be changed or proxied to actually make this testable.
- * It is currently tightly coupled to JPATH_ADMINISTRATOR.
- *
- * @return void
+ * @return array
*
- * @since 11.1
+ * @since 12.1
*/
- public function testGetActions()
+ public function casesGetActionsFromData()
{
- $this->markTestSkipped(
- 'This test is skipped because the JAccess::getActions method is tightly coupled to components in the CMS.'
- );
-
- $access = new JAccess();
- $array1 = array(
- 'name' => "core.admin",
- 'title' => "JACTION_ADMIN",
- 'description' => "JACTION_ADMIN_COMPONENT_DESC"
- );
- $array2 = array(
- 'name' => "core.manage",
- 'title' => "JACTION_MANAGE",
- 'description' => "JACTION_MANAGE_COMPONENT_DESC"
- );
- $array3 = array(
- 'name' => "core.create",
- 'title' => "JACTION_CREATE",
- 'description' => "JACTION_CREATE_COMPONENT_DESC"
- );
- $array4 = array(
- 'name' => "core.delete",
- 'title' => "JACTION_DELETE",
- 'description' => "JACTION_DELETE_COMPONENT_DESC"
- );
- $array5 = array(
- 'name' => "core.edit",
- 'title' => "JACTION_EDIT",
- 'description' => "JACTION_EDIT_COMPONENT_DESC"
- );
- $array6 = array(
- 'name' => "core.edit.state",
- 'title' => "JACTION_EDITSTATE",
- 'description' => "JACTION_EDITSTATE_COMPONENT_DESC"
- );
-
-
- $obj = $access->getActions('com_banners', 'component');
- $arraystdClass = (array)$obj[0];
- $this->assertThat(
- $array1,
- $this->equalTo($arraystdClass)
- );
-
- $arraystdClass = (array)$obj[1];
- $this->assertThat(
- $array2,
- $this->equalTo($arraystdClass)
- );
-
- $arraystdClass = (array)$obj[2];
- $this->assertThat(
- $array3,
- $this->equalTo($arraystdClass)
- );
-
- $arraystdClass = (array)$obj[3];
- $this->assertThat(
- $array4,
- $this->equalTo($arraystdClass)
+ return array(
+ array(
+ '<access component="com_banners">
+ <section name="component">
+ <action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
+ <action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
+ <action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
+ <action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
+ <action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
+ <action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
+ </section>
+ <section name="category">
+ <action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
+ <action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
+ <action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
+ <action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
+ </section>
+</access>',
+ "/access/section[@name='component']/",
+ array(
+ (object)array('name' => "core.admin", 'title' => "JACTION_ADMIN", 'description' => "JACTION_ADMIN_COMPONENT_DESC"),
+ (object)array('name' => "core.manage", 'title' => "JACTION_MANAGE", 'description' => "JACTION_MANAGE_COMPONENT_DESC"),
+ (object)array('name' => "core.create", 'title' => "JACTION_CREATE", 'description' => "JACTION_CREATE_COMPONENT_DESC"),
+ (object)array('name' => "core.delete", 'title' => "JACTION_DELETE", 'description' => "JACTION_DELETE_COMPONENT_DESC"),
+ (object)array('name' => "core.edit", 'title' => "JACTION_EDIT", 'description' => "JACTION_EDIT_COMPONENT_DESC"),
+ (object)array('name' => "core.edit.state", 'title' => "JACTION_EDITSTATE", 'description' => "JACTION_EDITSTATE_COMPONENT_DESC")
+ ),
+ 'Unable to get actions from the component section.'
+ ),
+ array(
+ '<access component="com_banners">
+ <section name="component">
+ <action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
+ <action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
+ <action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
+ <action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
+ <action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
+ <action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
+ </section>
+ <section name="category">
+ <action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
+ <action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
+ <action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
+ <action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
+ </section>
+</access>',
+ "/access/section[@name='unexisting']/",
+ array(),
+ 'Unable to get actions from an unexiting section.'
+ ),
+ array(
+ '<access component="com_banners',
+ "/access/section[@name='component']/",
+ false,
+ 'Getting actions from a non XML string must return false.'
+ ),
+ array(
+ array(),
+ "/access/section[@name='component']/",
+ false,
+ 'Getting actions from neither a string, neither an JXMLElement must return false.'
+ ),
);
+ }
- $arraystdClass = (array)$obj[4];
+ /**
+ * Tests the JAccess::getActionsFromData method.
+ *
+ * @return void
+ *
+ * @since 12.1
+ *
+ * @dataProvider casesGetActionsFromData
+ */
+ public function testGetActionsFromData($data, $xpath, $expected, $msg)
+ {
$this->assertThat(
- $array5,
- $this->equalTo($arraystdClass)
+ JAccess::getActionsFromData($data, $xpath),
+ $this->equalTo($expected),
+ 'Line:' . __LINE__ . $msg
);
+ }
- $arraystdClass = (array)$obj[5];
+ /**
+ * Tests the JAccess::getActionsFromFile method.
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ public function testGetActionsFromFile()
+ {
$this->assertThat(
- $array6,
- $this->equalTo($arraystdClass)
+ JAccess::getActionsFromFile('/path/to/unexisting/file'),
+ $this->equalTo(false),
+ 'Line:' . __LINE__ . ' Getting actions from an unexisting file must return false'
);
+ file_put_contents(JPATH_TESTS . '/tmp/access/access.xml', '<access component="com_banners">
+ <section name="component">
+ <action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
+ <action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
+ <action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
+ <action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
+ <action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
+ <action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
+ </section>
+ <section name="category">
+ <action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
+ <action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
+ <action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
+ <action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
+ </section>
+</access>');
$this->assertThat(
- $array7 = array(),
- $this->equalTo($access->getActions('com_complusoft', 'component'))
+ JAccess::getActionsFromFile(JPATH_TESTS . '/tmp/access/access.xml'),
+ $this->equalTo(
+ array(
+ (object)array('name' => "core.admin", 'title' => "JACTION_ADMIN", 'description' => "JACTION_ADMIN_COMPONENT_DESC"),
+ (object)array('name' => "core.manage", 'title' => "JACTION_MANAGE", 'description' => "JACTION_MANAGE_COMPONENT_DESC"),
+ (object)array('name' => "core.create", 'title' => "JACTION_CREATE", 'description' => "JACTION_CREATE_COMPONENT_DESC"),
+ (object)array('name' => "core.delete", 'title' => "JACTION_DELETE", 'description' => "JACTION_DELETE_COMPONENT_DESC"),
+ (object)array('name' => "core.edit", 'title' => "JACTION_EDIT", 'description' => "JACTION_EDIT_COMPONENT_DESC"),
+ (object)array('name' => "core.edit.state", 'title' => "JACTION_EDITSTATE", 'description' => "JACTION_EDITSTATE_COMPONENT_DESC")
+ )
+ ),
+ 'Line:' . __LINE__ . ' Getting actions from an xml file must return correct array.'
);
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.