Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
cron_job_expired_workflow.inc
1 <?php
18 require_once SQ_CORE_PACKAGE_PATH.'/system/cron/cron_job/cron_job.inc';
19 require_once SQ_INCLUDE_PATH.'/workflow_manager.inc';
20 require_once SQ_FUDGE_PATH.'/general/datetime.inc';
21 
38 {
39 
40 
47  function __construct($assetid=0)
48  {
49  parent::__construct($assetid);
50 
51  }//end constructor
52 
53 
65  public function create(Array &$link)
66  {
67  require_once SQ_CORE_PACKAGE_PATH.'/system/system_asset_fns.inc';
68  if (!system_asset_fns_create_pre_check($this)) {
69  return FALSE;
70  }
71  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
72  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
73 
74  if ($linkid = parent::create($link)) {
75  if (!system_asset_fns_create_cleanup($this)) {
76  $linkid = FALSE;
77  }
78  }
79 
80  if ($linkid) {
81  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
82  } else {
83  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
84  }
85 
86  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
87  return $linkid;
88 
89  }//end create()
90 
91 
101  protected function _getName($short_name=FALSE)
102  {
103  return translate('cron_job_expired_workflow');
104 
105  }//end _getName()
106 
107 
114  public function canClone()
115  {
116  return FALSE;
117 
118  }//end canClone()
119 
120 
129  public function canDelete()
130  {
131  return FALSE;
132 
133  }//end canDelete()
134 
135 
149  protected function _exec(&$msg)
150  {
151  try {
152  if (MatrixDAL::getDbType() === 'oci') {
153  $sql = 'SELECT
154  aw.assetid, aw.schemaid, aw.wflow , aw.granted , a.name
155  FROM
156  sq_ast_wflow aw, sq_ast a
157  WHERE
158  aw.assetid = a.assetid
159  AND
160  DBMS_LOB.GETLENGTH(aw.wflow) > 0
161  AND
162  aw.granted = 1';
163 
164  $query = MatrixDAL::preparePdoQuery($sql);
165  $rows = MatrixDAL::executePdoAll($query);
166  } else {
167  $rows = MatrixDAL::executeAll('cron_job_expired_workflow', 'getAllRunningWorkflows');
168  }
169  } catch (DALException $e) {
170  throw new Exception ('Unable to get running workflows due to database error: '.$e->getMessage());
171  }
172 
173  $now = time();
174  $cm = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('cron_manager');
175  $last_run = $cm->attr('last_run');
176 
177  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
178 
179  foreach ($rows as $row) {
180  $ms->openQueue();
181 
182  $workflow = unserialize($row['wflow']);
183  $schemaid = $row['schemaid'];
184  $wfm = $GLOBALS['SQ_SYSTEM']->getWorkflowManager();
185  $step =& $wfm->getCurrentStep($workflow); // need by ref
186 
187  if (($step['started'] != 0) && ($step['expiry_time'] != 0)) {
188  $exp_time = $step['started'] + $step['expiry_time'];
189 
190  if ($exp_time < $now) {
191  // workflow step has expired since the last cron run
192 
193  if ($step['escalate']) {
194  // Escalate the job, at any time
195  if (!$wfm->escalateWorkflow($row['assetid'], $schemaid)) {
196  trigger_localised_error('CRON0052', E_USER_WARNING, $schemaid, $assetid);
197  }
198  } else {
199  // Send a stale message, but only if this is the first
200  // time the cron has run that the workflow has gone stale
201  if ($exp_time > $last_run) {
202  $this->_processExpiredWorkflowStep($row['assetid'], $row['name'], $workflow['schema_name'], $schemaid, $step);
203  }
204  }
205  //break;
206  }
207  }
208 
209  // Don't send escalation message for all dependants (See #5034)
210  $escalation_wf_msgs = Array();
211  foreach($ms->queueContents() as $queued_message) {
212  $ms_assetid = $queued_message->parameters['assetid'];
213  if ($ms_assetid) {
214  $parents = $GLOBALS['SQ_SYSTEM']->am->getDependantParents($ms_assetid, '', TRUE, FALSE);
215  foreach($parents as $key => $parentid) {
216  if ($ms_assetid == $parentid) {
217  unset($parents[$key]);
218  }
219  }//end foreach
220 
221  // If asset has no dependant parents or more than 1 dependant parents, send the workflow message
222  if(count($parents) > 1 || empty($parents)) {
223  $escalation_wf_msgs[] = $queued_message;
224  } else {
225  // The asset's only dependant parent is not in workflow, it means workflow was started at this asset
226  $dependant_workflows = $wfm->getSchemaWorkflows($parents[0]);
227  if (empty($dependant_workflows[$schemaid]['steps']) || (isset($dependant_workflows[$schemaid]['complete']) && $dependant_workflows[$schemaid]['complete'])) {
228  $escalation_wf_msgs[] = $queued_message;
229  }//end if
230 
231  }//end else
232  }//end if
233  }//end foreach
234 
235  $ms->abortQueue();
236 
237  // Send all the relevant escalation workflow messages
238  $ms->send($escalation_wf_msgs);
239  unset($escalation_wf_msgs);
240  }
241  unset($rows);
242 
243  return SQ_CRON_JOB_COMPLETED;
244 
245  }//end _exec()
246 
247 
264  protected function _processExpiredWorkflowStep($assetid, $asset_name, $schema_name, $schemaid, $step_data)
265  {
266  $wfm = $GLOBALS['SQ_SYSTEM']->getWorkflowManager();
267  if ($wfm->silentWorkflowParty($assetid)) {
268  return;
269  }
270 
271  $ms = $GLOBALS['SQ_SYSTEM']->getMessagingService();
272  $subject = 'Stale Workflow Step';
273  $hrefs = $GLOBALS['SQ_SYSTEM']->am->getAssetBackendHref(Array($assetid => 'workflow'), FALSE);
274  $href = str_replace('./', '', current($hrefs));
275  $root_urls = explode("\n", SQ_CONF_SYSTEM_ROOT_URLS);
276  $url = 'http://'.current($root_urls).'/'.$href;
277  $type = 'asset.workflow.stale';
278  $admins = $GLOBALS['SQ_SYSTEM']->am->getPermission($assetid, SQ_PERMISSION_ADMIN, TRUE, FALSE, TRUE);
279 
280  $schema_workflows = $wfm->getSchemaWorkflows($assetid);
281  $workflow =& $schema_workflows[$schemaid];
282  $schema_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($schemaid);
283  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
284 
285  // don't automatically escalate, just notify admins
286  $msg_reps = Array(
287  'asset_name' => $asset_name,
288  'assetid' => $assetid,
289  'step_id' => implode('.', $workflow['current_step']),
290  'step_name' => $step_data['step_name'],
291  'schema' => $schema_name,
292  'started_time' => easy_datetime($step_data['started']),
293  'expiry_time' => easy_time_total($step_data['expiry_time']),
294  'workflow_url' => $url,
295  'asset_url' => $asset->getDependantParentsURL(),
296  );
297 
298  // If there are no admins, send it to system admins instead
299  if (empty($admins)) $admins = Array(0);
300  $msg = $ms->newMessage($admins, $type, $msg_reps);
301  $msg->parameters['assetid'] = $assetid;
302 
303  // Does this step have a custom message for stale workflow?
304  if (isset($step_data['message_stale']) && trim($step_data['message_stale']) !== '' ) {
305  $msg->body = trim($step_data['message_stale']);
306  }
307 
308  // Does this step have a custom subject for stale workflow?
309  if (isset($step_data['subject_stale']) && trim($step_data['subject_stale']) !== '' ) {
310  $subject = trim(array_get_index($step_data, 'subject_stale', 'Stale Workflow Step'));
311  $msg->subject = (!empty($subject)) ? $subject : 'Stale Workflow Step';
312  }//end if
313 
314  if (!is_null($schema_asset)) {
315  if ($schema_asset->attr('schema_reply_to_email_address') != '') {
316  $msg->parameters['reply_to'] = $schema_asset->attr('schema_reply_to_email_address');
317  } else {
318  $msg->parameters['reply_to'] = $msg->from;
319  }
320  if ($schema_asset->attr('schema_from_email_address') != '') {
321  $msg->from = $schema_asset->attr('schema_from_email_address');
322  }
323  }
324 
325  $wfm->addMessageReplacements($asset, $msg->subject, $msg->body, $msg->replacements);
326  $ms->enqueueMessage($msg);
327 
328  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
329 
330  }//end _processExpiredWorkflowStep()
331 
332 
343  public function run()
344  {
345  $res = parent::run();
346  if ($res & SQ_CRON_JOB_REMOVE) {
347  $res = $res - SQ_CRON_JOB_REMOVE;
348  }
349  return $res;
350 
351  }//end run()
352 
353 
354 }//end class
355 
356 
357 
358 ?>