Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
hipo_job_edit_status.inc
1 <?php
17 require_once SQ_SYSTEM_ROOT.'/core/hipo/hipo_job.inc';
18 
28 {
29 
30 
36  function HIPO_Job_Edit_Status($code_name='')
37  {
38  $this->HIPO_Job($code_name);
39 
40  }//end constructor
41 
42 
52  public static function paintConfig(&$o, $class, $write_access)
53  {
54  // metadata regeneration threshhold HIPO config entry
55  $o->openField(translate('edit_status_threshold'));
56 
57  if ($write_access) {
58  text_box($class.'[SQ_HIPO_EDIT_STATUS_THRESHOLD]', SQ_HIPO_EDIT_STATUS_THRESHOLD, 5);
59  } else {
60  echo SQ_HIPO_EDIT_STATUS_THRESHOLD;
61  }
62  echo ' '.translate('assets');
63 
64  $o->closeField();
65 
66  }//end paintConfig()
67 
68 
75  public static function getConfigVars()
76  {
77  return Array(
78  'SQ_HIPO_EDIT_STATUS_THRESHOLD' => Array('editable' => 1, 'default' => 1),
79  );
80 
81  }//end getConfigVars()
82 
83 
95  function getCodeName()
96  {
97  $running_dependants = '';
98  if (!empty($this->_running_vars['process_dependants'])) {
99  $running_dependants = 'dependants';
100  }
101  return parent::getCodeName().$this->_running_vars['assetid'].$running_dependants;
102 
103  }//end getCodeName()
104 
105 
112  function getHipoName()
113  {
114  return translate('hipo_name_edit_status');
115 
116  }//end getHipoName()
117 
118 
127  {
128  return Array(
129  Array(
130  'name' => translate('hipo_editing_status'),
131  'function_call' => Array(
132  'process_function' => 'processStatus',
133  ),
134  'running_mode' => 'server',
135  'auto_step' => TRUE,
136  'allow_cancel' => TRUE,
137  'percent_done' => 0,
138  'complete' => FALSE,
139  'message' => '',
140  ),
141  );
142 
143  }//end getInitialStepData()
144 
145 
155  {
156  if (SQ_HIPO_EDIT_STATUS_THRESHOLD == 0) return 0;
157  if (!isset($this->_running_vars['todo_assetids'])) {
158  return 0;
159  }
160 
161  return (((count($this->_running_vars['todo_assetids']) + 1) / SQ_HIPO_EDIT_STATUS_THRESHOLD) * 100);
162 
163  }//end getThresholdPercentageRequired()
164 
165 
172  function prepare()
173  {
174 
175  // to start editing a status, we need to have an asset id to edit
176  if (!isset($this->_running_vars['assetid'])) {
177  trigger_localised_error('HIPO0012', E_USER_WARNING);
178  return '';
179  }
180 
181  // so we have an assetid to start at, but make sure it is a valid assetid
182  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_running_vars['assetid']);
183  if (is_null($asset)) {
184  trigger_localised_error('HIPO0011', E_USER_WARNING, $this->_running_vars['assetid']);
185  return '';
186  }
187 
188  if (!empty($this->_running_vars['process_dependants'])) {
189  // we are _only_ going to do the dependant assets, no independant ones at all. this should only ever
190  // happen from spawned jobs
191  $this->_running_vars['todo_assetids'] = $GLOBALS['SQ_SYSTEM']->am->getDependantChildren($asset->id);
192  $this->_running_vars['done_root'] = TRUE;
193  } else {
194  // we have a valid asset, so get all the assets below this one in the tree(s) so we know what assets
195  // we will be edting the status of
196 
197  // if there is no dependants setting, or if it is true, get only dependants
198  if (!isset($this->_running_vars['dependants_only']) || !empty($this->_running_vars['dependants_only'])) {
199  $this->_running_vars['dependants_only'] = FALSE;
200  $child_assets = Array();
201  } else {
202  // get all children
203  $this->_running_vars['dependants_only'] = TRUE;
204  $child_assets = $GLOBALS['SQ_SYSTEM']->am->getChildren($asset->id, '', TRUE, FALSE);
205  }
206  // exclude shadow children
207  foreach ($child_assets as $id => $asset) {
208  $id_parts = explode(':', $id);
209  if(isset($id_parts[1])) {
210  unset($child_assets[$id]);
211  }
212  }
213 
214  $this->_running_vars['todo_assetids'] = $child_assets;
215  $this->_running_vars['done_root'] = FALSE;
216  }
217  $this->_running_vars['done_assetids'] = Array();
218 
219  // internal messages being stored
220  if (!isset($this->_running_vars['messages']) || empty($this->_running_vars['messages'])) {
221  $this->_running_vars['messages'] = Array();
222  }
223 
224  unset($asset);
225 
226  $to_do = array_keys($this->_running_vars['todo_assetids']);
227  if (empty($this->_running_vars['process_dependants'])) {
228  $to_do[] = $this->_running_vars['assetid'];
229  }
230  $this->_running_vars['current_asset_statuses'] = $GLOBALS['SQ_SYSTEM']->am->getAssetInfo($to_do, '', TRUE, 'status');
231 
232  return parent::prepare();
233 
234  }//end prepare()
235 
236 
245  function load($code_name)
246  {
247  // need this because it'll complain about Internal Message being an incomplete class
248  require_once SQ_INCLUDE_PATH.'/internal_message.inc';
249  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
250  return parent::load($code_name);
251 
252  }//end load()
253 
254 
267  function paint(&$o, $nested=FALSE)
268  {
269  parent::paint($o, $nested);
270 
271  // paint dependant hipo job here
272  if (!empty($this->_running_vars['dependant_hipo_job'])) {
273  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
274  $hipo = $hh->getJob($this->_running_vars['dependant_hipo_job']);
275  if (!is_null($hipo)) {
276  $hipo->paint($o, TRUE);
277  } else {
278  unset($this->_running_vars['dependant_hipo_job']);
279  }
280  }
281 
282  }//end paint()
283 
284 
291  function freestyle()
292  {
293  while (!empty($this->_running_vars['todo_assetids']) || !$this->_running_vars['done_root'] || !empty($this->_running_vars['dependant_hipo_job'])) {
294  if (!$this->processStatus($this->_steps[0], get_class($this), TRUE)) {
295  return FALSE;
296  }
297  }
298  return TRUE;
299 
300  }//end freestyle()
301 
302 
314  function processServer(&$step_data, $prefix)
315  {
316  // we are probably going to be sending some internal messages during this
317  // process, so we'll open a new queue here
318  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
319  $ms->openQueue();
320 
321  if (!parent::processServer($step_data, $prefix)) {
322  $ms->abortQueue();
323  return FALSE;
324  }
325 
326  // close the internal message queue and send the messages that
327  // were generated during this status change
328  $ms->closeQueue();
329 
330  return TRUE;
331 
332  }//end processServer()
333 
334 
345  function processStatus(&$step_data, $prefix, $freestyle=FALSE)
346  {
347  $send_messages = array_get_index($this->_running_vars, 'send_messages', TRUE);
348 
349  // process dependant hipo_job_edit_status if necessary
350  if (!empty($this->_running_vars['dependant_hipo_job'])) {
351  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
352  $hipo = $hh->getJob($this->_running_vars['dependant_hipo_job']);
353 
354  // bail if we've completed this job
355  if (is_null($hipo)) return FALSE;
356 
357  if ($freestyle && $hipo->freestyle()) {
358  // we're freestylin' and that it, done
359  unset($this->_running_vars['dependant_hipo_job']);
360 
361  // Add the messages saved from the sub-job into our list of messages
362  $this->_running_vars['messages'] = array_get_index($hipo->_running_vars, 'messages', Array());
363 
364  $hipo->save();
365  $hh->uncacheJob($hipo->code_name);
366  } else if ($hipo->process() && $hipo->complete()) {
367  // process the sub hipo on each refresh
368  $running_vars = $hipo->getRunningVars();
369  if (isset($running_vars['assetid'])) {
370  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($running_vars['assetid']);
371  $asset->_updated(FALSE);
372  }
373 
374  // Add the messages saved from the sub-job into our list of messages
375  $this->_running_vars['messages'] = array_get_index($hipo->_running_vars, 'messages', Array());
376 
377  unset($this->_running_vars['dependant_hipo_job']);
378 
379  }
380 
381  // HIPO job completed, and there are no assets left to process
382  // => we are done
383  if ((empty($this->_running_vars['dependant_hipo_job']) === TRUE) && (empty($this->_running_vars['todo_assetids']) === TRUE)) {
384  $step_data['percent_done'] = 100;
385  $step_data['complete'] = TRUE;
386  }
387 
388  return TRUE;
389 
390  }
391  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
392 
393  // create a queue to store the messages
394  $ms->openQueue();
395 
396 
397  if (!empty($this->_running_vars['todo_assetids']) || !$this->_running_vars['done_root']) {
398  if (empty($this->_running_vars['done_assetids']) && !$this->_running_vars['done_root']) {
399 
400  // make sure we process the root asset first
401  $assetid = $this->_running_vars['assetid'];
402  $this->_running_vars['done_root'] = TRUE;
403 
404  } else {
405  $tmp_keys = array_keys($this->_running_vars['todo_assetids']);
406  $assetid = $tmp_keys[0];
407  unset($this->_running_vars['todo_assetids'][$assetid]);
408  }
409  $new_status = $this->_running_vars['new_status'];
410  // if the current status of the status is the same as the new status
411  // if its same there is nothing to be done. otherwise processStatusChange on the asset
412  // one exception is that current asset is in a workflow, the status will always be pending approval
413  $current_status = array_get_index($this->_running_vars['current_asset_statuses'], $assetid, 0);
414  if (($current_status != $new_status) || ($current_status & SQ_SC_STATUS_PENDING)) {
415  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
416  if (!is_null($asset)) {
417  // if an asset has dependants, we don't want to run _updated() on it until
418  // after we have processed them. _updated is run after the execution of the
419  // sub-sub-hipo thingy has completed
420  $dependants = $GLOBALS['SQ_SYSTEM']->am->getDependantChildren($asset->id);
421 
422  // If we are moving into a "pending approval" state and we have been sent
423  // a workflow stream name, then set that as the stream to use before changing status
424  if ((($current_status & (SQ_SC_STATUS_CAN_APPROVE | SQ_STATUS_LIVE)) > 0) && (($new_status & SQ_SC_STATUS_PENDING) > 0)) {
425  if (array_get_index($this->_running_vars, 'workflow_stream') !== NULL) {
426  $wfm = $GLOBALS['SQ_SYSTEM']->getWorkflowManager();
427  $wfm->setStartingStream($assetid, $this->_running_vars['workflow_stream']);
428  }
429  }
430  if (empty($dependants) || !empty($this->_running_vars['process_dependants'])) {
431  $asset->processStatusChange($new_status, FALSE);
432  } else {
433  $asset->processStatusChange($new_status, FALSE, FALSE);
434  }
435  $step_data['message'] = translate('hipo_edit_status', htmlentities($asset->name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET), $asset->id);
436 
437  // this asset has dependants, so we are going to spawn another edit_status hipo
438  // to take care of processing them
439  if (!empty($dependants) && empty($this->_running_vars['process_dependants'])) {
440  $messages = array_merge($this->_running_vars['messages'], $ms->queueContents());
441  if ($code_name = $this->spawnDependantStatusHipo($asset->id, $new_status, $messages)) {
442  $this->_running_vars['dependant_hipo_job'] = $code_name;
443  }
444  }
445  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
446  unset($asset);
447  } else {
448  $step_data['message'] = translate('hipo_skipping_asset', $assetid);
449  $this->_addError(translate('hipo_cannot_edit_status', $assetid));
450  }
451  } else {
452  $step_data['message'] = translate('hipo_skipping_asset', $assetid);
453  }
454  // add this assetid to the done array so we dont do it again
455  $this->_running_vars['done_assetids'][] = $assetid;
456  }//end if empty done ids and not done root
457 
458  // (FB'08: "Workflow email not sent for dependant asset if it is not linked".)
459  // If a dependant asset is not linked elsewhere than where it is now,
460  // assume that its workflow messages would be duplicated by the parent,
461  // and not send it. Otherwise, add it to the queue.
462  if(empty($this->_running_vars['process_dependants']) && isset($assetid)) {
463  $this->_running_vars['messages'] = array_merge($this->_running_vars['messages'], $ms->queueContents());
464  } else {
465  foreach($ms->queueContents() as $internal_message) {
466  $asset_id = $internal_message->parameters['assetid'];
467  $parents = $GLOBALS['SQ_SYSTEM']->am->getDependantParents($asset_id,'',TRUE,FALSE);
468  if(count($parents) > 1 ) {
469  $this->_running_vars['messages'][] = $internal_message;
470  }
471  }
472  }
473 
474  // We've plucked out the messages we want, now dump the rest
475  $ms->abortQueue();
476 
477  if (empty($this->_running_vars['todo_assetids'])) {
478  // We only send or messages if we are not a dependant job, and
479  // we are not asked to not send our messages (send_messages === FALSE)
480  if (empty($this->_running_vars['process_dependants']) && ($send_messages === TRUE) && isset($assetid)) {
481  // send workflow email at this point
482  // there might still be a dependant job waiting to be processed
483  $ms->send($this->_running_vars['messages']);
484  }
485 
486  if (empty($this->_running_vars['dependant_hipo_job'])) {
487  // todo array is empty, and no dependant job left
488  $step_data['percent_done'] = 100;
489  $step_data['complete'] = TRUE;
490  } else {
491  // todo array is empty, but sub-hipo is processing the dependants
492  // so we'll continue until it completes
493  $step_data['complete'] = FALSE;
494  }
495  } else {
496  $total = count($this->_running_vars['todo_assetids']) + count($this->_running_vars['done_assetids']);
497  $step_data['percent_done'] = (count($this->_running_vars['done_assetids']) / $total) * 100;
498  $step_data['complete'] = FALSE;
499  }
500 
501  return TRUE;
502 
503  }//end processStatus()
504 
505 
516  function spawnDependantStatusHipo($assetid, $new_status, $messages)
517  {
518  $init_hipo = new Hipo_Job_Edit_Status();
519 
520  $options['auto_complete'] = TRUE;
521 
522  // we pass the asset id of the 'umbrella' for the dependant assets
523  // and the 'process_dependants' flag. the sub-sub-hipo thingy will
524  // take care of working out what assets (depdants) to process
525  $running_vars = Array(
526  'assetid' => $assetid,
527  'new_status' => $new_status,
528  'process_dependants' => TRUE,
529  'messages' => $messages,
530  );
531 
532  if (array_key_exists('workflow_stream', $this->_running_vars) === TRUE) {
533  $running_vars['workflow_stream'] = $this->_running_vars['workflow_stream'];
534  }
535 
536  $init_hipo->setRunningVars($running_vars);
537  foreach ($options as $k => $v) {
538  $init_hipo->setOption($k, $v);
539  }
540 
541  // create our sub-sub-hipo thingy, until this job is completed, we need
542  // to process it in place of our todo assets
543  $code_name = $init_hipo->initialise($this->source_code_name);
544  if ($code_name) return $code_name;
545  return FALSE;
546 
547  }//end spawnDependantStatusHipo()
548 
549 
550 }//end class
551 
552 ?>