Nette\Application\Routers\Route::setMask PHP Method

setMask() private method

Parse mask and array of default values; initializes object.
private setMask ( $mask, array $metadata ) : void
$metadata array
return void
    private function setMask($mask, array $metadata)
    {
        $this->mask = $mask;
        // detect '//host/path' vs. '/abs. path' vs. 'relative path'
        if (preg_match('#(?:(https?):)?(//.*)#A', $mask, $m)) {
            $this->type = self::HOST;
            list(, $this->scheme, $mask) = $m;
        } elseif (substr($mask, 0, 1) === '/') {
            $this->type = self::PATH;
        } else {
            $this->type = self::RELATIVE;
        }
        foreach ($metadata as $name => $meta) {
            if (!is_array($meta)) {
                $metadata[$name] = $meta = [self::VALUE => $meta];
            }
            if (array_key_exists(self::VALUE, $meta)) {
                if (is_scalar($meta[self::VALUE])) {
                    $metadata[$name][self::VALUE] = (string) $meta[self::VALUE];
                }
                $metadata[$name]['fixity'] = self::CONSTANT;
            }
        }
        if (strpbrk($mask, '?<>[]') === FALSE) {
            $this->re = '#' . preg_quote($mask, '#') . '/?\\z#A';
            $this->sequence = [$mask];
            $this->metadata = $metadata;
            return;
        }
        // PARSE MASK
        // <parameter-name[=default] [pattern]> or [ or ] or ?...
        $parts = Strings::split($mask, '/<([^<>= ]+)(=[^<> ]*)? *([^<>]*)>|(\\[!?|\\]|\\s*\\?.*)/');
        $this->xlat = [];
        $i = count($parts) - 1;
        // PARSE QUERY PART OF MASK
        if (isset($parts[$i - 1]) && substr(ltrim($parts[$i - 1]), 0, 1) === '?') {
            // name=<parameter-name [pattern]>
            $matches = Strings::matchAll($parts[$i - 1], '/(?:([a-zA-Z0-9_.-]+)=)?<([^> ]+) *([^>]*)>/');
            foreach ($matches as list(, $param, $name, $pattern)) {
                // $pattern is not used
                if (isset(static::$styles['?' . $name])) {
                    $meta = static::$styles['?' . $name];
                } else {
                    $meta = static::$styles['?#'];
                }
                if (isset($metadata[$name])) {
                    $meta = $metadata[$name] + $meta;
                }
                if (array_key_exists(self::VALUE, $meta)) {
                    $meta['fixity'] = self::OPTIONAL;
                }
                unset($meta['pattern']);
                $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]);
                $metadata[$name] = $meta;
                if ($param !== '') {
                    $this->xlat[$name] = $param;
                }
            }
            $i -= 5;
        }
        // PARSE PATH PART OF MASK
        $brackets = 0;
        // optional level
        $re = '';
        $sequence = [];
        $autoOptional = TRUE;
        $aliases = [];
        do {
            $part = $parts[$i];
            // part of path
            if (strpbrk($part, '<>') !== FALSE) {
                throw new Nette\InvalidArgumentException("Unexpected '{$part}' in mask '{$mask}'.");
            }
            array_unshift($sequence, $part);
            $re = preg_quote($part, '#') . $re;
            if ($i === 0) {
                break;
            }
            $i--;
            $part = $parts[$i];
            // [ or ]
            if ($part === '[' || $part === ']' || $part === '[!') {
                $brackets += $part[0] === '[' ? -1 : 1;
                if ($brackets < 0) {
                    throw new Nette\InvalidArgumentException("Unexpected '{$part}' in mask '{$mask}'.");
                }
                array_unshift($sequence, $part);
                $re = ($part[0] === '[' ? '(?:' : ')?') . $re;
                $i -= 4;
                continue;
            }
            $pattern = trim($parts[$i]);
            $i--;
            // validation condition (as regexp)
            $default = $parts[$i];
            $i--;
            // default value
            $name = $parts[$i];
            $i--;
            // parameter name
            array_unshift($sequence, $name);
            if ($name[0] === '?') {
                // "foo" parameter
                $name = substr($name, 1);
                $re = $pattern ? '(?:' . preg_quote($name, '#') . "|{$pattern}){$re}" : preg_quote($name, '#') . $re;
                $sequence[1] = $name . $sequence[1];
                continue;
            }
            // pattern, condition & metadata
            if (isset(static::$styles[$name])) {
                $meta = static::$styles[$name];
            } else {
                $meta = static::$styles['#'];
            }
            if (isset($metadata[$name])) {
                $meta = $metadata[$name] + $meta;
            }
            if ($pattern == '' && isset($meta[self::PATTERN])) {
                $pattern = $meta[self::PATTERN];
            }
            if ($default !== '') {
                $meta[self::VALUE] = (string) substr($default, 1);
                $meta['fixity'] = self::PATH_OPTIONAL;
            }
            $meta['filterTable2'] = empty($meta[self::FILTER_TABLE]) ? NULL : array_flip($meta[self::FILTER_TABLE]);
            if (array_key_exists(self::VALUE, $meta)) {
                if (isset($meta['filterTable2'][$meta[self::VALUE]])) {
                    $meta['defOut'] = $meta['filterTable2'][$meta[self::VALUE]];
                } elseif (isset($meta[self::FILTER_OUT])) {
                    $meta['defOut'] = call_user_func($meta[self::FILTER_OUT], $meta[self::VALUE]);
                } else {
                    $meta['defOut'] = $meta[self::VALUE];
                }
            }
            $meta[self::PATTERN] = "#(?:{$pattern})\\z#A";
            // include in expression
            $aliases['p' . $i] = $name;
            $re = '(?P<p' . $i . '>(?U)' . $pattern . ')' . $re;
            if ($brackets) {
                // is in brackets?
                if (!isset($meta[self::VALUE])) {
                    $meta[self::VALUE] = $meta['defOut'] = NULL;
                }
                $meta['fixity'] = self::PATH_OPTIONAL;
            } elseif (!$autoOptional) {
                unset($meta['fixity']);
            } elseif (isset($meta['fixity'])) {
                // auto-optional
                $re = '(?:' . $re . ')?';
                $meta['fixity'] = self::PATH_OPTIONAL;
            } else {
                $autoOptional = FALSE;
            }
            $metadata[$name] = $meta;
        } while (TRUE);
        if ($brackets) {
            throw new Nette\InvalidArgumentException("Missing '[' in mask '{$mask}'.");
        }
        $this->aliases = $aliases;
        $this->re = '#' . $re . '/?\\z#A';
        $this->metadata = $metadata;
        $this->sequence = $sequence;
    }