ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilForumCronNotification.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 include_once "Services/Cron/classes/class.ilCronJob.php";
5 include_once "./Modules/Forum/classes/class.ilForumMailNotification.php";
6 
14 {
16 
20  protected $settings;
21 
25  public static $providerObject = array();
26 
30  protected static $deleted_ids_cache = array();
31 
35  protected static $ref_ids_by_obj_id = array();
36 
40  protected static $accessible_ref_ids_by_user = array();
41 
45  protected $num_sent_messages = 0;
46 
50  public function __construct()
51  {
52  $this->settings = new ilSetting('frma');
53  }
54 
55  public function getId()
56  {
57  return "frm_notification";
58  }
59 
60  public function getTitle()
61  {
62  global $lng;
63 
64  return $lng->txt("cron_forum_notification");
65  }
66 
67  public function getDescription()
68  {
69  global $lng;
70 
71  return $lng->txt("cron_forum_notification_crob_desc");
72  }
73 
74  public function getDefaultScheduleType()
75  {
76  return self::SCHEDULE_TYPE_IN_HOURS;
77  }
78 
79  public function getDefaultScheduleValue()
80  {
81  return 1;
82  }
83 
84  public function hasAutoActivation()
85  {
86  return false;
87  }
88 
89  public function hasFlexibleSchedule()
90  {
91  return true;
92  }
93 
97  public function hasCustomSettings()
98  {
99  return true;
100  }
101 
105  public function keepAlive()
106  {
107  \ilCronManager::ping($this->getId());
108  }
109 
113  public function run()
114  {
115  global $ilDB, $ilLog, $ilSetting, $lng;
116 
118 
119  $lng->loadLanguageModule('forum');
120 
121  if(!($last_run_datetime = $ilSetting->get('cron_forum_notification_last_date')))
122  {
123  $last_run_datetime = null;
124  }
125 
126  $this->num_sent_messages = 0;
127  $cj_start_date = date('Y-m-d H:i:s');
128 
129  if($last_run_datetime != null &&
130  checkDate(date('m', strtotime($last_run_datetime)), date('d', strtotime($last_run_datetime)), date('Y', strtotime($last_run_datetime))))
131  {
132  $threshold = max(strtotime($last_run_datetime), strtotime('-' . (int)$this->settings->get('max_notification_age', 30) . ' days', time()));
133  }
134  else
135  {
136  $threshold = strtotime('-' . (int)$this->settings->get('max_notification_age', 30) . ' days', time());
137  }
138 
139  $threshold_date = date('Y-m-d H:i:s', $threshold);
140  $new_posts_condition = '
141  frm_posts.pos_status = %s AND (
142  (frm_posts.pos_date >= %s AND frm_posts.pos_date = frm_posts.pos_activation_date) OR
143  (frm_posts.pos_activation_date >= %s AND frm_posts.pos_date < frm_posts.pos_activation_date)
144  ) ';
145  $types = array('integer', 'timestamp', 'timestamp');
146  $values = array(1, $threshold_date, $threshold_date);
147 
148  /*** new posts ***/
149  $res = $ilDB->queryf('
150  SELECT frm_threads.thr_subject thr_subject,
151  frm_data.top_name top_name,
152  frm_data.top_frm_fk obj_id,
153  frm_notification.user_id user_id,
154  frm_threads.thr_pk thread_id,
155  frm_posts.*
156  FROM frm_notification, frm_posts, frm_threads, frm_data
157  WHERE frm_posts.pos_thr_fk = frm_threads.thr_pk AND '.$new_posts_condition.'
158  AND ((frm_threads.thr_top_fk = frm_data.top_pk AND frm_data.top_frm_fk = frm_notification.frm_id)
159  OR (frm_threads.thr_pk = frm_notification.thread_id
160  AND frm_data.top_pk = frm_threads.thr_top_fk) )
161  AND frm_posts.pos_display_user_id != frm_notification.user_id
162  ORDER BY frm_posts.pos_date ASC',
163  $types,
164  $values
165  );
166 
167  $numRows = $ilDB->numRows($res);
168  if($numRows > 0)
169  {
170  $this->sendCronForumNotification($res, ilForumMailNotification::TYPE_POST_NEW);
171  }
172 
173  $this->keepAlive();
174 
175  /*** updated posts ***/
176  $updated_condition = '
177  frm_posts.pos_cens = %s AND frm_posts.pos_status = %s AND
178  (frm_posts.pos_update > frm_posts.pos_date AND frm_posts.pos_update >= %s ) ';
179  $types = array('integer', 'integer', 'timestamp');
180  $values = array(0, 1, $threshold_date);
181 
182  $res = $ilDB->queryf('
183  SELECT frm_threads.thr_subject thr_subject,
184  frm_data.top_name top_name,
185  frm_data.top_frm_fk obj_id,
186  frm_notification.user_id user_id,
187  frm_threads.thr_pk thread_id,
188  frm_posts.*
189  FROM frm_notification, frm_posts, frm_threads, frm_data
190  WHERE frm_posts.pos_thr_fk = frm_threads.thr_pk AND '.$updated_condition.'
191  AND ((frm_threads.thr_top_fk = frm_data.top_pk AND frm_data.top_frm_fk = frm_notification.frm_id)
192  OR (frm_threads.thr_pk = frm_notification.thread_id
193  AND frm_data.top_pk = frm_threads.thr_top_fk) )
194  AND frm_posts.pos_display_user_id != frm_notification.user_id
195  ORDER BY frm_posts.pos_date ASC',
196  $types,
197  $values
198  );
199 
200  $numRows = $ilDB->numRows($res);
201  if($numRows > 0)
202  {
203  $this->sendCronForumNotification($res, ilForumMailNotification::TYPE_POST_UPDATED);
204  }
205 
206  /*** censored posts ***/
207  $censored_condition = '
208  frm_posts.pos_cens = %s AND frm_posts.pos_status = %s AND
209  (frm_posts.pos_cens_date >= %s AND frm_posts.pos_cens_date > frm_posts.pos_activation_date ) ';
210  $types = array('integer', 'integer', 'timestamp');
211  $values = array(1, 1, $threshold_date );
212 
213  $res = $ilDB->queryf('
214  SELECT frm_threads.thr_subject thr_subject,
215  frm_data.top_name top_name,
216  frm_data.top_frm_fk obj_id,
217  frm_notification.user_id user_id,
218  frm_threads.thr_pk thread_id,
219  frm_posts.*
220  FROM frm_notification, frm_posts, frm_threads, frm_data
221  WHERE frm_posts.pos_thr_fk = frm_threads.thr_pk AND '.$censored_condition.'
222  AND ((frm_threads.thr_top_fk = frm_data.top_pk AND frm_data.top_frm_fk = frm_notification.frm_id)
223  OR (frm_threads.thr_pk = frm_notification.thread_id
224  AND frm_data.top_pk = frm_threads.thr_top_fk) )
225  AND (frm_posts.pos_display_user_id != frm_notification.user_id)
226  ORDER BY frm_posts.pos_date ASC',
227  $types,
228  $values
229  );
230 
231  $numRows = $ilDB->numRows($res);
232  if($numRows > 0)
233  {
234  $this->sendCronForumNotification($res, ilForumMailNotification::TYPE_POST_CENSORED);
235  }
236 
237  $this->keepAlive();
238 
239  /*** uncensored posts ***/
240  $uncensored_condition = '
241  frm_posts.pos_cens = %s AND frm_posts.pos_status = %s AND
242  ( frm_posts.pos_cens_date >= %s AND frm_posts.pos_cens_date > frm_posts.pos_activation_date )';
243  $types = array('integer', 'integer', 'timestamp');
244  $values = array(0, 1, $threshold_date);
245 
246  $res = $ilDB->queryf('
247  SELECT frm_threads.thr_subject thr_subject,
248  frm_data.top_name top_name,
249  frm_data.top_frm_fk obj_id,
250  frm_notification.user_id user_id,
251  frm_threads.thr_pk thread_id,
252  frm_posts.*
253  FROM frm_notification, frm_posts, frm_threads, frm_data
254  WHERE frm_posts.pos_thr_fk = frm_threads.thr_pk AND '.$uncensored_condition.'
255  AND ((frm_threads.thr_top_fk = frm_data.top_pk AND frm_data.top_frm_fk = frm_notification.frm_id)
256  OR (frm_threads.thr_pk = frm_notification.thread_id
257  AND frm_data.top_pk = frm_threads.thr_top_fk) )
258  AND frm_posts.pos_display_user_id != frm_notification.user_id
259  ORDER BY frm_posts.pos_date ASC',
260  $types,
261  $values
262  );
263 
264  $numRows = $ilDB->numRows($res);
265  if($numRows > 0)
266  {
267  $this->sendCronForumNotification($res, ilForumMailNotification::TYPE_POST_UNCENSORED);
268  }
269 
270  $this->keepAlive();
271 
272  /*** deleted threads ***/
273  $res = $ilDB->queryF('
274  SELECT frm_posts_deleted.thread_title thr_subject,
275  frm_posts_deleted.forum_title top_name,
276  frm_posts_deleted.obj_id obj_id,
277  frm_notification.user_id user_id,
278  frm_posts_deleted.pos_display_user_id,
279  frm_posts_deleted.pos_usr_alias,
280  frm_posts_deleted.deleted_id,
281  frm_posts_deleted.post_date pos_date,
282  frm_posts_deleted.post_title pos_subject,
283  frm_posts_deleted.post_message pos_message
284 
285  FROM frm_notification, frm_posts_deleted
286 
287  WHERE ( frm_posts_deleted.obj_id = frm_notification.frm_id
288  OR frm_posts_deleted.thread_id = frm_notification.thread_id)
289  AND frm_posts_deleted.pos_display_user_id != frm_notification.user_id
290  AND frm_posts_deleted.is_thread_deleted = %s
291  ORDER BY frm_posts_deleted.post_date ASC',
292  array('integer'), array(1));
293  $numRows = $ilDB->numRows($res);
294  if($numRows > 0)
295  {
296  $this->sendCronForumNotification($res, ilForumMailNotification::TYPE_THREAD_DELETED);
297  if(count(self::$deleted_ids_cache) > 0)
298  {
299  $ilDB->manipulate('DELETE FROM frm_posts_deleted WHERE '. $ilDB->in('deleted_id', self::$deleted_ids_cache, false, 'integer'));
300  $ilLog->write(__METHOD__ . ':DELETED ENTRIES: frm_posts_deleted');
301  }
302  }
303 
304  $this->keepAlive();
305 
306  /*** deleted posts ***/
307  $res = $ilDB->queryF('
308  SELECT frm_posts_deleted.thread_title thr_subject,
309  frm_posts_deleted.forum_title top_name,
310  frm_posts_deleted.obj_id obj_id,
311  frm_notification.user_id user_id,
312  frm_posts_deleted.pos_display_user_id,
313  frm_posts_deleted.pos_usr_alias,
314  frm_posts_deleted.deleted_id,
315  frm_posts_deleted.post_date pos_date,
316  frm_posts_deleted.post_title pos_subject,
317  frm_posts_deleted.post_message pos_message
318 
319  FROM frm_notification, frm_posts_deleted
320 
321  WHERE ( frm_posts_deleted.obj_id = frm_notification.frm_id
322  OR frm_posts_deleted.thread_id = frm_notification.thread_id)
323  AND frm_posts_deleted.pos_display_user_id != frm_notification.user_id
324  AND frm_posts_deleted.is_thread_deleted = %s
325  ORDER BY frm_posts_deleted.post_date ASC',
326  array('integer'), array(0));
327 
328  $numRows = $ilDB->numRows($res);
329  if($numRows > 0)
330  {
331  $this->sendCronForumNotification($res, ilForumMailNotification::TYPE_POST_DELETED);
332  if(count(self::$deleted_ids_cache) > 0)
333  {
334  $ilDB->manipulate('DELETE FROM frm_posts_deleted WHERE '. $ilDB->in('deleted_id', self::$deleted_ids_cache, false, 'integer'));
335  $ilLog->write(__METHOD__ . ':DELETED ENTRIES: frm_posts_deleted');
336  }
337  }
338 
339  $ilSetting->set('cron_forum_notification_last_date', $cj_start_date);
340 
341  $mess = 'Sent '.$this->num_sent_messages.' messages.';
342  $ilLog->write(__METHOD__.': '.$mess);
343 
344  $result = new ilCronJobResult();
345  if($this->num_sent_messages)
346  {
347  $status = ilCronJobResult::STATUS_OK;
348  $result->setMessage($mess);
349  };
350  $result->setStatus($status);
351  return $result;
352  }
353 
358  protected function getRefIdsByObjId($a_obj_id)
359  {
360  if(!array_key_exists($a_obj_id, self::$ref_ids_by_obj_id))
361  {
362  self::$ref_ids_by_obj_id[$a_obj_id] = ilObject::_getAllReferences($a_obj_id);
363  }
364 
365  return (array)self::$ref_ids_by_obj_id[$a_obj_id];
366  }
367 
373  protected function getFirstAccessibleRefIdBUserAndObjId($a_user_id, $a_obj_id)
374  {
378  global $ilAccess;
379 
380  if(!array_key_exists($a_user_id, self::$accessible_ref_ids_by_user))
381  {
382  self::$accessible_ref_ids_by_user[$a_user_id] = array();
383  }
384 
385  if(!array_key_exists($a_obj_id, self::$accessible_ref_ids_by_user[$a_user_id]))
386  {
387  $accessible_ref_id = 0;
388  foreach($this->getRefIdsByObjId($a_obj_id) as $ref_id)
389  {
390  if($ilAccess->checkAccessOfUser($a_user_id, 'read', '', $ref_id))
391  {
392  $accessible_ref_id = $ref_id;
393  break;
394  }
395  }
396  self::$accessible_ref_ids_by_user[$a_user_id][$a_obj_id] = $accessible_ref_id;
397  }
398 
399  return (int)self::$accessible_ref_ids_by_user[$a_user_id][$a_obj_id];
400  }
401 
406  public function sendCronForumNotification($res, $notification_type)
407  {
412  global $ilDB, $ilLog;
413 
414  include_once './Modules/Forum/classes/class.ilForumCronNotificationDataProvider.php';
415  include_once './Modules/Forum/classes/class.ilForumMailNotification.php';
416 
417  while($row = $ilDB->fetchAssoc($res))
418  {
419  if($notification_type == ilForumMailNotification::TYPE_POST_DELETED
420  || $notification_type == ilForumMailNotification::TYPE_THREAD_DELETED)
421  {
422  // important! save the deleted_id to cache before proceeding getFirstAccessibleRefIdBUserAndObjId !
423  self::$deleted_ids_cache[$row['deleted_id']] = $row['deleted_id'];
424  }
425 
426  $ref_id = $this->getFirstAccessibleRefIdBUserAndObjId($row['user_id'], $row['obj_id']);
427  if($ref_id < 1)
428  {
429  $ilLog->write(__METHOD__.': User-Id: '.$row['user_id'].' has no read permission for object id: '.$row['obj_id']);
430  continue;
431  }
432 
433  $row['ref_id'] = $ref_id;
434 
435  if($this->existsProviderObject($row['pos_pk']))
436  {
437  self::$providerObject[$row['pos_pk']]->addRecipient($row['user_id']);
438  }
439  else
440  {
441  $this->addProviderObject($row);
442  }
443  }
444 
445  $i = 0;
446  foreach(self::$providerObject as $provider)
447  {
448  $mailNotification = new ilForumMailNotification($provider);
449  $mailNotification->setIsCronjob(true);
450  $mailNotification->setType($notification_type);
451  $mailNotification->setRecipients(array_unique($provider->getCronRecipients()));
452 
453  $mailNotification->send();
454 
455  if ($i > 0 && ($i % self::KEEP_ALIVE_CHUNK_SIZE) == 0) {
456  $this->keepAlive();
457  }
458 
459  $this->num_sent_messages += count($provider->getCronRecipients());
460  $ilLog->write(__METHOD__.':SUCCESSFULLY SEND: NotificationType: '.$notification_type.' -> Recipients: '. implode(', ',$provider->getCronRecipients()));
461 
462  ++$i;
463  }
464 
465  $this->resetProviderCache();
466  }
467 
472  public function existsProviderObject($post_id)
473  {
474  if(isset(self::$providerObject[$post_id]))
475  {
476  return true;
477  }
478  return false;
479  }
480 
484  private function addProviderObject($row)
485  {
486  $tmp_provider = new ilForumCronNotificationDataProvider($row);
487 
488  self::$providerObject[$row['pos_pk']] = $tmp_provider;
489  self::$providerObject[$row['pos_pk']]->addRecipient($row['user_id']);
490  }
491 
495  private function resetProviderCache()
496  {
497  self::$providerObject = array();
498  }
499 
505  public function addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
506  {
510  global $lng;
511 
512  switch($a_form_id)
513  {
515  $a_fields['cron_forum_notification'] = $a_is_active ?
516  $lng->txt('enabled') :
517  $lng->txt('disabled');
518  break;
519  }
520  }
521 
525  public function activationWasToggled($a_currently_active)
526  {
527  global $ilSetting;
528 
529  // propagate cron-job setting to object setting
530  if((bool)$a_currently_active)
531  {
532  $ilSetting->set('forum_notification', 2);
533  }
534  else
535  {
536  $ilSetting->set('forum_notification', 1);
537  }
538  }
539 
543  public function addCustomSettingsToForm(ilPropertyFormGUI $a_form)
544  {
548  global $lng;
549 
550  $lng->loadLanguageModule('forum');
551 
552  $max_notification_age = new ilNumberInputGUI($lng->txt('frm_max_notification_age'), 'max_notification_age');
553  $max_notification_age->setSize(5);
554  $max_notification_age->setSuffix($lng->txt('frm_max_notification_age_unit'));
555  $max_notification_age->setRequired(true);
556  $max_notification_age->allowDecimals(false);
557  $max_notification_age->setMinValue(1);
558  $max_notification_age->setInfo($lng->txt('frm_max_notification_age_info'));
559  $max_notification_age->setValue($this->settings->get('max_notification_age', 30));
560 
561  $a_form->addItem($max_notification_age);
562  }
563 
568  public function saveCustomSettings(ilPropertyFormGUI $a_form)
569  {
570  $this->settings->set('max_notification_age', $a_form->getInput('max_notification_age'));
571  return true;
572  }
573 }
ILIAS Setting Class.
$result
This class represents a property form user interface.
addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
Add external settings to form.
Cron job application base class.
addItem($a_item)
Add Item (Property, SectionHeader).
static _getAllReferences($a_id)
get all reference ids of object
addCustomSettingsToForm(ilPropertyFormGUI $a_form)
Add custom settings to form.
This class represents a number property in a property form.
saveCustomSettings(ilPropertyFormGUI $a_form)
getInput($a_post_var, $ensureValidation=true)
Returns the value of a HTTP-POST variable, identified by the passed id.
setSize($a_size)
Set Size.
static ping($a_job_id)
Keep cron job alive.
$ref_id
Definition: sahs_server.php:39
global $ilSetting
Definition: privfeed.php:40
global $lng
Definition: privfeed.php:40
global $ilDB
Cron job result data container.