Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • Application
  • Helpers
  • LinkGenerator
  • PresenterFactory
  • Request

Interfaces

  • IPresenter
  • IPresenterFactory
  • IResponse
  • IRouter

Exceptions

  • AbortException
  • ApplicationException
  • BadRequestException
  • ForbiddenRequestException
  • InvalidPresenterException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Application;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * Default presenter loader.
 15:  */
 16: class PresenterFactory implements IPresenterFactory
 17: {
 18:     use Nette\SmartObject;
 19: 
 20:     /** @var array[] of module => splited mask */
 21:     private $mapping = [
 22:         '*' => ['', '*Module\\', '*Presenter'],
 23:         'Nette' => ['NetteModule\\', '*\\', '*Presenter'],
 24:     ];
 25: 
 26:     /** @var array */
 27:     private $cache = [];
 28: 
 29:     /** @var callable */
 30:     private $factory;
 31: 
 32: 
 33:     /**
 34:      * @param  callable  function (string $class): IPresenter
 35:      */
 36:     public function __construct(callable $factory = null)
 37:     {
 38:         $this->factory = $factory ?: function ($class) { return new $class; };
 39:     }
 40: 
 41: 
 42:     /**
 43:      * Creates new presenter instance.
 44:      * @param  string  presenter name
 45:      * @return IPresenter
 46:      */
 47:     public function createPresenter($name)
 48:     {
 49:         return call_user_func($this->factory, $this->getPresenterClass($name));
 50:     }
 51: 
 52: 
 53:     /**
 54:      * Generates and checks presenter class name.
 55:      * @param  string  presenter name
 56:      * @return string  class name
 57:      * @throws InvalidPresenterException
 58:      */
 59:     public function getPresenterClass(&$name)
 60:     {
 61:         if (isset($this->cache[$name])) {
 62:             return $this->cache[$name];
 63:         }
 64: 
 65:         if (!is_string($name) || !Nette\Utils\Strings::match($name, '#^[a-zA-Z\x7f-\xff][a-zA-Z0-9\x7f-\xff:]*\z#')) {
 66:             throw new InvalidPresenterException("Presenter name must be alphanumeric string, '$name' is invalid.");
 67:         }
 68: 
 69:         $class = $this->formatPresenterClass($name);
 70:         if (!class_exists($class)) {
 71:             throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' was not found.");
 72:         }
 73: 
 74:         $reflection = new \ReflectionClass($class);
 75:         $class = $reflection->getName();
 76: 
 77:         if (!$reflection->implementsInterface(IPresenter::class)) {
 78:             throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is not Nette\\Application\\IPresenter implementor.");
 79:         } elseif ($reflection->isAbstract()) {
 80:             throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is abstract.");
 81:         }
 82: 
 83:         $this->cache[$name] = $class;
 84: 
 85:         if ($name !== ($realName = $this->unformatPresenterClass($class))) {
 86:             trigger_error("Case mismatch on presenter name '$name', correct name is '$realName'.", E_USER_WARNING);
 87:             $name = $realName;
 88:         }
 89: 
 90:         return $class;
 91:     }
 92: 
 93: 
 94:     /**
 95:      * Sets mapping as pairs [module => mask]
 96:      * @return static
 97:      */
 98:     public function setMapping(array $mapping)
 99:     {
100:         foreach ($mapping as $module => $mask) {
101:             if (is_string($mask)) {
102:                 if (!preg_match('#^\\\\?([\w\\\\]*\\\\)?(\w*\*\w*?\\\\)?([\w\\\\]*\*\w*)\z#', $mask, $m)) {
103:                     throw new Nette\InvalidStateException("Invalid mapping mask '$mask'.");
104:                 }
105:                 $this->mapping[$module] = [$m[1], $m[2] ?: '*Module\\', $m[3]];
106:             } elseif (is_array($mask) && count($mask) === 3) {
107:                 $this->mapping[$module] = [$mask[0] ? $mask[0] . '\\' : '', $mask[1] . '\\', $mask[2]];
108:             } else {
109:                 throw new Nette\InvalidStateException("Invalid mapping mask for module $module.");
110:             }
111:         }
112:         return $this;
113:     }
114: 
115: 
116:     /**
117:      * Formats presenter class name from its name.
118:      * @param  string
119:      * @return string
120:      * @internal
121:      */
122:     public function formatPresenterClass($presenter)
123:     {
124:         $parts = explode(':', $presenter);
125:         $mapping = isset($parts[1], $this->mapping[$parts[0]])
126:             ? $this->mapping[array_shift($parts)]
127:             : $this->mapping['*'];
128: 
129:         while ($part = array_shift($parts)) {
130:             $mapping[0] .= str_replace('*', $part, $mapping[$parts ? 1 : 2]);
131:         }
132:         return $mapping[0];
133:     }
134: 
135: 
136:     /**
137:      * Formats presenter name from class name.
138:      * @param  string
139:      * @return string|null
140:      * @internal
141:      */
142:     public function unformatPresenterClass($class)
143:     {
144:         foreach ($this->mapping as $module => $mapping) {
145:             $mapping = str_replace(['\\', '*'], ['\\\\', '(\w+)'], $mapping);
146:             if (preg_match("#^\\\\?$mapping[0]((?:$mapping[1])*)$mapping[2]\\z#i", $class, $matches)) {
147:                 return ($module === '*' ? '' : $module . ':')
148:                     . preg_replace("#$mapping[1]#iA", '$1:', $matches[1]) . $matches[3];
149:             }
150:         }
151:         return null;
152:     }
153: }
154: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0