1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Application;
13:
14: use Nette;
15:
16:
17: 18: 19: 20: 21:
22: class PresenterFactory extends Nette\Object implements IPresenterFactory
23: {
24:
25: public $caseSensitive = FALSE;
26:
27:
28: private $baseDir;
29:
30:
31: private $cache = array();
32:
33:
34: private $container;
35:
36:
37: 38: 39:
40: public function __construct($baseDir, Nette\DI\Container $container)
41: {
42: $this->baseDir = $baseDir;
43: $this->container = $container;
44: }
45:
46:
47: 48: 49: 50: 51:
52: public function createPresenter($name)
53: {
54: $presenter = $this->container->createInstance($this->getPresenterClass($name));
55: if (method_exists($presenter, 'setContext')) {
56: $this->container->callMethod(array($presenter, 'setContext'));
57: }
58: foreach (array_reverse(get_class_methods($presenter)) as $method) {
59: if (substr($method, 0, 6) === 'inject') {
60: $this->container->callMethod(array($presenter, $method));
61: }
62: }
63:
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;
66: }
67: return $presenter;
68: }
69:
70:
71: 72: 73: 74: 75: 76:
77: public function getPresenterClass(& $name)
78: {
79: if (isset($this->cache[$name])) {
80: list($class, $name) = $this->cache[$name];
81: return $class;
82: }
83:
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.");
86: }
87:
88: $class = $this->formatPresenterClass($name);
89:
90: if (!class_exists($class)) {
91:
92: $file = $this->formatPresenterFile($name);
93: if (is_file($file) && is_readable($file)) {
94: Nette\Utils\LimitedScope::load($file, TRUE);
95: }
96:
97: if (!class_exists($class)) {
98: throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' was not found in '$file'.");
99: }
100: }
101:
102: $reflection = new Nette\Reflection\ClassType($class);
103: $class = $reflection->getName();
104:
105: if (!$reflection->implementsInterface('Nette\Application\IPresenter')) {
106: throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is not Nette\\Application\\IPresenter implementor.");
107: }
108:
109: if ($reflection->isAbstract()) {
110: throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is abstract.");
111: }
112:
113:
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'.");
118: } else {
119: $this->cache[$name] = array($class, $realName);
120: $name = $realName;
121: }
122: } else {
123: $this->cache[$name] = array($class, $realName);
124: }
125:
126: return $class;
127: }
128:
129:
130: 131: 132: 133: 134:
135: public function formatPresenterClass($presenter)
136: {
137: return str_replace(':', 'Module\\', $presenter) . 'Presenter';
138: }
139:
140:
141: 142: 143: 144: 145:
146: public function unformatPresenterClass($class)
147: {
148: return str_replace('Module\\', ':', substr($class, 0, -9));
149: }
150:
151:
152: 153: 154: 155: 156:
157: public function formatPresenterFile($presenter)
158: {
159: $path = '/' . str_replace(':', 'Module/', $presenter);
160: return $this->baseDir . substr_replace($path, '/presenters', strrpos($path, '/'), 0) . 'Presenter.php';
161: }
162:
163: }
164: