I developed a large site which depends on JACLplus Pro to segment out different areas of content for access by logged in members with different group associations.
First off, I would like to say that, besides the annoying IONCUBE or Zend Optimizer encoding, JACLplus is the BEST 3PD ACL solution for Joomla. While it requires hacks to core files, the *way* in which it integrates is as close as possible to the native manipulation of access control groups and how they are processed by other extensions.
Here's the trick (I'm pulling this from memory):
Whereas Joomla looks up the 'aid' or ('gid' ?) when checking group access, JACLplus using a JACL specific id. What is important about this ID, though, is the *sub group* assignment.
When you create a new access control group, which is similar to "Registered", it gains it's own ID in Joomla core AND a it's own ID in JACLplus tables. The reason the JACLplus tables are important is because of the way sub-group access rules can be added to existing groups.
So, if you create a new access group called "Premium Group", you can assign it access to any number of subgroups (for example, "This Group", "That Group", "The Group"). This is a uniquely powerful feature because it allows you to assign detailed levels of access control to a user with the assignment of just ONE Joomla Access Level which (with JACLplus) can also provide access to any number of associated sub-groups.
How to do you fix NoNumber extensions to become compatible with JACLplus?
You need to check for
if( defined('_JACL') )
Below is some sample code to give an idea of how to access the jaclplus gids:
*************************
The following code describes a modified onLoginUser function as found in Joomla.php under /plugins/user/
/**
* This method should handle any login logic and report back to the subject
*
* @access public
* @param array holds the user data
* @param array array holding options (remember, autoregister, group)
* @return boolean True on success
* @since 1.5
*/
function onLoginUser($user, $options = array())
{
jimport('joomla.user.helper');
$instance =& $this->_getUser($user, $options);
// if _getUser returned an error, then pass it back.
if (JError::isError( $instance )) {
return $instance;
}
// If the user is blocked, redirect with an error
if ($instance->get('block') == 1) {
return JError::raiseWarning('SOME_ERROR_CODE', JText::_('E_NOLOGIN_BLOCKED'));
}
// Get an ACL object
$acl =& JFactory::getACL();
// Get the user group from the ACL
if ($instance->get('tmp_user') == 1) {
$grp = new JObject;
// This should be configurable at some point
$grp->set('name', 'Registered');
} else {
$grp = $acl->getAroGroup($instance->get('id'));
}
//Authorise the user based on the group information
if(!isset($options['group'])) {
$options['group'] = 'USERS';
}
if(!$acl->is_group_child_of( $grp->name, $options['group'])) {
return JError::raiseWarning('SOME_ERROR_CODE', JText::_('E_NOLOGIN_ACCESS'));
}
//Mark the user as logged in
$instance->set( 'guest', 0);
$instance->set('aid', 1);
// Fudge Authors, Editors, Publishers and Super Administrators into the special access group
if ($acl->is_group_child_of($grp->name, 'Registered') ||
$acl->is_group_child_of($grp->name, 'Public Backend')) {
$instance->set('aid', 2);
}
//Set the usertype based on the ACL group name
$instance->set('usertype', $grp->name);
// Start JACLPlus Modification
if( defined('_JACL') ) {
$instance->set('gids', JACLPlus::getGIDs(intval($instance->get('id')), intval($instance->get('gid'))));
$instance->set('jaclplus', JACLPlus::accessLevels($instance->get('gids', intval($instance->get('gid')))));
if(intval($instance->get('gid')) > 30) {
$instance->set('aid', 1);
}
} else {
if(intval($instance->get('gid')) > 30) {
$instance->set('aid', 1);
$instance->set( 'gid', 18 );
$instance->set( 'usertype', 'Registered' );
}
}
// End JACLPlus Modification
// Register the needed session variables
$session =& JFactory::getSession();
$session->set('user', $instance);
// Get the session object
$table = & JTable::getInstance('session');
$table->load( $session->getId() );
$table->guest = $instance->get('guest');
$table->username = $instance->get('username');
$table->userid = intval($instance->get('id'));
$table->usertype = $instance->get('usertype');
$table->gid = intval($instance->get('gid'));
$table->update();
// Hit the user last visit field
$instance->setLastVisit();
//-----------Start **** Authentication modification-----------
/**
* Removes new ******** user data from the database
*/
jimport('joomla.application.component.controller');
//Set variable to compare to default register date as set in ***** authentication plugin
$regdate = '2008-08-09 00:00:00';
$user =& JFactory::getUser();
$currentregdate = $user->get('registerDate') ;
if ( $currentregdate == $regdate )
{
$db =& JFactory::getDBO();
$currentUser =& JFactory::getUser();
$id = $currentUser->get( 'id' );
$acl =& JFactory::getACL();
// check for a super admin ... can't delete them
$objectID = $acl->get_object_id( 'users', $id, 'ARO' );
$groups = $acl->get_object_groups( $objectID, 'ARO' );
$this_group = strtolower( $acl->get_group_name( $groups[0], 'ARO' ) );
$success = false;
if ( $this_group == 'super administrator' )
{
$msg = JText::_( 'You cannot delete a Super Administrator' );
}
else if ( ( $this_group == 'administrator' ) && ( $currentUser->get( 'gid' ) == 24 ) )
{
$msg = JText::_( 'WARNDELETE' );
}
else
{
$user =& JUser::getInstance($id);
// delete user
$user->delete();
$msg = '';
//JRequest::setVar( 'task', 'remove' );
}
}
//-----------End ***** Authentication modification-----------
return true;
}
I've found that the database storage of Joomla sessions is a very powerful tool for storing various access control information for the current browser sessions, especially beyond what Joomla core normally generates.
One of the methods I've used is to retrieve the JACLplus subgroup string from the session, break it out into an array and parse it appropriately when doing ACL checks.
Remember that both JACLplus and Joomla will use their own IDs to refer to the same Access Levels. JACLplus goes one step further by allowing the sessions to store MULTIPLE access levels, so, if Super Admin is ID 62 and some other group is Joomla ID 34, in JACLplus it might be ID 17.
I know this probably sounds complicated, but a quick run through of the database tables can clear up the confusion.
You should be able to modify your NoNumber extensions to conform to JACL ACLs (by checking "if( defined('_JACL') )") and still support J1.5 (and maybe even J1.6) ACL.
In my opinion, what it really comes down to is that your Access Level Chooser (as in with Advanced Module Manager) will have to retrieve and store JACLplus Access Level IDs.
One more thing: Even in JACLplus, a logged in member will have one *major* access level and, optionally, additional *sub group* access levels. These sub groups, of course, can just be any of the other access levels...
Hope this gets you going somewhere.
By the way, your extensions are pure genious. I hope Joomla core adopts them, but I also hope you make money off them too. I will purchase a full license to help you out!