<commit_before><?php

namespace Gatekeeper\Endpoints;

use Site;
use Cache;
use ActiveRecord;
use HandleBehavior;
use RecordValidator;
use TableNotFoundException;
use Gatekeeper\Gatekeeper;
use Gatekeeper\Metrics\Metrics;
use Symfony\Component\Yaml\Yaml;

class Endpoint extends ActiveRecord
{
    public static $metricTTL = 60;
    protected $_metricsCache = [
        'counters' => [],
        'averages' => []
    ];
    public static $validPathRegex = '/^[a-zA-Z][a-zA-Z0-9_\\-]*(\\/[a-zA-Z][a-zA-Z0-9_\\-]*)*$/';

    // ActiveRecord configuration
    public static $tableName = 'endpoints';
    public static $singularNoun = 'endpoint';
    public static $pluralNoun = 'endpoints';
    public static $collectionRoute = '/endpoints';
    public static $useCache = true;

    public static $fields = [
        'Title',
        'Handle' => [
            'unique' => true
        ],
        'Path' => [
            'unique' => true
        ],
        'InternalEndpoint',
        'AdminName' => [
            'notnull' => false
        ],
        'AdminEmail' => [
            'notnull' => false
        ],
        'Public' => [
            'type' => 'boolean',
            'default' => false
        ],
        'DeprecationDate' => [
            'type' => 'timestamp',
            'notnull' => false
        ],
        'GlobalRateCount' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'GlobalRatePeriod' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'UserRateCount' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'UserRatePeriod' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'GlobalBandwidthCount' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'GlobalBandwidthPeriod' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'KeyRequired' => [
            'type' => 'boolean',
            'default' => false
        ],
        'CachingEnabled' => [
            'type' => 'boolean',
            'default' => true
        ],
        'AlertOnError' => [
            'type' => 'boolean',
            'default' => true
        ],
        'AlertNearMaxRequests' => [
            'type' => 'decimal',
            'length' => '3,2',
            'notnull' => false
        ],
        'PingFrequency' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'PingURI' => [
            'type' => 'string',
            'notnull' => false
        ],
        'PingTestPattern' => [
            'type' => 'string',
            'notnull' => false
        ]
    ];

    public static $relationships = [
        'Rewrites' => [
            'type' => 'one-many',
            'class' => EndpointRewrite::class,
            'order' => 'Priority'
        ]
    ];

    public static $validators = [
        'Title' => [
            'minlength' => 2
        ],
        'Path' => [
            'required' => true,
            'validator' => [__CLASS__, 'validatePath']
        ],
        'InternalEndpoint' => 'URL',
        'AdminEmail' => [
            'validator' => 'email',
            'required' => false
        ],
        'DeprecationDate' => [
            'validator' => 'datetime',
            'required' => false
        ],
        'GlobalRateCount' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ],
        'GlobalRatePeriod' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ],
        'UserRateCount' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ],
        'UserRatePeriod' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ]
    ];

    public static function getFromPath($path)
    {
        // get sorted list of paths (longest to shortest)
        if (false == ($endpointPaths = Cache::fetch('endpoint-paths'))) {
            try {
                $endpointPaths = \DB::valuesTable('ID', 'Path', 'SELECT ID, Path FROM `%s` ORDER BY LENGTH(Path) DESC', static::$tableName);
            } catch(TableNotFoundException $e) {
                $endpointPaths = [];
            }

            Cache::store('endpoint-paths', $endpointPaths);
        }


        // normalize path to string without / prefix
        if (is_array($path)) {
            $path = implode('/', $path);
        }

        $path = ltrim($path, '/');


        // match longest path as prefix
        foreach ($endpointPaths AS $endpointId => $endpointPath) {
            if ($endpointPath == $path || 0 === stripos($path, $endpointPath . '/')) {
                return static::getByID($endpointId);
            }
        }<commit_msg>match root paths without case sensitivity<commit_after><?php

namespace Gatekeeper\Endpoints;

use Site;
use Cache;
use ActiveRecord;
use HandleBehavior;
use RecordValidator;
use TableNotFoundException;
use Gatekeeper\Gatekeeper;
use Gatekeeper\Metrics\Metrics;
use Symfony\Component\Yaml\Yaml;

class Endpoint extends ActiveRecord
{
    public static $metricTTL = 60;
    protected $_metricsCache = [
        'counters' => [],
        'averages' => []
    ];
    public static $validPathRegex = '/^[a-zA-Z][a-zA-Z0-9_\\-]*(\\/[a-zA-Z][a-zA-Z0-9_\\-]*)*$/';

    // ActiveRecord configuration
    public static $tableName = 'endpoints';
    public static $singularNoun = 'endpoint';
    public static $pluralNoun = 'endpoints';
    public static $collectionRoute = '/endpoints';
    public static $useCache = true;

    public static $fields = [
        'Title',
        'Handle' => [
            'unique' => true
        ],
        'Path' => [
            'unique' => true
        ],
        'InternalEndpoint',
        'AdminName' => [
            'notnull' => false
        ],
        'AdminEmail' => [
            'notnull' => false
        ],
        'Public' => [
            'type' => 'boolean',
            'default' => false
        ],
        'DeprecationDate' => [
            'type' => 'timestamp',
            'notnull' => false
        ],
        'GlobalRateCount' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'GlobalRatePeriod' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'UserRateCount' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'UserRatePeriod' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'GlobalBandwidthCount' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'GlobalBandwidthPeriod' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'KeyRequired' => [
            'type' => 'boolean',
            'default' => false
        ],
        'CachingEnabled' => [
            'type' => 'boolean',
            'default' => true
        ],
        'AlertOnError' => [
            'type' => 'boolean',
            'default' => true
        ],
        'AlertNearMaxRequests' => [
            'type' => 'decimal',
            'length' => '3,2',
            'notnull' => false
        ],
        'PingFrequency' => [
            'type' => 'uint',
            'notnull' => false
        ],
        'PingURI' => [
            'type' => 'string',
            'notnull' => false
        ],
        'PingTestPattern' => [
            'type' => 'string',
            'notnull' => false
        ]
    ];

    public static $relationships = [
        'Rewrites' => [
            'type' => 'one-many',
            'class' => EndpointRewrite::class,
            'order' => 'Priority'
        ]
    ];

    public static $validators = [
        'Title' => [
            'minlength' => 2
        ],
        'Path' => [
            'required' => true,
            'validator' => [__CLASS__, 'validatePath']
        ],
        'InternalEndpoint' => 'URL',
        'AdminEmail' => [
            'validator' => 'email',
            'required' => false
        ],
        'DeprecationDate' => [
            'validator' => 'datetime',
            'required' => false
        ],
        'GlobalRateCount' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ],
        'GlobalRatePeriod' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ],
        'UserRateCount' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ],
        'UserRatePeriod' => [
            'validator' => 'number',
            'required' => false,
            'min' => 1
        ]
    ];

    public static function getFromPath($path)
    {
        // get sorted list of paths (longest to shortest)
        if (false == ($endpointPaths = Cache::fetch('endpoint-paths'))) {
            try {
                $endpointPaths = \DB::valuesTable('ID', 'Path', 'SELECT ID, Path FROM `%s` ORDER BY LENGTH(Path) DESC', static::$tableName);
            } catch(TableNotFoundException $e) {
                $endpointPaths = [];
            }

            Cache::store('endpoint-paths', $endpointPaths);
        }


        // normalize path to string without / prefix
        if (is_array($path)) {
            $path = implode('/', $path);
        }

        $path = ltrim($path, '/');


        // match longest path as prefix
        foreach ($endpointPaths AS $endpointId => $endpointPath) {
            if (0 === strcasecmp($endpointPath, $path) || 0 === stripos($path, $endpointPath . '/')) {
                return static::getByID($endpointId);
            }
        }
{'fraction_non_alphanumeric': 0.16122448979591836, 'fraction_numerical': 0.0029591836734693877, 'mean_word_length': 1.453316645807259, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 181, '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': '6710809', 'n_tokens_mistral': 2811, 'n_tokens_neox': 2753, 'n_words': 568}