4
* This file is part of the Nette Framework (http://nette.org)
6
* Copyright (c) 2004 David Grudl (http://davidgrudl.com)
8
* For the full copyright and license information, please view
9
* the file license.txt that was distributed with this source code.
12
namespace Nette\Application;
18
* Default presenter loader.
22
class PresenterFactory extends Nette\Object implements IPresenterFactory
25
public $caseSensitive = FALSE;
31
private $cache = array();
33
/** @var Nette\DI\Container */
40
public function __construct($baseDir, Nette\DI\Container $container)
42
$this->baseDir = $baseDir;
43
$this->container = $container;
48
* Creates new presenter instance.
49
* @param string presenter name
52
public function createPresenter($name)
54
$presenter = $this->container->createInstance($this->getPresenterClass($name));
55
if (method_exists($presenter, 'setContext')) {
56
$this->container->callMethod(array($presenter, 'setContext'));
58
foreach (array_reverse(get_class_methods($presenter)) as $method) {
59
if (substr($method, 0, 6) === 'inject') {
60
$this->container->callMethod(array($presenter, $method));
64
if ($presenter instanceof UI\Presenter && $presenter->invalidLinkMode === NULL) {
65
$presenter->invalidLinkMode = $this->container->parameters['debugMode'] ? UI\Presenter::INVALID_LINK_WARNING : UI\Presenter::INVALID_LINK_SILENT;
72
* Generates and checks presenter class name.
73
* @param string presenter name
74
* @return string class name
75
* @throws InvalidPresenterException
77
public function getPresenterClass(& $name)
79
if (isset($this->cache[$name])) {
80
list($class, $name) = $this->cache[$name];
84
if (!is_string($name) || !Nette\Utils\Strings::match($name, '#^[a-zA-Z\x7f-\xff][a-zA-Z0-9\x7f-\xff:]*\z#')) {
85
throw new InvalidPresenterException("Presenter name must be alphanumeric string, '$name' is invalid.");
88
$class = $this->formatPresenterClass($name);
90
if (!class_exists($class)) {
91
// internal autoloading
92
$file = $this->formatPresenterFile($name);
93
if (is_file($file) && is_readable($file)) {
94
Nette\Utils\LimitedScope::load($file, TRUE);
97
if (!class_exists($class)) {
98
throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' was not found in '$file'.");
102
$reflection = new Nette\Reflection\ClassType($class);
103
$class = $reflection->getName();
105
if (!$reflection->implementsInterface('Nette\Application\IPresenter')) {
106
throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is not Nette\\Application\\IPresenter implementor.");
109
if ($reflection->isAbstract()) {
110
throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is abstract.");
113
// canonicalize presenter name
114
$realName = $this->unformatPresenterClass($class);
115
if ($name !== $realName) {
116
if ($this->caseSensitive) {
117
throw new InvalidPresenterException("Cannot load presenter '$name', case mismatch. Real name is '$realName'.");
119
$this->cache[$name] = array($class, $realName);
123
$this->cache[$name] = array($class, $realName);
131
* Formats presenter class name from its name.
135
public function formatPresenterClass($presenter)
137
return str_replace(':', 'Module\\', $presenter) . 'Presenter';
142
* Formats presenter name from class name.
146
public function unformatPresenterClass($class)
148
return str_replace('Module\\', ':', substr($class, 0, -9));
153
* Formats presenter class file name.
157
public function formatPresenterFile($presenter)
159
$path = '/' . str_replace(':', 'Module/', $presenter);
160
return $this->baseDir . substr_replace($path, '/presenters', strrpos($path, '/'), 0) . 'Presenter.php';