BatchDisplayController.php
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2015 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of the MIT License.
7  *
8  * See the LICENSE file distributed with this work for
9  * additional information.
10  */
12 
23 
24 /**
25  * BatchDisplayController is used to load a tree of Node instances recursivly and
26  * return them in lists of a given size. The reconstruction of the tree must be
27  * handled by the client.
28  *
29  * The controller supports the following actions:
30  *
31  * <div class="controller-action">
32  * <div> __Action__ _default_ </div>
33  * <div>
34  * Load the Nodes.
35  * | Parameter | Description
36  * |---------------------------|-------------------------
37  * | _in_ / _out_ `oid` | The object id of the Node to start loading from
38  * | _in_ `translateValues` | Boolean whether list values should be translated to their display values (optional, default: _true_)
39  * | _in_ `nodesPerCall` | The number of Node instances to load in one call (default: 50)
40  * | _out_ `list` | Array of Node instances
41  * </div>
42  * </div>
43  *
44  * For additional actions and parameters see [BatchController actions](@ref BatchController).
45  *
46  * @author ingo herwig <ingo@wemove.com>
47  */
49 
50  // session name constants
51  private $REQUEST = 'BatchDisplayController.request';
52  private $REGISTRY = 'BatchDisplayController.registry';
53  private $ITERATOR_ID = 'BatchDisplayController.iteratorid';
54 
55  // default values, maybe overriden by corresponding request values (see above)
56  private $_NODES_PER_CALL = 50;
57 
58  /**
59  * @see Controller::initialize()
60  */
61  public function initialize(Request $request, Response $response) {
62  parent::initialize($request, $response);
63 
64  // initialize controller
65  if ($request->getAction() != 'continue') {
66  $session = $this->getSession();
67 
68  // set defaults
69  if (!$request->hasValue('nodesPerCall')) {
70  $request->setValue('nodesPerCall', $this->_NODES_PER_CALL);
71  }
72  if (!$request->hasValue('translateValues')) {
73  $request->setValue('translateValues', true);
74  }
75 
76  // store request in session
77  $session->set($this->REQUEST, $request);
78  $reg = array();
79  $session->set($this->REGISTRY, $reg);
80  }
81  }
82 
83  /**
84  * @see Controller::validate()
85  */
86  protected function validate() {
87  $request = $this->getRequest();
88  $response = $this->getResponse();
89  if ($request->getAction() != 'continue') {
90  $oid = ObjectId::parse($request->getValue('oid'));
91  if(!$oid) {
92  $response->addError(ApplicationError::get('OID_INVALID',
93  array('invalidOids' => array($request->getValue('oid')))));
94  return false;
95  }
96  if (!$this->checkLanguageParameter()) {
97  return false;
98  }
99  }
100  // do default validation
101  return parent::validate();
102  }
103 
104  /**
105  * @see BatchController::getWorkPackage()
106  */
107  protected function getWorkPackage($number) {
108  if ($number == 0) {
109  return array('name' => $this->getMessage()->getText('Loading'),
110  'size' => 1, 'oids' => array(1), 'callback' => 'startProcess');
111  }
112  else {
113  return null;
114  }
115  }
116 
117  /**
118  * Initialize the iterator (oids parameter will be ignored)
119  * @param $oids The oids to process
120  */
121  protected function startProcess($oids) {
122  $session = $this->getSession();
123  $persistenceFacade = $this->getPersistenceFacade();
124 
125  // restore the request from session
126  $request = $session->get($this->REQUEST);
127  $nodeOID = ObjectId::parse($request->getValue('oid'));
128 
129  // do the action
130  $iterator = new PersistentIterator($persistenceFacade, $session, $nodeOID);
131  $iteratorID = $iterator->save();
132  $session->set($this->ITERATOR_ID, $iteratorID);
133 
134  // display the first node in order to reduce the number of calls
135  $this->loadNode($iterator->current());
136 
137  $iterator->next();
138 
139  // proceed if nodes are left
140  if ($iterator->valid()) {
141  $iteratorID = $iterator->save();
142  $session->set($this->ITERATOR_ID, $iteratorID);
143 
144  $name = $this->getMessage()->getText('Loading tree: continue with %0%',
145  array($iterator->current()));
146  $this->addWorkPackage($name, 1, array(null), 'loadNodes');
147  }
148  else {
149  // set the result and finish
150  $this->endProcess();
151  }
152  }
153 
154  /**
155  * Load nodes provided by the persisted iterator (oids parameter will be ignored)
156  * @param $oids The oids to process
157  */
158  protected function loadNodes($oids) {
159  $session = $this->getSession();
160  $persistenceFacade = $this->getPersistenceFacade();
161 
162  // restore the request from session
163  $request = $session->get($this->REQUEST);
164 
165  // check for iterator in session
166  $iterator = null;
167  $iteratorID = $session->get($this->ITERATOR_ID);
168  if ($iteratorID != null) {
169  $iterator = PersistentIterator::load($persistenceFacade, $session, $iteratorID);
170  }
171 
172  // no iterator, finish
173  if ($iterator == null) {
174  // set the result and finish
175  $this->endProcess();
176  }
177 
178  // process _NODES_PER_CALL nodes
179  $counter = 0;
180  while ($iterator->valid() && $counter < $request->getValue('nodesPerCall')) {
181  $currentOID = $iterator->current();
182  $this->loadNode($currentOID);
183 
184  $iterator->next();
185  $counter++;
186  }
187 
188  // decide what to do next
189  if ($iterator->valid()) {
190  // proceed with current iterator
191  $iteratorID = $iterator->save();
192  $session->set($this->ITERATOR_ID, $iteratorID);
193 
194  $name = $this->getMessage()->getText('Loading tree: continue with %0%',
195  array($iterator->current()));
196  $this->addWorkPackage($name, 1, array(null), 'loadNodes');
197  }
198  else {
199  // set the result and finish
200  $this->endProcess();
201  }
202  }
203 
204  /**
205  * Finish the process and set the result
206  */
207  protected function endProcess() {
208  $session = $this->getSession();
209 
210  // clear session variables
211  $tmp = null;
212  $session->set($this->REQUEST, $tmp);
213  $session->set($this->REGISTRY, $tmp);
214  $session->set($this->ITERATOR_ID, $tmp);
215  }
216 
217  /**
218  * Load the node with the given object id and assign it to the response.
219  * @param $oid The oid of the node to copy
220  */
221  protected function loadNode(ObjectId $oid) {
222  // check if we already loaded the node
223  if ($this->isRegistered($oid)) {
224  return;
225  }
226  $persistenceFacade = $this->getPersistenceFacade();
227  $session = $this->getSession();
228 
229  // restore the request from session
230  $request = $session->get($this->REQUEST);
231 
232  // load the node
233  $node = $persistenceFacade->load($oid);
234  if ($node == null) {
235  throw new PersistenceException("Can't load node '".$oid."'");
236  }
237 
238  // translate all nodes to the requested language if requested
239  if ($this->isLocalizedRequest()) {
240  $localization = $this->getLocalization();
241  $node = $localization->loadTranslation($node, $request->getValue('language'), true, true);
242  }
243 
244  // translate values if requested
245  if ($request->getBooleanValue('translateValues')) {
246  $nodes = array($node);
247  if ($this->isLocalizedRequest()) {
248  NodeUtil::translateValues($nodes, $request->getValue('language'));
249  }
250  else {
252  }
253  }
254 
255  // assign it to the response
256  $this->addNodeToResponse($node);
257 
258  $this->register($oid);
259 
260  $logger = $this->getLogger();
261  if ($logger->isInfoEnabled()) {
262  $logger->info("Loaded: ".$node->getOID());
263  }
264  if ($logger->isDebugEnabled()) {
265  $logger->debug($node->toString());
266  }
267  }
268 
269  /**
270  * Register an object id in the registry
271  * @param $oid The object id to register
272  */
273  protected function register(ObjectId $oid) {
274  $session = $this->getSession();
275  $registry = $session->get($this->REGISTRY);
276  $registry[] = $oid;
277  $session->set($this->REGISTRY, $registry);
278  }
279 
280  /**
281  * Check if an object id is registered in the registry
282  * @param $oid The object id to check
283  * @return Boolean whether the oid is registered or not
284  */
285  protected function isRegistered(ObjectId $oid) {
286  $session = $this->getSession();
287  $registry = $session->get($this->REGISTRY);
288 
289  return in_array($oid, $registry);
290  }
291 
292  /**
293  * Add a given node to the list variable of the response
294  * @param $node A reference to the node to add
295  */
296  protected function addNodeToResponse(Node $node) {
297  $response = $this->getResponse();
298  if (!$response->hasValue('list')) {
299  $objects = array();
300  $response->setValue('list', $objects);
301  }
302 
303  $objects = $response->getValue('list');
304  $objects[] = $node;
305  $response->setValue('list', $objects);
306  }
307 }
308 ?>
Response holds the response values that are used as output from Controller instances.
Definition: Response.php:20
initialize(Request $request, Response $response)
getRequest()
Get the Request instance.
Definition: Controller.php:190
startProcess($oids)
Initialize the iterator (oids parameter will be ignored)
getMessage()
Get the Message instance.
Definition: Controller.php:254
static load($persistenceFacade, $session, $uid)
Load an iterator state from the session.
BatchDisplayController is used to load a tree of Node instances recursivly and return them in lists o...
addWorkPackage($name, $size, $oids, $callback, $args=null)
Add a work package to session.
static translateValues(&$nodes, $language=null)
Translate all list values in a list of Nodes.
Definition: NodeUtil.php:253
isLocalizedRequest()
Check if the current request is localized.
Definition: Controller.php:300
ObjectId is the unique identifier of an object.
Definition: ObjectId.php:27
setValue($name, $value, $forceSet=false, $trackChange=true)
Definition: Node.php:119
getLocalization()
Get the Localization instance.
Definition: Controller.php:246
isRegistered(ObjectId $oid)
Check if an object id is registered in the registry.
checkLanguageParameter()
Checks the language request parameter and adds an response error, if it is not contained in the Local...
Definition: Controller.php:315
getAction()
Get the name of the action.
Request holds the request values that are used as input to Controller instances.
Definition: Request.php:20
BatchController is used to process complex, longer running actions, that need to be divided into seve...
addNodeToResponse(Node $node)
Add a given node to the list variable of the response.
static parse($oid)
Parse a serialized object id string into an ObjectId instance.
Definition: ObjectId.php:144
hasValue($name)
Check for existance of a value.
PersistenceException signals an exception in the persistence service.
Application controllers.
Definition: namespaces.php:3
endProcess()
Finish the process and set the result.
setValue($name, $value)
Set a value.
loadNodes($oids)
Load nodes provided by the persisted iterator (oids parameter will be ignored)
static get($code, $data=null)
Factory method for retrieving a predefind error instance.
loadNode(ObjectId $oid)
Load the node with the given object id and assign it to the response.
PersistentIterator is used to iterate over a tree/list built of oids using a Depth-First-Algorithm.
getLogger()
Get the Logger instance.
Definition: Controller.php:206
getResponse()
Get the Response instance.
Definition: Controller.php:198
getSession()
Get the Session instance.
Definition: Controller.php:214
Node adds the concept of relations to PersistentObject.
Definition: Node.php:34
getPersistenceFacade()
Get the PersistenceFacade instance.
Definition: Controller.php:222