19 declare(strict_types=1);
65 $this->
lng = $lng ?? $DIC->language();
66 $this->ilDB = $database ?? $DIC->database();
68 $this->
refinery = $refinery ?? $DIC->refinery();
69 $this->cronManager = $cronManager ?? $DIC->cron()->manager();
74 return 'frm_notification';
79 return $this->
lng->txt(
'cron_forum_notification');
84 return $this->
lng->txt(
'cron_forum_notification_crob_desc');
89 return CronJobScheduleType::SCHEDULE_TYPE_IN_HOURS;
114 $this->
logger->debug(
'Sending ping to cron manager ...');
115 $this->cronManager->ping($this->
getId());
116 $this->
logger->debug(sprintf(
'Current memory usage: %s', memory_get_usage(
true)));
123 $this->
logger = $DIC->logger()->frm();
124 $this->tree = $DIC->repositoryTree();
128 $this->
lng->loadLanguageModule(
'forum');
130 $this->
logger->info(
'Started forum notification job ...');
132 if (!($last_run_datetime = $this->
settings->get(
'cron_forum_notification_last_date'))) {
133 $last_run_datetime = null;
136 $this->num_sent_messages = 0;
137 $cj_start_date = date(
'Y-m-d H:i:s');
139 if ((
string) $this->
settings->get(
'max_notification_age',
'') ===
'') {
140 $this->
logger->info(sprintf(
141 'No maximum notification age set, %s days will be used to determine the ' .
142 'left interval when querying the relevant forum events.',
143 self::DEFAULT_MAX_NOTIFICATION_AGE_IN_DAYS
147 if ($last_run_datetime !== null &&
149 (
int) date(
'm', strtotime($last_run_datetime)),
150 (
int) date(
'd', strtotime($last_run_datetime)),
151 (
int) date(
'Y', strtotime($last_run_datetime))
154 strtotime($last_run_datetime),
155 strtotime(
'-' . (
int) $this->
settings->get(
'max_notification_age', (
string) self::DEFAULT_MAX_NOTIFICATION_AGE_IN_DAYS) .
' days')
158 $threshold = strtotime(
'-' . (
int) $this->
settings->get(
'max_notification_age', (
string) self::DEFAULT_MAX_NOTIFICATION_AGE_IN_DAYS) .
' days');
161 $this->
logger->info(sprintf(
'Threshold for forum event determination is: %s', date(
'Y-m-d H:i:s', $threshold)));
163 $threshold_date = date(
'Y-m-d H:i:s', $threshold);
177 $this->
settings->set(
'cron_forum_notification_last_date', $cj_start_date);
179 $mess =
'Sent ' . $this->num_sent_messages .
' messages.';
181 $this->
logger->info($mess);
182 $this->
logger->info(
'Finished forum notification job');
185 if ($this->num_sent_messages !== 0) {
187 $result->setMessage($mess);
190 $result->setStatus($status);
200 if (!array_key_exists($a_obj_id, self::$ref_ids_by_obj_id)) {
204 return self::$ref_ids_by_obj_id[$a_obj_id];
210 $ilAccess = $DIC->access();
212 if (!array_key_exists($a_user_id, self::$accessible_ref_ids_by_user)) {
213 self::$accessible_ref_ids_by_user[$a_user_id] = [];
216 if (!array_key_exists($a_obj_id, self::$accessible_ref_ids_by_user[$a_user_id])) {
217 $accessible_ref_id = 0;
219 if ($ilAccess->checkAccessOfUser($a_user_id,
'read',
'', $ref_id)) {
224 self::$accessible_ref_ids_by_user[$a_user_id][$a_obj_id] = $accessible_ref_id;
227 return (
int) self::$accessible_ref_ids_by_user[$a_user_id][$a_obj_id];
233 $ilDB = $DIC->database();
235 while ($row = $ilDB->fetchAssoc($res)) {
239 self::$deleted_ids_cache[$row[
'deleted_id']] = $row[
'deleted_id'];
250 'The recipient with id %s has no "read" permission for object with id %s',
261 $row[
'closest_container'] = null;
266 $provider_id = isset($row[
'deleted_id']) ? -((
int) $row[
'deleted_id']) : (
int) $row[
'pos_pk'];
268 self::$providerObject[$provider_id .
'_' . $notification_type]->addRecipient((
int) $row[
'user_id']);
274 $usrIdsToPreload = [];
275 foreach (self::$providerObject as
$provider) {
276 if ($provider->getPosAuthorId() !== 0) {
277 $usrIdsToPreload[$provider->getPosAuthorId()] = $provider->getPosAuthorId();
279 if ($provider->getPosDisplayUserId() !== 0) {
280 $usrIdsToPreload[$provider->getPosDisplayUserId()] = $provider->getPosDisplayUserId();
282 if ($provider->getPostUpdateUserId() !== 0) {
283 $usrIdsToPreload[$provider->getPostUpdateUserId()] = $provider->getPostUpdateUserId();
290 foreach (self::$providerObject as $provider) {
291 if ($i > 0 && ($i % self::KEEP_ALIVE_CHUNK_SIZE) === 0) {
295 $recipients = array_unique($provider->getCronRecipients());
299 'Trying to send forum notifications for posting id "%s", type "%s" and recipients: %s',
300 $provider->getPostId(),
302 implode(
', ', $recipients)
307 $mailNotification->setIsCronjob(
true);
308 $mailNotification->setType($notification_type);
309 $mailNotification->setRecipients($recipients);
311 $mailNotification->send();
313 $this->num_sent_messages += count($provider->getCronRecipients());
314 $this->
logger->info(
'Sent notifications ... ');
325 public function determineClosestContainer(
int $frm_ref_id): ?
ilObject 327 if (isset(self::$container_by_frm_ref_id[$frm_ref_id])) {
328 return self::$container_by_frm_ref_id[$frm_ref_id];
331 $ref_id = $this->tree->checkForParentType($frm_ref_id,
'crs');
333 $ref_id = $this->tree->checkForParentType($frm_ref_id,
'grp');
339 self::$container_by_frm_ref_id[$frm_ref_id] =
$container;
348 return isset(self::$providerObject[$provider_id .
'_' . $notification_type]);
357 self::$providerObject[$provider_id .
'_' . $notification_type] = $tmp_provider;
358 self::$providerObject[$provider_id .
'_' . $notification_type]->addRecipient((
int) $row[
'user_id']);
363 self::$providerObject = [];
369 $a_fields[
'cron_forum_notification'] = $a_is_active ?
370 $this->
lng->txt(
'enabled') :
371 $this->
lng->txt(
'disabled');
379 if ($a_currently_active) {
383 $setting->
set(
'forum_notification', (
string) $value);
388 $this->
lng->loadLanguageModule(
'forum');
391 $this->
lng->txt(
'frm_max_notification_age'),
392 'max_notification_age' 394 $max_notification_age->setSize(5);
395 $max_notification_age->setSuffix($this->
lng->txt(
'frm_max_notification_age_unit'));
396 $max_notification_age->setRequired(
true);
397 $max_notification_age->allowDecimals(
false);
398 $max_notification_age->setMinValue(1);
399 $max_notification_age->setInfo($this->
lng->txt(
'frm_max_notification_age_info'));
400 $max_notification_age->setValue(
402 'max_notification_age',
403 (
string) self::DEFAULT_MAX_NOTIFICATION_AGE_IN_DAYS
407 $a_form->
addItem($max_notification_age);
413 'max_notification_age',
416 $this->refinery->kindlyTo()->int(),
418 $this->
refinery->kindlyTo()->float(),
422 $this->
refinery->kindlyTo()->string()
432 frm_posts.pos_status = %s AND ( 433 (frm_posts.pos_date >= %s AND frm_posts.pos_date = frm_posts.pos_activation_date) OR 434 (frm_posts.pos_activation_date >= %s AND frm_posts.pos_date < frm_posts.pos_activation_date) 437 $values = [1, $threshold_date, $threshold_date];
439 $res = $this->ilDB->queryF(
455 frm_notification.interested_events & %s AND 456 frm_posts.pos_cens = %s AND frm_posts.pos_status = %s AND 457 (frm_posts.pos_update > frm_posts.pos_date AND frm_posts.pos_update >= %s) ';
466 $res = $this->ilDB->queryF(
482 frm_notification.interested_events & %s AND 483 frm_posts.pos_cens = %s AND frm_posts.pos_status = %s AND 484 (frm_posts.pos_cens_date >= %s AND frm_posts.pos_cens_date > frm_posts.pos_activation_date ) ';
493 $res = $this->ilDB->queryF(
509 frm_notification.interested_events & %s AND 510 frm_posts.pos_cens = %s AND frm_posts.pos_status = %s AND 511 (frm_posts.pos_cens_date >= %s AND frm_posts.pos_cens_date > frm_posts.pos_activation_date ) ';
520 $res = $this->ilDB->queryF(
528 'uncensored posting',
535 $res = $this->ilDB->queryF(
543 'frm_threads_deleted',
551 $res = $this->ilDB->queryF(
567 $numRows = $this->ilDB->numRows($res);
569 $this->
logger->info(sprintf(
'Sending notifications for %s "%s" events ...', $numRows, $actionName));
571 $this->
logger->info(sprintf(
'Sent notifications for %s ...', $actionName));
580 string $actionDescription,
581 int $notificationType
583 $numRows = $this->ilDB->numRows($res);
585 $this->
logger->info(sprintf(
'Sending notifications for %s "%s" events ...', $numRows, $actionDescription));
587 if (self::$deleted_ids_cache !== []) {
588 $this->ilDB->manipulate(
589 'DELETE FROM frm_posts_deleted WHERE ' . $this->ilDB->in(
591 self::$deleted_ids_cache,
596 $this->
logger->info(
'Deleted obsolete entries of table "' . $action .
'" ...');
598 $this->
logger->info(sprintf(
'Sent notifications for %s ...', $actionDescription));
607 SELECT frm_threads.thr_subject thr_subject, 608 frm_data.top_name top_name, 609 frm_data.top_frm_fk obj_id, 610 frm_notification.user_id user_id, 611 frm_threads.thr_pk thread_id, 613 FROM frm_notification, frm_posts, frm_threads, frm_data, frm_posts_tree 614 WHERE frm_posts.pos_thr_fk = frm_threads.thr_pk AND ' . $condition .
' 615 AND ((frm_threads.thr_top_fk = frm_data.top_pk AND frm_data.top_frm_fk = frm_notification.frm_id) 616 OR (frm_threads.thr_pk = frm_notification.thread_id 617 AND frm_data.top_pk = frm_threads.thr_top_fk) ) 618 AND frm_posts.pos_author_id != frm_notification.user_id 619 AND frm_posts_tree.pos_fk = frm_posts.pos_pk AND frm_posts_tree.parent_pos != 0 620 ORDER BY frm_posts.pos_date ASC';
626 SELECT frm_posts_deleted.thread_title thr_subject, 627 frm_posts_deleted.forum_title top_name, 628 frm_posts_deleted.obj_id obj_id, 629 frm_notification.user_id user_id, 630 frm_posts_deleted.pos_display_user_id, 631 frm_posts_deleted.pos_usr_alias, 632 frm_posts_deleted.deleted_id, 633 frm_posts_deleted.post_date pos_date, 634 frm_posts_deleted.post_title pos_subject, 635 frm_posts_deleted.post_message pos_message, 636 frm_posts_deleted.deleted_by 638 FROM frm_notification, frm_posts_deleted 640 WHERE ( frm_posts_deleted.obj_id = frm_notification.frm_id 641 OR frm_posts_deleted.thread_id = frm_notification.thread_id) 642 AND frm_posts_deleted.pos_display_user_id != frm_notification.user_id 643 AND frm_posts_deleted.is_thread_deleted = %s 644 AND frm_notification.interested_events & %s 645 ORDER BY frm_posts_deleted.post_date ASC';
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
readonly ilSetting $settings
existsProviderObject(int $provider_id, int $notification_type)
Interface Observer Contains several chained tasks and infos about them.
__construct(ilDBInterface $database=null, ilForumNotificationCache $notificationCache=null, ilLanguage $lng=null, ilSetting $settings=null, \ILIAS\Refinery\Factory $refinery=null, ilCronManager $cronManager=null)
set(string $a_key, string $a_val)
static _getAllReferences(int $id)
get all reference ids for object ID
Class ilForumCronNotificationDataProvider.
sendNotificationForDeletedThreads()
static array $deleted_ids_cache
readonly ilCronManager $cronManager
sendNotificationForUncensoredPosts(string $threshold_date)
sendDeleteNotifications(ilDBStatement $res, string $action, string $actionDescription, int $notificationType)
createSelectOfDeletionNotificationsSql()
const TYPE_THREAD_DELETED
const KEEP_ALIVE_CHUNK_SIZE
readonly ilDBInterface $ilDB
addProviderObject(int $provider_id, array $row, int $notification_type)
addCustomSettingsToForm(ilPropertyFormGUI $a_form)
const DEFAULT_MAX_NOTIFICATION_AGE_IN_DAYS
sendNotificationForCensoredPosts(string $threshold_date)
static array $ref_ids_by_obj_id
getDefaultScheduleValue()
final const STATUS_NO_ACTION
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
activationWasToggled(ilDBInterface $db, ilSetting $setting, bool $a_currently_active)
Class ilForumNotificationCache.
static array $accessible_ref_ids_by_user
sendNotificationForNewPosts(string $threshold_date)
saveCustomSettings(ilPropertyFormGUI $a_form)
getRefIdsByObjId(int $a_obj_id)
readonly ILIAS Refinery Factory $refinery
readonly ilForumNotificationCache $notificationCache
addToExternalSettingsForm(int $a_form_id, array &$a_fields, bool $a_is_active)
static array $container_by_frm_ref_id
sendCronForumNotification(ilDBStatement $res, int $notification_type)
getFirstAccessibleRefIdBUserAndObjId(int $a_user_id, int $a_obj_id)
sendNotificationForUpdatedPosts(string $threshold_date)
sendNotification(ilDBStatement $res, string $actionName, int $notificationType)
const TYPE_POST_UNCENSORED
createForumPostSql(string $condition)
static array $providerObject
sendNotificationForDeletedPosts()