patterns = array_map('strtolower', $data_group ? array_merge(self::ALWAYS, self::DATA_ONLY) : self::ALWAYS); $this->top = array_map('strtolower', $top_level); $this->top_patterns = array_map('strtolower', $top_patterns); foreach ($user as $rule) { $rule = strtolower(trim((string) $rule, " \t/")); if ($rule !== '' && $rule[0] === '!') { $rule = ltrim(substr($rule, 1), '/'); if ($rule !== '') { $this->include[] = $rule; } } elseif ($rule !== '') { $this->user[] = $rule; } } $this->prefix = strtolower($prefix); } public function excluded(string $rel): bool { $rel = strtolower($rel); $segments = explode('/', $rel); if (in_array($segments[0], $this->top, true)) { return true; } foreach ($this->top_patterns as $pattern) { if (fnmatch($pattern, $segments[0])) { return true; } } $path = $this->prefix . $rel; foreach ($this->include as $rule) { if (self::matches($rule, $path, $segments)) { return false; } } foreach ($segments as $segment) { foreach ($this->patterns as $pattern) { if (fnmatch($pattern, $segment)) { return true; } } } foreach ($this->user as $rule) { if (self::matches($rule, $path, $segments)) { return true; } } return false; } private static function matches(string $rule, string $path, array $segments): bool { if (strpos($rule, '/') !== false) { return fnmatch($rule, $path) || fnmatch($rule . '/*', $path); } foreach ($segments as $segment) { if (fnmatch($rule, $segment)) { return true; } } return false; } }