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