Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
hipo_job.inc
1 <?php
18 // include the hipo system config file
19 require_once SQ_DATA_PATH.'/private/conf/hipo.inc';
20 
30 {
31 
36  var $code_name = '';
37 
42  var $source_code_name = '';
43 
48  var $userid = 0;
49 
54  var $last_updated = 0;
55 
62  var $hipo_name = '';
63 
68  var $is_prepared = FALSE;
69 
77  var $uses_trans = TRUE;
78 
83  var $_hipo_vars = Array(
84  'current_step' => 0,
85  'percent_done' => 0,
86  'initialise_mode' => '', // the mode that this job was initialised() in,
87  // used to decide what to do when we are completed
88  'running_mode' => '', // the mode that is currently doing the processing
89  'aborted' => FALSE, // whether we have been aborted or not
90  'server_taskid' => '', // id the HIPO server gave the task when it went
91  // into running_mode='server'
92  'message' => '',
93  'job_dir' => '', // the directory where the jobs include file is located
94  'errors' => Array(),
95  );
96 
101  var $_options = Array(
102  'on_complete_url' => '',
103  'auto_complete' => TRUE,
104  );
105 
110  var $_running_vars = Array();
111 
116  var $_current_mode = 'web';
117 
155  var $_steps = Array();
156 
157 
164  function HIPO_Job($code_name='')
165  {
166  $this->_current_mode = (SQ_PHP_CLI) ? 'server' : 'web';
167  if (!empty($code_name)) $this->load($code_name);
168 
169  }//end constructor
170 
171 
178  function getCodeName()
179  {
180  return strtolower(get_class($this));
181 
182  }//end getCodeName()
183 
184 
195  function getHipoName()
196  {
197  return $this->hipo_name;
198 
199  }//end getHipoName()
200 
201 
215  {
216  return $this->_steps;
217 
218  }//end getInitialStepData()
219 
220 
227  function complete()
228  {
229  return ($this->_hipo_vars['current_step'] >= count($this->_steps) || $this->_hipo_vars['aborted']);
230 
231  }//end complete()
232 
233 
240  function percentDone()
241  {
242  return (int) $this->_hipo_vars['percent_done'];
243 
244  }//end percentDone()
245 
246 
253  function &getRunningVars()
254  {
255  return $this->_running_vars;
256 
257  }//end getRunningVars()
258 
259 
268  function setRunningVars(&$vars)
269  {
270  if (!is_array($vars)) {
271  trigger_localised_error('HIPO0045', E_USER_WARNING);
272  return;
273  }
274  $this->_running_vars =& $vars;
275 
276  }//end setRunningVars()
277 
278 
288  function setOption($name, $value)
289  {
290  if (!isset($this->_options[$name])) {
291  trigger_localised_error('HIPO0044', E_USER_WARNING, $name);
292  return;
293  }
294  $this->_options[$name] = $value;
295 
296  }//end setOption()
297 
298 
307  function getOption($name)
308  {
309  if (!isset($this->_options[$name])) {
310  trigger_localised_error('HIPO0044', E_USER_WARNING, $name);
311  return NULL;
312  }
313  return $this->_options[$name];
314 
315  }//end getOption()
316 
317 
327  function setHipoVar($name, $value)
328  {
329  if (!isset($this->_hipo_vars[$name])) {
330  trigger_localised_error('HIPO0044', E_USER_WARNING, $name);
331  return;
332  }
333  $this->_hipo_vars[$name] = $value;
334 
335  }//end setHipoVar()
336 
337 
346  function getHipoVar($name)
347  {
348  if (!isset($this->_hipo_vars[$name])) {
349  trigger_localised_error('HIPO0044', E_USER_WARNING, $name);
350  return NULL;
351  }
352  return $this->_hipo_vars[$name];
353 
354  }//end getHipoVar()
355 
356 
368  function _addError($error, $warning=FALSE)
369  {
370  $error = trim($error);
371  if (!empty($error)) {
372  $this->_hipo_vars['errors'][] = Array(
373  'time' => time(),
374  'message' => $error,
375  'warning' => $warning,
376  );
377  }
378 
379  }//end _addError()
380 
381 
388  function getErrors()
389  {
390  return $this->_hipo_vars['errors'];
391 
392  }//end getErrors()
393 
394 
402  function prepare()
403  {
404  $this->is_prepared = TRUE;
405  return TRUE;
406 
407  }//end prepare()
408 
409 
423  function initialise($source_code_name=NULL)
424  {
425  if (!$this->is_prepared) {
426  if (!$this->prepare()) return FALSE;
427  }
428 
429  $this->_hipo_vars['initialise_mode'] = $this->_current_mode;
430  $this->_hipo_vars['running_mode'] = $this->_current_mode;
431 
432  if (empty($source_code_name)) {
433  $source_initialise_mode = $this->_current_mode;
434  } else {
435  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
436  $source_job = $hh->getJob($source_code_name);
437  if (is_null($source_job) || ($source_job->source_code_name != $source_job->code_name)) {
438  return '';
439  }
440  $source_initialise_mode = $source_job->getInitialiseMode();
441  }
442 
443  // get the initial set of steps
444  $init_steps = $this->getInitialStepData();
445 
446  for ($i = 0; $i < count($init_steps); $i++) {
447  // if we are starting from a server script but this job needs the web to run,
448  // then we are in trouble, so get out of here
449  if ($source_initialise_mode == 'server' && $init_steps[$i]['running_mode'] == 'web') {
450  trigger_localised_error('HIPO0043', E_USER_WARNING);
451  return '';
452  // if we aren't using the server and we are in a web script
453  // make sure that all the steps are changed accordingly
454  } else if ($this->_current_mode == 'web' && !SQ_HIPO_USE_SERVER) {
455  $init_steps[$i]['running_mode'] = 'web';
456 
457  } else if ($init_steps[$i]['running_mode'] == 'server' && empty($init_steps[$i]['auto_step'])) {
458  trigger_localised_error('HIPO0042', E_USER_WARNING);
459  $init_steps[$i]['auto_step'] = TRUE;
460 
461  }// end if
462  }// end for
463 
464  // set the step member variable now that it's all translated and converted
465  $this->_steps = $init_steps;
466 
467  $steps = serialize($this->_steps);
468  $vars = serialize($this->_running_vars);
469  $options = serialize($this->_options);
470  $hipo_vars = serialize($this->_hipo_vars);
471  $code_name = $this->getCodeName();
472  $message = '';
473 
474  if (empty($source_code_name)) {
475  $source_code_name = $code_name;
476  }
477 
478  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db3');
479  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
480  $db = MatrixDAL::getDb();
481 
482  try {
483  $bind_vars['code_name'] = $code_name;
484  $result = MatrixDAL::executeAssoc('core', 'getHipoJobsUser', NULL, $bind_vars);
485  $existing = array_get_index($result, 0, Array());
486  } catch (Exception $e) {
487  throw new Exception('Unable to get HIPO job code name: '.$code_name.' due to database error: '.$e->getMessage());
488  }
489 
490  if (!empty($existing)) {
491  $user = $GLOBALS['SQ_SYSTEM']->am->getAsset($existing['userid']);
492  trigger_localised_error('HIPO0041', E_USER_WARNING, $user->name, $user->id, $GLOBALS['SQ_SYSTEM']->datetime(iso8601_ts($existing['last_updated'])));
493  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
494  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
495  return '';
496  }
497 
498  $now = time();
499 
500  try {
501  $bind_vars = Array(
502  'code_name' => $code_name,
503  'job_type' => get_class($this),
504  'userid' => $GLOBALS['SQ_SYSTEM']->currentUserId(),
505  'running' => 0,
506  'source_code_name' => $source_code_name,
507  'hipo_vars' => $hipo_vars,
508  'options' => $options,
509  'steps' => $steps,
510  'running_vars' => $vars,
511  'last_updated' => ts_iso8601($now),
512  );
513 
514  MatrixDAL::executeQuery('core', 'insertHipoJob', $bind_vars);
515  } catch (Exception $e) {
516  throw new Exception('Unable to insert new HIPO job due to database error: '.$e->getMessage());
517  }
518 
519  try {
520  $result = MatrixDAL::executeOne('core', 'getHipoJobsUser', $bind_vars);
521  } catch (Exception $e) {
522  throw new Exception('Unable to get HIPO job code name: '.$code_name.' due to database error: '.$e->getMessage());
523  }
524 
525  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
526  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
527 
528  $this->userid = $GLOBALS['SQ_SYSTEM']->currentUserId();
529  $this->last_updated = $now;
530 
531  return $code_name;
532 
533  }//end initialise()
534 
535 
546  public static function paintConfig(&$o, $class, $write_access)
547  {
548 
549  }//end paintConfig()
550 
551 
568  public static function getConfigVars()
569  {
570  return Array();
571 
572  }//end getConfigVars()
573 
574 
581  function getThreshold()
582  {
583  $config_vars = $this->getConfigVars();
584  if (empty($config_vars)) return 1;
585  foreach ($config_vars as $name => $value) {
586  if (strpos($name, 'THRESHOLD') !== FALSE) {
587  return constant($name);
588  }
589  }
590  return 1;
591 
592  }//end getThreshold()
593 
594 
602  {
603  return 0;
604 
605  }//end getThresholdPercentageRequired()
606 
607 
614  function freestyle()
615  {
616  return TRUE;
617 
618  }//end freestyle()
619 
620 
629  function load($code_name)
630  {
631  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db3');
632  $db = $GLOBALS['SQ_SYSTEM']->db;
633  $db = MatrixDAL::getDb();
634  try {
635  $bind_vars['code_name'] = $code_name;
636  $result = MatrixDAL::executeAssoc('core', 'loadHipoVars', $bind_vars);
637  $result = $result[0];
638  } catch (Exception $e) {
639  throw new Exception('Unable to load the HIPO vars for: '.$code_name.' due to database error: '.$e->getMessage());
640  }
641 
642  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
643 
644  if (empty($result)) return FALSE;
645 
646  if ($result['job_type'] != get_class($this)) {
647  trigger_localised_error('HIPO0040', E_USER_WARNING, $result['job_type'], get_class($this));
648  return FALSE;
649  }
650 
651  $this->code_name = $code_name;
652  $this->source_code_name = $result['source_code_name'];
653  $this->userid = $result['userid'];
654  $this->_hipo_vars = unserialize($result['hipo_vars']);
655  $this->_options = unserialize($result['options']);
656  $this->_steps = unserialize($result['steps']);
657  $this->_running_vars = unserialize($result['running_vars']);
658  $this->last_updated = iso8601_ts($result['last_updated']);
659 
660  // previous last_updated - the last_updated var from the last time load() was called
661  $prev_last_updated = array_get_index($this->_hipo_vars, 'timeout_prev_last_updated', $this->last_updated);
662 
663  // If this task utilises server processing
664  $running_at_server = isset($this->_steps[$this->_hipo_vars['current_step']]) && isset($this->_steps[$this->_hipo_vars['current_step']]['running_mode']) && $this->_steps[$this->_hipo_vars['current_step']]['running_mode'] == 'server';
665 
666  if ($this->_current_mode != 'server' && $running_at_server && SQ_HIPO_USE_SERVER) {
667  if ($this->last_updated > $prev_last_updated) {
668  // keep the last_updated record up to date
669  $prev_last_updated = $this->last_updated;
670 
671  } else {
672  $time_since_update = time() - $prev_last_updated;
673 
674  // is it time to send a request yet?
675  // check whether we've failed to update
676  if ($time_since_update > SQ_HIPO_SERVER_STATUS_CHECK_THRESHOLD) {
677  // check whether the process is still alive - send a request to the server
678 
679  // if there is no system taskid then there is nothing we can do
680  if (empty($this->_hipo_vars['server_taskid'])) {
681  return FALSE;
682  }
683 
684  require_once SQ_SYSTEM_ROOT.'/core/server/squiz_server_client_mysource3.inc';
685 
686  $data = Array(
687  'command' => 'alive',
688  'userid' => $GLOBALS['SQ_SYSTEM']->currentUserId(),
689  'source_code_name' => $this->source_code_name,
690  'taskid' => $this->_hipo_vars['server_taskid'],
691  );
692 
693  $alive = FALSE;
694  $client = new Squiz_Server_Client_MySource3();
695  if ($client->connect()) {
696  if ($client->write('HIPO_Job', $data)) {
697  $ack = $client->read();
698  if (!is_null($ack)) {
699  switch ($ack['result']) {
700  case 'ack':
701  $this->_renewLastUpdated();
702  $prev_last_updated = $this->last_updated;
703  $alive = TRUE;
704  break;
705 
706  case 'error':
707  case 'dead':
708  $alive = FALSE;
709  trigger_localised_error('HIPO0048', E_USER_WARNING, $ack['msg'].' (TaskID #'.$this->_hipo_vars['server_taskid'].')');
710  break;
711 
712  default :
713  trigger_localised_error('HIPO0047', E_USER_WARNING, print_r($ack, TRUE).' (TaskID #'.$this->_hipo_vars['server_taskid'].')');
714  }//end switch ($ack['result'])
715  }//end if (!is_null($ack))
716  }//end if ($client->write())
717  $client->disconnect();
718  }//end if ($client->connect())
719 
720  // not alive, die
721  if (!$alive) {
722  $this->abort();
723  return FALSE;
724  }
725 
726  }//end if ($time_since_update > SQ_HIPO_SERVER_STATUS_CHECK_THRESHOLD)
727  }//end else ($this->last_updated > $prev_last_updated)
728 
729  $this->_hipo_vars['timeout_prev_last_update'] = $prev_last_updated;
730 
731  }//end if ($this->_current_mode != 'server')
732 
733  return TRUE;
734 
735  }//end load()
736 
737 
747  function save($ignore_running_mode=FALSE)
748  {
749  if ((!$GLOBALS['SQ_SYSTEM']->userRoot()) && (!$GLOBALS['SQ_SYSTEM']->userSystemAdmin()) && ($this->userid != $GLOBALS['SQ_SYSTEM']->currentUserId())) {
750  trigger_localised_error('HIPO0039', E_USER_WARNING, $this->code_name);
751  return FALSE;
752  }
753 
754  // if we have called save and we aren't the running version, dont save
755  if (!$ignore_running_mode && $this->_current_mode != $this->_hipo_vars['running_mode']) {
756  return FALSE;
757  }
758 
759  $this->_updateProgress();
760 
761  // Second let's decide, depening on the circumstances, whether to delete or update
762  $delete = FALSE;
763  // if we have aborted, delete right now
764  if ($this->_hipo_vars['aborted']) {
765  $delete = TRUE;
766  } else if ($this->complete()) {
767  // if we are running from the web, we can delete the DB entry
768  // because we are now done with it
769  if ($this->_current_mode == 'web') {
770  $delete = TRUE;
771 
772  // running from the server/cmdline
773  } else {
774 
775  // The idea here is that if we are the top hipo job AND we were initialised in a web script
776  // then we need to leave the DB entry so that the refreshing we script can get the data one last time
777  if ($this->code_name != $this->source_code_name || $this->_hipo_vars['initialise_mode'] != 'web') {
778  $delete = TRUE;
779  }
780 
781  }// endif
782 
783  }// end if
784 
785  $now = time();
786 
787  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db3');
788  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
789 
790  $db = MatrixDAL::getDb();
791  // now we just do what we are told
792  if ($delete) {
793  try {
794  $bind_vars['code_name'] = $this->code_name;
795  MatrixDAL::executeQuery('core', 'deleteHipoJobFromCodeName', $bind_vars);
796  } catch (Exception $e) {
797  throw new Exception('Unable to delete HIPO job with code name: '.$code_name.' due to database error: '.$e->getMessage());
798  }
799  } else {
800 
801  try {
802  $bind_vars = Array (
803  'hipo_vars' => serialize($this->_hipo_vars),
804  'options' => serialize($this->_options),
805  'steps' => serialize($this->_steps),
806  'running_vars' => serialize($this->_running_vars),
807  'last_updated' => ts_iso8601($now),
808  'code_name' => $this->code_name,
809  );
810  MatrixDAL::executeQuery('core', 'updateHipoJobVars', $bind_vars);
811  } catch (Exception $e) {
812  throw new Exception('Unable to update HIPO job vars due to database error: '.$e->getMessage());
813  }
814 
815  }
816 
817  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
818  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
819  $this->last_updated = $now;
820 
821  return TRUE;
822 
823  }//end save()
824 
825 
832  function _updateProgress()
833  {
834  // First let's make sure that everything is in order with the hipo vars and our complete status
835  if (!$this->complete()) {
836  $step = $this->_hipo_vars['current_step'];
837 
838  $prev_step_per = ($step / count($this->_steps)) * 100;
839  $this_step_per = ($this->complete()) ? 0 : ((1 / count($this->_steps)) * $this->_steps[$step]['percent_done']);
840  $this->_hipo_vars['percent_done'] = round($prev_step_per + $this_step_per, 2);
841 
842  if (!empty($this->_steps[$step]['complete'])) {
843  $this->getNextStep();
844  }
845 
846  }// end if
847 
848  // if we have completed then we need to re-set the running mode back to the init mode
849  if ($this->complete()) {
850  $this->_hipo_vars['running_mode'] = $this->_hipo_vars['initialise_mode'];
851  }
852 
853  }//end _updateProgress()
854 
855 
865  function _renewLastUpdated($new_time=NULL)
866  {
867  if (is_null($new_time)) $new_time = time();
868 
869  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db3');
870  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
871  $db = $GLOBALS['SQ_SYSTEM']->db;
872 
873  $sql = 'UPDATE
874  sq_hipo_job
875  SET
876  last_updated = :new_time
877  WHERE
878  code_name = :code_name';
879 
880  $query = MatrixDAL::preparePdoQuery($sql);
881  MatrixDAL::bindValueToPdo($query, 'new_time', ts_iso8601($new_time));
882  MatrixDAL::bindValueToPdo($query, 'code_name', $this->code_name);
883  MatrixDAL::execPdoQuery($query);
884 
885  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
886  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
887 
888  }//end _renewLastUpdated()
889 
890 
898  function &_getSubJob()
899  {
900  $step = $this->_hipo_vars['current_step'];
901  if (isset($this->_steps[$step])) {
902  if (!empty($this->_steps[$step]['hipo_job']) && !empty($this->_steps[$step]['hipo_job']['code_name']) && !empty($this->_steps[$step]['hipo_job']['job_type'])) {
903  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
904  $job = $hh->getJob($this->_steps[$step]['hipo_job']['code_name']);
905  return $job;
906  }// end if
907  }// endif
908 
909  $null = NULL; // because we need to return by ref
910  return $null;
911 
912  }//end _getSubJob()
913 
914 
921  function getInitialiseMode()
922  {
923  return $this->_hipo_vars['initialise_mode'];
924 
925  }//end getInitialiseMode()
926 
927 
938  function setRunningMode($mode, $server_taskid='')
939  {
940  if ($mode != 'web' && $mode != 'server') {
941  return FALSE;
942  }
943 
944  $sub_job = $this->_getSubJob();
945  if (!is_null($sub_job)) {
946  if (!$sub_job->setRunningMode($mode)) return FALSE;
947  }// end if
948 
949  $this->_hipo_vars['running_mode'] = $mode;
950  $this->_hipo_vars['server_taskid'] = $server_taskid;
951  if ($this->save(TRUE)) {
952  return TRUE;
953  } else {
954  return FALSE;
955  }
956 
957  }//end setRunningMode()
958 
959 
966  function getRunningMode()
967  {
968  return $this->_hipo_vars['running_mode'];
969 
970  }//end getRunningMode()
971 
972 
979  function autoStep()
980  {
981  $step = $this->_hipo_vars['current_step'];
982  if ($this->complete()) {
983  // if we are complete, but there are errors, we need to pause for them to be seen
984  if (!empty($this->_hipo_vars['errors'])) {
985  return FALSE;
986  } else {
987  return $this->_options['auto_complete'];
988  }
989 
990  } else if (!empty($this->_steps[$step]['function_call'])) {
991  return $this->_steps[$step]['auto_step'];
992 
993  } else if (!empty($this->_steps[$step]['hipo_job'])) {
994 
995  $sub_job = $this->_getSubJob();
996  // if we are processing a sub job, it's it's decision whether to auto step or not
997  if (!is_null($sub_job)) {
998  return $sub_job->autoStep();
999 
1000  // otherwise do what's set for this step
1001  } else {
1002  return $this->_steps[$step]['auto_step'];
1003 
1004  }// end if
1005 
1006  }// end if
1007 
1008  return FALSE;
1009 
1010  }//end autoStep()
1011 
1012 
1019  function getNextStep()
1020  {
1021  $this->_hipo_vars['current_step']++;
1022  for ($i = $this->_hipo_vars['current_step']; $i < count($this->_steps); $i++) {
1023  if (isset($this->_steps[$i]['skip_step']) && $this->_steps[$i]['skip_step']) {
1024  $this->_steps[$i]['complete'] = TRUE;
1025  $this->_steps[$i]['percent_done'] = 100;
1026  $this->_hipo_vars['current_step']++;
1027 
1028  continue;
1029  } else {
1030  break;
1031  }
1032  }
1033 
1034  return $this->_hipo_vars['current_step'];
1035 
1036  }//end getNextStep()
1037 
1038 
1047  function skipStep($stepid=0)
1048  {
1049  if (!isset($this->_steps[$stepid])) return FALSE;
1050  $this->_steps[$stepid]['skip_step'] = TRUE;
1051 
1052  return TRUE;
1053 
1054  }//end skipStep()
1055 
1056 
1069  function paint(&$o, $nested=FALSE)
1070  {
1071  if ($this->_current_mode != 'web') {
1072  trigger_localised_error('HIPO0038', E_USER_WARNING);
1073  return;
1074  }
1075 
1076  require_once SQ_LIB_PATH.'/html_form/html_form.inc';
1077  $step = $this->_hipo_vars['current_step'];
1078  $step_data = (isset($this->_steps[$step])) ? $this->_steps[$step] : Array();
1079 
1080  // if we have more than one step we need to "total" progress bar
1081  if ($nested && count($this->_steps) > 1) {
1082  if ($step_data) {
1083  $status_msg = $this->_steps[$step]['name'];
1084  } else {
1085  // this step doesnt exist - probably reached the end of the HIPO
1086  $status_msg = ($this->complete()) ? translate('completed') : translate('unknown_error_occurred');
1087  }
1088 
1089  $o->openSection($this->getHipoName());
1090  $o->openField('&nbsp;');
1091  HIPO_Job::paintProgressBar($this->_hipo_vars['percent_done'], translate('hipo_progress', $this->getHipoName()).' - '.$status_msg);
1092  $o->closeField();
1093  $o->closeSection();
1094  }
1095 
1096  // print the error report if there are errors
1097  if ($this->complete() && !empty($this->_hipo_vars['errors'])) {
1098  echo '<p>';
1099  $this->_paintErrorReport(TRUE);
1100  echo '</p>';
1101  return;
1102  }
1103 
1104  if ($step_data) {
1105  if (!empty($this->_steps[$step]['function_call'])) {
1106  $fn = (empty($this->_steps[$step]['function_call']['paint_function'])) ? 'paintStepDefault' : $this->_steps[$step]['function_call']['paint_function'];
1107  $prefix = $this->code_name.'step'.$step;
1108  $this->$fn($this->_steps[$step], $o, $prefix);
1109  } else if (!empty($step_data['hipo_job'])) {
1110  $sub_job = $this->_getSubJob();
1111  if (!is_null($sub_job)) {
1112  $o->closeRaw();
1113  $sub_job->paint($o, TRUE);
1114  $o->openRaw();
1115  }
1116  } else {
1117  trigger_localised_error('HIPO0037', E_USER_WARNING, $this->_hipo_vars['current_step']);
1118  }
1119  }//end if
1120 
1121  }//end paint()
1122 
1123 
1136  function process()
1137  {
1138  if ((!$GLOBALS['SQ_SYSTEM']->userRoot()) && (!$GLOBALS['SQ_SYSTEM']->userSystemAdmin()) && ($this->userid != $GLOBALS['SQ_SYSTEM']->currentUserId())) {
1139  trigger_localised_error('HIPO0036', E_USER_WARNING);
1140  return FALSE;
1141  }
1142 
1143  // if we are is a display mode different from the running mode, we should not be
1144  // doing any processing or saving - so just return TRUE here
1145  if ($this->_current_mode != $this->_hipo_vars['running_mode']) {
1146  return TRUE;
1147  }
1148 
1149  // if we are complete, then just save (which will clear the DB if needed)
1150  if ($this->complete()) return $this->save();
1151 
1152  $step = $this->_hipo_vars['current_step'];
1153  if ($this->_steps[$step]['running_mode'] == $this->_hipo_vars['running_mode']) {
1154 
1155  // call the correct process function based on the running mode
1156  if ($this->_hipo_vars['running_mode'] == 'web') {
1157  // web mode
1158  set_error_handler(Array(&$this, '_errorHandler'));
1159  $max_assets_to_process = max($this->getThreshold(), 1);
1160  $i = 0;
1161  $ret_val = TRUE;
1162  while (($i < $max_assets_to_process) && (!$this->_steps[$step]['complete'])) {
1163  $prefix = $this->code_name.'step'.$step;
1164  $ret_val = $ret_val && $this->processWeb($this->_steps[$step], $prefix);
1165  $i++;
1166  }
1167  restore_error_handler();
1168  return $ret_val;
1169 
1170  } else {
1171  // server mode
1172  $prefix = $this->code_name.'step'.$step;
1173  set_error_handler(Array(&$this, '_errorHandler'));
1174  $ret_val = $this->processServer($this->_steps[$step], $prefix);
1175  restore_error_handler();
1176  return $ret_val;
1177  }
1178 
1179  // if we are using the server
1180  } else if (SQ_HIPO_USE_SERVER) {
1181 
1182  switch ($this->_steps[$step]['running_mode']) {
1183  // We are currently running in a web script, but this step utilises server processing
1184  // let's put a call through the HIPO phone to the server
1185  case 'server' :
1186 
1187  require_once SQ_SYSTEM_ROOT.'/core/server/squiz_server_client_mysource3.inc';
1188 
1189  $data = Array(
1190  'command' => 'start',
1191  'userid' => $GLOBALS['SQ_SYSTEM']->currentUserId(),
1192  'source_code_name' => $this->source_code_name,
1193  );
1194 
1195  $ret_val = FALSE;
1196  $client = new Squiz_Server_Client_MySource3();
1197  if ($client->connect()) {
1198  if ($client->write('HIPO_Job', $data)) {
1199  $ack = $client->read();
1200  if (!is_null($ack)) {
1201  switch ($ack['result']) {
1202  case 'ack' :
1203  $ret_val = TRUE;
1204  break;
1205 
1206  case 'error' :
1207  trigger_localised_error('HIPO0054', E_USER_WARNING, $ack['msg']);
1208  break;
1209 
1210  default :
1211  trigger_localised_error('HIPO0053', E_USER_WARNING, print_r($ack, TRUE));
1212 
1213  }// end switch
1214  }// end if
1215  }// end if
1216 
1217  $client->disconnect();
1218 
1219  }// endif
1220 
1221  // return here because we don't want to save and override the DB value now that it's running
1222  // on the server
1223  return $ret_val;
1224  break;
1225 
1226  // We are currently running on the server, but this step needs web processing
1227  // let's reset the running mode and get out of here
1228  case 'web' :
1229  // if we have reached a new step, that uses a different running mode to ourselves, then change our running mode
1230  // pre_echo(__FUNCTION__."::".__LINE__.">>>>>>>>>>>>>>>>> RESET RUNNING MODE TO web <<<<<<<<<<<<<<<<<<<");
1231  log_error('The Squiz Server reset the running mode to WEB for User ID #'.$GLOBALS['SQ_SYSTEM']->currentUserId().' and Job '.$this->source_code_name);
1232  return $this->setRunningMode('web');
1233  break;
1234 
1235  default :
1236  trigger_localised_error('HIPO0052', E_USER_WARNING, $this->_steps[$step]['running_mode']);
1237  $this->abort();
1238  return FALSE;
1239 
1240  }//end switch
1241 
1242  // if we aren't using the server this should never happen (because of what happens in initialise())
1243  } else {
1244  trigger_localised_error('HIPO0051', E_USER_ERROR);
1245 
1246  }// endif
1247 
1248  }//end process()
1249 
1250 
1262  function processWeb(&$step_data, $prefix)
1263  {
1264  $process_ok = FALSE;
1265  if (!empty($step_data['function_call'])) {
1266  $fn = $step_data['function_call']['process_function'];
1267  $process_ok = $this->$fn($step_data, $prefix);
1268 
1269  } else if (!empty($step_data['hipo_job'])) {
1270  if (empty($step_data['hipo_job']['code_name']) || empty($step_data['hipo_job']['job_type'])) {
1271  $fn = $step_data['hipo_job']['init_details_function'];
1272  // First let's get the info needed to create this
1273  $job_type = '';
1274  $running_vars = Array();
1275  $options = Array();
1276  $hipo_vars = Array();
1277  $this->$fn($job_type, $running_vars, $options, $hipo_vars);
1278 
1279  // so they have decided to ignore this step ? that's cool
1280  if (empty($job_type)) {
1281  $process_ok = TRUE;
1282 
1283  } else {
1284  if (empty($hipo_vars)) {
1285  require_once SQ_SYSTEM_ROOT.'/core/hipo/jobs/'.$job_type.'.inc';
1286  } else {
1287  require_once $hipo_vars['job_dir'].'/'.$job_type.'.inc';
1288  }
1289 
1290  $init_hipo = new $job_type();
1291 
1292  $init_hipo->setRunningVars($running_vars);
1293  foreach ($options as $k => $v) {
1294  $init_hipo->setOption($k, $v);
1295  }
1296  foreach ($hipo_vars as $k => $v) {
1297  $init_hipo->setHipoVar($k, $v);
1298  }
1299 
1300  $code_name = $init_hipo->initialise($this->source_code_name);
1301  if ($code_name) {
1302  $step_data['hipo_job']['code_name'] = $code_name;
1303  $step_data['hipo_job']['job_type'] = $job_type;
1304  $process_ok = TRUE;
1305  }
1306 
1307  }// end if
1308 
1309  } else {
1310  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1311  $hipo = $hh->getJob($step_data['hipo_job']['code_name']);
1312  if (!is_null($hipo) && $hipo->process()) {
1313  $step_data['running_mode'] = $hipo->getRunningMode();
1314  $step_data['percent_done'] = $hipo->percentDone();
1315  $step_data['complete'] = $hipo->complete();
1316  $process_ok = TRUE;
1317  }
1318 
1319  }// end if
1320 
1321  } else {
1322  trigger_localised_error('HIPO0050', E_USER_WARNING, $this->_hipo_vars['current_step']);
1323 
1324  }// end if
1325 
1326  $save_ok = $this->save();
1327  return ($process_ok && $save_ok);
1328 
1329  }//end processWeb()
1330 
1331 
1345  function processServer(&$step_data, $prefix)
1346  {
1347  if (!empty($step_data['function_call'])) {
1348  $fn = $step_data['function_call']['process_function'];
1349  $prev_percent = (int) $this->_hipo_vars['percent_done'];
1350  while (!$step_data['complete']) {
1351  if (!$this->$fn($step_data, $prefix)) {
1352  $this->save();
1353  return FALSE;
1354  }
1355 
1356  $current_percent = (int) $this->_hipo_vars['percent_done'];
1357  if ((($current_percent != $prev_percent) && ($current_percent % 3 == 0)) || $step_data['complete']) {
1358  // Full save point or job is finished
1359  $this->save(FALSE);
1360  $prev_percent = $current_percent;
1361  } else {
1362  // Else progress to the next step
1363  $this->_updateProgress();
1364  }//end if
1365  }//end while
1366  return TRUE;
1367 
1368  } else if (!empty($step_data['hipo_job'])) {
1369 
1370  $fn = $step_data['hipo_job']['init_details_function'];
1371 
1372  // First let's get the info needed to create this
1373  $job_type = '';
1374  $running_vars = Array();
1375  $options = Array();
1376  $hipo_vars = Array();
1377  $this->$fn($job_type, $running_vars, $options, $hipo_vars);
1378 
1379  if (empty($job_type)) return FALSE;
1380 
1381  if (empty($hipo_vars)) {
1382  require_once SQ_SYSTEM_ROOT.'/core/hipo/jobs/'.$job_type.'.inc';
1383  } else {
1384  require_once $hipo_vars['job_dir'].'/'.$job_type.'.inc';
1385  }
1386 
1387  $init_hipo = new $job_type();
1388 
1389  $init_hipo->setRunningVars($running_vars);
1390  foreach ($options as $k => $v) {
1391  $init_hipo->setOption($k, $v);
1392  }
1393 
1394  $code_name = $init_hipo->initialise($this->source_code_name);
1395  if (!$code_name) return FALSE;
1396  unset($init_hipo);
1397 
1398  $step_data['hipo_job']['code_name'] = $code_name;
1399  $step_data['hipo_job']['job_type'] = $job_type;
1400  $this->save();
1401 
1402  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1403  $hipo = $hh->getJob($code_name, $job_type);
1404  if (is_null($hipo)) return FALSE;
1405 
1406  while (!$step_data['complete'] && $step_data['running_mode'] == 'server') {
1407  if (!$hipo->process()) return FALSE;
1408  $step_data['running_mode'] = $hipo->getRunningMode();
1409  $step_data['percent_done'] = $hipo->percentDone();
1410  $step_data['complete'] = $hipo->complete();
1411  $this->save();
1412  }
1413 
1414  return TRUE;
1415 
1416  } else {
1417  trigger_localised_error('HIPO0050', E_USER_WARNING, $this->_hipo_vars['current_step']);
1418  return FALSE;
1419 
1420  }// end if
1421 
1422  }//end processServer()
1423 
1424 
1434  function abort($abort_source=TRUE, $abort_dependant=TRUE)
1435  {
1436  // If "source_code_name" and "code_name" are differnet then this is a dependant job
1437  // Therefore get the job's source and abort it too
1438  if ($abort_source && $this->source_code_name != $this->code_name) {
1439  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1440  $source_job = $hh->getJob($this->source_code_name);
1441  if (is_null($source_job) || ($source_job->source_code_name != $source_job->code_name)) {
1442  return FALSE;
1443  }
1444  $source_job->abort(TRUE, FALSE);
1445  }
1446  // If the job has spawned a dependant job, abort it (Bug #5838)
1447  if ($abort_dependant) {
1448  $dependant_job = $this->getDependantHipoJob();
1449  if (!is_null($dependant_job)) {
1450  $dependant_job->abort(FALSE, TRUE);
1451  }
1452  }
1453 
1454  // if aborting through a web script, but the processing is running on the server we need to inform the server to abort
1455  if ($this->_current_mode == 'web' && $this->_hipo_vars['running_mode'] == 'server') {
1456 
1457  // if there is no system taskid then there is nothing we can do
1458  if (empty($this->_hipo_vars['server_taskid'])) {
1459  return FALSE;
1460  }
1461 
1462  require_once SQ_SYSTEM_ROOT.'/core/server/squiz_server_client_mysource3.inc';
1463 
1464  $data = Array(
1465  'command' => 'abort',
1466  'userid' => $GLOBALS['SQ_SYSTEM']->currentUserId(),
1467  'source_code_name' => $this->source_code_name,
1468  'taskid' => $this->_hipo_vars['server_taskid'],
1469  );
1470 
1471  $ret_val = FALSE;
1472  $client = new Squiz_Server_Client_MySource3();
1473  if ($client->connect()) {
1474  if ($client->write('HIPO_Job', $data)) {
1475  $ack = $client->read();
1476  if (!is_null($ack)) {
1477  switch ($ack['result']) {
1478  case 'ack' :
1479  $ret_val = TRUE;
1480  break;
1481 
1482  case 'error' :
1483  trigger_localised_error('HIPO0048', E_USER_WARNING, $ack['msg'].' (TaskID #'.$this->_hipo_vars['server_taskid'].')');
1484  break;
1485 
1486  default :
1487  trigger_localised_error('HIPO0047', E_USER_WARNING, print_r($ack, TRUE).' (TaskID #'.$this->_hipo_vars['server_taskid'].')');
1488 
1489  }// end switch
1490 
1491  }// end if
1492  }// end if
1493 
1494  $client->disconnect();
1495  }// endif
1496 
1497  if ($ret_val) return TRUE;
1498 
1499  trigger_localised_error('HIPO0046', E_USER_WARNING);
1500  // fall through and delete this job, set the running mode to allow the saving
1501  $this->setRunningMode('web');
1502 
1503  }//end if
1504 
1505  $this->jobAborted();
1506 
1507  $sub_job = $this->_getSubJob();
1508  if (!is_null($sub_job)) $sub_job->jobAborted();
1509 
1510  return TRUE;
1511 
1512  }//end abort()
1513 
1514 
1521  function jobAborted()
1522  {
1523  $this->setOption('auto_complete', TRUE);
1524  $this->_hipo_vars['aborted'] = TRUE;
1525  return $this->save();
1526 
1527  }//end jobAborted()
1528 
1529 
1537  {
1538  require_once SQ_FUDGE_PATH.'/general/datetime.inc';
1539 
1540  ?>
1541  <div align="center">
1542  <table border="0" cellspacing="1" cellpadding="1" bgcolor="#000000" width="95%">
1543  <tr>
1544  <td bgcolor="#412F49" align="center" width="100%">
1545  <span style="color: #FFFFFF;"><b><?php echo translate('hipo_error_report', $this->getHipoName());?></b><br />
1546  <span style="font-size: 80%;">
1547  <?php echo translate('hipo_herder_completion', (!$this->complete()) ? translate('not') : ''); ?>
1548  </span>
1549  </span>
1550  </td>
1551  </tr>
1552  <tr>
1553  <td bgcolor="#9E86AA" width="100%">
1554  <table border="0" width="100%" cellspacing="2" cellpadding="1">
1555  <?php
1556  foreach ($this->_hipo_vars['errors'] as $error) {
1557  $err_type = ($error['warning']) ? translate('warning').': ' : translate('error').': ';
1558  ?>
1559  <tr>
1560  <td align="left" valign="top">
1561  <b>
1562  <?php echo $err_type; ?>
1563  </b>
1564  <?php echo $error['message']; ?>
1565  <br/>
1566  <span class="sq-hipo-small"><?php echo translate('reported'); ?> <?php echo readable_datetime($error['time']);?></span>
1567  <hr/>
1568  </td>
1569  </tr>
1570  <?php
1571  }
1572  ?>
1573  </table>
1574  </td>
1575  </tr>
1576  <tr>
1577  <td bgcolor="#412F49" align="right">
1578  <b><a style="color: #FFFFFF; text-decoration: none;" href="<?php echo $this->_options['on_complete_url']; ?>"><?php echo translate('continue'); ?> >>&nbsp;</a>
1579  </td>
1580  </tr>
1581  </table>
1582  </div>
1583  <?php
1584 
1585  }//end _paintErrorReport()
1586 
1587 
1598  function paintStepDefault(&$step_data, &$o, $prefix)
1599  {
1600  $o->openSection($step_data['name']);
1601  $o->openField('&nbsp;');
1602  $this->paintProgressBar($step_data['percent_done'], $step_data['message']);
1603  $o->closeField();
1604  $o->closeSection();
1605 
1606  }//end paintStepDefault()
1607 
1608 
1623  public static function paintProgressBar($percent_done, $message='', $label_class='sq-hipo-progress-bar-label', $percent_class='sq-hipo-progress-bar-percent', $bar_main_class='sq-hipo-progress-bar-main', $bar_done_class='sq-hipo-progress-bar-done')
1624  {
1625  ?>
1626  <table width="100%" border="0" cellspacing="0" cellpadding="0">
1627  <tr>
1628  <td class="<?php echo $label_class; ?>"><b><?php echo nl2br($message); ?></b></td>
1629  <td class="<?php echo $percent_class; ?>"><b><?php echo round($percent_done); ?>%</b></td>
1630  </tr>
1631  <tr>
1632  <td colspan="2"><img src="<?php echo sq_web_path('lib').'/web/images/blank.gif'; ?>" width="1" height="10" alt="blank" /></td>
1633  <tr>
1634  <td colspan="2" width="100%">
1635  <table width="100%" cellspacing="0" cellpadding="0" border="0">
1636  <tr>
1637  <td class="<?php echo $bar_main_class; ?>" width="100%">
1638  <table width="<?php echo ($percent_done) ? round($percent_done) : '1'; ?>%" cellspacing="0" cellpadding="0" border="0">
1639  <tr>
1640  <td class="<?php echo $bar_done_class; ?>"><img src="<?php echo sq_web_path('lib').'/web/images/blank.gif'; ?>" width="1" height="8" alt="blank" /></td>
1641  </tr>
1642  </table>
1643  </td>
1644  </tr>
1645  </table>
1646  </td>
1647  </tr>
1648  </table>
1649  <?php
1650 
1651  }//end paintProgressBar()
1652 
1653 
1666  function _errorHandler($err_no, $err_msg, $err_file, $err_line)
1667  {
1668  $terminate = ((E_USER_ERROR | E_ERROR) & $err_no);
1669 
1670  // Treat PHP 5.2 catchable fatals as PHP 5.1 fatals
1671  if (defined('E_RECOVERABLE_ERROR') && ($err_no == E_RECOVERABLE_ERROR)) {
1672  $terminate = TRUE;
1673  }
1674 
1675  // if the function didn't have an '@' prepended OR if we are about to terminate
1676  // catch the error
1677  if ((error_reporting() & $err_no) || $terminate) {
1678  // Strip out the file path begining
1679  $err_file = hide_system_root($err_file);
1680  $err_msg = hide_system_root($err_msg);
1681 
1682  $text_msg = strip_tags(preg_replace(Array('/<br\\/?>/i', '/<p[^>]*>/i'), Array("\n", "\n\n"), $err_msg));
1683 
1684  // send a report to the system error log
1685  if (ini_get('log_errors')) {
1686  log_error($text_msg, $err_no, $err_file, $err_line);
1687  }
1688 
1689  $msg = $text_msg;
1690  if (SQ_CONF_DEBUG & 1) {
1691  $msg .= ' ('.$err_file.':'.$err_line.')';
1692  }
1693  $this->_addError($msg, !$terminate);
1694 
1695  // the hipo job is about to die, make sure the errors are saved to be discovered later
1696  if ($terminate) $this->save();
1697 
1698  }//end error_reporting
1699 
1700  }//end _errorHandler()
1701 
1702 
1710  {
1711  $dependant_job = NULL;
1712  if (!empty($this->_running_vars['dependant_hipo_job'])) {
1713  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
1714  $dependant_job = $hh->getJob($this->_running_vars['dependant_hipo_job']);
1715  }
1716 
1717  return $dependant_job;
1718 
1719  }//end getDependantHipoJob()
1720 
1721 }//end class
1722 ?>