ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
class.ilMembershipCronNotifications.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 include_once "Services/Cron/classes/class.ilCronJob.php";
6 
13 {
14  public function getId()
15  {
16  return "mem_notification";
17  }
18 
19  public function getTitle()
20  {
21  global $lng;
22 
23  return $lng->txt("enable_course_group_notifications");
24  }
25 
26  public function getDescription()
27  {
28  global $lng;
29 
30  return $lng->txt("enable_course_group_notifications_desc");
31  }
32 
33  public function getDefaultScheduleType()
34  {
35  return self::SCHEDULE_TYPE_DAILY;
36  }
37 
38  public function getDefaultScheduleValue()
39  {
40  return;
41  }
42 
43  public function hasAutoActivation()
44  {
45  return false;
46  }
47 
48  public function hasFlexibleSchedule()
49  {
50  return true;
51  }
52 
53  public function run()
54  {
55  global $lng, $ilDB;
56 
58  $log->debug("===Member Notifications=== start");
59 
61  $status_details = null;
62 
63  $setting = new ilSetting("cron");
64  $last_run = $setting->get(get_class($this));
65 
66  // no last run?
67  if (!$last_run) {
68  $last_run = date("Y-m-d H:i:s", strtotime("yesterday"));
69 
70  $status_details = "No previous run found - starting from yesterday.";
71  }
72  // migration: used to be date-only value
73  elseif (strlen($last_run) == 10) {
74  $last_run .= " 00:00:00";
75 
76  $status_details = "Switched from daily runs to open schedule.";
77  }
78 
79  include_once "Services/Membership/classes/class.ilMembershipNotifications.php";
81 
82  if (sizeof($objects)) {
83  $log->debug("nr of objects: " . count($objects));
84 
85  // gather news for each user over all objects
86 
87  $user_news_aggr = array();
88 
89  include_once "Services/News/classes/class.ilNewsItem.php";
90  foreach ($objects as $ref_id => $user_ids) {
91  $log->debug("handle ref id " . $ref_id . ", users: " . count($user_ids));
92 
93  // gather news per object
94  $news_item = new ilNewsItem();
95  if ($news_item->checkNewsExistsForGroupCourse($ref_id, $last_run)) {
96  foreach ($user_ids as $user_id) {
97  // gather news for user
98  $user_news = $news_item->getNewsForRefId(
99  $ref_id,
100  false,
101  false,
102  $last_run,
103  false,
104  false,
105  false,
106  false,
107  $user_id
108  );
109  if ($user_news) {
110  $user_news_aggr[$user_id][$ref_id] = $user_news;
111 
112  // #17928
113  ilCronManager::ping($this->getId());
114  }
115  }
116  }
117  }
118  unset($objects);
119 
120  $log->debug("prepare sending mails");
121 
122  // send mails (1 max for each user)
123 
124  $old_lng = $lng;
127 
128  if (sizeof($user_news_aggr)) {
129  foreach ($user_news_aggr as $user_id => $user_news) {
130  $log->debug("sending mails to user " . $user_id . ", nr news: " . count($user_news));
131 
132  $this->sendMail($user_id, $user_news, $last_run);
133 
134  // #17928
135  ilCronManager::ping($this->getId());
136  }
137 
138  // mails were sent - set cron job status accordingly
139  $status = ilCronJobResult::STATUS_OK;
140  }
141 
143  $lng = $old_lng;
144  }
145 
146  $log->debug("save run");
147 
148  // save last run
149  $setting->set(get_class($this), date("Y-m-d H:i:s"));
150 
151  $result = new ilCronJobResult();
152  $result->setStatus($status);
153 
154  if ($status_details) {
155  $result->setMessage($status_details);
156  }
157 
158  $log->debug("===Member Notifications=== done");
159 
160  return $result;
161  }
162 
172  protected function parseNewsItem($a_parent_ref_id, array &$a_filter_map, array $a_item, $a_is_sub = false)
173  {
174  global $lng;
175 
176  $lng->loadLanguageModule("news");
177 
178  $wrong_parent = (array_key_exists($a_item["id"], $a_filter_map) &&
179  $a_parent_ref_id != $a_filter_map[$a_item["id"]]);
180 
181  // #18223
182  if ($wrong_parent) {
183  return;
184  }
185 
186  $item_obj_title = trim(ilObject::_lookupTitle($a_item["context_obj_id"]));
187  $item_obj_type = $a_item["context_obj_type"];
188 
189  // sub-items
190  $sub = null;
191  if ($a_item["aggregation"]) {
192  $do_sub = true;
193  if ($item_obj_type == "file" &&
194  sizeof($a_item["aggregation"]) == 1) {
195  $do_sub = false;
196  }
197  if ($do_sub) {
198  $sub = array();
199  foreach ($a_item["aggregation"] as $subitem) {
200  $sub_res = $this->parseNewsItem($a_parent_ref_id, $a_filter_map, $subitem, true);
201  if ($sub_res) {
202  $sub[md5($sub_res)] = $sub_res;
203  }
204  }
205  }
206  }
207 
208  if (!$a_is_sub) {
210  $a_item["context_obj_type"],
211  $a_item["title"],
212  $a_item["content_is_lang_var"],
213  $a_item["agg_ref_id"],
214  $a_item["aggregation"]
215  );
216  } else {
218  $a_item["context_obj_type"],
219  $a_item["title"],
220  $a_item["content_is_lang_var"]
221  );
222  }
223 
225  $a_item["context_obj_type"],
226  $a_item["content"],
227  $a_item["content_text_is_lang_var"]
228  );
229 
230  $title = trim($title);
231 
232  // #18067 / #18186
233  $content = ilUtil::shortenText(trim(strip_tags($content)), 200, true);
234 
235  $res = "";
236  switch ($item_obj_type) {
237  case "frm":
238  if (!$a_is_sub) {
239  $res = $lng->txt("obj_" . $item_obj_type) .
240  ' "' . $item_obj_title . '": ' . $title;
241  } else {
242  $res .= '"' . $title . '": "' . $content . '"';
243  }
244  break;
245 
246  case "file":
247  if (!is_array($a_item["aggregation"]) ||
248  sizeof($a_item["aggregation"]) == 1) {
249  $res = $lng->txt("obj_" . $item_obj_type) .
250  ' "' . $item_obj_title . '" - ' . $title;
251  } else {
252  // if files were removed from aggregation update summary count
253  $title = str_replace(
254  " " . sizeof($a_item["aggregation"]) . " ",
255  " " . sizeof($sub) . " ",
256  $title
257  );
258  $res = $title;
259  }
260  break;
261 
262  default:
263  $res = $lng->txt("obj_" . $item_obj_type) .
264  ' "' . $item_obj_title . '"';
265  if ($title) {
266  $res .= ': "' . $title . '"';
267  }
268  if ($content) {
269  $res .= ' - ' . $content;
270  }
271  break;
272  }
273 
274  $res = $a_is_sub
275  ? "- " . $res
276  : "# " . $res;
277 
278  if (is_array($sub) && sizeof($sub)) {
279  $res .= "\n" . implode("\n", $sub);
280  }
281 
282  return trim($res);
283  }
284 
291  protected function filterDuplicateItems(array $a_objects)
292  {
293  global $tree;
294 
295  $parent_map = $news_map = $parsed_map = array();
296 
297  // gather news ref ids and news parent ref ids
298  foreach ($a_objects as $parent_ref_id => $news) {
299  foreach ($news as $item) {
300  $news_map[$item["id"]] = $item["ref_id"];
301  $parent_map[$item["id"]][$parent_ref_id] = $parent_ref_id;
302 
303  if ($item["aggregation"]) {
304  foreach ($item["aggregation"] as $subitem) {
305  $news_map[$subitem["id"]] = $subitem["ref_id"];
306  $parent_map[$subitem["id"]][$parent_ref_id] = $parent_ref_id;
307  }
308  }
309  }
310  }
311  // if news has multiple parents find "lowest" parent in path
312  foreach ($parent_map as $news_id => $parents) {
313  if (sizeof($parents) > 1 && isset($news_map[$news_id])) {
314  $path = $tree->getPathId($news_map[$news_id]);
315  $lookup = array_flip($path);
316 
317  $level = 0;
318  foreach ($parents as $parent_ref_id) {
319  $level = max($level, $lookup[$parent_ref_id]);
320  }
321 
322  $parsed_map[$news_id] = $path[$level];
323  }
324  }
325 
326  return $parsed_map;
327  }
328 
336  protected function sendMail($a_user_id, array $a_objects, $a_last_run)
337  {
338  global $lng, $ilUser, $ilClientIniFile, $tree;
339 
340  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
341  $ntf = new ilSystemNotification();
342  $ntf->setLangModules(array("crs", "news"));
343  // no single object anymore
344  // $ntf->setRefId($a_ref_id);
345  // $ntf->setGotoLangId('url');
346  // $ntf->setSubjectLangId('crs_subject_course_group_notification');
347 
348  // user specific language
349  $lng = $ntf->getUserLanguage($a_user_id);
350 
351  include_once './Services/Locator/classes/class.ilLocatorGUI.php';
352  require_once "./Services/UICore/classes/class.ilTemplate.php";
353  require_once "./Services/Link/classes/class.ilLink.php";
354 
355  $filter_map = $this->filterDuplicateItems($a_objects);
356 
357  $tmp = array();
358  foreach ($a_objects as $parent_ref_id => $news) {
359  $parent = array();
360 
361  // path
362  $path = array();
363  foreach ($tree->getPathId($parent_ref_id) as $node) {
364  $path[] = $node;
365  }
366  $path = implode("-", $path);
367 
368  $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
369  $parent_type = ilObject::_lookupType($parent_obj_id);
370 
371  $parent["title"] = $lng->txt("obj_" . $parent_type) . ' "' . ilObject::_lookupTitle($parent_obj_id) . '"';
372  $parent["url"] = " " . $lng->txt("crs_course_group_notification_link") . " " . ilLink::_getStaticLink($parent_ref_id);
373 
374  // news summary
375  $parsed = array();
376  foreach ($news as $item) {
377  $parsed_item = $this->parseNewsItem($parent_ref_id, $filter_map, $item);
378  if ($parsed_item) {
379  $parsed[md5($parsed_item)] = $parsed_item;
380  }
381  }
382  // any news?
383  if (sizeof($parsed)) {
384  $parent["news"] = implode("\n", $parsed);
385  $tmp[$path] = $parent;
386  }
387  }
388 
389  // any objects?
390  if (!sizeof($tmp)) {
391  return;
392  }
393 
394  ksort($tmp);
395  $counter = 0;
396  $obj_index = array();
397  $txt = "";
398  foreach ($tmp as $path => $item) {
399  $counter++;
400 
401  $txt .= "(" . $counter . ") " . $item["title"] . "\n" .
402  $item["url"] . "\n\n" .
403  $item["news"] . "\n\n";
404 
405  $obj_index[] = "(" . $counter . ") " . $item["title"];
406  }
407 
408  $ntf->setIntroductionLangId("crs_intro_course_group_notification_for");
409 
410  // index
411  $period = sprintf(
412  $lng->txt("crs_intro_course_group_notification_index"),
415  );
416  $ntf->addAdditionalInfo(
417  $period,
418  trim(implode("\n", $obj_index)),
419  true,
420  true
421  );
422 
423  // object list
424  $ntf->addAdditionalInfo(
425  "",
426  trim($txt),
427  true
428  );
429 
430  // :TODO: does it make sense to add client to subject?
431  $client = $ilClientIniFile->readVariable('client', 'name');
432  $subject = sprintf($lng->txt("crs_subject_course_group_notification"), $client);
433 
434  // #10044
435  $mail = new ilMail(ANONYMOUS_USER_ID);
436  $mail->enableSOAP(false); // #10410
437  $mail->sendMail(
438  ilObjUser::_lookupLogin($a_user_id),
439  null,
440  null,
441  $subject,
442  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
443  null,
444  array("system")
445  );
446  }
447 
448  public function addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
449  {
450  global $lng;
451 
452  switch ($a_form_id) {
455  $a_fields["enable_course_group_notifications"] = $a_is_active ?
456  $lng->txt("enabled") :
457  $lng->txt("disabled");
458  break;
459  }
460  }
461 
462  public function activationWasToggled($a_currently_active)
463  {
464  global $ilSetting;
465 
466  // propagate cron-job setting to object setting
467  $ilSetting->set("crsgrp_ntf", (bool) $a_currently_active);
468  }
469 }
static _lookupLogin($a_user_id)
lookup login
static shortenText( $a_str, $a_len, $a_dots=false, $a_next_blank=false, $a_keep_extension=false)
shorten a string to given length.
const IL_CAL_DATETIME
$result
Cron job application base class.
$client
Definition: resume.php:9
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false)
Format a date public.
static setUseRelativeDates($a_status)
set use relative dates
static _lookupTitle($a_id)
lookup object title
filterDuplicateItems(array $a_objects)
Filter duplicate news items from structure.
const IL_CAL_UNIX
parseNewsItem($a_parent_ref_id, array &$a_filter_map, array $a_item, $a_is_sub=false)
Convert news item to summary html.
static useRelativeDates()
check if relative dates are used
$counter
foreach($_POST as $key=> $value) $res
static determineNewsContent($a_context_obj_type, $a_content, $a_is_lang_var)
Determine new content.
This class handles base functions for mail handling.
static _lookupObjId($a_id)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
Date and time handling
$ilUser
Definition: imgupload.php:18
$txt
Definition: error.php:11
Create styles array
The data for the language used.
static _lookupType($a_id, $a_reference=false)
lookup object type
addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
static ping($a_job_id)
Keep cron job alive.
global $ilSetting
Definition: privfeed.php:17
global $lng
Definition: privfeed.php:17
global $ilDB
static determineNewsTitle( $a_context_obj_type, $a_title, $a_content_is_lang_var, $a_agg_ref_id=0, $a_aggregation="")
Determine title for news item entry.
static getLogger($a_component_id)
Get component logger.
static getActiveUsersforAllObjects()
Get active notifications for all objects.
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
Cron job result data container.
Wrapper classes for system notifications.
sendMail($a_user_id, array $a_objects, $a_last_run)
Send news mail for 1 user and n objects.