wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.BatchDisplayController.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.BatchDisplayController.php 1079 2009-09-08 15:21:33Z iherwig $
18  */
19 require_once(BASE."wcmf/application/controller/class.BatchController.php");
20 require_once(BASE."wcmf/lib/persistence/class.PersistenceFacade.php");
21 require_once(BASE."wcmf/lib/model/class.PersistentIterator.php");
22 require_once(BASE."wcmf/lib/model/class.Node.php");
23 require_once(BASE."wcmf/lib/model/class.NodeUtil.php");
24 
25 /**
26  * @class BatchDisplayController
27  * @ingroup Controller
28  * @brief BatchDisplayController is a controller that loads a tree of Nodes recursivly and
29  * returns the Nodes in lists of a given size. The reconstruction of the tree must
30  * be handled by the client.
31  *
32  * <b>Input actions:</b>
33  * - see BatchController
34  *
35  * <b>Output actions:</b>
36  * - see BatchController
37  *
38  * @param[in,out] oid The oid of the Node to start loading from
39  * @param[in] translateValues True/False. If true, list values will be translated using FormUtil::translateValue. If not given,
40  * all values will be returned as is, default: true
41  * @param[in] nodes_per_call The number of nodes to process in one call, default: 50
42  * @param[out] objects An array of Nodes
43  *
44  * @author ingo herwig <ingo@wemove.com>
45  */
47 {
48  // session name constants
49  var $REQUEST = 'BatchDisplayController.request';
50  var $REGISTRY = 'BatchDisplayController.registry';
51  var $ITERATOR_ID = 'BatchDisplayController.iteratorid';
52 
53  // default values, maybe overriden by corresponding request values (see above)
54  var $_NODES_PER_CALL = 50;
55 
56  /**
57  * @see Controller::initialize()
58  */
59  function initialize(&$request, &$response)
60  {
61  parent::initialize($request, $response);
62 
63  // initialize controller
64  if ($request->getAction() != 'continue')
65  {
66  $session = &SessionData::getInstance();
67 
68  // set defaults
69  if (!$request->hasValue('nodes_per_call')) {
70  $request->setValue('nodes_per_call', $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, array(BASE."wcmf/lib/presentation/class.ControllerMessage.php"));
78  $reg = array();
79  $session->set($this->REGISTRY, $reg);
80  }
81  }
82  /**
83  * @see Controller::validate()
84  */
85  function validate()
86  {
87  if ($this->_request->getAction() != 'continue')
88  {
89  // check request values
90  if(strlen($this->_request->getValue('oid')) == 0)
91  {
92  $this->appendErrorMsg("No 'oid' given in data.");
93  return false;
94  }
95  }
96  // do default validation
97  return parent::validate();
98  }
99  /**
100  * @see BatchController::getWorkPackage()
101  */
102  function getWorkPackage($number)
103  {
104  if ($number == 0) {
105  return array('name' => Message::get('Loading'), 'size' => 1, 'oids' => array(1), 'callback' => 'startProcess');
106  }
107  else {
108  return null;
109  }
110  }
111  /**
112  * @see LongTaskController::getDisplayText()
113  */
114  function getDisplayText($step)
115  {
116  return $this->_workPackages[$step-1]['name']." ...";
117  }
118  /**
119  * Copy/Move the first node (oids parameter will be ignored)
120  * @param oids The oids to process
121  */
122  function startProcess($oids)
123  {
124  $session = &SessionData::getInstance();
125 
126  // restore the request from session
127  $request = $session->get($this->REQUEST);
128  $nodeOID = $request->getValue('oid');
129 
130  // do the action
131  $iterator = new PersistentIterator($nodeOID);
132  $iteratorID = $iterator->save();
133  $session->set($this->ITERATOR_ID, $iteratorID);
134 
135  // display the first node in order to reduce the number of calls
136  $this->loadNode($iterator->getCurrentOID());
137 
138  $iterator->proceed();
139 
140  // proceed if nodes are left
141  if (!$iterator->isEnd())
142  {
143  $iteratorID = $iterator->save();
144  $session->set($this->ITERATOR_ID, $iteratorID);
145 
146  $name = Message::get('Loading tree: continue with %1%', array($iterator->getCurrentOID()));
147  $this->addWorkPackage($name, 1, array(null), 'loadNodes');
148  }
149  else
150  {
151  // set the result and finish
152  $this->endProcess();
153  }
154  }
155  /**
156  * Load nodes provided by the persisted iterator (oids parameter will be ignored)
157  * @param oids The oids to process
158  */
159  function loadNodes($oids)
160  {
161  $session = &SessionData::getInstance();
162 
163  // restore the request from session
164  $request = $session->get($this->REQUEST);
165 
166  // check for iterator in session
167  $iterator = null;
168  $iteratorID = $session->get($this->ITERATOR_ID);
169  if ($iteratorID != null) {
170  $iterator = &PersistentIterator::load($iteratorID);
171  }
172 
173  // no iterator, finish
174  if ($iterator == null)
175  {
176  // set the result and finish
177  $this->endProcess();
178  }
179 
180  // process _NODES_PER_CALL nodes
181  $counter = 0;
182  while (!$iterator->isEnd() && $counter < $request->getValue('nodes_per_call'))
183  {
184  $currentOID = $iterator->getCurrentOID();
185  $this->loadNode($currentOID);
186 
187  $iterator->proceed();
188  $counter++;
189  }
190 
191  // decide what to do next
192  if (!$iterator->isEnd())
193  {
194  // proceed with current iterator
195  $iteratorID = $iterator->save();
196  $session->set($this->ITERATOR_ID, $iteratorID);
197 
198  $name = Message::get('Loading tree: continue with %1%', array($iterator->getCurrentOID()));
199  $this->addWorkPackage($name, 1, array(null), 'loadNodes');
200  }
201  else
202  {
203  // set the result and finish
204  $this->endProcess();
205  }
206  }
207  /**
208  * Finish the process and set the result
209  */
210  function endProcess()
211  {
212  $session = &SessionData::getInstance();
213 
214  // clear session variables
215  $tmp = null;
216  $session->set($this->REQUEST, $tmp);
217  $session->set($this->REGISTRY, $tmp);
218  $session->set($this->ITERATOR_ID, $tmp);
219  }
220  /**
221  * Load the node with the given object id and assign it to the response.
222  * @param oid The oid of the node to copy
223  */
224  function loadNode($oid)
225  {
226  // check if we already loaded the node
227  if ($this->isRegistered($oid))
228  return;
229 
230  $persistenceFacade = &PersistenceFacade::getInstance();
231  $session = &SessionData::getInstance();
232 
233  // restore the request from session
234  $request = $session->get($this->REQUEST);
235 
236  // load the node
237  $node = &$persistenceFacade->load($oid, BUIDLDEPTH_SINGLE);
238  if ($node == null) {
239  WCMFException::throwEx("Can't load node '".$oid."'", __FILE__, __LINE__);
240  }
241 
242  // translate all nodes to the requested language if requested
243  if ($this->isLocalizedRequest())
244  {
245  $localization = Localization::getInstance();
246  $localization->loadTranslation($node, $request->getValue('language'), true, true);
247  }
248 
249  // translate values if requested
250  if ($request->getBooleanValue('translateValues'))
251  {
252  $nodes = array($node);
253  if ($this->isLocalizedRequest()) {
254  NodeUtil::translateValues($nodes, $request->getValue('language'));
255  }
256  else {
258  }
259  }
260 
261  // assign it to the response
262  $this->addNodeToResponse($node);
263 
264  $this->register($oid);
265 
266  if (Log::isInfoEnabled(__CLASS__)) {
267  Log::info("Loaded: ".$node->getOID(), __CLASS__);
268  }
269  if (Log::isDebugEnabled(__CLASS__)) {
270  Log::debug($node->toString(), __CLASS__);
271  }
272  }
273  /**
274  * Register an object id in the registry
275  * @param oid The object id to register
276  */
277  function register($oid)
278  {
279  $session = &SessionData::getInstance();
280  $registry = $session->get($this->REGISTRY);
281  array_push($registry, $oid);
282  $session->set($this->REGISTRY, $registry);
283  }
284  /**
285  * Check if an object id is registered in the registry
286  * @param oid The object id to check
287  * @return True/False wether the oid is registered or not
288  */
289  function isRegistered($oid)
290  {
291  $session = &SessionData::getInstance();
292  $registry = $session->get($this->REGISTRY);
293 
294  return in_array($oid, $registry);
295  }
296  /**
297  * Add a given node to the objects variable of the response
298  * @param node A reference to the node to add
299  */
300  function addNodeToResponse(&$node)
301  {
302  if (!$this->_response->hasValue('objects')) {
303  $objects = array();
304  $this->_response->setValue('objects', $objects);
305  }
306 
307  $objects = &$this->_response->getValue('objects');
308  $objects[sizeof($objects)] = &$node;
309  $this->_response->setValue('objects', $objects);
310  }
311 }
312 ?>
debug($message, $category)
Definition: class.Log.php:39
get($message, $parameters=null, $domain='', $lang='')
BatchDisplayController is a controller that loads a tree of Nodes recursivly and returns the Nodes in...
info($message, $category)
Definition: class.Log.php:49
throwEx($message, $file='', $line='')
isInfoEnabled($category)
Definition: class.Log.php:99
translateValues(&$nodes, $language=null)
isDebugEnabled($category)
Definition: class.Log.php:89
addWorkPackage($name, $size, $oids, $callback, $args=null)
PersistentIterator is used to iterate over a tree/list build of oids using a Depth-First-Algorithm. To persist its state use the PersistentIterator::save() method, to restore its state use the static PersistentIterator::load() method, which returns the loaded instance. States are identified by an unique id, which is provided after saving. PersistentIterator implements the 'Iterator Pattern'.
BatchController allows to define work packages that will be processed in a sequence. It simplifies the usage of LongTaskController functionality for splitting different bigger tasks into many smaller (similar) tasks where the whole number of tasks isn't known at designtime.