ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilExAssignmentReminder.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2018 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
15 {
16  const SUBMIT_REMINDER = "submit";
17  const GRADE_REMINDER = "grade";
18  const FEEDBACK_REMINDER = "peer";
19 
20  protected $db;
21  protected $tree;
22  protected $now;
23 
24  protected $rmd_status;
25  protected $rmd_start;
26  protected $rmd_end;
27  protected $rmd_frequency;
28  protected $rmd_last_send;
29  protected $rmd_tpl_id;
30 
31  protected $ass_id;
32  protected $exc_id;
33  protected $rmd_type;
34 
35  protected $log;
36 
37  //todo remove the params as soon as possible.
38  public function __construct($a_exc_id = "", $a_ass_id = "", $a_type = "")
39  {
40  global $DIC;
41  $this->db = $DIC->database();
42  $this->tree = $DIC->repositoryTree();
43  $this->access = $DIC->access();
44  $this->log = ilLoggerFactory::getLogger("exc");
45 
46  if ($a_ass_id) {
47  $this->ass_id = $a_ass_id;
48  }
49  if ($a_exc_id) {
50  $this->exc_id = $a_exc_id;
51  }
52  if ($a_type) {
53  $this->rmd_type = $a_type;
54  }
55  if ($a_exc_id and $a_ass_id and $a_type) {
56  $this->read();
57  }
58  }
59 
60  public function getReminderType()
61  {
62  return $this->rmd_type;
63  }
64 
69  public function setReminderStatus($a_status)
70  {
71  $this->rmd_status = $a_status;
72  }
73 
78  public function getReminderStatus()
79  {
80  return $this->rmd_status;
81  }
82 
87  public function setReminderStart($a_num_days)
88  {
89  $this->rmd_start = $a_num_days;
90  }
91 
96  public function getReminderStart()
97  {
98  return $this->rmd_start;
99  }
100 
105  public function setReminderEnd($a_date)
106  {
107  $this->rmd_end = $a_date;
108  }
109 
114  public function getReminderEnd()
115  {
116  return $this->rmd_end;
117  }
118 
123  public function setReminderFrequency($a_num_days)
124  {
125  $this->rmd_frequency = $a_num_days;
126  }
127 
132  public function getReminderFrequency()
133  {
134  return $this->rmd_frequency;
135  }
136 
137  public function setReminderLastSend($a_timestamp)
138  {
139  $this->rmd_last_send = $a_timestamp;
140  }
141 
142  public function getReminderLastSend()
143  {
144  return $this->rmd_last_send;
145  }
146 
147  public function setReminderMailTemplate($a_tpl_id)
148  {
149  $this->rmd_tpl_id = $a_tpl_id;
150  }
151 
152  public function getReminderMailTemplate()
153  {
154  return $this->rmd_tpl_id;
155  }
156 
157  public function save()
158  {
159  $this->db->insert("exc_ass_reminders", array(
160  "type" => array("text", $this->rmd_type),
161  "ass_id" => array("integer", $this->ass_id),
162  "exc_id" => array("integer", $this->exc_id),
163  "status" => array("integer", $this->getReminderStatus()),
164  "start" => array("integer", $this->getReminderStart()),
165  "end" => array("integer", $this->getReminderEnd()),
166  "freq" => array("integer", $this->getReminderFrequency()),
167  "last_send" => array("integer", $this->getReminderLastSend()),
168  "template_id" => array("integer", $this->getReminderMailTemplate())
169  ));
170  }
171 
172  public function update()
173  {
174  $this->db->update(
175  "exc_ass_reminders",
176  array(
177  "status" => array("integer", $this->getReminderStatus()),
178  "start" => array("integer", $this->getReminderStart()),
179  "end" => array("integer", $this->getReminderEnd()),
180  "freq" => array("integer", $this->getReminderFrequency()),
181  "last_send" => array("integer", $this->getReminderLastSend()),
182  "template_id" => array("integer", $this->getReminderMailTemplate())
183  ),
184  array(
185  "type" => array("text", $this->rmd_type),
186  "exc_id" => array("integer", $this->exc_id),
187  "ass_id" => array("integer", $this->ass_id)
188  )
189  );
190  }
191 
192 
193  public function read()
194  {
195  $set = $this->db->query("SELECT status, start, freq, end, last_send, template_id" .
196  " FROM exc_ass_reminders" .
197  " WHERE type ='" . $this->rmd_type . "'" .
198  " AND ass_id = " . $this->ass_id .
199  " AND exc_id = " . $this->exc_id);
200 
201  $rec = $this->db->fetchAssoc($set);
202  if (is_array($rec)) {
203  $this->initFromDB($rec);
204  }
205  }
206 
211  protected function initFromDB(array $a_set)
212  {
213  $this->setReminderStatus($a_set["status"]);
214  $this->setReminderStart($a_set["start"]);
215  $this->setReminderEnd($a_set["end"]);
216  $this->setReminderFrequency($a_set["freq"]);
217  $this->setReminderLastSend($a_set["last_send"]);
218  $this->setReminderMailTemplate($a_set["template_id"]);
219  }
220 
221 
222  // Specific Methods to be used via Cron Job.
228  public function getReminders($a_type = "")
229  {
230  $now = time();
231  $today = date("Y-m-d");
232 
233  $this->log->debug("Get reminders $a_type.");
234 
235  //remove time from the timestamp (86400 = 24h)
236  //$now = floor($now/86400)*86400;
237  $and_type = "";
238  if ($a_type == self::SUBMIT_REMINDER || $a_type == self::GRADE_REMINDER || $a_type == self::FEEDBACK_REMINDER) {
239  $and_type = " AND type = '" . $a_type . "'";
240  }
241 
242  $query = "SELECT last_send_day, ass_id, exc_id, status, start, freq, end, type, last_send, template_id" .
243  " FROM exc_ass_reminders" .
244  " WHERE status = 1" .
245  " AND start <= " . $now .
246  " AND end > " . ($now - 86400) .
247  $and_type;
248 
249 
250  $result = $this->db->query($query);
251 
252  $array_data = array();
253  while ($rec = $this->db->fetchAssoc($result)) {
254  $rem = array(
255  "ass_id" => $rec["ass_id"],
256  "exc_id" => $rec["exc_id"],
257  "start" => $rec["start"],
258  "end" => $rec["end"],
259  "freq" => $rec["freq"],
260  "type" => $rec["type"],
261  "last_send" => $rec["last_send"],
262  "last_send_day" => $rec["last_send_day"],
263  "template_id" => $rec["template_id"]
264  );
265 
266  $end_day = date("Y-m-d", $rec["end"]);
267 
268  //frequency
269  $next_send = "";
270  if ($rec["last_send_day"] != "") {
271  $date = new DateTime($rec["last_send_day"]);
272  $date->add(new DateInterval('P' . $rec["freq"] . 'D'));
273  $next_send = $date->format('Y-m-d');
274  }
275  $this->log->debug("ass: " . $rec["ass_id"] . ", last send: " . $rec["last_send_day"] .
276  ", freq: " . $rec["freq"] . ", end_day: $end_day, today: " . $today . ", next send: $next_send");
277  if ($rec["last_send_day"] == "" || $next_send <= $today) {
278  if ($end_day >= $today) {
279  $this->log->debug("included");
280  array_push($array_data, $rem);
281  }
282  }
283  }
284 
285  return $array_data;
286  }
287 
288 
294  public function parseSubmissionReminders($a_reminders)
295  {
296  $reminders = $a_reminders;
297  $users_to_remind = array();
298 
299  foreach ($reminders as $rem) {
300  $ass_id = $rem["ass_id"];
301  $ass_obj = new ilExAssignment($ass_id);
302 
303  $exc_id = $rem["exc_id"];
304 
306  foreach ($exc_refs as $exc_ref) {
307 
308  // check if we have an upper course
309  if ($course_ref_id = $this->tree->checkForParentType($exc_ref, 'crs')) {
310  $obj = new ilObjCourse($course_ref_id);
311  $participants_class = "ilCourseParticipants";
312  $parent_ref_id = $course_ref_id;
313  $parent_obj_type = 'crs';
314 
315  // check if we have an upper group
316  } elseif ($group_ref_id = $parent_ref_id = $this->tree->checkForParentType($exc_ref, 'grp')) {
317  $obj = new ilObjGroup($group_ref_id);
318  $participants_class = "ilGroupParticipants";
319  $parent_ref_id = $group_ref_id;
320  $parent_obj_type = 'grp';
321  } else {
322  continue;
323  }
324 
325  // get participants
326  $parent_obj_id = $obj->getId();
327  $participants_ids = $participants_class::getInstance($parent_ref_id)->getMembers();
328 
329  foreach ($participants_ids as $member_id) {
330  $this->log->debug("submission reminder: ass: $ass_id, member: $member_id.");
331 
332  // check read permission
333  if ($this->access->checkAccessOfUser($member_id, "read", "", $exc_ref)) {
335 
336  $deadline_day = date("Y-m-d", $state->getOfficialDeadline());
337  $today = date("Y-m-d");
338  $date = new DateTime($deadline_day);
339  $date->sub(new DateInterval('P' . $rem["start"] . 'D'));
340  $send_from = $date->format('Y-m-d');
341  $this->log->debug("today: $today, send from: $send_from, start: " . $rem["start"] . ", submission allowed: " . $state->isSubmissionAllowed());
342 
343  // check if user can submit and difference in days is smaller than reminder start
344  if ($state->isSubmissionAllowed() && $send_from <= $today) {
345  $submission = new ilExSubmission($ass_obj, $member_id);
346 
347  // check if user has submitted anything
348  if (!$submission->getLastSubmission()) {
349  $member_data = array(
350  "parent_type" => $parent_obj_type,
351  "parent_id" => $parent_obj_id,
352  "exc_id" => $exc_id,
353  "exc_ref" => $exc_ref,
354  "ass_id" => $ass_id,
355  "member_id" => $member_id,
356  "reminder_type" => $rem["type"],
357  "template_id" => $rem["template_id"]
358  );
359  array_push($users_to_remind, $member_data);
360  }
361  }
362  }
363  }
364  }
365  }
366  return $users_to_remind;
367  }
368 
369  public function parseGradeReminders($a_reminders)
370  {
371  $reminders = $a_reminders;
372  $users_to_remind = array();
373 
374  $has_pending_to_grade = false;
375 
376  foreach ($reminders as $rem) {
377  //$this->log->debug("---- parse grade reminder with values -> ",$rem);
378  $ass_obj = new ilExAssignment($rem["ass_id"]);
379  $members_data = $ass_obj->getMemberListData();
380 
381  //$this->log->debug("--- get members list data => ",$members_data);
382  foreach ($members_data as $member_id => $assignment_data) {
383  if ($assignment_data["status"] == ilExerciseManagementGUI::GRADE_NOT_GRADED) {
384  //at least there is one submission pending to grade.
385  $has_pending_to_grade = true;
386  continue;
387  }
388  }
389 
390  /* //DEBUG
391  if($has_pending_to_grade){
392  $this->log->debug("SOMEONE HAS TO BE GRADED");
393  } else {
394  $this->log->debug("There is nothing to Grade");
395  }
396  */
397 
398  if ($has_pending_to_grade) {
399  //get tutor of this exercise.
400  include_once "./Services/Notification/classes/class.ilNotification.php";
401 
403 
404  foreach ($users as $user_id) {
405  $exc_refs = ilObject::_getAllReferences($rem["exc_id"]);
406  $unike_usr_id = array();
407  foreach ($exc_refs as $exc_ref) {
408  if ($this->access->checkAccessOfUser($user_id, "write", "", $exc_ref)) {
409  if (!in_array($user_id, $unike_usr_id)) {
410  $member_data = array(
411  "exc_id" => $rem["exc_id"],
412  "exc_ref" => $exc_ref,
413  "ass_id" => $rem["ass_id"],
414  "member_id" => $user_id,
415  "reminder_type" => $rem["type"],
416  "template_id" => $rem["template_id"]
417  );
418  array_push($users_to_remind, $member_data);
419  array_push($unike_usr_id, $user_id);
420  }
421  }
422  }
423  }
424  }
425  }
426 
427  return $users_to_remind;
428  }
429 
430  public function parsePeerReminders($a_reminders)
431  {
432  $reminders = $a_reminders;
433  $users_to_remind = array();
434 
435  foreach ($reminders as $reminder) {
436  $giver_ids = array_unique(ilExPeerReview::lookupGiversWithPendingFeedback($reminder["ass_id"]));
437  foreach ($giver_ids as $giver_id) {
438  $state = ilExcAssMemberState::getInstanceByIds($reminder["ass_id"], $giver_id);
439  $days_diff = (($state->getPeerReviewDeadline() - time()) / (60 * 60 * 24));
440 
441  if ($state->isPeerReviewAllowed() && $days_diff < $reminder["start"]) {
442  $exc_refs = ilObject::_getAllReferences($reminder["exc_id"]);
443  foreach ($exc_refs as $exc_ref) {
444  if ($this->access->checkAccessOfUser($giver_id, "read", "", $exc_ref)) {
445  $member_data = array(
446  "exc_id" => $reminder["exc_id"],
447  "exc_ref" => $exc_ref,
448  "ass_id" => $reminder["ass_id"],
449  "member_id" => $giver_id,
450  "reminder_type" => $reminder["type"],
451  "template_id" => $reminder["template_id"]
452  );
453  array_push($users_to_remind, $member_data);
454  }
455  }
456  }
457  }
458  }
459 
460  return $users_to_remind;
461  }
462 
466  public function checkReminders()
467  {
468  $submit_reminders = $this->getReminders(self::SUBMIT_REMINDER);
469  $parsed_submit_reminders = $this->parseSubmissionReminders($submit_reminders);
470 
471  $grade_reminders = $this->getReminders(self::GRADE_REMINDER);
472  $parsed_grade_reminders = $this->parseGradeReminders($grade_reminders);
473 
474  $peer_reminders = $this->getReminders(self::FEEDBACK_REMINDER);
475  $parsed_peer_reminders = $this->parsePeerReminders($peer_reminders);
476 
477  /* //DEBUG
478  $this->log->debug("ALL SUBMIT REMINDERS");
479  $this->log->dump($submit_reminders);
480  $this->log->debug("PARSED SUBMIT REMINDERS");
481  $this->log->dump($parsed_submit_reminders);
482  $this->log->debug("GRADE REMINDERS ARRAY");
483  $this->log->dump($grade_reminders);
484  $this->log->debug("PARSED GRADE REMINDERS");
485  $this->log->dump($parsed_grade_reminders);
486  $this->log->debug("PEER REMINDERS ARRAY");
487  $this->log->dump($peer_reminders);
488  $this->log->debug("PARSED PEER REMINDERS");
489  $this->log->dump($parsed_peer_reminders);
490  */
491 
492  $reminders = array_merge($parsed_submit_reminders, $parsed_grade_reminders, $parsed_peer_reminders);
493 
494  $reminders_sent = $this->sendReminders($reminders);
495 
496  return $reminders_sent;
497  }
498 
503  protected function sendReminders($reminders)
504  {
505  global $DIC;
506 
507  $tpl = null;
508 
509  foreach ($reminders as $reminder) {
510  $template_id = $reminder['template_id'];
511 
512  $rmd_type = $reminder["reminder_type"];
513  $this->log->debug("Sending reminder type = " . $rmd_type);
514 
515  //if the template exists (can be deleted via Administration/Mail)
516  if ($template_id) {
518  $templateService = $DIC['mail.texttemplates.service'];
519  $tpl = $templateService->loadTemplateForId((int) $template_id);
520  }
521 
522  if ($tpl) {
523  $this->log->debug("** send reminder WITH template.");
524  $subject = $tpl->getSubject();
525 
526  $placeholder_params = array(
527  "exc_id" => $reminder["exc_id"],
528  "exc_ref" => $reminder["exc_ref"],
529  "ass_id" => $reminder["ass_id"],
530  "member_id" => $reminder["member_id"]
531  );
532  $message = $this->sentReminderPlaceholders($tpl->getMessage(), $placeholder_params, $rmd_type);
533  } else {
534  $this->log->debug("** send reminder WITHOUT template.");
535 
536  $ass_title = ilExAssignment::lookupTitle($reminder["ass_id"]);
537  $exc_title = ilObjExercise::_lookupTitle($reminder["exc_id"]);
538 
539  // use language of recipient to compose message
540  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
541  $ulng = ilLanguageFactory::_getLanguageOfUser($reminder["member_id"]);
542  $ulng->loadLanguageModule('exc');
543 
544  $link = ilLink::_getLink($reminder["exc_ref"], "exc", array(), "_" . $reminder["ass_id"]);
545 
546  $message = sprintf($ulng->txt('exc_reminder_salutation'), ilObjUser::_lookupFullname($reminder["member_id"])) . "\n\n";
547 
548  $this->log->debug("send: MAIL TYPE = " . $rmd_type . ", user: " . $reminder["member_id"] . ", ass: " . $reminder["ass_id"]);
549 
550  switch ($rmd_type) {
551  case "submit":
552  $subject = sprintf($ulng->txt('exc_reminder_submit_subject'), $ass_title);
553  $message .= $ulng->txt('exc_reminder_submit_body') . ":\n\n";
554  break;
555 
556  case "grade":
557  $subject = sprintf($ulng->txt('exc_reminder_grade_subject'), $ass_title);
558  $message .= $ulng->txt('exc_reminder_grade_body') . ":\n\n";
559  break;
560 
561  case "peer":
562  $subject = sprintf($ulng->txt('exc_reminder_peer_subject'), $ass_title);
563  $message .= $ulng->txt('exc_reminder_peer_body') . ":\n\n";
564  break;
565  }
566 
567  $message .= $ulng->txt('obj_exc') . ": " . $exc_title . "\n";
568  $message .= $ulng->txt('obj_ass') . ": " . $ass_title . "\n";
569  $message .= "\n" . $ulng->txt('exc_reminder_link') . ": " . $link;
570  }
571  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
572  $mail_obj->appendInstallationSignature(true);
573  $mail_obj->sendMail(
574  ilObjUser::_lookupLogin($reminder["member_id"]),
575  "",
576  "",
577  $subject,
578  $message,
579  array(),
580  array("system")
581  );
582  }
583 
584  $this->updateRemindersLastDate($reminders);
585  return sizeof($reminders);
586  }
587 
588  //see ilObjSurvey.
589  protected function sentReminderPlaceholders($a_message, $a_reminder_data, $a_reminder_type)
590  {
591  // see ilMail::replacePlaceholders()
592  try {
593  switch ($a_reminder_type) {
594  case \ilExAssignmentReminder::SUBMIT_REMINDER:
596  break;
597  case \ilExAssignmentReminder::GRADE_REMINDER:
599  break;
600  case \ilExAssignmentReminder::FEEDBACK_REMINDER:
602  break;
603  default:
604  exit();
605  }
606 
607  $user = new \ilObjUser($a_reminder_data["member_id"]);
608 
609  $processor = new \ilMailTemplatePlaceholderResolver($context, $a_message);
610  $a_message = $processor->resolve($user, $a_reminder_data);
611  } catch (\Exception $e) {
612  \ilLoggerFactory::getLogger('mail')->error(__METHOD__ . ' has been called with invalid context.');
613  }
614 
615  return $a_message;
616  }
617 
622  protected function updateRemindersLastDate($a_reminders)
623  {
624  $today = date("Y-m-d");
625  foreach ($a_reminders as $reminder) {
626  $sql = "UPDATE exc_ass_reminders" .
627  " SET last_send = " . $this->db->quote(time(), 'integer') .
628  " , last_send_day = " . $this->db->quote($today, 'date') .
629  " WHERE type = " . $this->db->quote($reminder["reminder_type"], 'text') .
630  " AND ass_id = " . $this->db->quote($reminder["ass_id"], 'integer') .
631  " AND exc_id = " . $this->db->quote($reminder["exc_id"], 'integer');
632 
633  $this->db->manipulate($sql);
634  }
635  }
636 
641  public function deleteReminders($a_ass_id)
642  {
643  $sql = "DELETE FROM exc_ass_reminders" .
644  " WHERE ass_id = " . $a_ass_id;
645 
646  $this->db->manipulate($sql);
647  }
648 }
static _lookupLogin($a_user_id)
lookup login
setReminderStatus($a_status)
Set reminder for users without submission.
getReminders($a_type="")
Get reminders available by date/frequence.
Exercise assignment.
$context
Definition: webdav.php:25
$result
global $DIC
Definition: saml.php:7
$tpl
Definition: ilias.php:10
static _lookupFullname($a_user_id)
Lookup Full Name.
updateRemindersLastDate($a_reminders)
Update reminders last_send value with the current timestamp.
deleteReminders($a_ass_id)
remove reminders from DB when the parent assignment is deleted.
getReminderStart()
Get num days before the deadline to start sending notifications.
static _lookupTitle($a_id)
lookup object title
static _getAllReferences($a_id)
get all reference ids of object
static getInstanceByIds($a_ass_id, $a_user_id=0)
Get instance by IDs (recommended for consumer code)
static getNotificationsForObject($type, $id, $page_id=null, $ignore_threshold=false)
Get all users for given object.
getReminderEnd()
get the ending of the reminder
$a_type
Definition: workflow.php:92
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
getReminderStatus()
Get the reminder status.
checkReminders()
CRON send reminders.
catch(Exception $e) $message
Class ilObjCourse.
static lookupGiversWithPendingFeedback($a_ass_id)
TODO: import/export reminder data with the exercise/assignment.
setReminderFrequency($a_num_days)
Set frequency in days.
$query
$user
Definition: migrateto20.php:57
setReminderStart($a_num_days)
Set num days before the deadline to start sending notifications.
$users
Definition: authpage.php:44
static _getLanguageOfUser($a_usr_id)
Get language object of user.
setReminderEnd($a_date)
Set the ending of the reminder.
exit
Definition: backend.php:16
initFromDB(array $a_set)
Import DB record.
Class ilObjGroup.
Exercise submission //TODO: This class has to much static methods related to delivered "files"...
static getLogger($a_component_id)
Get component logger.
parseSubmissionReminders($a_reminders)
Filter the reminders by object(crs,grp) by active status and if have members.
sentReminderPlaceholders($a_message, $a_reminder_data, $a_reminder_type)
getReminderFrequency()
get submit reminder frequency in days.
$template_id
static lookupTitle($a_id)
Lookup title.
__construct($a_exc_id="", $a_ass_id="", $a_type="")