Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/croogo/croogo/Core/src/Utility/VisibilityFilter.php
<?php

namespace Croogo\Core\Utility;

use
Cake\Collection\CollectionInterface;
use
Cake\Datasource\ResultSetInterface;
use
Cake\Http\ServerRequest;
use
Cake\Log\LogTrait;
use
Cake\ORM\Entity;
use
Cake\Routing\Router;
use
Cake\Utility\Hash;
use
Psr\Log\LogLevel;
use
Traversable;

/**
 * VisibilityFilter
 *
 * @author   Rachman Chavik <rchavik@xintesa.com>
 * @package  Croogo.Croogo.Lib.Utility
 * @license  http://www.opensource.org/licenses/mit-license.php The MIT License
 * @link     http://www.croogo.org
 */
class VisibilityFilter
{

    use
LogTrait;

   
/**
     * StringConverter instance
     */
   
protected $_converter = null;

   
/**
     * Known url keys
     */
   
protected $_urlKeys = [
       
'admin' => false,
       
'plugin' => false,
       
'controller' => false,
       
'action' => false,
       
'named' => false,
       
'pass' => false,
    ];

   
/**
     * Constructor
     *
     * @param \Cake\Http\ServerRequest $request
     */
   
public function __construct(ServerRequest $request = null)
    {
        if (
$request) {
           
$this->_request = $request;
        } else {
           
$this->_request = new Request();
        }
       
$this->_converter = new StringConverter();
    }

   
/**
     * Check that request (passed in the constructor) is visible based on list of
     * specified rules.  The rules can specified in link string format or just a
     * plain URL fragment.  Whenever possible, use link string formatted rule since
     * a URL fragment can be expensive.
     *
     * The current request is checked against negative rules first (implicitly
     * hidden), then against positive rules (implicitly visible).
     * If there's no positive rule, defaults to visible.
     *
     * @param array $rules Array of rules in link string format
     * @return bool True if the rules are satisfied
     * @see StringConverter::linkStringToArray()
     */
   
protected function _isVisible($rules)
    {
       
$negativeRules = array_filter($rules, function ($value) {
            if (
$value[0] === '-') {
                return
true;
            }

            return
false;
        });
        foreach (
$negativeRules as $rule) {
            if (
$this->_ruleMatch(substr($rule, 1))) {
                return
false;
            }
        }

       
$positiveRules = array_diff($rules, $negativeRules);
        if (empty(
$positiveRules)) {
            return
true;
        }
        foreach (
$positiveRules as $rule) {
            if (
$rule[0] == '+') {
               
$rule = substr($rule, 1);
            }
            if (
$this->_ruleMatch($rule)) {
                return
true;
            }
        }

        return
false;
    }

   
/**
     * Check that request matches a single rule
     *
     * @param string $rule Rule in link string or plain URL fragment
     * @return bool True if request satisfies the rule
     */
   
protected function _ruleMatch($rule)
    {
        if (
strpos($rule, ':') !== false) {
           
$url = array_filter($this->_converter->linkStringToArray($rule));
            if (isset(
$url['?'])) {
               
$queryString = $url['?'];
                unset(
$url['?']);
            }
        } else {
           
$url = Router::parse($rule);
           
$named = array_diff_key($url, $this->_urlKeys);
           
$url['named'] = $named;
        }

       
$intersect = array_intersect_key($this->_request->params, $url);
       
$matched = $intersect == $url;

        if (
$matched && isset($queryString)) {
           
$matched = $this->_request->query == $queryString;
        }

        return
$matched;
    }

   
/**
     * Remove values based on rules in visibility_path field.
     *
     * Options:
     *   - field Field name containing the visibility path rules
     *
     * @param \Traversable $traversable
     * @param array $options
     * @return \Cake\Collection\Collection
     */
   
public function remove(Traversable $traversable, $options = [])
    {
       
$options = Hash::merge([
           
'field' => null,
        ],
$options);
       
$field = $options['field'];

        return
collection($traversable)->filter(function (Entity $entity) use ($field) {
           
$rules = $entity->get($field);
            if (empty(
$rules)) {
                return
true;
            }

            if (!
is_array($rules)) {
               
$this->log('Invalid visibility_path rule', LogLevel::ERROR);
            }

            return
$this->_isVisible($rules);
        });
    }
}