wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.ActionMapper.php
Go to the documentation of this file.
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2014 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of any of the following licenses
7  * at your choice:
8  *
9  * - GNU Lesser General Public License (LGPL)
10  * http://www.gnu.org/licenses/lgpl.html
11  * - Eclipse Public License (EPL)
12  * http://www.eclipse.org/org/documents/epl-v10.php
13  *
14  * See the license.txt file distributed with this work for
15  * additional information.
16  *
17  * $Id: class.ActionMapper.php 1462 2014-02-04 23:52:27Z iherwig $
18  */
19 require_once(BASE."wcmf/lib/core/class.WCMFException.php");
20 require_once(BASE."wcmf/lib/util/class.Log.php");
21 require_once(BASE."wcmf/lib/util/class.Message.php");
22 require_once(BASE."wcmf/lib/util/class.SessionData.php");
23 require_once(BASE."wcmf/lib/util/class.ObjectFactory.php");
24 require_once(BASE."wcmf/lib/presentation/class.Request.php");
25 require_once(BASE."wcmf/lib/presentation/class.Response.php");
26 require_once(BASE."wcmf/lib/presentation/class.WCMFInifileParser.php");
27 require_once(BASE."wcmf/lib/presentation/format/class.Formatter.php");
28 require_once(BASE."wcmf/lib/security/class.RightsManager.php");
29 require_once(BASE."wcmf/3rdparty/Bs_StopWatch.class.php");
30 
31 /**
32  * @class ActionMapper
33  * @ingroup Presentation
34  * @brief ActionMapper is the central class in our implementation of the mvc pattern.
35  * It calls the different Controllers based on the referring Controller and the given action.
36  *
37  * @author ingo herwig <ingo@wemove.com>
38  */
40 {
42  var $_lastControllers = array();
43 
44  /**
45  * Returns an instance of the class.
46  * @return A reference to the only instance of the Singleton object
47  */
48  function &getInstance()
49  {
50  static $instance = null;
51 
52  if (!isset($instance))
53  $instance = new ActionMapper();
54 
55  return $instance;
56  }
57  /**
58  * Process an action depending on a given referrer. The ActionMapper will instantiate the required Controller class
59  * as configured in the iniFile and delegates the request to it.
60  * @note This method is static so that it can be used without an instance. (This is necessary to call it in onError() which
61  * cannot be a class method because php's set_error_handler() does not allow this).
62  * @param request A reference to a Request instance
63  * @return A reference to an Response instance or null on error.
64  */
65  function &processAction(&$request)
66  {
67  // allow static call
68  $actionMapper = ActionMapper::getInstance();
69 
70  $referrer = $request->getSender();
71  $context = $request->getContext();
72  $action = $request->getAction();
73 
74  // this array stores all controllers executed since the last view displayed (the last call of main.php)
75 
76  // store last controller
77  array_push($actionMapper->_lastControllers, $referrer);
78 
79  $parser = &WCMFInifileParser::getInstance();
80  $rightsManager = &RightsManager::getInstance();
81 
82  $logExecutionTime = $parser->getValue('logExecuteTime', 'cms');
83 
84  // check authorization for controller/context/action triple
85  if (!$rightsManager->authorize($referrer, $context, $action))
86  {
87  $authUser = &$rightsManager->getAuthUser();
88  if (!$authUser)
89  {
90  WCMFException::throwEx(Message::get("Authorization failed: no valid user. Maybe your session has expired."), __FILE__, __LINE__);
91  Log::error("The request was: ".$request->toString(), __CLASS__);
92  }
93  else
94  {
95  $login = $authUser->getName();
96  Log::error("Authorization failed for '".$actionKey."' user '".$login."'", __CLASS__);
97  WCMFException::throwEx(Message::get("You don't have the permission to perform this action."), __FILE__, __LINE__);
98  return null;
99  }
100  }
101 
102  // get best matching action key from inifile
103  $actionKey = $parser->getBestActionKey('actionmapping', $referrer, $context, $action);
104 
105  session_start();
106  if (Log::isDebugEnabled(__CLASS__))
107  Log::debug($referrer."?".$context."?".$action.' -> '.$actionKey, __CLASS__);
108 
109  if (strlen($actionKey) == 0)
110  {
111  // re-execute the initial referrer
112  $controllerClass = $actionMapper->_lastControllers[0];
113  Log::warn("No actionkey found for ".$referrer."?".$context."?".$action.". Executing ".$controllerClass." ...", __CLASS__);
114  }
115  else
116  {
117  // get next controller
118  if (($controllerClass = $parser->getValue($actionKey, 'actionmapping')) === false)
119  {
120  WCMFException::throwEx($parser->getErrorMsg(), __FILE__, __LINE__);
121  return null;
122  }
123  }
124  if (strlen($controllerClass) == 0)
125  {
126  WCMFException::throwEx("No controller found for best action key ".$actionKey.". Request was $referrer?$context?$action", __FILE__, __LINE__);
127  return null;
128  }
129 
130 /*
131  // check authorization for next controller/context/action triple
132  if (!$rightsManager->authorize($controllerClass, $context, $action))
133  return null;
134 */
135  // create controller delegate instance if configured
136  if ($actionMapper->_controllerDelegate == null)
137  {
138  if ($parser->getValue('ControllerDelegate', 'implementation') !== false)
139  {
140  $objectFactory = &ObjectFactory::getInstance();
141  $actionMapper->_controllerDelegate = &$objectFactory->createInstanceFromConfig('implementation', 'ControllerDelegate');
142  }
143  }
144 
145  // instantiate controller
146  if (($classFile = $parser->getValue($controllerClass, 'classmapping')) === false)
147  {
148  WCMFException::throwEx($parser->getErrorMsg(), __FILE__, __LINE__);
149  return null;
150  }
151  if (file_exists(BASE.$classFile))
152  {
153  require_once(BASE.$classFile);
154  $controllerObj = new $controllerClass($actionMapper->_controllerDelegate);
155  }
156  else
157  {
158  WCMFException::throwEx("Definition of Controller ".$controllerClass." in '".$classFile."' not found.", __FILE__, __LINE__);
159  return null;
160  }
161 
162  // everything is right in place, start processing
163  if (Log::isDebugEnabled(__CLASS__))
164  Log::debug("Request: ".$request->toString(), __CLASS__);
165  Formatter::deserialize($request);
166 
167  // create the response
168  $response = new Response($controllerClass, $context, $action, array());
169  $response->setFormat($request->getResponseFormat());
170 
171  // initialize controller
172  if (Log::isDebugEnabled(__CLASS__))
173  Log::debug("Execute ".$controllerClass." with request: ".$request->toString(), __CLASS__);
174  $controllerObj->initialize($request, $response);
175 
176  // execute controller
177  if ($logExecutionTime)
178  {
179  $stopWatch = new Bs_StopWatch();
180  $stopWatch->reset();
181  }
182  $result = $controllerObj->execute();
183 
184  if ($logExecutionTime && Log::isDebugEnabled(__CLASS__))
185  Log::debug($controllerClass." execution time: ".$stopWatch->getTime()." ms", __CLASS__);
186 
187  if ($result === false)
188  {
189  // stop processing
190  return $response;
191  }
192  else if ($result === true)
193  {
194  // proceed based on the result
195  $nextRequest = new Request($controllerClass, $response->getContext(), $response->getAction(), $response->getData());
196  $nextRequest->setResponseFormat($request->getResponseFormat());
197  $response = &ActionMapper::processAction($nextRequest);
198  }
199  else
200  {
201  WCMFException::throwEx("Controller::execute must return true or false. Executed controller was ".$controllerClass.".", __FILE__, __LINE__);
202  return null;
203  }
204  return $response;
205  }
206  /**
207  * Reset the state of ActionMapper to initial. Especially clears the processed controller queue.
208  */
209  function reset()
210  {
211  // allow static call
212  $actionMapper = ActionMapper::getInstance();
213  $actionMapper->_lastControllers = array();
214  }
215 }
216 ?>
error($message, $category)
Definition: class.Log.php:69
debug($message, $category)
Definition: class.Log.php:39
get($message, $parameters=null, $domain='', $lang='')
warn($message, $category)
Definition: class.Log.php:59
setResponseFormat($format)
& processAction(&$request)
Request holds the request values that are used as input to Controller instances. It is typically inst...
throwEx($message, $file='', $line='')
isDebugEnabled($category)
Definition: class.Log.php:89
Response holds the response values that are used as output from Controller instances. It is typically instantiated by the ActionMapper instance and filled during Controller execution.
deserialize(&$request)
ActionMapper is the central class in our implementation of the mvc pattern. It calls the different Co...