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