Exemple #1
0
 /**
  * @param  string  presenter name
  * @return string  class name
  * @throws InvalidPresenterException
  */
 public function getPresenterClass(&$name)
 {
     if (isset($this->cache[$name])) {
         list($class, $name) = $this->cache[$name];
         return $class;
     }
     if (!is_string($name) || !Strings::match($name, "#^[a-zA-Z-ÿ][a-zA-Z0-9-ÿ:]*\$#")) {
         throw new InvalidPresenterException("Presenter name must be alphanumeric string, '{$name}' is invalid.");
     }
     $class = $this->formatPresenterClass($name);
     if (!class_exists($class)) {
         // internal autoloading
         $file = $this->formatPresenterFile($name);
         if (is_file($file) && is_readable($file)) {
             LimitedScope::load($file, TRUE);
         }
         if (!class_exists($class)) {
             throw new InvalidPresenterException("Cannot load presenter '{$name}', class '{$class}' was not found in '{$file}'.");
         }
     }
     $reflection = new ClassReflection($class);
     $class = $reflection->getName();
     if (!$reflection->implementsInterface('IPresenter')) {
         throw new InvalidPresenterException("Cannot load presenter '{$name}', class '{$class}' is not IPresenter implementor.");
     }
     if ($reflection->isAbstract()) {
         throw new InvalidPresenterException("Cannot load presenter '{$name}', class '{$class}' is abstract.");
     }
     // canonicalize presenter name
     $realName = $this->unformatPresenterClass($class);
     if ($name !== $realName) {
         if ($this->caseSensitive) {
             throw new InvalidPresenterException("Cannot load presenter '{$name}', case mismatch. Real name is '{$realName}'.");
         } else {
             $this->cache[$name] = array($class, $realName);
             $name = $realName;
         }
     } else {
         $this->cache[$name] = array($class, $realName);
     }
     return $class;
 }
Exemple #2
0
 /**
  * Tokenize string.
  * @param  string
  * @return array
  */
 public function tokenize($input)
 {
     $this->input = $input;
     if ($this->types) {
         $this->tokens = Strings::matchAll($input, $this->re);
         $len = 0;
         $count = count($this->types);
         $line = 1;
         foreach ($this->tokens as &$match) {
             $type = NULL;
             for ($i = 1; $i <= $count; $i++) {
                 if (!isset($match[$i])) {
                     break;
                 } elseif ($match[$i] != NULL) {
                     $type = $this->types[$i - 1];
                     break;
                 }
             }
             $match = self::createToken($match[0], $type, $line);
             $len += strlen($match['value']);
             $line += substr_count($match['value'], "\n");
         }
         if ($len !== strlen($input)) {
             $errorOffset = $len;
         }
     } else {
         $this->tokens = Strings::split($input, $this->re, PREG_SPLIT_NO_EMPTY);
         if ($this->tokens && !Strings::match(end($this->tokens), $this->re)) {
             $tmp = Strings::split($this->input, $this->re, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
             list(, $errorOffset) = end($tmp);
         }
     }
     if (isset($errorOffset)) {
         $line = $errorOffset ? substr_count($this->input, "\n", 0, $errorOffset) + 1 : 1;
         $col = $errorOffset - strrpos(substr($this->input, 0, $errorOffset), "\n") + 1;
         $token = str_replace("\n", '\\n', substr($input, $errorOffset, 10));
         throw new TokenizerException("Unexpected '{$token}' on line {$line}, column {$col}.");
     }
     return $this->tokens;
 }
Exemple #3
0
    /**
     * Parses macro tag to name, arguments a modifiers parts.
     * @param  string {name arguments | modifiers}
     * @return array
     */
    public function parseMacroTag($tag)
    {
        $match = Strings::match($tag, '~^
			(
				(?P<name>\\?|/?[a-z]\\w*+(?:[.:]\\w+)*+(?!::|\\())|   ## ?, name, /name, but not function( or class::
				(?P<noescape>!?)(?P<shortname>/?[=\\~#%^&_]?)      ## !expression, !=expression, ...
			)(?P<args>.*?)
			(?P<modifiers>\\|[a-z](?:' . Parser::RE_STRING . '|[^\'"])*)?
		()$~isx');
        if (!$match) {
            return FALSE;
        }
        if ($match['name'] === '') {
            $match['name'] = ($tmp = $match['shortname']) ? $tmp : '=';
            if (!$match['noescape'] && substr($match['shortname'], 0, 1) !== '/') {
                $match['modifiers'] .= '|escape';
            }
        }
        return array($match['name'], trim($match['args']), $match['modifiers']);
    }
    /**
     * Parses phpDoc comment.
     * @param  string
     * @return array
     */
    private static function parseComment($comment)
    {
        static $tokens = array('true' => TRUE, 'false' => FALSE, 'null' => NULL, '' => TRUE);
        $res = array();
        $comment = preg_replace('#^\\s*\\*\\s?#ms', '', trim($comment, '/*'));
        $parts = preg_split('#^\\s*(?=@' . self::RE_IDENTIFIER . ')#m', $comment, 2);
        $description = trim($parts[0]);
        if ($description !== '') {
            $res['description'] = array($description);
        }
        $matches = XApp_Utils_Strings::matchAll(isset($parts[1]) ? $parts[1] : '', '~
				(?<=\\s|^)@(' . self::RE_IDENTIFIER . ')[ \\t]*      ##  annotation
				(
					\\((?>' . self::RE_STRING . '|[^\'")@]+)+\\)|  ##  (value)
					[^(@\\r\\n][^@\\r\\n]*|)                     ##  value
			~xi');
        foreach ($matches as $match) {
            list(, $name, $value) = $match;
            if (substr($value, 0, 1) === '(') {
                $items = array();
                $key = '';
                $val = TRUE;
                $value[0] = ',';
                while ($m = Strings::match($value, '#\\s*,\\s*(?>(' . self::RE_IDENTIFIER . ')\\s*=\\s*)?(' . self::RE_STRING . '|[^\'"),\\s][^\'"),]*)#A')) {
                    $value = substr($value, strlen($m[0]));
                    list(, $key, $val) = $m;
                    $val = rtrim($val);
                    if ($val[0] === "'" || $val[0] === '"') {
                        $val = substr($val, 1, -1);
                    } elseif (is_numeric($val)) {
                        $val = 1 * $val;
                    } else {
                        $lval = strtolower($val);
                        $val = array_key_exists($lval, $tokens) ? $tokens[$lval] : $val;
                    }
                    if ($key === '') {
                        $items[] = $val;
                    } else {
                        $items[$key] = $val;
                    }
                }
                $value = count($items) < 2 && $key === '' ? $val : $items;
            } else {
                $value = trim($value);
                if (is_numeric($value)) {
                    $value = 1 * $value;
                } else {
                    $lval = strtolower($value);
                    $value = array_key_exists($lval, $tokens) ? $tokens[$lval] : $value;
                }
            }
            $class = $name . 'Annotation';
            if (class_exists($class)) {
                $res[$name][] = new $class(is_array($value) ? $value : array('value' => $value));
            } else {
                $res[$name][] = is_array($value) ? Nette\ArrayHash::from($value) : $value;
            }
        }
        return $res;
    }
Exemple #5
0
 /**
  * Maps HTTP request to a Request object.
  * @return PresenterRequest|NULL
  */
 public function match(IHttpRequest $httpRequest)
 {
     // combine with precedence: mask (params in URL-path), fixity, query, (post,) defaults
     // 1) URL MASK
     $url = $httpRequest->getUrl();
     if ($this->type === self::HOST) {
         $path = '//' . $url->getHost() . $url->getPath();
     } elseif ($this->type === self::RELATIVE) {
         $basePath = $url->getBasePath();
         if (strncmp($url->getPath(), $basePath, strlen($basePath)) !== 0) {
             return NULL;
         }
         $path = (string) substr($url->getPath(), strlen($basePath));
     } else {
         $path = $url->getPath();
     }
     if ($path !== '') {
         $path = rtrim($path, '/') . '/';
     }
     if (!($matches = Strings::match($path, $this->re))) {
         // stop, not matched
         return NULL;
     }
     // deletes numeric keys, restore '-' chars
     $params = array();
     foreach ($matches as $k => $v) {
         if (is_string($k) && $v !== '') {
             $params[str_replace('___', '-', $k)] = $v;
             // trick
         }
     }
     // 2) CONSTANT FIXITY
     foreach ($this->metadata as $name => $meta) {
         if (isset($params[$name])) {
             //$params[$name] = $this->flags & self::CASE_SENSITIVE === 0 ? strtolower($params[$name]) : */$params[$name]; // strtolower damages UTF-8
         } elseif (isset($meta['fixity']) && $meta['fixity'] !== self::OPTIONAL) {
             $params[$name] = NULL;
             // cannot be overwriten in 3) and detected by isset() in 4)
         }
     }
     // 3) QUERY
     if ($this->xlat) {
         $params += self::renameKeys($httpRequest->getQuery(), array_flip($this->xlat));
     } else {
         $params += $httpRequest->getQuery();
     }
     // 4) APPLY FILTERS & FIXITY
     foreach ($this->metadata as $name => $meta) {
         if (isset($params[$name])) {
             if (!is_scalar($params[$name])) {
             } elseif (isset($meta[self::FILTER_TABLE][$params[$name]])) {
                 // applies filterTable only to scalar parameters
                 $params[$name] = $meta[self::FILTER_TABLE][$params[$name]];
             } elseif (isset($meta[self::FILTER_TABLE]) && !empty($meta[self::FILTER_STRICT])) {
                 return NULL;
                 // rejected by filterTable
             } elseif (isset($meta[self::FILTER_IN])) {
                 // applies filterIn only to scalar parameters
                 $params[$name] = call_user_func($meta[self::FILTER_IN], (string) $params[$name]);
                 if ($params[$name] === NULL && !isset($meta['fixity'])) {
                     return NULL;
                     // rejected by filter
                 }
             }
         } elseif (isset($meta['fixity'])) {
             $params[$name] = $meta[self::VALUE];
         }
     }
     // 5) BUILD Request
     if (!isset($params[self::PRESENTER_KEY])) {
         throw new InvalidStateException('Missing presenter in route definition.');
     }
     if (isset($this->metadata[self::MODULE_KEY])) {
         if (!isset($params[self::MODULE_KEY])) {
             throw new InvalidStateException('Missing module in route definition.');
         }
         $presenter = $params[self::MODULE_KEY] . ':' . $params[self::PRESENTER_KEY];
         unset($params[self::MODULE_KEY], $params[self::PRESENTER_KEY]);
     } else {
         $presenter = $params[self::PRESENTER_KEY];
         unset($params[self::PRESENTER_KEY]);
     }
     return new PresenterRequest($presenter, $httpRequest->getMethod(), $params, $httpRequest->getPost(), $httpRequest->getFiles(), array(PresenterRequest::SECURED => $httpRequest->isSecured()));
 }
 /**
  * Parses PHP file.
  * @param  string
  * @return void
  */
 private static function parseScript($file)
 {
     $T_NAMESPACE = PHP_VERSION_ID < 50300 ? -1 : T_NAMESPACE;
     $T_NS_SEPARATOR = PHP_VERSION_ID < 50300 ? -1 : T_NS_SEPARATOR;
     $s = file_get_contents($file);
     if (Strings::match($s, '#//nette' . 'loader=(\\S*)#')) {
         return;
         // TODO: allways ignore?
     }
     $expected = $namespace = $class = $docComment = NULL;
     $level = $classLevel = 0;
     foreach (token_get_all($s) as $token) {
         if (is_array($token)) {
             switch ($token[0]) {
                 case T_DOC_COMMENT:
                     $docComment = $token[1];
                 case T_WHITESPACE:
                 case T_COMMENT:
                     continue 2;
                 case T_STRING:
                 case $T_NS_SEPARATOR:
                 case T_VARIABLE:
                     if ($expected) {
                         $name .= $token[1];
                     }
                     continue 2;
                 case T_FUNCTION:
                 case T_VAR:
                 case T_PUBLIC:
                 case T_PROTECTED:
                 case $T_NAMESPACE:
                 case T_CLASS:
                 case T_INTERFACE:
                     $expected = $token[0];
                     $name = NULL;
                     continue 2;
                 case T_STATIC:
                 case T_ABSTRACT:
                 case T_FINAL:
                     continue 2;
                     // ignore in expectation
                 // ignore in expectation
                 case T_CURLY_OPEN:
                 case T_DOLLAR_OPEN_CURLY_BRACES:
                     $level++;
             }
         }
         if ($expected) {
             switch ($expected) {
                 case T_CLASS:
                 case T_INTERFACE:
                     $class = $namespace . $name;
                     $classLevel = $level;
                     $name = '';
                     // break intentionally omitted
                 // break intentionally omitted
                 case T_FUNCTION:
                     if ($token === '&') {
                         continue 2;
                         // ignore
                     }
                 case T_VAR:
                 case T_PUBLIC:
                 case T_PROTECTED:
                     if ($class && $name !== NULL && $docComment) {
                         self::$cache[$class][$name] = self::parseComment($docComment);
                     }
                     break;
                 case $T_NAMESPACE:
                     $namespace = $name . '\\';
             }
             $expected = $docComment = NULL;
         }
         if ($token === ';') {
             $docComment = NULL;
         } elseif ($token === '{') {
             $docComment = NULL;
             $level++;
         } elseif ($token === '}') {
             $level--;
             if ($level === $classLevel) {
                 $class = NULL;
             }
         }
     }
 }
Exemple #7
0
 /**
  * {control name[:method] [params]}
  */
 public function macroControl(MacroNode $node, PhpWriter $writer)
 {
     $pair = $node->tokenizer->fetchWord();
     if ($pair === FALSE) {
         throw new CompileException("Missing control name in {control}");
     }
     $pair = explode(':', $pair, 2);
     $name = $writer->formatWord($pair[0]);
     $method = isset($pair[1]) ? ucfirst($pair[1]) : '';
     $method = Strings::match($method, '#^\\w*$#') ? "render{$method}" : "{\"render{$method}\"}";
     $param = $writer->formatArray();
     if (!Strings::contains($node->args, '=>')) {
         $param = substr($param, 6, -1);
         // removes array()
     }
     return ($name[0] === '$' ? "if (is_object({$name})) \$_ctrl = {$name}; else " : '') . '$_ctrl = $_control->getComponent(' . $name . '); ' . 'if ($_ctrl instanceof IRenderable) $_ctrl->validateControl(); ' . "\$_ctrl->{$method}({$param})";
 }
Exemple #8
0
 /**
  * Changes current action. Only alphanumeric characters are allowed.
  * @param  string
  * @return void
  */
 public function changeAction($action)
 {
     if (is_string($action) && Strings::match($action, '#^[a-zA-Z0-9][a-zA-Z0-9_\\x7f-\\xff]*$#')) {
         $this->action = $action;
         $this->view = $action;
     } else {
         $this->error('Action name is not alphanumeric string.');
     }
 }
Exemple #9
0
 /**
  * Regular expression validator: matches control's value regular expression?
  * @param  TextBase
  * @param  string
  * @return bool
  */
 public static function validatePattern(TextBase $control, $pattern)
 {
     return (bool) Strings::match($control->getValue(), "^({$pattern})\$u");
 }
Exemple #10
0
 /**
  * Builds HTML content.
  * @return void
  */
 protected function buildHtml()
 {
     if ($this->html instanceof ITemplate) {
         $this->html->mail = $this;
         if ($this->basePath === NULL && $this->html instanceof IFileTemplate) {
             $this->basePath = dirname($this->html->getFile());
         }
         $this->html = $this->html->__toString(TRUE);
     }
     if ($this->basePath !== FALSE) {
         $cids = array();
         $matches = Strings::matchAll($this->html, '#(src\\s*=\\s*|background\\s*=\\s*|url\\()(["\'])(?![a-z]+:|[/\\#])(.+?)\\2#i', PREG_OFFSET_CAPTURE);
         foreach (array_reverse($matches) as $m) {
             $file = rtrim($this->basePath, '/\\') . '/' . $m[3][0];
             if (!isset($cids[$file])) {
                 $cids[$file] = substr($this->addEmbeddedFile($file)->getHeader("Content-ID"), 1, -1);
             }
             $this->html = substr_replace($this->html, "{$m[1][0]}{$m[2][0]}cid:{$cids[$file]}{$m[2][0]}", $m[0][1], strlen($m[0][0]));
         }
     }
     if (!$this->getSubject() && ($matches = Strings::match($this->html, '#<title>(.+?)</title>#is'))) {
         $this->setSubject(html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'));
     }
 }