Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/acl/src/Adapter/Utility/PhpAro.php
<?php
/**
 * PHP configuration based Access Request Object
 *
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */
namespace Acl\Adapter\Utility;

use
Cake\Utility\Hash;
use
Cake\Utility\Inflector;

/**
 * Access Request Object
 *
 */
class PhpAro
{

   
/**
     * role to resolve to when a provided ARO is not listed in
     * the internal tree
     *
     * @var string
     */
   
const DEFAULT_ROLE = 'Role/default';

   
/**
     * map external identifiers. E.g. if
     *
     * ['Users' => ['username' => 'jeff', 'role' => 'editor']]
     *
     * is passed as an ARO to one of the methods of AclComponent, PhpAcl
     * will check if it can be resolved to an User or a Role defined in the
     * configuration file.
     *
     * @var array
     * @see app/Config/acl.php
     */
   
public $map = [
       
'User' => 'Users/username',
       
'Role' => 'Users/role',
    ];

   
/**
     * aliases to map
     *
     * @var array
     */
   
public $aliases = [];

   
/**
     * internal ARO representation
     *
     * @var array
     */
   
protected $_tree = [];

   
/**
     * Constructor
     *
     * @param array $aro Aro instance
     * @param array $map Map
     * @param array $aliases Aliases
     */
   
public function __construct(array $aro = [], array $map = [], array $aliases = [])
    {
        if (!empty(
$map)) {
           
$this->map = $map;
        }

       
$this->aliases = $aliases;
       
$this->build($aro);
    }

   
/**
     * From the perspective of the given ARO, walk down the tree and
     * collect all inherited AROs levelwise such that AROs from different
     * branches with equal distance to the requested ARO will be collected at the same
     * index. The resulting array will contain a prioritized list of (list of) roles ordered from
     * the most distant AROs to the requested one itself.
     *
     * @param string|array $aro An ARO identifier
     * @return array prioritized AROs
     */
   
public function roles($aro)
    {
       
$aros = [];
       
$aro = $this->resolve($aro);
       
$stack = [[$aro, 0]];

        while (!empty(
$stack)) {
            list(
$element, $depth) = array_pop($stack);
           
$aros[$depth][] = $element;

            foreach (
$this->_tree as $node => $children) {
                if (
in_array($element, $children)) {
                   
array_push($stack, [$node, $depth + 1]);
                }
            }
        }

        return
array_reverse($aros);
    }

   
/**
     * resolve an ARO identifier to an internal ARO string using
     * the internal mapping information.
     *
     * @param string|array $aro ARO identifier (Users.jeff, ['Users' => ...], etc)
     * @return string internal aro string (e.g. Users/jeff, Role/default)
     */
   
public function resolve($aro)
    {
        foreach (
$this->map as $aroGroup => $map) {
            list(
$model, $field) = explode('/', $map, 2);
           
$mapped = '';

            if (
is_array($aro)) {
                if (isset(
$aro['model']) && isset($aro['foreign_key']) && $aro['model'] === $aroGroup) {
                   
$mapped = $aroGroup . '/' . $aro['foreign_key'];
                } elseif (isset(
$aro[$model][$field])) {
                   
$mapped = $aroGroup . '/' . $aro[$model][$field];
                } elseif (isset(
$aro[$field])) {
                   
$mapped = $aroGroup . '/' . $aro[$field];
                }
            } elseif (
is_string($aro)) {
               
$aro = ltrim($aro, '/');

                if (
strpos($aro, '/') === false) {
                   
$mapped = $aroGroup . '/' . $aro;
                } else {
                    list(
$aroModel, $aroValue) = explode('/', $aro, 2);

                   
$aroModel = Inflector::camelize($aroModel);

                    if (
$aroModel === $model || $aroModel === $aroGroup) {
                       
$mapped = $aroGroup . '/' . $aroValue;
                    }
                }
            }

            if (isset(
$this->_tree[$mapped])) {
                return
$mapped;
            }

           
// is there a matching alias defined (e.g. Role/1 => Role/admin)?
           
if (!empty($this->aliases[$mapped])) {
                return
$this->aliases[$mapped];
            }
        }

        return static::
DEFAULT_ROLE;
    }

   
/**
     * adds a new ARO to the tree
     *
     * @param array $aro one or more ARO records
     * @return void
     */
   
public function addRole(array $aro)
    {
        foreach (
$aro as $role => $inheritedRoles) {
            if (!isset(
$this->_tree[$role])) {
               
$this->_tree[$role] = [];
            }

            if (!empty(
$inheritedRoles)) {
                if (
is_string($inheritedRoles)) {
                   
$inheritedRoles = array_map('trim', explode(',', $inheritedRoles));
                }

                foreach (
$inheritedRoles as $dependency) {
                   
// detect cycles
                   
$roles = $this->roles($dependency);

                    if (
in_array($role, Hash::flatten($roles))) {
                       
$path = '';

                        foreach (
$roles as $roleDependencies) {
                           
$path .= implode('|', (array)$roleDependencies) . ' -> ';
                        }

                       
trigger_error(sprintf('cycle detected when inheriting %s from %s. Path: %s', $role, $dependency, $path . $role));
                        continue;
                    }

                    if (!isset(
$this->_tree[$dependency])) {
                       
$this->_tree[$dependency] = [];
                    }

                   
$this->_tree[$dependency][] = $role;
                }
            }
        }
    }

   
/**
     * adds one or more aliases to the internal map. Overwrites existing entries.
     *
     * @param array $alias alias from => to (e.g. Role/13 -> Role/editor)
     * @return void
     */
   
public function addAlias(array $alias)
    {
       
$this->aliases = $alias + $this->aliases;
    }

   
/**
     * build an ARO tree structure for internal processing
     *
     * @param array $aros array of AROs as key and their inherited AROs as values
     * @return void
     */
   
public function build(array $aros)
    {
       
$this->_tree = [];
       
$this->addRole($aros);
    }
}