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:
23: class PresenterFactory implements IPresenterFactory
24: {
25:
26: public $caseSensitive = FALSE;
27:
28:
29: private $baseDir;
30:
31:
32: private $cache = array();
33:
34:
35: private $container;
36:
37:
38:
39: 40: 41:
42: public function __construct($baseDir, Nette\DI\Container $container)
43: {
44: $this->baseDir = $baseDir;
45: $this->container = $container;
46: }
47:
48:
49:
50: 51: 52: 53: 54:
55: public function createPresenter($name)
56: {
57: $presenter = $this->container->createInstance($this->getPresenterClass($name));
58: if (method_exists($presenter, 'setContext')) {
59: $this->container->callMethod(array($presenter, 'setContext'));
60: }
61: foreach (array_reverse(get_class_methods($presenter)) as $method) {
62: if (substr($method, 0, 6) === 'inject') {
63: $this->container->callMethod(array($presenter, $method));
64: }
65: }
66:
67: if ($presenter instanceof UI\Presenter && $presenter->invalidLinkMode === NULL) {
68: $presenter->invalidLinkMode = $this->container->parameters['debugMode'] ? UI\Presenter::INVALID_LINK_WARNING : UI\Presenter::INVALID_LINK_SILENT;
69: }
70: return $presenter;
71: }
72:
73:
74:
75: 76: 77: 78: 79:
80: public function getPresenterClass(& $name)
81: {
82: if (isset($this->cache[$name])) {
83: list($class, $name) = $this->cache[$name];
84: return $class;
85: }
86:
87: if (!is_string($name) || !Nette\Utils\Strings::match($name, "#^[a-zA-Z\x7f-\xff][a-zA-Z0-9\x7f-\xff:]*$#")) {
88: throw new InvalidPresenterException("Presenter name must be alphanumeric string, '$name' is invalid.");
89: }
90:
91: $class = $this->formatPresenterClass($name);
92:
93: if (!class_exists($class)) {
94:
95: $file = $this->formatPresenterFile($name);
96: if (is_file($file) && is_readable($file)) {
97: Nette\Utils\LimitedScope::load($file, TRUE);
98: }
99:
100: if (!class_exists($class)) {
101: throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' was not found in '$file'.");
102: }
103: }
104:
105: $reflection = new Nette\Reflection\ClassType($class);
106: $class = $reflection->getName();
107:
108: if (!$reflection->implementsInterface('Nette\Application\IPresenter')) {
109: throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is not Nette\\Application\\IPresenter implementor.");
110: }
111:
112: if ($reflection->isAbstract()) {
113: throw new InvalidPresenterException("Cannot load presenter '$name', class '$class' is abstract.");
114: }
115:
116:
117: $realName = $this->unformatPresenterClass($class);
118: if ($name !== $realName) {
119: if ($this->caseSensitive) {
120: throw new InvalidPresenterException("Cannot load presenter '$name', case mismatch. Real name is '$realName'.");
121: } else {
122: $this->cache[$name] = array($class, $realName);
123: $name = $realName;
124: }
125: } else {
126: $this->cache[$name] = array($class, $realName);
127: }
128:
129: return $class;
130: }
131:
132:
133:
134: 135: 136: 137: 138:
139: public function formatPresenterClass($presenter)
140: {
141: return str_replace(':', 'Module\\', $presenter) . 'Presenter';
142: }
143:
144:
145:
146: 147: 148: 149: 150:
151: public function unformatPresenterClass($class)
152: {
153: return str_replace('Module\\', ':', substr($class, 0, -9));
154: }
155:
156:
157:
158: 159: 160: 161: 162:
163: public function formatPresenterFile($presenter)
164: {
165: $path = '/' . str_replace(':', 'Module/', $presenter);
166: return $this->baseDir . substr_replace($path, '/presenters', strrpos($path, '/'), 0) . 'Presenter.php';
167: }
168:
169: }
170: