ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 {
17  protected $data;
18 
19  public function getId()
20  {
21  return "mem_notification";
22  }
23 
24  public function getTitle()
25  {
26  global $DIC;
27 
28  $lng = $DIC['lng'];
29 
30  return $lng->txt("enable_course_group_notifications");
31  }
32 
33  public function getDescription()
34  {
35  global $DIC;
36 
37  $lng = $DIC['lng'];
38 
39  return $lng->txt("enable_course_group_notifications_desc");
40  }
41 
42  public function getDefaultScheduleType()
43  {
44  return self::SCHEDULE_TYPE_DAILY;
45  }
46 
47  public function getDefaultScheduleValue()
48  {
49  return;
50  }
51 
52  public function hasAutoActivation()
53  {
54  return false;
55  }
56 
57  public function hasFlexibleSchedule()
58  {
59  return true;
60  }
61 
62  public function run()
63  {
64  global $DIC;
65 
66  $lng = $DIC['lng'];
67  $ilDB = $DIC['ilDB'];
68 
69  $log = $DIC->logger()->mmbr();
70  $log->debug("===Member Notifications=== start");
71 
73  $status_details = null;
74 
75  $setting = new ilSetting("cron");
76  $last_run = $setting->get(get_class($this));
77 
78  // no last run?
79  if (!$last_run) {
80  $last_run = date("Y-m-d H:i:s", strtotime("yesterday"));
81 
82  $status_details = "No previous run found - starting from yesterday.";
83  }
84  // migration: used to be date-only value
85  elseif (strlen($last_run) == 10) {
86  $last_run .= " 00:00:00";
87 
88  $status_details = "Switched from daily runs to open schedule.";
89  }
90  //$last_run = date("Y-m-d H:i:s", strtotime("yesterday"));
91 
92  $log->debug("Last run: " . $last_run);
93 
94  include_once("./Services/Membership/classes/class.ilMembershipCronNotificationsData.php");
95  $this->data = new ilMembershipCronNotificationsData($last_run, $this->getId());
96 
97  $log->debug("prepare sending mails");
98 
99  // send mails (1 max for each user)
100 
101  $old_lng = $lng;
104 
105  $user_news_aggr = $this->data->getAggregatedNews();
106  if (sizeof($user_news_aggr)) {
107  foreach ($user_news_aggr as $user_id => $user_news) {
108  $log->debug("sending mails to user " . $user_id . ", nr news: " . count($user_news));
109 
110  $this->sendMail($user_id, $user_news, $last_run);
111 
112  ilCronManager::ping($this->getId());
113  }
114 
115  // mails were sent - set cron job status accordingly
116  $status = ilCronJobResult::STATUS_OK;
117  }
118 
120  $lng = $old_lng;
121 
122  $log->debug("save run");
123 
124  // save last run
125  $setting->set(get_class($this), date("Y-m-d H:i:s"));
126 
127  $result = new ilCronJobResult();
128  $result->setStatus($status);
129 
130  if ($status_details) {
131  $result->setMessage($status_details);
132  }
133 
134  $log->debug("===Member Notifications=== done");
135 
136  return $result;
137  }
138 
148  protected function parseNewsItem($a_parent_ref_id, array &$a_filter_map, array $a_item, $a_is_sub = false, $a_user_id = 0)
149  {
150  global $DIC;
151 
152  $lng = $DIC['lng'];
153  $obj_definiton = $DIC["objDefinition"];
154 
155  $lng->loadLanguageModule("news");
156 
157  $wrong_parent = (array_key_exists($a_item["id"], $a_filter_map) &&
158  $a_parent_ref_id != $a_filter_map[$a_item["id"]]);
159 
160  // #18223
161  if ($wrong_parent) {
162  return;
163  }
164 
165  $item_obj_title = trim(ilObject::_lookupTitle($a_item["context_obj_id"]));
166  $item_obj_type = $a_item["context_obj_type"];
167 
168  // sub-items
169  $sub = null;
170  if ($a_item["aggregation"]) {
171  $do_sub = true;
172  if ($item_obj_type == "file" &&
173  sizeof($a_item["aggregation"]) == 1) {
174  $do_sub = false;
175  }
176  if ($do_sub) {
177  $sub = array();
178  foreach ($a_item["aggregation"] as $subitem) {
179  $sub_res = $this->parseNewsItem($a_parent_ref_id, $a_filter_map, $subitem, true, $a_user_id);
180  if ($sub_res) {
181  $sub[md5($sub_res)] = $sub_res;
182  }
183  }
184  }
185  }
186 
187  if (!$a_is_sub) {
189  $a_item["context_obj_type"],
190  $a_item["title"],
191  $a_item["content_is_lang_var"],
192  $a_item["agg_ref_id"],
193  $a_item["aggregation"]
194  );
195  } else {
197  $a_item["context_obj_type"],
198  $a_item["title"],
199  $a_item["content_is_lang_var"]
200  );
201  }
202 
204  $a_item["context_obj_type"],
205  $a_item["content"],
206  $a_item["content_text_is_lang_var"]
207  );
208 
209  $title = trim($title);
210 
211  // #18067 / #18186
212  $content = ilUtil::shortenText(trim(strip_tags($content)), 200, true);
213 
214  $res = "";
215  switch ($item_obj_type) {
216  case "frm":
217  if (!$a_is_sub) {
218  $res = $lng->txt("obj_" . $item_obj_type) .
219  ' "' . $item_obj_title . '": ' . $title;
220  } else {
221  $res .= '"' . $title . '": "' . $content . '"';
222  }
223  break;
224 
225  case "file":
226  if (!is_array($a_item["aggregation"]) ||
227  sizeof($a_item["aggregation"]) == 1) {
228  $res = $lng->txt("obj_" . $item_obj_type) .
229  ' "' . $item_obj_title . '" - ' . $title;
230  } else {
231  // if files were removed from aggregation update summary count
232  $title = str_replace(
233  " " . sizeof($a_item["aggregation"]) . " ",
234  " " . sizeof($sub) . " ",
235  $title
236  );
237  $res = $title;
238  }
239  break;
240 
241  default:
242  $type_txt = ($obj_definiton->isPlugin($item_obj_type))
243  ? ilObjectPlugin::lookupTxtById($item_obj_type, "obj_" . $item_obj_type)
244  : $lng->txt("obj_" . $item_obj_type);
245  $res = $type_txt .
246  ' "' . $item_obj_title . '"';
247  if ($title) {
248  $res .= ': "' . $title . '"';
249  }
250  if ($content) {
251  $res .= ' - ' . $content;
252  }
253  break;
254  }
255 
256  // comments
257  $comments = $this->data->getComments($a_item["id"], $a_user_id);
258  if (count($comments) > 0) {
259  $res .= "\n" . $lng->txt("news_new_comments") . " (" . count($comments) . ")";
260  }
261  foreach ($comments as $c) {
262  $res .= "\n* " .
264  new ilDateTime($c->getCreationDate(), IL_CAL_DATETIME)
265  ) . ": " .
266  ilUtil::shortenText(trim(strip_tags($c->getText())), 60, true, true);
267  }
268 
269 
270  // likes
271  include_once("./Services/Like/classes/class.ilLikeGUI.php");
272  $likes = $this->data->getLikes($a_item["id"], $a_user_id);
273  if (count($likes) > 0) {
274  $res .= "\n" . $lng->txt("news_new_reactions") . " (" . count($likes) . ")";
275  }
276  foreach ($likes as $l) {
277  $res .= "\n* " .
279  new ilDateTime($l["timestamp"], IL_CAL_DATETIME)
280  ) . ": " .
281  ilLikeGUI::getExpressionText((int) $l["expression"]);
282  }
283 
284 
285  $res = $a_is_sub
286  ? "- " . $res
287  : "# " . $res;
288 
289  if (is_array($sub) && sizeof($sub)) {
290  $res .= "\n" . implode("\n", $sub);
291  }
292 
293  return trim($res);
294  }
295 
302  protected function filterDuplicateItems(array $a_objects)
303  {
304  global $DIC;
305 
306  $tree = $DIC['tree'];
307 
308  $parent_map = $news_map = $parsed_map = array();
309 
310  // gather news ref ids and news parent ref ids
311  foreach ($a_objects as $parent_ref_id => $news) {
312  foreach ($news as $item) {
313  $news_map[$item["id"]] = $item["ref_id"];
314  $parent_map[$item["id"]][$parent_ref_id] = $parent_ref_id;
315 
316  if ($item["aggregation"]) {
317  foreach ($item["aggregation"] as $subitem) {
318  $news_map[$subitem["id"]] = $subitem["ref_id"];
319  $parent_map[$subitem["id"]][$parent_ref_id] = $parent_ref_id;
320  }
321  }
322  }
323  }
324  // if news has multiple parents find "lowest" parent in path
325  foreach ($parent_map as $news_id => $parents) {
326  if (sizeof($parents) > 1 && $news_map[$news_id] > 0) {
327  $path = $tree->getPathId($news_map[$news_id]);
328  $lookup = array_flip($path);
329 
330  $level = 0;
331  foreach ($parents as $parent_ref_id) {
332  $level = max($level, $lookup[$parent_ref_id]);
333  }
334 
335  $parsed_map[$news_id] = $path[$level];
336  }
337  }
338 
339  return $parsed_map;
340  }
341 
349  protected function sendMail($a_user_id, array $a_objects, $a_last_run)
350  {
351  global $DIC;
352 
353  $lng = $DIC['lng'];
354  $ilUser = $DIC['ilUser'];
355  $ilClientIniFile = $DIC['ilClientIniFile'];
356  $tree = $DIC['tree'];
357 
359 
360  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
361  $ntf = new ilSystemNotification();
362  $ntf->setLangModules(array("crs", "news"));
363  // no single object anymore
364  // $ntf->setRefId($a_ref_id);
365  // $ntf->setGotoLangId('url');
366  // $ntf->setSubjectLangId('crs_subject_course_group_notification');
367 
368  // user specific language
369  $lng = $ntf->getUserLanguage($a_user_id);
370 
371  include_once './Services/Locator/classes/class.ilLocatorGUI.php';
372  require_once "./Services/UICore/classes/class.ilTemplate.php";
373  require_once "./Services/Link/classes/class.ilLink.php";
374 
375  $filter_map = $this->filterDuplicateItems($a_objects);
376 
377  $tmp = array();
378 
379  foreach ($a_objects as $parent_ref_id => $items) {
380  $parent = array();
381 
382  // path
383  $path = array();
384  foreach ($tree->getPathId($parent_ref_id) as $node) {
385  $path[] = $node;
386  }
387  $path = implode("-", $path);
388 
389  $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
390  $parent_type = ilObject::_lookupType($parent_obj_id);
391 
392  $parent["title"] = $lng->txt("obj_" . $parent_type) . ' "' . ilObject::_lookupTitle($parent_obj_id) . '"';
393  $parent["url"] = " " . $lng->txt("crs_course_group_notification_link") . " " . ilLink::_getStaticLink($parent_ref_id);
394 
395  $log->debug("ref id: " . $parent_ref_id . ", items: " . count($items));
396 
397  // news summary
398  $parsed = array();
399  if (is_array($items)) {
400  foreach ($items as $news_item) {
401  // # Type "<Object Title>": "<News Title>" - News Text
402  $parsed_item = $this->parseNewsItem($parent_ref_id, $filter_map, $news_item, false, $a_user_id);
403  if ($parsed_item) {
404  $parsed[md5($parsed_item)] = $parsed_item;
405  }
406  }
407  }
408 
409  // any news?
410  if (sizeof($parsed)) {
411  $parent["news"] = implode("\n\n", $parsed);
412  $tmp[$path] = $parent;
413  }
414  }
415 
416  // any objects?
417  if (!sizeof($tmp)) {
418  $log->debug("returning");
419  return;
420  }
421 
422  ksort($tmp);
423  $counter = 0;
424  $obj_index = array();
425  $txt = "";
426  foreach ($tmp as $path => $item) {
427  $counter++;
428 
429  $txt .= "(" . $counter . ") " . $item["title"] . "\n" .
430  $item["url"] . "\n\n" .
431  $item["news"] . "\n\n";
432 
433  $obj_index[] = "(" . $counter . ") " . $item["title"];
434  }
435 
436  $ntf->setIntroductionLangId("crs_intro_course_group_notification_for");
437 
438  // index
439  $period = sprintf(
440  $lng->txt("crs_intro_course_group_notification_index"),
443  );
444  $ntf->addAdditionalInfo(
445  $period,
446  trim(implode("\n", $obj_index)),
447  true,
448  true
449  );
450 
451  // object list
452  $ntf->addAdditionalInfo(
453  "",
454  trim($txt),
455  true
456  );
457 
458  // :TODO: does it make sense to add client to subject?
459  $client = $ilClientIniFile->readVariable('client', 'name');
460  $subject = sprintf($lng->txt("crs_subject_course_group_notification"), $client);
461 
462  // #10044
463  $mail = new ilMail(ANONYMOUS_USER_ID);
464  $mail->enableSOAP(false); // #10410
465  $mail->sendMail(
466  ilObjUser::_lookupLogin($a_user_id),
467  null,
468  null,
469  $subject,
470  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
471  null,
472  array("system")
473  );
474  }
475 
476  public function addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
477  {
478  global $DIC;
479 
480  $lng = $DIC['lng'];
481 
482  switch ($a_form_id) {
485  $a_fields["enable_course_group_notifications"] = $a_is_active ?
486  $lng->txt("enabled") :
487  $lng->txt("disabled");
488  break;
489  }
490  }
491 
492  public function activationWasToggled($a_currently_active)
493  {
494  global $DIC;
495 
496  $ilSetting = $DIC['ilSetting'];
497 
498  // propagate cron-job setting to object setting
499  $ilSetting->set("crsgrp_ntf", (bool) $a_currently_active);
500  }
501 }
static _lookupLogin($a_user_id)
lookup login
$path
Definition: aliased.php:25
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
static lookupTxtById($plugin_id, $lang_var)
$result
global $DIC
Definition: saml.php:7
Cron job application base class.
static getExpressionText($a_const)
Get unicode for const.
Manage data for ilMembershipCronNotifications cron job.
static setUseRelativeDates($a_status)
set use relative dates
static _lookupTitle($a_id)
lookup object title
$log
Definition: sabredav.php:21
filterDuplicateItems(array $a_objects)
Filter duplicate news items from structure.
const IL_CAL_UNIX
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date public.
static useRelativeDates()
check if relative dates are used
foreach($_POST as $key=> $value) $res
static determineNewsContent($a_context_obj_type, $a_content, $a_is_lang_var)
Determine new content.
$lng
static _lookupObjId($a_id)
Date and time handling
$ilUser
Definition: imgupload.php:18
static getNamePresentation( $a_user_id, $a_user_image=false, $a_profile_link=false, $a_profile_back_link="", $a_force_first_lastname=false, $a_omit_login=false, $a_sortable=true, $a_return_data_array=false, $a_ctrl_path="ilpublicuserprofilegui")
Default behaviour is:
$txt
Definition: error.php:11
static _lookupType($a_id, $a_reference=false)
lookup object type
addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
parseNewsItem($a_parent_ref_id, array &$a_filter_map, array $a_item, $a_is_sub=false, $a_user_id=0)
Convert news item to summary html.
static ping($a_job_id)
Keep cron job alive.
global $l
Definition: afr.php:30
global $ilSetting
Definition: privfeed.php:17
$this data['403_header']
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.
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.