Perforce Chronicle 2012.2/486814
API Documentation

P4Cms_Acl Class Reference

Extends Zend_Acl to add several features: More...

List of all members.

Public Member Functions

 __sleep ()
 Provide magic sleep to selectively serialize properties.
 get ($resource)
 Overrides parent method to add resource temporarily if it doesn't exist, but has the form 'parentResource/id' where parentResource is an existing resource.
 getAllowedPrivileges ($role, $resource)
 Returns list of all privileges for which the role has access to the resource.
 getAllPrivileges ()
 Get all privileges in all resources registered with the acl.
 getRecord ()
 Get the record to use for persistent storage of this acl.
 getResourceObjects ()
 Get all of the registered resource objects.
 hasRecord ()
 Determine if this acl has an associated record for storage purposes.
 installDefaults ()
 Install default ACL resources and rules defined in packages.
 installModuleDefaults (P4Cms_Module $module)
 Install default ACL resources and rules defined in a module.
 isAllowed ($role=null, $resource=null, $privilege=null)
 Overrides isAllowed to return false for non-super roles accessing privileges that require super-user access.
 makeActive ()
 Make this acl instance the active one.
 removeModuleDefaults (P4Cms_Module $module)
 Remove default ACL resources and rules defined in a module.
 save ()
 Save this ACL to the associated record.
 setRecord (P4Cms_Record $record=null)
 Set the record to use for persistent storage of this acl.
 setRoles ($roles=null)
 Set all roles at once.

Static Public Member Functions

static fetch ($id, P4Cms_Record_Adapter $adapter=null)
 Fetch a persisted ACL instance from a given record id.
static fetchActive ()
 Fetch the active acl.
static hasActive ()
 Determine if there is an active acl.
static setActive (P4Cms_Acl $acl=null)
 Set the statically accessible ACL instance.

Public Attributes

const RECORD_STORAGE_FIELD = 'acl'

Protected Attributes

 $_record
 $_tempResources = array()

Static Protected Attributes

static $_activeAcl

Detailed Description

Extends Zend_Acl to add several features:

  • Allows ACL to be fetched from and saved in records.
  • Allows roles to be set externally (e.g. from Perforce)
  • No longer serializes roles (so they may be stored elsewhere).
  • Adds concept of a statically accessible 'active' acl.
  • Provides access to resource objects.
Copyright:
2011-2012 Perforce Software. All rights reserved
License:
Please see LICENSE.txt in top-level folder of this distribution.
Version:
2012.2/486814

Member Function Documentation

P4Cms_Acl::__sleep ( )

Provide magic sleep to selectively serialize properties.

This is needed for caching and saving the acl. Note that save is even more selective about what gets serialized.

Returns:
array list of properties to serialize
    {
        // remove temporary resources
        foreach ($this->_tempResources as $resource) {
            $this->remove($resource);
        }
        $this->_tempResources = array();

        return array(
            '_roleRegistry',
            '_resources',
            '_record',
            '_rules'
        );
    }
static P4Cms_Acl::fetch ( id,
P4Cms_Record_Adapter adapter = null 
) [static]

Fetch a persisted ACL instance from a given record id.

Reads the identified record from storage and unserializes it into a new P4Cms_Acl instance.

Parameters:
string$idthe id of the record to read from.
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
Returns:
P4Cms_Acl previously stored acl instance.
    {
        $record     = P4Cms_Record::fetch($id, null, $adapter);
        $serialized = $record->getValue(static::RECORD_STORAGE_FIELD);

        // attempt to unserialize acl from storage.
        $acl = unserialize($serialized);
        if (!$acl instanceof P4Cms_Acl) {
            throw new P4Cms_Acl_Exception(
                "Cannot fetch ACL from $id record. Record did not unserialize to ACL."
            );
        }

        // hang onto record for potential future save.
        $acl->setRecord($record);

        return $acl;
    }
static P4Cms_Acl::fetchActive ( ) [static]

Fetch the active acl.

Guaranteed to return an acl instance or throw an exception if no acl instance has been set as active.

Returns:
P4Cms_Acl the currently active acl.
Exceptions:
P4Cms_Acl_Exceptionif there is no currently active acl.
    {
        if (!static::$_activeAcl || !static::$_activeAcl instanceof P4Cms_Acl) {
            throw new P4Cms_Acl_Exception("There is no active ACL.");
        }

        return static::$_activeAcl;
    }
P4Cms_Acl::get ( resource)

Overrides parent method to add resource temporarily if it doesn't exist, but has the form 'parentResource/id' where parentResource is an existing resource.

Temporary resources are not serialized.

Parameters:
Zend_Acl_Resource_Interface | string$resourceresource to return identified resource for.
Exceptions:
Zend_Acl_Exception
Returns:
Zend_Acl_Resource_Interface identified resource.
    {
        try {
            return parent::get($resource);
        } catch (Zend_Acl_Exception $e) {
            $resource      = is_string($resource) ? $resource : $resource->getResourceId();
            $resourceParts = explode('/', $resource);
            if (count($resourceParts) > 1 && $this->has($resourceParts[0])) {
                $resource = new P4Cms_Acl_Resource($resource);
                $this->addResource($resource, $resourceParts[0]);
                $this->_tempResources[] = $resource;
                return $resource;
            } else {
                // resource not found
                throw $e;
            }
        }
    }
P4Cms_Acl::getAllowedPrivileges ( role,
resource 
)

Returns list of all privileges for which the role has access to the resource.

Parameters:
Zend_Acl_Role_Interface | string$rolethe role to check for
Zend_Acl_Resource_Interface | string$resourcethe resource to check for
Returns:
array list of privileges for which the role has access to the resource
    {
        if ($resource instanceof P4Cms_Acl_Resource) {
            $privileges = $resource->getPrivileges();
        } else {
            $privileges = $this->getAllPrivileges()->toArray(true);
        }

        $allowed = array();
        foreach ($privileges as $privilege) {
            $privilege = $privilege->getId();
            if ($this->isAllowed($role, $resource, $privilege)) {
                $allowed[$privilege] = 1;
            }
        }

        return array_keys($allowed);
    }
P4Cms_Acl::getAllPrivileges ( )

Get all privileges in all resources registered with the acl.

Returns:
array a flat list of all privileges in all resources.
    {
        $privileges = new P4Cms_Model_Iterator;
        foreach ($this->getResourceObjects() as $resource) {
            if ($resource instanceof P4Cms_Acl_Resource) {
                foreach ($resource->getPrivileges() as $privilege) {
                    $privileges[] = $privilege;
                }
            }
        }

        return $privileges;
    }
P4Cms_Acl::getRecord ( )

Get the record to use for persistent storage of this acl.

Returns:
P4Cms_Record the record to save acl to.
Exceptions:
P4Cms_Acl_Exceptionif no record object has been set.
    {
        if (!$this->_record instanceof P4Cms_Record) {
            throw new P4Cms_Acl_Exception("Cannot get record. No record has been set.");
        }

        return $this->_record;
    }
P4Cms_Acl::getResourceObjects ( )

Get all of the registered resource objects.

Returns:
array list of resource instances
    {
        return array_map(
            function($resource)
            {
                return $resource['instance'];
            },
            $this->_resources
        );
    }
static P4Cms_Acl::hasActive ( ) [static]

Determine if there is an active acl.

Returns:
boolean true if there is an active acl.
    {
        try {
            static::fetchActive();
            return true;
        } catch (P4Cms_Acl_Exception $e) {
            return false;
        }
    }
P4Cms_Acl::hasRecord ( )

Determine if this acl has an associated record for storage purposes.

Returns:
boolean true if there is an associated record.
    {
        try {
            $this->getRecord();
            return true;
        } catch (P4Cms_Acl_Exception $e) {
            return false;
        }
    }
P4Cms_Acl::installDefaults ( )

Install default ACL resources and rules defined in packages.

Does not save the acl automatically, must call save() to persist.

Returns:
P4Cms_Acl provides fluent interface.
    {
        // clear the module/theme cache
        P4Cms_Module::clearCache();
        P4Cms_Theme::clearCache();

        // defaults are defined by modules.
        $modules = P4Cms_Module::fetchAllEnabled();
        foreach ($modules as $module) {
            $this->installModuleDefaults($module);
        }

        return $this;
    }
P4Cms_Acl::installModuleDefaults ( P4Cms_Module module)

Install default ACL resources and rules defined in a module.

Does not save the acl automatically, must call save() to persist.

Parameters:
P4Cms_Module$modulethe module whose ACL resources and rules need to be installed
Returns:
P4Cms_Acl provides fluent interface.
    {
        // extract resources from package info.
        $info      = $module->getPackageInfo();
        $resources = isset($info['acl']) && is_array($info['acl'])
                   ? $info['acl']
                   : array();

        // register resources with acl.
        foreach ($resources as $resourceId => $resourceInfo) {

            // add resource if it doesn't exist.
            if (!$this->has($resourceId)) {
                $this->add(new P4Cms_Acl_Resource($resourceId));
            }
            $resource = $this->get($resourceId);

            // set resource label if one is specified.
            if (isset($resourceInfo['label'])) {
                $resource->setLabel($resourceInfo['label']);
            }

            // add any new privileges to resource.
            $privileges = isset($resourceInfo['privileges']) && is_array($resourceInfo['privileges'])
                        ? $resourceInfo['privileges']
                        : array();
            foreach ($privileges as $key => $value) {

                // try to normalize privilege entry to object.
                try {
                    $privilege = $resource->normalizePrivilege($value, $key);
                } catch (InvalidArgumentException $e) {
                    P4Cms_Log::logException("Failed to install default privilege.", $e);
                    continue;
                }

                // skip if privilege exists.
                if ($resource->hasPrivilege($privilege->getId())) {
                    continue;
                }

                // add the privilege.
                $resource->addPrivilege($privilege);

                // use a proxy for assertions to allow for assert
                // classes that might not exist at all times.
                $assert = $privilege->getOption('assertion');
                if ($assert) {
                    $assert = new P4Cms_Acl_Assert_Proxy($assert);
                }

                // set default allow rules.
                // determine which roles to allow access for.
                if ($privilege->getOption('allowAll')) {
                    $this->allow(null, $resource, $privilege->getId(), $assert);
                } else {
                    $roles = $privilege->getDefaultAllowed();
                    $roles = array_filter($roles, array($this, 'hasRole'));
                    if ($roles) {
                        $this->allow($roles, $resource, $privilege->getId(), $assert);
                    }
                }
            }
        }

        return $this;
    }
P4Cms_Acl::isAllowed ( role = null,
resource = null,
privilege = null 
)

Overrides isAllowed to return false for non-super roles accessing privileges that require super-user access.

Parameters:
Zend_Acl_Role_Interface | string$rolethe role to check for access
Zend_Acl_Resource_Interface | string$resourcethe resource to check access to
string$privilegethe privilege in question
Returns:
boolean
    {
        $role     = is_string($role)     ? $this->getRole($role) : $role;
        $resource = is_string($resource) ? $this->get($resource) : $resource;

        // non-super roles are not allowed super privileges.
        if ($privilege && $resource->hasPrivilege($privilege)) {
            $needsSuper = $resource->getPrivilege($privilege)->getOption('needsSuper');
            if ($needsSuper && !P4Cms_Acl_Role::isSuper($role->getRoleId())) {
                return false;
            }
        }

        return parent::isAllowed($role, $resource, $privilege);
    }
P4Cms_Acl::makeActive ( )

Make this acl instance the active one.

Returns:
P4Cms_Acl provides fluent interface.
    {
        static::setActive($this);

        return $this;
    }
P4Cms_Acl::removeModuleDefaults ( P4Cms_Module module)

Remove default ACL resources and rules defined in a module.

Does not save the acl automatically, must call save() to persist.

Parameters:
P4Cms_Module$modulethe module whose ACL resources and rules need to be removed
Returns:
P4Cms_Acl provides fluent interface.
    {
        // extract resources from package info.
        $info      = $module->getPackageInfo();
        $resources = isset($info['acl']) && is_array($info['acl'])
                   ? $info['acl']
                   : array();

        // remove resources from acl.
        foreach ($resources as $resourceId => $resourceInfo) {
            // do nothing if resource doesn't exist.
            if (!$this->has($resourceId)) {
                continue;
            }
            $resource = $this->get($resourceId);

            // remove module default privileges from resource.
            $privileges = isset($resourceInfo['privileges']) && is_array($resourceInfo['privileges'])
                        ? $resourceInfo['privileges']
                        : array();
            foreach ($privileges as $key => $value) {
                // remove the privilege.
                $resource->removePrivilege($key);
            }

            // remove resource if it does not have any privileges.
            if (!$resource->hasPrivileges()) {
                $this->remove($resource);
            }
        }

        return $this;
    }
P4Cms_Acl::save ( )

Save this ACL to the associated record.

Returns:
P4Cms_Acl provides fluent interface.
Exceptions:
P4Cms_Acl_Exceptionif no record has been associated with this acl.
    {
        // we don't want roles or the record to make it into storage
        $acl = clone $this;
        $acl->setRoles(null)
            ->setRecord(null);

        $this->getRecord()
             ->setValue(static::RECORD_STORAGE_FIELD, serialize($acl))
             ->save();

        return $this;
    }
static P4Cms_Acl::setActive ( P4Cms_Acl acl = null) [static]

Set the statically accessible ACL instance.

Parameters:
P4Cms_Acl | null$aclthe acl instance to make active or null to clear.
    {
        static::$_activeAcl = $acl;
    }
P4Cms_Acl::setRecord ( P4Cms_Record record = null)

Set the record to use for persistent storage of this acl.

Parameters:
P4Cms_Record | null$recorda record object to save acl to - null to clear.
Returns:
P4Cms_Acl provides fluent interface.
    {
        $this->_record = $record;

        return $this;
    }
P4Cms_Acl::setRoles ( roles = null)

Set all roles at once.

To reduce the weight of serialized roles we normalize them to Zend_Acl_Role objects. Our role objects compose Perforce group objects and spec definitions, etc. and are considerably larger.

Parameters:
mixed$rolesthe set of roles to use for this acl can be a Zend_Acl_Role_Registry instance, a iterator of role objects, or null to clear.
Returns:
P4Cms_Acl provides fluent interface.
    {
        // extract roles from iterator.
        if ($roles instanceof Iterator) {
            $registry = new Zend_Acl_Role_Registry;
            foreach ($roles as $role) {
                if (!$role instanceof Zend_Acl_Role_Interface) {
                    throw new InvalidArgumentException(
                        "Cannot set roles. Encountered invalid role."
                    );
                }
                $registry->add(new Zend_Acl_Role($role->getRoleId()));
            }
            $roles = $registry;
        }

        if ($roles !== null && !$roles instanceof Zend_Acl_Role_Registry) {
            throw new InvalidArgumentException(
                "Cannot set roles. Roles must be a Zend_Acl_Role_Registry instance, "
              . "a iterator of role objects, or null."
            );
        }

        // set the registry.
        $this->_roleRegistry = $roles;

        return $this;
    }

Member Data Documentation

P4Cms_Acl::$_activeAcl [static, protected]
P4Cms_Acl::$_record [protected]
P4Cms_Acl::$_tempResources = array() [protected]

The documentation for this class was generated from the following file: