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
5include_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 {
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
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}
$result
global $l
Definition: afr.php:30
$path
Definition: aliased.php:25
An exception for terminatinating execution or to throw for unit testing.
const IL_CAL_UNIX
const IL_CAL_DATETIME
Cron job result data container.
Cron job application base class.
const SCHEDULE_TYPE_DAILY
static ping($a_job_id)
Keep cron job alive.
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date @access public.
static setUseRelativeDates($a_status)
set use relative dates
static useRelativeDates()
check if relative dates are used
@classDescription Date and time handling
static getExpressionText($a_const)
Get unicode for const.
static getLogger($a_component_id)
Get component logger.
Manage data for ilMembershipCronNotifications cron job.
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.
sendMail($a_user_id, array $a_objects, $a_last_run)
Send news mail for 1 user and n objects.
activationWasToggled($a_currently_active)
Cron job status was changed.
filterDuplicateItems(array $a_objects)
Filter duplicate news items from structure.
addToExternalSettingsForm($a_form_id, array &$a_fields, $a_is_active)
Add external settings to form.
hasFlexibleSchedule()
Can the schedule be configured?
hasAutoActivation()
Is to be activated on "installation".
static determineNewsContent($a_context_obj_type, $a_content, $a_is_lang_var)
Determine new content.
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 _lookupLogin($a_user_id)
lookup login
static lookupTxtById($plugin_id, $lang_var)
static _lookupObjId($a_id)
static _lookupTitle($a_id)
lookup object title
static _lookupType($a_id, $a_reference=false)
lookup object type
ILIAS Setting Class.
Wrapper classes for system notifications.
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:
static shortenText( $a_str, $a_len, $a_dots=false, $a_next_blank=false, $a_keep_extension=false)
shorten a string to given length.
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
$txt
Definition: error.php:11
global $ilSetting
Definition: privfeed.php:17
$log
Definition: sabredav.php:21
global $DIC
Definition: saml.php:7
$lng
foreach($_POST as $key=> $value) $res
global $ilDB
$this data['403_header']
$ilUser
Definition: imgupload.php:18