1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
37:
38: namespace Simpletools\Mvc;
39:
40: 41: 42:
43: class Controller extends \Simpletools\Mvc\Common
44: {
45: protected static $_instance = null;
46:
47: public function __construct($env)
48: {
49: $this->_appDir = &$env->appDir;
50: $this->_view = &$env->view;
51: $this->_autoRender = &$env->autoRender;
52: $this->_forwarded = &$env->forwarded;
53: $this->_params = &$env->params;
54: $this->_objects = &$env->objects;
55: $this->_errorCode = &$env->errorCode;
56: $this->_shifts_params = &$env->shifts_params;
57: $this->_classes = &$env->classes;
58: $this->_current_controller = &$env->current_controller;
59: $this->_404_error_header = &$env->_404_error_header;
60: $this->_view_enabled = &$env->view_enabled;
61: $this->_routingHooks = &$env->_routingHooks;
62:
63: $this->_routingNamespaces = &$env->routingNamespaces;
64: $this->_activeRoutingNamespace = &$env->activeRoutingNamespace;
65: $this->_activeRoutingNamespaceUrlPath = &$env->activeRoutingNamespaceUrlPath;
66:
67: if(empty(self::$_instance))
68: {
69: self::$_instance = &$this;
70: }
71:
72: if($this->_objects)
73: {
74: foreach($this->_objects as $objectName => &$object)
75: {
76: $this->{$objectName} = &$object;
77: }
78: }
79: }
80:
81: public static function &getInstance($empty=null)
82: {
83: if (!empty(self::$_instance))
84: {
85: return self::$_instance;
86: }
87: else
88: {
89: throw new \Exception('Asking for instance before instance has been created. This method should be use after SimpleMVC::dispatch() only',123);
90: }
91: }
92:
93: public function setCommonObject($objectName,&$obj)
94: {
95: $this->{$objectName} = $obj;
96: }
97:
98: public function render($controller,$view=null)
99: {
100: if(!$this->_view_enabled) return;
101:
102: $this->_autoRender = false;
103:
104: if($view === null)
105: {
106: $view = $controller;
107: $controller = self::getCorrectControllerName($this->getParam('controller'));
108: }
109: else if(
110: stripos($controller,'.') !== false ||
111: stripos($controller,'-') !== false ||
112: stripos($controller,' ') !== false
113: )
114: $controller = self::getCorrectControllerName($controller);
115: else
116: $controller = ucfirst($controller);
117:
118:
119: $namespace = $this->_activeRoutingNamespace;
120:
121: $n = substr($controller,0,1);
122: if($n=='\\' OR $n == '/')
123: {
124: $controller = trim(str_replace('/','\\',$controller),'\\');
125: $_path = explode('\\',$controller);
126: $controller = array_pop($_path);
127: $namespace = implode('\\',$_path);
128: }
129:
130: if($namespace)
131: {
132: $namespacePath = str_replace('\\', DIRECTORY_SEPARATOR, $namespace)."/";
133:
134: if(strtolower($view) == 'error')
135: {
136: $path = $this->_appDir.'/views/'.$namespacePath.$controller.'/'.$view.'.'.$this->_view->getViewExt();
137:
138: if(!realpath($path))
139: {
140: $namespacePath = '';
141: }
142: }
143: }
144: else
145: {
146: $namespacePath = '';
147: }
148:
149: $v = realpath($this->_appDir.'/views/'.$namespacePath.$controller.'/'.$view.'.'.$this->_view->getViewExt());
150:
151: if($v)
152: {
153: $this->_autoRender = false;
154: $this->_view->render($v);
155: }
156: else
157: {
158: if($view != 'error')
159: {
160: $this->error('v404');
161: }
162: else
163: {
164: trigger_error("<u>SimpleMVC ERROR</u> - There is a missing Error View.", E_USER_ERROR);
165: exit;
166: }
167: }
168: }
169:
170: public function error($errorCode='v404')
171: {
172: $this->_autoRender = true;
173: if($this->_404_error_header) header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
174: $this->_errorCode = $errorCode;
175:
176: $namespace = $this->_activeRoutingNamespace;
177: $path = (!$namespace) ? '' : str_replace('\\',DIRECTORY_SEPARATOR,$namespace).'/';
178: $path = $this->_appDir. '/controllers/'.$path.'ErrorController.php';
179:
180: $className = $namespace.'\ErrorController';
181:
182: if($namespace && !($_c = realpath($path)))
183: {
184: $namespace = '';
185: $path = $this->_appDir.'/controllers/ErrorController.php';
186: if(!($_c = realpath($path)))
187: {
188: trigger_error("<u>SimpleMVC ERROR</u> - Missing ErrorController.php", E_USER_ERROR);
189: }
190: else
191: {
192: $className = 'ErrorController';
193: }
194: }
195: elseif(!$namespace)
196: {
197: $className = 'ErrorController';
198: $path = $this->_appDir.'/controllers/ErrorController.php';
199:
200: if(!($_c = realpath($path)))
201: {
202: trigger_error("<u>SimpleMVC ERROR</u> - Missing ErrorController.php", E_USER_ERROR);
203: }
204: }
205:
206: $this->forward('Error','error');
207: }
208:
209: private function &_getEnv()
210: {
211: $env = new \StdClass();
212: $env->appDir = &$this->_appDir;
213: $env->view = &$this->_view;
214: $env->autoRender = &$this->_autoRender;
215: $env->forwarded = &$this->_forwarded;
216: $env->params = &$this->_params;
217: $env->objects = &$this->_objects;
218: $env->errorCode = &$this->_errorCode;
219: $env->shifts_params = &$this->_shifts_params;
220: $env->classes = &$this->_classes;
221: $env->current_controller = &$this->_current_controller;
222: $env->_404_error_header = &$this->_404_error_header;
223: $env->view_enabled = &$this->_view_enabled;
224:
225: $env->routingNamespaces = &$this->_routingNamespaces;
226: $env->activeRoutingNamespace = &$this->_activeRoutingNamespace;
227: $env->activeRoutingNamespaceUrlPath = &$this->_activeRoutingNamespaceUrlPath;
228:
229: return $env;
230: }
231:
232: public function forward($controller,$action=null,$params=false)
233: {
234: $this->_forwarded = true;
235:
236: $incontroller=$controller;
237: if($action){$inaction=$action;}
238: else
239: {
240: $inaction=$controller;
241: $incontroller=$this->getParam('controller');
242: }
243:
244: if($action === null)
245: {
246: if(
247: stripos($controller,'.') !== false ||
248: stripos($controller,'-') !== false ||
249: stripos($controller,' ') !== false
250: )
251: $controller = self::getCorrectActionName($controller);
252: else
253: $controller = lcfirst($controller);
254:
255: $action = $controller;
256: $controller = self::getCorrectControllerName($this->getParam('controller'));
257: }
258: else
259: {
260: if(
261: stripos($controller,'.') !== false ||
262: stripos($controller,'-') !== false ||
263: stripos($controller,' ') !== false
264: )
265: $controller = self::getCorrectControllerName($controller);
266: else
267: $controller = ucfirst($controller);
268:
269: if(
270: stripos($action,'.') !== false ||
271: stripos($action,'-') !== false ||
272: stripos($action,' ') !== false
273: )
274: $action = self::getCorrectActionName($action);
275: else
276: $action = lcfirst($action);
277: }
278:
279: $this->setNewParams($incontroller,$inaction,$params);
280:
281: $this->_autoRender = true;
282:
283: if($controller == 'error' || $action == 'error')
284: $this->_errorCode = 'custom error';
285:
286: $_c = false;
287:
288: $namespace = $this->_activeRoutingNamespace;
289: $orgController = $controller;
290:
291: $n = substr($controller,0,1);
292: if($n=='\\' OR $n == '/')
293: {
294: $controller = trim(str_replace('/','\\',$controller),'\\');
295: $_path = explode('\\',$controller);
296: $controller = array_pop($_path);
297: $namespace = implode('\\',$_path);
298: }
299:
300: $className = (!$namespace) ? $controller.'Controller' : $namespace."\\".$controller.'Controller';
301:
302: if($namespace && strtolower($controller) == 'error')
303: {
304: $path = str_replace('\\',DIRECTORY_SEPARATOR,$namespace).'/'.$controller.'Controller.php';
305: $path = $this->_appDir.'/controllers/'.$path;
306:
307: if(
308: !isset($this->_classes[$className]) &&
309: !($_c = realpath($path))
310: )
311: {
312: $namespace = '';
313: $className = $controller.'Controller';
314: }
315: }
316:
317: $path = (!$namespace) ? $controller.'Controller.php' : str_replace('\\',DIRECTORY_SEPARATOR,$namespace).'/'.$controller.'Controller.php';
318: $path = $this->_appDir.'/controllers/'.$path;
319:
320: if(
321: isset($this->_classes[$className]) ||
322: ($_c = realpath($path))
323: )
324: {
325: if(!isset($this->_classes[$className]) && $_c)
326: {
327: require($_c);
328: }
329:
330: if(class_exists($className))
331: {
332: if(!isset($this->_classes[$className]))
333: {
334: $this->_classes[$className] = new $className($this->_getEnv());
335: $this->_forwarded = false;
336: }
337:
338: if($this->_routingHooks)
339: {
340: \Simpletools\Mvc\RoutingHook::fire('beforeForwardController',array('controller'=>$controller,'action'=>$action));
341: }
342:
343: if(is_callable(array($this->_classes[$className],'init')) && !$this->_forwarded)
344: {
345: if($this->_routingHooks)
346: {
347: \Simpletools\Mvc\RoutingHook::fire('beforeControllerInit',array('controller'=>$controller,'action'=>$action));
348: \Simpletools\Mvc\RoutingHook::fire('beforeForwardControllerInit',array('controller'=>$controller,'action'=>$action));
349: }
350:
351: if($this->_current_controller != $controller)
352: {
353: $this->_classes[$className]->init();
354: $this->_current_controller = $controller;
355: }
356: $this->_forwarded = true;
357:
358: if($this->_routingHooks)
359: {
360: \Simpletools\Mvc\RoutingHook::fire('afterForwardControllerInit',array('controller'=>$controller,'action'=>$action));
361: }
362: }
363:
364: if($this->_routingHooks)
365: {
366: \Simpletools\Mvc\RoutingHook::fire('afterForwardController',array('controller'=>$controller,'action'=>$action));
367: }
368:
369: if($this->_autoRender)
370: {
371: $actionMethod = $action.'Action';
372:
373: if(is_callable(array($this->_classes[$className],$actionMethod)))
374: {
375: if($this->_routingHooks)
376: {
377: \Simpletools\Mvc\RoutingHook::fire('beforeControllerAction',array('controller'=>$controller,'action'=>$action));
378: }
379:
380: $this->_classes[$className]->$actionMethod();
381:
382: if($this->_routingHooks)
383: {
384: \Simpletools\Mvc\RoutingHook::fire('afterControllerAction',array('controller'=>$controller,'action'=>$action));
385: }
386: }
387: elseif($className!='ErrorController')
388: {
389: if($this->_routingHooks)
390: {
391: \Simpletools\Mvc\RoutingHook::fire('missingControllerActionError',array('controller'=>$controller,'action'=>$action));
392: }
393:
394: return $this->error('a404');
395: }
396: elseif($actionMethod=='errorAction')
397: {
398: if($this->_routingHooks)
399: {
400: \Simpletools\Mvc\RoutingHook::fire('missingControllerActionError',array('controller'=>$controller,'action'=>$action));
401: }
402:
403: throw new \Exception("Missing errorAction() under ErrorController", 1);
404: }
405: else
406: {
407: if($this->_routingHooks)
408: {
409: \Simpletools\Mvc\RoutingHook::fire('missingControllerError',array('controller'=>$controller,'action'=>$action));
410: }
411:
412: throw new \Exception("Missing correct error handling structure", 1);
413: }
414: }
415:
416: if($this->_autoRender)
417: {
418: $this->render($orgController,$action);
419: }
420:
421: }
422: else
423: {
424: if($this->_routingHooks)
425: {
426: \Simpletools\Mvc\RoutingHook::fire('missingControllerError',array('controller'=>$controller,'action'=>$action));
427: }
428:
429: $this->error('c405');
430: }
431: }
432: else
433: {
434: if($this->_routingHooks)
435: {
436: \Simpletools\Mvc\RoutingHook::fire('missingControllerError',array('controller'=>$controller,'action'=>$action));
437: }
438:
439: $this->error('c404');
440: }
441: }
442:
443: public function setNewParams($controller,$action,$params)
444: {
445: unset($this->_params['number']);
446: unset($this->_params['associative']);
447:
448: $this->_params['associative']['controller'] = $controller;
449: $this->_params['associative']['action'] = $action;
450:
451: $this->_params['number'][] = $controller;
452: $this->_params['number'][] = $action;
453:
454: if($params)
455: {
456: foreach($params as $key=>$value)
457: {
458: $this->_params['number'][] = $value;
459: $this->_params['associative'][$key] = $value;
460: }
461: }
462: }
463:
464: public function &view()
465: {
466: return $this->_view;
467: }
468:
469: public function setViewProperty($key,$value)
470: {
471: $this->_view->{$key} = $value;
472: }
473:
474: public function getActiveRoutingNamespaceDir()
475: {
476: return str_replace('\\',DIRECTORY_SEPARATOR,$this->_activeRoutingNamespace);
477: }
478:
479: public function getActiveRoutingNamespaceUrlPath()
480: {
481: return '/'.$this->_activeRoutingNamespaceUrlPath;
482: }
483:
484: public function getActiveRoutingNamespace($useDirectorySeparator=false)
485: {
486: return $this->_activeRoutingNamespace;
487: }
488:
489:
490: public function enableView()
491: {
492: $this->_view_enabled = true;
493: }
494:
495: public function disableView()
496: {
497: $this->_view_enabled = false;
498: }
499:
500: public function isAction($action=null)
501: {
502: if(!$action)
503: $action = self::getCorrectActionName($this->getParam('action')).'Action';
504: else
505: $action = self::getCorrectActionName($action).'Action';
506:
507: return is_callable(array($this,$action));
508: }
509: }
510:
511: ?>