ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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  // see 29967
293  $res = str_replace("<br />", " ", $res);
294  $res = strip_tags($res);
295 
296  return trim($res);
297  }
298 
305  protected function filterDuplicateItems(array $a_objects)
306  {
307  global $DIC;
308 
309  $tree = $DIC['tree'];
310 
311  $parent_map = $news_map = $parsed_map = array();
312 
313  // gather news ref ids and news parent ref ids
314  foreach ($a_objects as $parent_ref_id => $news) {
315  foreach ($news as $item) {
316  $news_map[$item["id"]] = $item["ref_id"];
317  $parent_map[$item["id"]][$parent_ref_id] = $parent_ref_id;
318 
319  if ($item["aggregation"]) {
320  foreach ($item["aggregation"] as $subitem) {
321  $news_map[$subitem["id"]] = $subitem["ref_id"];
322  $parent_map[$subitem["id"]][$parent_ref_id] = $parent_ref_id;
323  }
324  }
325  }
326  }
327  // if news has multiple parents find "lowest" parent in path
328  foreach ($parent_map as $news_id => $parents) {
329  if (sizeof($parents) > 1 && $news_map[$news_id] > 0) {
330  $path = $tree->getPathId($news_map[$news_id]);
331  $lookup = array_flip($path);
332 
333  $level = 0;
334  foreach ($parents as $parent_ref_id) {
335  $level = max($level, $lookup[$parent_ref_id]);
336  }
337 
338  $parsed_map[$news_id] = $path[$level];
339  }
340  }
341 
342  return $parsed_map;
343  }
344 
352  protected function sendMail($a_user_id, array $a_objects, $a_last_run)
353  {
354  global $DIC;
355 
356  $lng = $DIC['lng'];
357  $ilUser = $DIC['ilUser'];
358  $ilClientIniFile = $DIC['ilClientIniFile'];
359  $tree = $DIC['tree'];
360 
362 
363  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
364  $ntf = new ilSystemNotification();
365  $ntf->setLangModules(array("crs", "news"));
366  // no single object anymore
367  // $ntf->setRefId($a_ref_id);
368  // $ntf->setGotoLangId('url');
369  // $ntf->setSubjectLangId('crs_subject_course_group_notification');
370 
371  // user specific language
372  $lng = $ntf->getUserLanguage($a_user_id);
373 
374  include_once './Services/Locator/classes/class.ilLocatorGUI.php';
375  require_once "./Services/UICore/classes/class.ilTemplate.php";
376  require_once "./Services/Link/classes/class.ilLink.php";
377 
378  $filter_map = $this->filterDuplicateItems($a_objects);
379 
380  $tmp = array();
381 
382  foreach ($a_objects as $parent_ref_id => $items) {
383  $parent = array();
384 
385  // path
386  $path = array();
387  foreach ($tree->getPathId($parent_ref_id) as $node) {
388  $path[] = $node;
389  }
390  $path = implode("-", $path);
391 
392  $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
393  $parent_type = ilObject::_lookupType($parent_obj_id);
394 
395  $parent["title"] = $lng->txt("obj_" . $parent_type) . ' "' . ilObject::_lookupTitle($parent_obj_id) . '"';
396  $parent["url"] = " " . $lng->txt("crs_course_group_notification_link") . " " . ilLink::_getStaticLink($parent_ref_id);
397 
398  $log->debug("ref id: " . $parent_ref_id . ", items: " . count($items));
399 
400  // news summary
401  $parsed = array();
402  if (is_array($items)) {
403  foreach ($items as $news_item) {
404  if ($news_item === null) {
405  continue;
406  }
407 
408  // # Type "<Object Title>": "<News Title>" - News Text
409  $parsed_item = $this->parseNewsItem($parent_ref_id, $filter_map, $news_item, false, $a_user_id);
410  if ($parsed_item) {
411  $parsed[md5($parsed_item)] = $parsed_item;
412  }
413  }
414  }
415 
416  // any news?
417  if (sizeof($parsed)) {
418  $parent["news"] = implode("\n\n", $parsed);
419  $tmp[$path] = $parent;
420  }
421  }
422 
423  // any objects?
424  if (!sizeof($tmp)) {
425  $log->debug("returning");
426  return;
427  }
428 
429  ksort($tmp);
430  $counter = 0;
431  $obj_index = array();
432  $txt = "";
433  foreach ($tmp as $path => $item) {
434  $counter++;
435 
436  $txt .= "(" . $counter . ") " . $item["title"] . "\n" .
437  $item["url"] . "\n\n" .
438  $item["news"] . "\n\n";
439 
440  $obj_index[] = "(" . $counter . ") " . $item["title"];
441  }
442 
443  $ntf->setIntroductionLangId("crs_intro_course_group_notification_for");
444 
445  // index
446  $period = sprintf(
447  $lng->txt("crs_intro_course_group_notification_index"),
450  );
451  $ntf->addAdditionalInfo(
452  $period,
453  trim(implode("\n", $obj_index)),
454  true,
455  true
456  );
457 
458  // object list
459  $ntf->addAdditionalInfo(
460  "",
461  trim($txt),
462  true
463  );
464 
465  // :TODO: does it make sense to add client to subject?
466  $client = $ilClientIniFile->readVariable('client', 'name');
467  $subject = sprintf($lng->txt("crs_subject_course_group_notification"), $client);
468 
469  $mail_content = $ntf->composeAndGetMessage($a_user_id, null, "read", true);
470  $log->debug("sending mail content: " . $mail_content);
471 
472  // #10044
473  $mail = new ilMail(ANONYMOUS_USER_ID);
474  $mail->enqueue(
475  ilObjUser::_lookupLogin($a_user_id),
476  null,
477  null,
478  $subject,
479  $mail_content,
480  []
481  );
482  }
483 
484  public function addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
485  {
486  global $DIC;
487 
488  $lng = $DIC['lng'];
489 
490  switch ($a_form_id) {
493  $a_fields["enable_course_group_notifications"] = $a_is_active ?
494  $lng->txt("enabled") :
495  $lng->txt("disabled");
496  break;
497  }
498  }
499 
500  public function activationWasToggled($a_currently_active)
501  {
502  global $DIC;
503 
504  $ilSetting = $DIC['ilSetting'];
505 
506  // propagate cron-job setting to object setting
507  $ilSetting->set("crsgrp_ntf", (bool) $a_currently_active);
508  }
509 }
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
$c
Definition: cli.php:37
static lookupTxtById($plugin_id, $lang_var)
const ANONYMOUS_USER_ID
Definition: constants.php:25
$result
Cron job application base class.
static getExpressionText($a_const)
Get unicode for const.
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
Manage data for ilMembershipCronNotifications cron job.
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
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
$log
Definition: result.php:15
static _lookupObjId($a_id)
global $DIC
Definition: goto.php:24
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:13
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 $ilSetting
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.
Cron job result data container.
$ilUser
Definition: imgupload.php:18
Wrapper classes for system notifications.
sendMail($a_user_id, array $a_objects, $a_last_run)
Send news mail for 1 user and n objects.