<commit_before><?php

namespace PhpAbac\Manager;

use PhpAbac\Model\PolicyRuleAttribute;

use PhpAbac\Comparison\ArrayComparison;
use PhpAbac\Comparison\BooleanComparison;
use PhpAbac\Comparison\DatetimeComparison;
use PhpAbac\Comparison\NumericComparison;
use PhpAbac\Comparison\StringComparison;

class ComparisonManager {
    /** @var \PhpAbac\Manager\AttributeManager **/
    protected $attributeManager;
    /** @var array **/
    protected $comparisons = [
        'array' => ArrayComparison::class,
        'boolean' => BooleanComparison::class,
        'datetime' => DatetimeComparison::class,
        'numeric' => NumericComparison::class,
        'string' => StringComparison::class,
    ];
    /** @var array **/
    protected $rejectedAttributes = [];
    
    /**
     * @param \PhpAbac\Manager\AttributeManager $manager
     */
    public function __construct(AttributeManager $manager) {
        $this->attributeManager = $manager;
    }
    
    /**
     * This method retrieve the comparison class, instanciate it,
     * and then perform the configured comparison
     * It does return a control value for special operations,
     * but the real check is at the end of the enforce() method,
     * when the rejected attributes are counted
     * 
     * @param PolicyRuleAttribute $pra
     * @return bool
     */
    public function compare(PolicyRuleAttribute $pra) {
        $attribute = $pra->getAttribute();
        // The expected value can be set in the configuration as dynamic
        // In this case, we retrieve the expected value in the passed options
        $praValue =
            ($pra->getValue() === 'dynamic')
            ? $this->getDynamicAttribute($attribute->getSlug())
            : $pra->getValue()
        ;
        // Checking that the configured comparison type is available
        if(!isset($this->comparisons[$pra->getComparisonType()])) {
            throw new \InvalidArgumentException('The requested comparison class does not exist');
        }
        // The comparison class will perform the attribute check with the configured method
        // For more complex comparisons, the comparison manager is injected
        $comparison = new $this->comparisons[$pra->getComparisonType()]($this);
        if(!method_exists($comparison, $pra->getComparison())) {
            throw new \InvalidArgumentException('The requested comparison method does not exist');
        }
        // Then the comparison is performed with needed
        $result = $comparison->{$pra->getComparison()}($praValue, $attribute->getValue(), $pra->getExtraData());
        // If the checked attribute is not valid, the attribute slug is marked as rejected
        // The rejected attributes will be returned instead of the expected true boolean
        if($result !== true) {
            if(!in_array($attribute->getSlug(), $this->rejectedAttributes)) {
                $this->rejectedAttributes[] = $attribute->getSlug();
            }
            return false;
        }
        return true;
    }
    
    /**
     * @param array $dynamicAttributes
     */
    public function setDynamicAttributes($dynamicAttributes) {
        $this->dynamicAttributes = $dynamicAttributes;
    }
    
    /**
     * A dynamic attribute is a value given by the user code as an option
     * If a policy rule attribute is dynamic,
     * we check that the developer has given a dynamic value in the options
     * 
     * Dynamic attributes are given with slugs as key
     * 
     * @param string $attributeSlug
     * @return mixed
     * @throws \InvalidArgumentException
     */
    public function getDynamicAttribute($attributeSlug) {
        if(!isset($this->dynamicAttributes[$attributeSlug])) {
            throw new \InvalidArgumentException("The dynamic value for attribute $attributeSlug was not given");
        }
        return $this->dynamicAttributes[$attributeSlug];
    }
    
    /**
     * @param string $type
     * @param string $class
     */
    public function addComparison($type, $class) {
        $this->comparisons[$type] = $class;
    }
    
    /**
     * @return \PhpAbac\Manager\AttributeManager
     */
    public function getAttributeManager() {
        return $this->attributeManager;
    }
    
    /**
     * This method is called when all the policy rule attributes are checked
     * All along the comparisons, the failing attributes slugs are stored
     * If the rejected attributes array is not empty, it means that the rule is not enforced
     * 
     * @return array|bool
     */
    public function getResult() {
        $result =
            (count($this->rejectedAttributes) > 0)
            ? $this->rejectedAttributes
            : true
        ;
        $this->rejectedAttributes = [];
        return $result;
    }
}<commit_msg>Disable error reporting for auxiliary comparisons<commit_after><?php

namespace PhpAbac\Manager;

use PhpAbac\Model\PolicyRuleAttribute;

use PhpAbac\Comparison\ArrayComparison;
use PhpAbac\Comparison\BooleanComparison;
use PhpAbac\Comparison\DatetimeComparison;
use PhpAbac\Comparison\NumericComparison;
use PhpAbac\Comparison\StringComparison;

class ComparisonManager {
    /** @var \PhpAbac\Manager\AttributeManager **/
    protected $attributeManager;
    /** @var array **/
    protected $comparisons = [
        'array' => ArrayComparison::class,
        'boolean' => BooleanComparison::class,
        'datetime' => DatetimeComparison::class,
        'numeric' => NumericComparison::class,
        'string' => StringComparison::class,
    ];
    /** @var array **/
    protected $rejectedAttributes = [];

    /**
     * @param \PhpAbac\Manager\AttributeManager $manager
     */
    public function __construct(AttributeManager $manager) {
        $this->attributeManager = $manager;
    }

    /**
     * This method retrieve the comparison class, instanciate it,
     * and then perform the configured comparison
     * It does return a control value for special operations,
     * but the real check is at the end of the enforce() method,
     * when the rejected attributes are counted.
     *
     * If the second parameter is set to true, compare will not report errors.
     * This is used to test a bunch of comparisons expecting not all of them true to return a granted access.
     * In fact, this parameter is used in comparisons which need to perform comparisons on their own.
     *
     * @param PolicyRuleAttribute $pra
     * @param boolean $subComparing
     * @return bool
     */
    public function compare(PolicyRuleAttribute $pra, $subComparing = false) {
        $attribute = $pra->getAttribute();
        // The expected value can be set in the configuration as dynamic
        // In this case, we retrieve the expected value in the passed options
        $praValue =
            ($pra->getValue() === 'dynamic')
            ? $this->getDynamicAttribute($attribute->getSlug())
            : $pra->getValue()
        ;
        // Checking that the configured comparison type is available
        if(!isset($this->comparisons[$pra->getComparisonType()])) {
            throw new \InvalidArgumentException('The requested comparison class does not exist');
        }
        // The comparison class will perform the attribute check with the configured method
        // For more complex comparisons, the comparison manager is injected
        $comparison = new $this->comparisons[$pra->getComparisonType()]($this);
        if(!method_exists($comparison, $pra->getComparison())) {
            throw new \InvalidArgumentException('The requested comparison method does not exist');
        }
        // Then the comparison is performed with needed
        $result = $comparison->{$pra->getComparison()}($praValue, $attribute->getValue(), $pra->getExtraData());
        // If the checked attribute is not valid, the attribute slug is marked as rejected
        // The rejected attributes will be returned instead of the expected true boolean
        // In case of sub comparing, the error reporting is disabled
        if($result !== true && $subComparing === false) {
            if(!in_array($attribute->getSlug(), $this->rejectedAttributes)) {
                $this->rejectedAttributes[] = $attribute->getSlug();
            }
            return false;
        }
        return true;
    }

    /**
     * @param array $dynamicAttributes
     */
    public function setDynamicAttributes($dynamicAttributes) {
        $this->dynamicAttributes = $dynamicAttributes;
    }

    /**
     * A dynamic attribute is a value given by the user code as an option
     * If a policy rule attribute is dynamic,
     * we check that the developer has given a dynamic value in the options
     *
     * Dynamic attributes are given with slugs as key
     *
     * @param string $attributeSlug
     * @return mixed
     * @throws \InvalidArgumentException
     */
    public function getDynamicAttribute($attributeSlug) {
        if(!isset($this->dynamicAttributes[$attributeSlug])) {
            throw new \InvalidArgumentException("The dynamic value for attribute $attributeSlug was not given");
        }
        return $this->dynamicAttributes[$attributeSlug];
    }

    /**
     * @param string $type
     * @param string $class
     */
    public function addComparison($type, $class) {
        $this->comparisons[$type] = $class;
    }

    /**
     * @return \PhpAbac\Manager\AttributeManager
     */
    public function getAttributeManager() {
        return $this->attributeManager;
    }

    /**
     * This method is called when all the policy rule attributes are checked
     * All along the comparisons, the failing attributes slugs are stored
     * If the rejected attributes array is not empty, it means that the rule is not enforced
     *
     * @return array|bool
     */
    public function getResult() {
        $result =
            (count($this->rejectedAttributes) > 0)
            ? $this->rejectedAttributes
            : true
        ;
        $this->rejectedAttributes = [];
        return $result;
    }
}
{'fraction_non_alphanumeric': 0.10011954572624028, 'fraction_numerical': 0.00019924287706714485, 'mean_word_length': 2.6163544668587897, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2743273', 'n_tokens_mistral': 2511, 'n_tokens_neox': 2481, 'n_words': 815}