tomverran/robots

View on GitHub
src/Robot/AccessRules.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php
namespace tomverran\Robot;


class AccessRules
{
    private $rules;

    /**
     * @param string[] $rules A map of path => allowed
     */
    public function __construct(array $rules)
    {
        uksort($rules, function($r1, $r2) {
            return strlen($r2) - strlen($r1);
        });
        $this->rules = $rules;
    }

    private function convertPathToRegex($path) {
        $pathWithoutTrailingDollar = rtrim($path, '$');

        $quotedWithWildcards = implode('.*?', array_map(function($input) {
            return preg_quote($input, '#');
        }, explode('*', $pathWithoutTrailingDollar)));

        $trailingDollar = $path == $pathWithoutTrailingDollar ? '' : '$';
        return "#^${quotedWithWildcards}{$trailingDollar}#";
    }

    private function urlDecodeNonSlashes($str)
    {
        return implode('', array_map(function($input) {
            return strtolower($input) == '%2f' ? $input : urldecode($input);
        }, preg_split('/(%2F)/i', $str, -1, PREG_SPLIT_DELIM_CAPTURE)));
    }

    public function isAllowed($url)
    {
        $matches = [];
        foreach($this->rules as $ruleUrl => $allowed) {
            if ($ruleUrl && preg_match($this->convertPathToRegex($this->urlDecodeNonSlashes($ruleUrl)), $this->urlDecodeNonSlashes($url))) {
                $matches[$ruleUrl] = $allowed;
            }
        }
        return empty($matches) || array_shift($matches);
    }
}