# user-access-manager/1.2.4.3/class/UamAccessHandler.class.php

User Access Manager, version 1.2.4.3. 764 lines.

- Page: https://pluginprobe.com/plugins/user-access-manager/1.2.4.3/code/class/UamAccessHandler.class.php
- Raw: https://pluginprobe.com/plugins/user-access-manager/1.2.4.3/raw/class/UamAccessHandler.class.php
- Modified: 2013-05-08T18:28:46+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/user-access-manager/1.2.4.3/code/class/UamAccessHandler.class.php#L10-L20`.

```php
<?php
/**
 * UamAccessHandler.class.php
 * 
 * The UamUserGroup class file.
 * 
 * PHP versions 5
 * 
 * @category  UserAccessManager
 * @package   UserAccessManager
 * @author    Alexander Schneider <alexanderschneider85@googlemail.com>
 * @copyright 2008-2013 Alexander Schneider
 * @license   http://www.gnu.org/licenses/gpl-2.0.html  GNU General Public License, version 2
 * @version   SVN: $Id$
 * @link      http://wordpress.org/extend/plugins/user-access-manager/
 */

/**
 * The access handler class.
 * 
 * @category UserAccessManager
 * @package  UserAccessManager
 * @author   Alexander Schneider <alexanderschneider85@gmail.com>
 * @license  http://www.gnu.org/licenses/gpl-2.0.html  GNU General Public License, version 2
 * @link     http://wordpress.org/extend/plugins/user-access-manager/
 */

class UamAccessHandler
{
    protected $_oUserAccessManager = null;
    protected $_aObjectUserGroups = array();
    protected $_aObjectAccess = array();
    protected $_aUserGroups = array(
        'filtered' => array(),
        'noneFiltered' => array(),
    );
    protected $_aPlObjects = array();
    protected $_aObjectTypes = array(
        'category',
        'user',
        'role',
    );
    protected $_aPostableTypes = array(
        'post',
        'page',
        'attachment',
    );
    protected $_aAllObjectTypes = null;
    protected $_aSqlResults = array();
    
    /**
     * The constructor
     * 
     * @param UserAccessManager $oUserAccessManager The user access manager object.
     */
    public function __construct(UserAccessManager $oUserAccessManager)
    {
        $this->_oUserAccessManager = $oUserAccessManager;
        
        $aPostTypes = get_post_types(array(), 'objects');
        
        foreach ($aPostTypes as $oPostType) {
            if ($oPostType->publicly_queryable) {
                $this->_aPostableTypes[] = $oPostType->name;
            }
        }
        
        $this->_aObjectTypes = array_merge($this->_aPostableTypes, $this->_aObjectTypes);
    }
    
    /**
     * Returns the user access manager object.
     * 
     * @return UserAccessManager
     */
    public function &getUserAccessManager()
    {
        return $this->_oUserAccessManager;
    }
    
    /**
     * Returns the predefined object types.
     * 
     * @return array
     */
    public function getObjectTypes()
    {
        return $this->_aObjectTypes;
    }
    
    /**
     * Returns the predefined object types.
     * 
     * @return array;
     */
    public function getPostableTypes()
    {
        return $this->_aPostableTypes;
    }
    
    /**
     * Returns all _aObjects types.
     * 
     * @return array
     */
    public function getAllObjectTypes()
    {
        if (isset($this->_aAllObjectTypes)) {
            return $this->_aAllObjectTypes;
        }
        
        $aPlObjects = $this->getPlObjects();

        $this->_aAllObjectTypes = array_merge(
            $this->_aObjectTypes,
            array_keys($aPlObjects)
        );
        
        return $this->_aAllObjectTypes;
    }
    
    /**
     * Magic method getter.
     * 
     * @param string $sName      The name of the function
     * @param array  $aArguments The arguments for the function
     * 
     * @return mixed
     */
    public function __call($sName, $aArguments)
    {
        $oUserAccessManager = $this->getUserAccessManager();

        if ($oUserAccessManager->startsWith($sName, 'getUserGroupsFor')) {
            $sPrefix = 'getUserGroupsFor';
        } elseif ($oUserAccessManager->startsWith($sName, 'checkAccessFor')) {
            $sPrefix = 'checkAccessFor';
        }

        if (isset($sPrefix)) {
            $sObjectType = str_replace($sPrefix, '', $sName);
            $sObjectType = strtolower($sObjectType);

            $iObjectId = $aArguments[0];

            if ($sPrefix == 'getUserGroupsFor') {
                return $this->getUserGroupsForObject($sObjectType, $iObjectId);
            } elseif ($sPrefix == 'checkAccessFor') {
                return $this->checkObjectAccess($sObjectType, $iObjectId);
            }
        }

        return null;
    }
    
    /**
     * Filter the user groups of an object if authors_can_add_posts_to_groups
     * option is enabled
     * 
     * @param UamUserGroup[] $aUserGroups The user groups.
     * 
     * @return array
     */
    protected function _filterUserGroups($aUserGroups)
    {
        $aUamOptions = $this->getUserAccessManager()->getAdminOptions();
        
        if ($aUamOptions['authors_can_add_posts_to_groups'] == 'true'
        	&& !$this->checkUserAccess('manage_user_groups')
        	&& $this->getUserAccessManager()->atAdminPanel()
        ) {
            $oCurrentUser = $this->getUserAccessManager()->getCurrentUser();
            $aUserGroupsForUser = $this->getUserGroupsForObject('user', $oCurrentUser->ID);
            
            foreach ($aUserGroups as $sKey => $oUamUserGroup) {
                if (!isset($aUserGroupsForUser[$oUamUserGroup->getId()])) {
                    unset($aUserGroups[$sKey]);
                }
            }
        }
        
        return $aUserGroups;
    }
    
    /**
     * Returns all user groups or one requested by the user group _iId.
     * 
     * @param integer $iUserGroupId The _iId of the single user group which should be returned.
     * @param boolean $blFilter      Filter the groups.
     * 
     * @return UamUserGroup[]|UamUserGroup
     */
    public function getUserGroups($iUserGroupId = null, $blFilter = true)
    {
        if ($blFilter) {
            $sFilterAttr = 'filtered';
        } else {
            $sFilterAttr = 'noneFiltered';
        }
        
        if ($iUserGroupId === null
            && $this->_aUserGroups[$sFilterAttr] != array()
        ) {
            return $this->_aUserGroups[$sFilterAttr];
        } elseif ($iUserGroupId !== null
                  && $this->_aUserGroups[$sFilterAttr] != array()
        ) {
            if (isset($this->_aUserGroups[$sFilterAttr][$iUserGroupId])) {
                return $this->_aUserGroups[$sFilterAttr][$iUserGroupId];
            } else {
                return null;
            }
        }
        
        $this->_aUserGroups[$sFilterAttr] = array();

        /**
         * @var wpdb $wpdb
         */
        global $wpdb;

        $aUserGroupsDb = $wpdb->get_results(
        	"SELECT ID
        	FROM " . DB_ACCESSGROUP . "
        	ORDER BY ID", ARRAY_A
        );
        
        if (isset($aUserGroupsDb)) {
            foreach ($aUserGroupsDb as $aUserGroupDb) {
                $this->_aUserGroups[$sFilterAttr][$aUserGroupDb['ID']] = new UamUserGroup($this, $aUserGroupDb['ID']);
            }
        }
        
        //Filter the user groups
        if ($blFilter) {
            $this->_aUserGroups[$sFilterAttr] = $this->_filterUserGroups($this->_aUserGroups[$sFilterAttr]);
        }
        
        if ($iUserGroupId == null) {
            return $this->_aUserGroups[$sFilterAttr];
        } else {
            if (isset($this->_aUserGroups[$sFilterAttr][$iUserGroupId])) {
                return $this->_aUserGroups[$sFilterAttr][$iUserGroupId];
            } else {
                return null;
            }
        }
    }
    
    /**
     * Adds a user group.
     * 
     * @param UamUserGroup $oUserGroup The user group which we want to add.
     * 
     * @return null
     */
    public function addUserGroup($oUserGroup)
    {
        $this->getUserGroups();
        $this->_aUserGroups['noneFiltered'][$oUserGroup->getId()] = $oUserGroup;
        $this->_aUserGroups['filtered'] = array();
    }
    
    /**
     * Deletes a user group.
     * 
     * @param integer $iUserGroupId The user group _iId which we want to delete.
     * 
     * @return null
     */
    public function deleteUserGroup($iUserGroupId)
    {
        if ($this->getUserGroups($iUserGroupId) != null) {
            $this->getUserGroups($iUserGroupId)->delete();
            unset($this->_aUserGroups['noneFiltered'][$iUserGroupId]);
            $this->_aUserGroups['filtered'] = array();
        }
    }
    
    /**
     * Returns the user groups for the given object.
     * 
     * @param string  $sObjectType The object type.
     * @param integer $iObjectId   The _iId of the object.
     * @param boolean $blFilter    Filter the groups.
     * 
     * @return UamUserGroup[]
     */
    public function getUserGroupsForObject($sObjectType, $iObjectId, $blFilter = true)
    {
        if (!in_array($sObjectType, $this->getAllObjectTypes())) {
            return array();
        }
        
        if ($sObjectType == 'user') {
            $blFilter = false;
        }
        
        if ($blFilter) {
            $sFilterAttr = 'filtered';
        } else {
            $sFilterAttr = 'noneFiltered';
        }
        
        if (isset($this->_aObjectUserGroups[$sObjectType][$sFilterAttr][$iObjectId])) {
            return $this->_aObjectUserGroups[$sObjectType][$sFilterAttr][$iObjectId];
        }
        
        $aObjectUserGroups = array();
        $aUserGroups = $this->getUserGroups(null, $blFilter);
        
        /*$blPlObject = false;
        $aPostableTypes = $this->getPostableTypes();

        if (!in_array($sObjectType, $aPostableTypes)) {
            $blPlObject = true;
        }*/
       
        $aCurIp = explode(".", $_SERVER['REMOTE_ADDR']);
        
        if (isset($aUserGroups)) {
            foreach ($aUserGroups as $oUserGroup) {
                $mObjectMembership = $oUserGroup->objectIsMember($sObjectType, $iObjectId, true);

                if ($mObjectMembership !== false
                    || $sObjectType == 'user'
                    && $this->checkUserIp($aCurIp, $oUserGroup->getIpRange())
                ) {
                    if (is_array($mObjectMembership)) {
                        $oUserGroup->aSetRecursive[$sObjectType][$iObjectId] = $mObjectMembership;
                    }

                    $aObjectUserGroups[$oUserGroup->getId()] = $oUserGroup;
                }
            }
        }
        
        //Filter the user groups
        if ($blFilter) {
            $aObjectUserGroups = $this->_filterUserGroups($aObjectUserGroups);
        }
        
        $this->_aObjectUserGroups[$sObjectType][$sFilterAttr][$iObjectId] = $aObjectUserGroups;
        return $this->_aObjectUserGroups[$sObjectType][$sFilterAttr][$iObjectId];
    }
    
    /**
     * Unset the user groups for _aObjects.
     * 
     * @return null
     */
    public function unsetUserGroupsForObject()
    {
        $this->_aObjectUserGroups = array();
    }
    
    /**
     * Checks if the current_user has access to the given post.
     * 
     * @param string  $sObjectType The object type which should be checked.
     * @param integer $iObjectId   The _iId of the object.
     * 
     * @return boolean
     */
    public function checkObjectAccess($sObjectType, $iObjectId)
    {
        if (!in_array($sObjectType, $this->getAllObjectTypes())) {
            return true;
        }
        
        if (isset($this->_aObjectAccess[$sObjectType][$iObjectId])) {
            return $this->_aObjectAccess[$sObjectType][$iObjectId];
        }

        $oCurrentUser = $this->getUserAccessManager()->getCurrentUser();
        $aPostableTypes = $this->getPostableTypes();

        if (in_array($sObjectType, $aPostableTypes)) {
            $oPost = get_post($iObjectId);
            $sAuthorId = $oPost->post_author;
        } else {
            $sAuthorId = -1;
        }
        
        $aUamOptions = $this->getUserAccessManager()->getAdminOptions();
        $aMembership = $this->getUserGroupsForObject($sObjectType, $iObjectId, false);
        
        if ($aMembership == array()
            || $this->checkUserAccess('manage_user_groups')
            || $oCurrentUser->ID == $sAuthorId
            && $aUamOptions['authors_has_access_to_own'] == 'true'
        ) {
            return $this->_aObjectAccess[$sObjectType][$iObjectId] = true;
        }
        
        $aCurIp = explode(".", $_SERVER['REMOTE_ADDR']);
        
        foreach ($aMembership as $sKey => $oUserGroup) {
            if ($this->checkUserIp($aCurIp, $oUserGroup->getIpRange())
                || $oUserGroup->objectIsMember('user', $oCurrentUser->ID)
            ) {
                return $this->_aObjectAccess[$sObjectType][$iObjectId] = true;
                break;
            }
            
            if ($this->getUserAccessManager()->atAdminPanel() && $oUserGroup->getWriteAccess() == 'all'
            	|| !$this->getUserAccessManager()->atAdminPanel() && $oUserGroup->getReadAccess() == 'all'
            ) {
                unset($aMembership[$sKey]);
            }
        }
        
        if ($aMembership == array()) {
            return $this->_aObjectAccess[$sObjectType][$iObjectId] = true;
        }
        
        return $this->_aObjectAccess[$sObjectType][$iObjectId] = false;
    }
    
    
    /*
     * SQL functions.
     */
    
    /**
     * Returns the user groups for the current user as sql string.
     * 
     * @return string
     */
    protected function _getUserGroupsForUserAsSqlString()
    {
        if (isset($this->_aSqlResults['groupsForUser'])) {
            return $this->_aSqlResults['groupsForUser'];
        }

        $oCurrentUser = $this->getUserAccessManager()->getCurrentUser();
        $aUserUserGroups = $this->getUserGroupsForObject('user', $oCurrentUser->ID, false);
        $aUserUserGroupIds = array();
        
        foreach ($aUserUserGroups as $oUserUserGroup) {
            $aUserUserGroupIds[] = $oUserUserGroup->getId();
        }
        
        if ($aUserUserGroupIds !== array()) {
            $sUserUserGroups = implode(', ', $aUserUserGroupIds);
        } else {
            $sUserUserGroups = "''";
        }
        
        $this->_aSqlResults['groupsForUser'] = $sUserUserGroups;
        return $this->_aSqlResults['groupsForUser'];
    }
    
    /**
     * Returns the categories assigned to the user.
     * 
     * @return array
     */
    public function getCategoriesForUser()
    {
        /**
         * @var wpdb $wpdb
         */
        global $wpdb;
        
        if (isset($this->_aSqlResults['categoriesAssignedToUser'])) {
            return $this->_aSqlResults['categoriesAssignedToUser'];
        }
        
        $sUserUserGroups = $this->_getUserGroupsForUserAsSqlString();
        
        $sCategoriesAssignedToUserSql = "
        	SELECT igc.object_id  
    		FROM ".DB_ACCESSGROUP_TO_OBJECT." AS igc
    		WHERE igc.object_type = 'category'
    		AND igc.group_id IN (".$sUserUserGroups.")";
        
        $this->_aSqlResults['categoriesAssignedToUser'] = $wpdb->get_col($sCategoriesAssignedToUserSql);
        return $this->_aSqlResults['categoriesAssignedToUser'];
    }
    
    /**
     * Returns the posts assigned to the user.
     * 
     * @return array
     */
    public function getPostsForUser()
    {
        /**
         * @var wpdb $wpdb
         */
        global $wpdb;
        
        if (isset($this->_aSqlResults['postsAssignedToUser'])) {
            return $this->_aSqlResults['postsAssignedToUser'];
        }
        
        $sUserUserGroup = $this->_getUserGroupsForUserAsSqlString();
        $sPostableTypes = "'".implode("','", $this->getPostableTypes())."'";
        
        $sPostAssignedToUserSql = "
        	SELECT igp.object_id  
        	FROM ".DB_ACCESSGROUP_TO_OBJECT." AS igp
        	WHERE igp.object_type IN (".$sPostableTypes.")
            AND igp.group_id IN (".$sUserUserGroup.")";
        
        $this->_aSqlResults['postsAssignedToUser'] = $wpdb->get_col($sPostAssignedToUserSql);
        return $this->_aSqlResults['postsAssignedToUser'];
    }
    
 	/**
     * Returns the excluded posts.
     * 
     * @return array
     */
    public function getExcludedPosts()
    {
        /**
         * @var wpdb $wpdb
         */
        global $wpdb;
        
        if ($this->checkUserAccess('manage_user_groups')) {
            $this->_aSqlResults['excludedPosts'] = array();
        }
        
        if (isset($this->_aSqlResults['excludedPosts'])) {
            return $this->_aSqlResults['excludedPosts'];
        }
        
        if ($this->getUserAccessManager()->atAdminPanel()) {
            $sAccessType = "write";
        } else {
            $sAccessType = "read";
        }

        $aCategoriesAssignedToUser = $this->getCategoriesForUser();
            
        if ($aCategoriesAssignedToUser !== array()) {
            $sCategoriesAssignedToUser = implode(', ', $aCategoriesAssignedToUser);
        } else {
            $sCategoriesAssignedToUser = "''";
        }
        
        $aPostAssignedToUser = $this->getPostsForUser();
        
        if ($aPostAssignedToUser !== array()) {
            $sPostAssignedToUser = implode(', ', $aPostAssignedToUser);
        } else {
            $sPostAssignedToUser = "''";
        }
        
        $sPostSql = "SELECT DISTINCT p.ID
        	FROM $wpdb->posts AS p 
        	INNER JOIN $wpdb->term_relationships AS tr 
        		ON p.ID = tr.object_id 
        	INNER JOIN $wpdb->term_taxonomy tt 
        		ON tr.term_taxonomy_id = tt.term_taxonomy_id
            WHERE tt.taxonomy = 'category' 
    		AND tt.term_id IN (
    			SELECT gc.object_id 
    			FROM ".DB_ACCESSGROUP." iag
    			INNER JOIN ".DB_ACCESSGROUP_TO_OBJECT." AS gc
    				ON iag.id = gc.group_id
    			WHERE gc.object_type = 'category'
    			AND iag.".$sAccessType."_access != 'all'
    			AND gc.object_id  NOT IN (".$sCategoriesAssignedToUser.")
    		) AND p.ID NOT IN (".$sPostAssignedToUser.")
    		UNION
    		SELECT DISTINCT gp.object_id 
    		FROM ".DB_ACCESSGROUP." AS ag
            INNER JOIN ".DB_ACCESSGROUP_TO_OBJECT." AS gp
                ON ag.id = gp.group_id
    		INNER JOIN $wpdb->term_relationships AS tr 
        		ON gp.object_id  = tr.object_id 
        	INNER JOIN $wpdb->term_taxonomy tt 
        		ON tr.term_taxonomy_id = tt.term_taxonomy_id
    		WHERE gp.object_type = 'post'
    		AND ag.".$sAccessType."_access != 'all'
    		AND gp.object_id  NOT IN (".$sPostAssignedToUser.")
    		AND tt.term_id NOT IN (".$sCategoriesAssignedToUser.")";
        
        $this->_aSqlResults['excludedPosts'] = $wpdb->get_col($sPostSql);
        return $this->_aSqlResults['excludedPosts'];
    }
    
    
    /*
     * Other functions
     */
    
    /**
     * Checks if the given ip matches with the range.
     * 
     * @param array $aCurIp    The ip of the current user.
     * @param array $aIpRanges The ip ranges.
     * 
     * @return boolean
     */
    public function checkUserIp($aCurIp, $aIpRanges)
    {
        if (isset($aIpRanges)) {
            foreach ($aIpRanges as $aIpRange) {
                $aIpRange = explode("-", $aIpRange);
                $aRangeBegin = explode(".", $aIpRange[0]);
                
                if (isset($aIpRange[1])) {
                    $aRangeEnd = explode(".", $aIpRange[1]);
                } else {
                    $aRangeEnd = explode(".", $aIpRange[0]);
                }
                
                if ($aRangeBegin[0] <= $aCurIp[0]  && $aCurIp[0] <= $aRangeEnd[0]
                    && $aRangeBegin[1] <= $aCurIp[1] && $aCurIp[1] <= $aRangeEnd[1]
                    && $aRangeBegin[2] <= $aCurIp[2] && $aCurIp[2] <= $aRangeEnd[2]
                    && $aRangeBegin[3] <= $aCurIp[3] && $aCurIp[3] <= $aRangeEnd[3]
                ) {
                    return true;
                }
            }
        }
        
        return false;
    }
    
    /**
     * Return the role of the user.
     * 
     * @param integer $iUserId The user _iId.
     * 
     * @return string|null
     */
    protected function _getUserRole($iUserId)
    {
        /**
         * @var wpdb $wpdb
         */
        global $wpdb;
        
        $oUserData = get_userdata($iUserId);
        
        if (!empty($oUserData->user_level) && !isset($oUserData->user_level)) {
            $oUserData->user_level = null;
        }
        
        if (isset($oUserData->{$wpdb->prefix . "capabilities"})) {
            $aCapabilities = $oUserData->{$wpdb->prefix . "capabilities"};
        } else {
            $aCapabilities = array();
        }
        
        $aRole  = (count($aCapabilities) > 0) ? array_keys($aCapabilities) : array('norole');
        return trim($aRole[0]);
    }
    
    /**
     * Checks if the user is an admin user
     * 
     * @param integer $iUserId The user _iId.
     * 
     * @return boolean
     */
    public function userIsAdmin($iUserId)
    {
        $sRole = $this->_getUserRole($iUserId);
        
        if ($sRole == 'administrator' || is_super_admin($iUserId)) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Checks the user access by user level.
     *
     * @param boolean $blAllowedCapability If true check also for the capability.
     *
     * @return boolean
     */
    public function checkUserAccess($blAllowedCapability = false)
    {
        $oCurrentUser = $this->getUserAccessManager()->getCurrentUser();
        $aUamOptions = $this->getUserAccessManager()->getAdminOptions();
        
        $sRole = $this->_getUserRole($oCurrentUser->ID);
        $aOrderedRoles = $this->getRolesOrdered();
        
        if (isset($aOrderedRoles[$sRole])
            && $aOrderedRoles[$sRole] >= $aOrderedRoles[$aUamOptions['full_access_role']]
            || $sRole == 'administrator' || is_super_admin($oCurrentUser->ID)
            || ($blAllowedCapability && $oCurrentUser->has_cap($blAllowedCapability))
        ) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Returns the roles as associative array.
     * 
     * @return array
     */
    public function getRolesOrdered()
    {
        $aOrderedRoles = array(
            'norole' => 0,
            'subscriber' => 1,
            'contributor' => 2,
            'author' => 3,
        	'editor' => 4,
            'administrator' => 5
        );
        
        return $aOrderedRoles;
    }
    
    /**
     * Registers object that should be handelt by the user access manager.
     * 
     * @param array $oObject The object which you want to register.
     * 
     * @return boolean
     */
    public function registerPlObject($oObject)
    {
        if (!isset($oObject['name']) || !isset($oObject['reference'])
            || !isset($oObject['getFull']) || !isset($oObject['getFullObjects'])
        ) {
            return false;
        }
        
        $this->_aPlObjects[$oObject['name']] = $oObject;
        
        return true;
    }
    
    /**
     * Returns a registered pluggable object.
     * 
     * @param string $sObjectName The name of the object which should be returned.
     * 
     * @return array
     */
    public function getPlObject($sObjectName)
    {
        if (isset($this->_aPlObjects[$sObjectName])) {
            return $this->_aPlObjects[$sObjectName];
        }
        
        return array();
    }
    
    /**
     * Returns all registered pluggable _aObjects.
     * 
     * @return array
     */
    public function getPlObjects()
    {
        return $this->_aPlObjects;
    }
}
```
