wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.MultipleActionController.php
Go to the documentation of this file.
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005 wemove digital solutions GmbH
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * $Id: class.MultipleActionController.php 1427 2012-12-21 19:03:06Z iherwig $
21  */
22 require_once(BASE."wcmf/lib/presentation/class.Controller.php");
23 require_once(BASE."wcmf/lib/presentation/class.ActionMapper.php");
24 
25 /**
26  * @class MultipleActionController
27  * @ingroup Controller
28  * @brief MultipleActionController is a controller that executes multiple actions by
29  * passing them do the appropriate controllers and returning all results as once.
30  *
31  * <b>Input actions:</b>
32  * - unspecified: Execute the given actions
33  *
34  * <b>Output actions:</b>
35  * - @em ok In any case
36  *
37  * @param[in] data An associative array with unique/sortable keys and values that describe an action to perform
38  * @param[out] data An associative array with the same keys and values that describe the resonse of each action
39  *
40  * The data array may contain the following special variables, that will be replaced by the described values:
41  * - {last_created_oid:type} will be replaced by the oid lastly created object of the given type
42  *
43  * An example of input data in JSON:
44  * @code
45  data: {
46  action1: {
47  usr_action: "new",
48  type: "ChiGoal"
49  }
50  action2: {
51  usr_action: "display",
52  oid: {last_created_oid:ChiGoal},
53  omitMetaData: true
54  }
55  }
56  * @endcode
57  *
58  * The output data for the preceding request could look like
59  * @code
60  data: {
61  action1: {
62  oid: "ChiGoal:123",
63  success: "1"
64  }
65  action2: {
66  oid: "ChiGoal:123",
67  node: {
68  "0": {
69  modified: "2001-01-01 01:01",
70  creator: "admin"
71  ...
72  }
73  ...
74  },
75  success: "1"
76  }
77  }
78  * @endcode
79  *
80  * @author ingo herwig <ingo@wemove.com>
81  */
83 {
84  /**
85  * @see Controller::validate()
86  */
87  function validate()
88  {
89  // check if we have an array of arrays
90  $data = &$this->_request->getValue('data');
91  foreach($data as $key => $value)
92  {
93  if (!is_array($value))
94  {
95  $this->setErrorMsg("Data should be an associative array of action definition arrays.");
96  return false;
97  }
98  }
99  return true;
100  }
101  /**
102  * @see Controller::hasView()
103  */
104  function hasView()
105  {
106  return false;
107  }
108  /**
109  * (Dis-)Associate the Nodes.
110  * @return Array of given context and action 'ok' in every case.
111  * @see Controller::executeKernel()
112  */
113  function executeKernel()
114  {
115  // create and execute requests for the actions given in data
116  $results = array();
117  $session = &SessionData::getInstance();
118  $data = &$this->_request->getValue('data');
119  $actions = array_keys($data);
120  $numActions = sizeof($actions);
121  $exceptions = array();
122  for($i=0; $i<$numActions; $i++)
123  {
124  $action = $actions[$i];
125  $GLOBALS['gJSONData'] = array();
126 
127  if (Log::isDebugEnabled(__CLASS__)) {
128  Log::debug("processing action: ".$action.":\n".StringUtil::getDump($data[$action]), __CLASS__);
129  }
130  // replace special variables
131  $this->replaceVariables($data[$action]);
132 
133  // for all requests we choose TerminateController as source controller
134  // to make sure that we process the action and return to here
135 
136  // create the request
137  $request = new Request(
138  'TerminateController',
139  $data[$action]['context'],
140  $data[$action]['usr_action'],
141  $data[$action]
142  );
143  $request->setFormat('Null');
144  $request->setResponseFormat($this->_request->getResponseFormat());
145 
146  // execute the request
147  try {
148  $response = &ActionMapper::processAction($request);
149  }
150  catch (ApplicationException $ex)
151  {
152  Log::error($ex->__toString(), __CLASS__);
153  $response = $ex->getResponse();
154  if ($response == null) {
155  $response = new Response('', '', $action, array());
156  $response->setFormat($request->getResponseFormat());
157  $requestData = $request->getData();
158  foreach ($requestData as $key => $value) {
159  $response->setValue($key, $value);
160  }
161  }
162  $response->setValue('success', false);
163  $response->setValue('errorCode', $ex->getCodeString());
164  $response->setValue('errorMessage', $ex->getMessage());
165  $exceptions[] = $ex;
166  }
167  catch (Exception $ex)
168  {
169  Log::error($ex->__toString(), __CLASS__);
170  $exceptions[] = $ex;
171  }
172 
173  // collect the result
174  $results[$action] = &$response->getData();
175  }
176  if (Log::isDebugEnabled(__CLASS__)) {
177  Log::debug($results, __CLASS__);
178  }
179 
180  // add error from first exception to mark the action set execution as failed
181  if (sizeof($exceptions) > 0) {
182  $ex = $exceptions[0];
183  $this->_response->setValue('success', false);
184  $this->_response->setValue('errorCode', $ex->getCodeString());
185  $this->_response->setValue('errorMessage', $ex->getMessage());
186  }
187  $this->_response->setValue('data', $results);
188  $this->_response->setAction('ok');
189  return true;
190  }
191 
192  /**
193  * Check the given data array for special variables to replace
194  * Variables have either the form 'variable_name' or 'variable_name:column_separated_parameters'
195  * @param data A reference to the associative data array
196  */
197  function replaceVariables(&$data)
198  {
199  $keys = array_keys($data);
200  for($i=0; $i<sizeof($keys); $i++)
201  {
202  $key = $keys[$i];
203  $value = $data[$key];
204 
205  // replace variables
206  $newKey = $this->replaceVariablesString($key);
207  $newValue = $this->replaceVariablesString($value);
208 
209  // replace entry
210  if ($key != $newKey || $value != $newValue)
211  {
212  if (Log::isDebugEnabled(__CLASS__))
213  {
214  if ($key != $newKey)
215  Log::debug("Replace $key by $newKey", __CLASS__);
216  if ($value != $newValue)
217  Log::debug("Replace $value by $newValue", __CLASS__);
218  }
219  unset($data[$key]);
220  $data[$newKey] = $newValue;
221  }
222  }
223  }
224 
225  /**
226  * Check the given string for special variables to replace
227  * Variables have either the form 'variable_name' or 'variable_name:column_separated_parameters'
228  * @param value The string
229  * @return The string
230  */
231  function replaceVariablesString($value)
232  {
233  preg_match_all('/\{([^\{]+)\}/', $value, $variableMatches);
234  $variables = $variableMatches[1];
235  foreach($variables as $variable)
236  {
237  preg_match('/^([^:]+)[:]*(.*)$/', $variable, $matches);
238  if (sizeof($matches > 0))
239  {
240  $variableName = $matches[1];
241  $parameters = $matches[2];
242 
243  // last_created_oid
244  if ($variableName == 'last_created_oid')
245  {
246  $type = $parameters;
248  {
249  $persistenceFacade = &PersistenceFacade::getInstance();
250  $oid = $persistenceFacade->getLastCreatedOID($type);
251  $value = preg_replace("/{".$variable."}/", $oid, $value);
252  }
253  }
254 
255  // Dionysos oid reference: {type:?}
256  if (PersistenceFacade::isKnownType($variableName))
257  {
258  $type = $variableName;
259  $persistenceFacade = &PersistenceFacade::getInstance();
260  $oid = $persistenceFacade->getLastCreatedOID($type);
261  $value = $oid;
262  }
263  }
264  }
265  return $value;
266  }
267 }
268 ?>
269 
error($message, $category)
Definition: class.Log.php:69
debug($message, $category)
Definition: class.Log.php:39
& processAction(&$request)
MultipleActionController is a controller that executes multiple actions by passing them do the approp...
Request holds the request values that are used as input to Controller instances. It is typically inst...
Controller is the base class of all controllers. If a Controller has a view it is expected to reside ...
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.
$GLOBALS['gJSONData']