ILIAS  release_8 Revision v8.24
class.ilNewsItem.php
Go to the documentation of this file.
1<?php
2
19const NEWS_NOTICE = 0;
20const NEWS_MESSAGE = 1;
21const NEWS_WARNING = 2;
22
23const NEWS_TEXT = "text";
24const NEWS_HTML = "html";
25const NEWS_AUDIO = "audio";
26const NEWS_USERS = "users";
27const NEWS_PUBLIC = "public";
28
41{
42 private int $mob_cnt_download = 0;
43 protected int $mob_cnt_play = 0;
44 protected ilDBInterface $db;
45 protected ilTree $tree;
48 protected ilObjUser $user;
49 protected ilLanguage $lng;
50 protected ilCtrl $ctrl;
51 protected int $id = 0;
52 protected string $title = "";
53 protected string $content = "";
54 protected bool $content_html = false;
55 protected int $context_obj_id = 0;
56 protected string $context_obj_type = "";
57 protected int $context_sub_obj_id = 0;
58 protected ?string $context_sub_obj_type = null;
59 protected string $content_type = "text";
60 protected string $creation_date = "";
61 protected string $update_date = "";
62 protected int $user_id = 0;
63 protected int $update_user_id = 0;
64 protected string $visibility = "users";
65 protected string $content_long = "";
66 protected int $priority = 1;
67 protected bool $content_is_lang_var = false;
68 protected int $mob_id = 0;
69 protected string $playtime = "";
70 private static int $privFeedId = 0;
71 private bool $limitation = false;
72 protected bool $content_text_is_lang_var = false;
74 protected ilLogger $log;
75
76 public function __construct(int $a_id = 0)
77 {
78 global $DIC;
79 $this->main_tpl = $DIC->ui()->mainTemplate();
80
81 $this->db = $DIC->database();
82 $this->tree = $DIC->repositoryTree();
83 $this->access = $DIC->access();
84 $this->obj_data_cache = $DIC["ilObjDataCache"];
85 $this->user = $DIC->user();
86 $this->lng = $DIC->language();
87 $this->ctrl = $DIC->ctrl();
88 if ($a_id > 0) {
89 $this->setId($a_id);
90 $this->read();
91 }
92 $this->limitation = true;
93 $this->log = $DIC->logger()->news();
94 }
95
96 public function setId(int $a_id): void
97 {
98 $this->id = $a_id;
99 }
100
101 public function getId(): int
102 {
103 return $this->id;
104 }
105
106 public function setTitle(string $a_title): void
107 {
108 $this->title = $a_title;
109 }
110
111 public function getTitle(): string
112 {
113 return $this->title;
114 }
115
116 public function setContent(string $a_content): void
117 {
118 $this->content = $a_content;
119 }
120
121 public function getContent(): string
122 {
123 return $this->content;
124 }
125
126 public function setContextObjId(int $a_context_obj_id): void
127 {
128 $this->context_obj_id = $a_context_obj_id;
129 }
130
131 public function getContextObjId(): int
132 {
134 }
135
136 public function setContextObjType(string $a_context_obj_type): void
137 {
138 $this->context_obj_type = $a_context_obj_type;
139 }
140
141 public function getContextObjType(): string
142 {
144 }
145
146 public function setContextSubObjId(int $a_context_sub_obj_id): void
147 {
148 $this->context_sub_obj_id = $a_context_sub_obj_id;
149 }
150
151 public function getContextSubObjId(): int
152 {
154 }
155
156 public function setContextSubObjType(?string $a_context_sub_obj_type): void
157 {
158 $this->context_sub_obj_type = $a_context_sub_obj_type;
159 }
160
161 public function getContextSubObjType(): ?string
162 {
164 }
165
166 public function setContentType(string $a_content_type = "text"): void
167 {
168 $this->content_type = $a_content_type;
169 }
170
171 public function getContentType(): string
172 {
173 return $this->content_type;
174 }
175
176 public function setCreationDate(string $a_creation_date): void
177 {
178 $this->creation_date = $a_creation_date;
179 }
180
181 public function getCreationDate(): string
182 {
184 }
185
186 public function setUpdateDate(string $a_update_date): void
187 {
188 $this->update_date = $a_update_date;
189 }
190
191 public function getUpdateDate(): string
192 {
193 return $this->update_date;
194 }
195
196 public function setUserId(int $a_user_id): void
197 {
198 $this->user_id = $a_user_id;
199 }
200
201 public function getUserId(): int
202 {
203 return $this->user_id;
204 }
205
206 public function setUpdateUserId(int $a_val): void
207 {
208 $this->update_user_id = $a_val;
209 }
210
211 public function getUpdateUserId(): int
212 {
214 }
215
219 public function setVisibility(
220 string $a_visibility = "users"
221 ): void {
222 $this->visibility = $a_visibility;
223 }
224
225 public function getVisibility(): string
226 {
227 return $this->visibility;
228 }
229
233 public function setContentLong(string $a_content_long): void
234 {
235 $this->content_long = $a_content_long;
236 }
237
238 public function getContentLong(): string
239 {
240 return $this->content_long;
241 }
242
243 public function setPriority(int $a_priority = 1): void
244 {
245 $this->priority = $a_priority;
246 }
247
248 public function getPriority(): int
249 {
250 return $this->priority;
251 }
252
253 public function setContentIsLangVar(
254 bool $a_content_is_lang_var = false
255 ): void {
256 $this->content_is_lang_var = $a_content_is_lang_var;
257 }
258
259 public function getContentIsLangVar(): bool
260 {
261 return $this->content_is_lang_var;
262 }
263
264 public function setMobId(int $a_mob_id): void
265 {
266 $this->mob_id = $a_mob_id;
267 }
268
269 public function getMobId(): int
270 {
271 return $this->mob_id;
272 }
273
277 public function setPlaytime(string $a_playtime): void
278 {
279 $this->playtime = $a_playtime;
280 }
281
282 public function getPlaytime(): string
283 {
284 return $this->playtime;
285 }
286
290 public function setLimitation(bool $a_limitation): void
291 {
292 $this->limitation = $a_limitation;
293 }
294
295 public function getLimitation(): bool
296 {
297 return $this->limitation;
298 }
299
300 public function setContentTextIsLangVar(bool $a_val = false): void
301 {
302 $this->content_text_is_lang_var = $a_val;
303 }
304
305 public function getContentTextIsLangVar(): bool
306 {
307 return $this->content_text_is_lang_var;
308 }
309
310 public function setMobPlayCounter(int $a_val): void
311 {
312 $this->mob_cnt_play = $a_val;
313 }
314
315 public function getMobPlayCounter(): int
316 {
317 return $this->mob_cnt_play;
318 }
319
320 public function setMobDownloadCounter(int $a_val): void
321 {
322 $this->mob_cnt_download = $a_val;
323 }
324
325 public function getMobDownloadCounter(): int
326 {
327 return $this->mob_cnt_download;
328 }
329
330 public function setContentHtml(bool $a_val): void
331 {
332 $this->content_html = $a_val;
333 }
334
335 public function getContentHtml(): bool
336 {
337 return $this->content_html;
338 }
339
344 public function read(): void
345 {
346 $ilDB = $this->db;
347
348 $query = "SELECT * FROM il_news_item WHERE id = " .
349 $ilDB->quote($this->getId(), "integer");
350 $set = $ilDB->query($query);
351 if ($rec = $ilDB->fetchAssoc($set)) {
352 $this->setTitle((string) $rec["title"]);
353 $this->setContent((string) $rec["content"]);
354 $this->setContextObjId((int) $rec["context_obj_id"]);
355 $this->setContextObjType($rec["context_obj_type"]);
356 $this->setContextSubObjId((int) $rec["context_sub_obj_id"]);
357 $this->setContextSubObjType((string) $rec["context_sub_obj_type"]);
358 $this->setContentType((string) $rec["content_type"]);
359 $this->setCreationDate((string) $rec["creation_date"]);
360 $this->setUpdateDate((string) $rec["update_date"]);
361 $this->setUserId((int) $rec["user_id"]);
362 $this->setUpdateUserId((int) $rec["update_user_id"]);
363 $this->setVisibility((string) $rec["visibility"]);
364 $this->setContentLong((string) $rec["content_long"]);
365 $this->setPriority((int) $rec["priority"]);
366 $this->setContentIsLangVar((bool) $rec["content_is_lang_var"]);
367 $this->setContentTextIsLangVar((bool) $rec["content_text_is_lang_var"]);
368 $this->setMobId((int) $rec["mob_id"]);
369 $this->setPlaytime((string) $rec["playtime"]);
370 $this->setMobPlayCounter((int) $rec["mob_cnt_play"]);
371 $this->setMobDownloadCounter((int) $rec["mob_cnt_download"]);
372 $this->setContentHtml((bool) $rec["content_html"]);
373 }
374 }
375
380 public function create(): void
381 {
382 $ilDB = $this->db;
383
384 // insert new record into db
385 $this->setId($ilDB->nextId("il_news_item"));
386 $ilDB->insert("il_news_item", [
387 "id" => ["integer", $this->getId()],
388 "title" => ["text", $this->getTitle()],
389 "content" => ["clob", $this->getContent()],
390 "content_html" => ["integer", (int) $this->getContentHtml()],
391 "context_obj_id" => ["integer", $this->getContextObjId()],
392 "context_obj_type" => ["text", $this->getContextObjType()],
393 "context_sub_obj_id" => ["integer", $this->getContextSubObjId()],
394 "context_sub_obj_type" => ["text", $this->getContextSubObjType()],
395 "content_type" => ["text", $this->getContentType()],
396 "creation_date" => ["timestamp", ilUtil::now()],
397 "update_date" => ["timestamp", ilUtil::now()],
398 "user_id" => ["integer", $this->getUserId()],
399 "update_user_id" => ["integer", $this->getUpdateUserId()],
400 "visibility" => ["text", $this->getVisibility()],
401 "content_long" => ["clob", $this->getContentLong()],
402 "priority" => ["integer", $this->getPriority()],
403 "content_is_lang_var" => ["integer", $this->getContentIsLangVar()],
404 "content_text_is_lang_var" => ["integer", (int) $this->getContentTextIsLangVar()],
405 "mob_id" => ["integer", $this->getMobId()],
406 "playtime" => ["text", $this->getPlaytime()]
407 ]);
408
409
410 $news_set = new ilSetting("news");
411 $max_items = $news_set->get("max_items");
412 if ($max_items <= 0) {
413 $max_items = 50;
414 }
415
416 // limit number of news
417 if ($this->getLimitation()) {
418 // Determine how many rows should be deleted
419 $query = "SELECT count(*) cnt " .
420 "FROM il_news_item " .
421 "WHERE " .
422 "context_obj_id = " . $ilDB->quote($this->getContextObjId(), "integer") .
423 " AND context_obj_type = " . $ilDB->quote($this->getContextObjType(), "text") .
424 " AND context_sub_obj_id = " . $ilDB->quote($this->getContextSubObjId(), "integer") .
425 " AND " . $ilDB->equals("context_sub_obj_type", $this->getContextSubObjType(), "text", true) . " ";
426
427 $set = $ilDB->query($query);
428 $rec = $ilDB->fetchAssoc($set);
429
430 // if we have more records than allowed, delete them
431 if (($rec["cnt"] > $max_items) && $this->getContextObjId() > 0) {
432 $query = "SELECT * " .
433 "FROM il_news_item " .
434 "WHERE " .
435 "context_obj_id = " . $ilDB->quote($this->getContextObjId(), "integer") .
436 " AND context_obj_type = " . $ilDB->quote($this->getContextObjType(), "text") .
437 " AND context_sub_obj_id = " . $ilDB->quote($this->getContextSubObjId(), "integer") .
438 " AND " . $ilDB->equals("context_sub_obj_type", $this->getContextSubObjType(), "text", true) .
439 " ORDER BY creation_date ASC";
440
441 $ilDB->setLimit($rec["cnt"] - $max_items, 0);
442 $del_set = $ilDB->query($query);
443 while ($del_item = $ilDB->fetchAssoc($del_set)) {
444 $del_news = new ilNewsItem((int) $del_item["id"]);
445 $del_news->delete();
446 }
447 }
448 }
449 }
450
457 public function update(bool $a_as_new = false): void
458 {
459 $ilDB = $this->db;
460
461 $fields = [
462 "title" => ["text", $this->getTitle()],
463 "content" => ["clob", $this->getContent()],
464 "content_html" => ["integer", (int) $this->getContentHtml()],
465 "context_obj_id" => ["integer", $this->getContextObjId()],
466 "context_obj_type" => ["text", $this->getContextObjType()],
467 "context_sub_obj_id" => ["integer", $this->getContextSubObjId()],
468 "context_sub_obj_type" => ["text", $this->getContextSubObjType()],
469 "content_type" => ["text", $this->getContentType()],
470 "user_id" => ["integer", $this->getUserId()],
471 "update_user_id" => ["integer", $this->getUpdateUserId()],
472 "visibility" => ["text", $this->getVisibility()],
473 "content_long" => ["clob", $this->getContentLong()],
474 "priority" => ["integer", $this->getPriority()],
475 "content_is_lang_var" => ["integer", $this->getContentIsLangVar()],
476 "content_text_is_lang_var" => ["integer", (int) $this->getContentTextIsLangVar()],
477 "mob_id" => ["integer", $this->getMobId()],
478 "mob_cnt_play" => ["integer", $this->getMobPlayCounter()],
479 "mob_cnt_download" => ["integer", $this->getMobDownloadCounter()],
480 "playtime" => ["text", $this->getPlaytime()]
481 ];
482
483 $now = ilUtil::now();
484 if ($a_as_new) {
485 $fields["creation_date"] = ["timestamp", $now];
486 }
487 $fields["update_date"] = ["timestamp", $now];
488
489 $ilDB->update("il_news_item", $fields, [
490 "id" => ["integer", $this->getId()]
491 ]);
492 }
493
494
499 public static function _getNewsItemsOfUser(
500 int $a_user_id,
501 bool $a_only_public = false,
502 bool $a_prevent_aggregation = false,
503 int $a_per = 0,
504 array &$a_cnt = []
505 ): array {
506 global $DIC;
507
508 $ilAccess = $DIC->access();
509
510 $fav_rep = new ilFavouritesDBRepository();
511
512 $news_item = new ilNewsItem();
513
514 $per = $a_per;
515
516 // this is currently not used
517 $ref_ids = [];
518
519 if (ilObjUser::_lookupPref($a_user_id, "pd_items_news") !== "n") {
520 // get all items of the personal desktop
521 $pd_items = $fav_rep->getFavouritesOfUser($a_user_id);
522 foreach ($pd_items as $item) {
523 if (!in_array($item["ref_id"], $ref_ids)) {
524 $ref_ids[] = (int) $item["ref_id"];
525 }
526 }
527
528 // get all memberships
529 $crs_mbs = ilParticipants::_getMembershipByType($a_user_id, ['crs']);
530 $grp_mbs = ilParticipants::_getMembershipByType($a_user_id, ['grp']);
531 $items = array_merge($crs_mbs, $grp_mbs);
532 foreach ($items as $i) {
533 $item_references = ilObject::_getAllReferences($i);
534 if (is_array($item_references) && count($item_references)) {
535 foreach ($item_references as $ref_id) {
536 if (!in_array($ref_id, $ref_ids)) {
537 $ref_ids[] = $ref_id;
538 }
539 }
540 }
541 }
542 }
543
544 $data = [];
545
546 foreach ($ref_ids as $ref_id) {
547 if (!$a_only_public) {
548 // this loop should not cost too much performance
549 $acc = $ilAccess->checkAccessOfUser($a_user_id, "read", "", $ref_id);
550
551 if (!$acc) {
552 continue;
553 }
554 }
555 if (self::getPrivateFeedId() > 0) {
556 global $DIC;
557
558 $rbacsystem = $DIC->rbac()->system();
559 $acc = $rbacsystem->checkAccessOfUser(self::getPrivateFeedId(), "read", $ref_id);
560
561 if (!$acc) {
562 continue;
563 }
564 }
565
567 $obj_type = ilObject::_lookupType($obj_id);
568 $news = $news_item->getNewsForRefId(
569 $ref_id,
570 $a_only_public,
571 false,
572 $per,
573 $a_prevent_aggregation,
574 false,
575 false,
576 false,
577 $a_user_id
578 );
579
580 // counter
581 if (!is_null($a_cnt)) {
582 $a_cnt[$ref_id] = count($news);
583 }
584
585 $data = self::mergeNews($data, $news);
586 }
587
588 $data = ilArrayUtil::sortArray($data, "creation_date", "desc", false, true);
589
590 return $data;
591 }
592
601 public function getNewsForRefId(
602 int $a_ref_id,
603 bool $a_only_public = false,
604 bool $a_stopnesting = false,
605 $a_time_period = 0,
606 bool $a_prevent_aggregation = true,
607 bool $a_forum_group_sequences = false,
608 bool $a_no_auto_generated = false,
609 bool $a_ignore_date_filter = false,
610 int $a_user_id = null,
611 int $a_limit = 0,
612 array $a_excluded = []
613 ): array {
614 $obj_id = ilObject::_lookupObjId($a_ref_id);
615 $obj_type = ilObject::_lookupType($obj_id);
616
617 // get starting date
618 $starting_date = "";
619 if ($obj_type === "grp" || $obj_type === "crs") {
620 // see #31471, #30687, and ilMembershipNotification
622 $obj_id,
623 'cont_use_news',
624 '1'
625 ) || (
627 $obj_id,
628 'cont_show_news',
629 '1'
631 $obj_id,
632 'news_timeline'
633 )
634 )) {
635 return [];
636 }
637
638 $hide_news_per_date = ilBlockSetting::_lookup(
639 "news",
640 "hide_news_per_date",
641 0,
642 $obj_id
643 );
644 if ($hide_news_per_date && !$a_ignore_date_filter) {
645 $starting_date = ilBlockSetting::_lookup(
646 "news",
647 "hide_news_date",
648 0,
649 $obj_id
650 );
651 }
652 }
653
654 if ($obj_type === "cat" && !$a_stopnesting) {
655 $news = $this->getAggregatedChildNewsData(
656 $a_ref_id,
657 $a_only_public,
658 $a_time_period,
659 $a_prevent_aggregation,
660 $starting_date,
661 $a_no_auto_generated
662 );
663 } elseif (($obj_type === "grp" || $obj_type === "crs") &&
664 !$a_stopnesting) {
665 $news = $this->getAggregatedNewsData(
666 $a_ref_id,
667 $a_only_public,
668 $a_time_period,
669 $a_prevent_aggregation,
670 $starting_date,
671 $a_no_auto_generated,
672 $a_user_id,
673 $a_limit,
674 $a_excluded
675 );
676 } else {
677 $news_item = new ilNewsItem();
678 $news_item->setContextObjId($obj_id);
679 $news_item->setContextObjType($obj_type);
680 $news = $news_item->queryNewsForContext(
681 $a_only_public,
682 $a_time_period,
683 $starting_date,
684 $a_no_auto_generated
685 );
686 $unset = [];
687 foreach ($news as $k => $v) {
688 if (!$a_only_public || $v["visibility"] == NEWS_PUBLIC ||
689 ($v["priority"] == 0 &&
691 "news",
692 "public_notifications",
693 0,
694 $obj_id
695 ))) {
696 $news[$k]["ref_id"] = $a_ref_id;
697 } else {
698 $unset[] = $k;
699 }
700 }
701 foreach ($unset as $un) {
702 unset($news[$un]);
703 }
704 }
705
706 if (!$a_prevent_aggregation) {
707 $news = $this->aggregateForums($news);
708 } elseif ($a_forum_group_sequences) {
709 $news = $this->aggregateForums($news, true);
710 }
711
712 return $news;
713 }
714
720 public function getAggregatedNewsData(
721 int $a_ref_id,
722 bool $a_only_public = false,
723 $a_time_period = 0,
724 bool $a_prevent_aggregation = false,
725 string $a_starting_date = "",
726 bool $a_no_auto_generated = false,
727 int $a_user_id = null,
728 int $a_limit = 0,
729 array $a_exclude = []
730 ): array {
731 $tree = $this->tree;
732 $ilAccess = $this->access;
733 $ilObjDataCache = $this->obj_data_cache;
734
735 // get news of parent object
736 $data = [];
737
738 // get subtree
739 $cur_node = $tree->getNodeData($a_ref_id);
740
741 // do not check for lft (materialized path)
742 if ($cur_node) {
743 $nodes = $tree->getSubTree($cur_node, true);
744 } else {
745 $nodes = [];
746 }
747
748 // preload object data cache
749 $ref_ids = [];
750 $obj_ids = [];
751 $ref_id = [];
752 foreach ($nodes as $node) {
753 $ref_ids[] = (int) $node["child"];
754 $obj_ids[] = (int) $node["obj_id"];
755 }
756
757 $ilObjDataCache->preloadReferenceCache($ref_ids);
758 if (!$a_only_public) {
760 }
761
762 // no check, for which of the objects any news are available
763 $news_obj_ids = self::filterObjIdsPerNews($obj_ids, $a_time_period, $a_starting_date);
764 //$news_obj_ids = $obj_ids;
765
766 // get news for all subtree nodes
767 $contexts = [];
768 foreach ($nodes as $node) {
769 // only go on, if news are available
770 if (!in_array($node["obj_id"], $news_obj_ids)) {
771 continue;
772 }
773
774 if (!$a_only_public) {
775 if (!$a_user_id) {
776 $acc = $ilAccess->checkAccess("read", "", (int) $node["child"]);
777 } else {
778 $acc = $ilAccess->checkAccessOfUser(
779 $a_user_id,
780 "read",
781 "",
782 (int) $node["child"]
783 );
784 }
785 if (!$acc) {
786 continue;
787 }
788 }
789
790 $ref_id[$node["obj_id"]] = $node["child"];
791 $contexts[] = [
792 "obj_id" => $node["obj_id"],
793 "obj_type" => $node["type"]
794 ];
795 }
796
797 // sort and return
798 $news = $this->queryNewsForMultipleContexts(
799 $contexts,
800 $a_only_public,
801 $a_time_period,
802 $a_starting_date,
803 $a_no_auto_generated,
804 $a_user_id,
805 $a_limit,
806 $a_exclude
807 );
808
809 $to_del = [];
810 foreach ($news as $k => $v) {
811 $news[$k]["ref_id"] = $ref_id[$v["context_obj_id"]];
812 }
813
814 $data = self::mergeNews($data, $news);
815 $data = ilArrayUtil::sortArray($data, "creation_date", "desc", false, true);
816
817 if (!$a_prevent_aggregation) {
818 $data = $this->aggregateFiles($data, $a_ref_id);
819 }
820
821 return $data;
822 }
823
827 protected function aggregateForums(
828 array $news,
829 bool $a_group_posting_sequence = false
830 ): array {
831 $to_del = [];
832 $forums = [];
833 $last_aggregation_forum = 0;
834
835 // aggregate
836 foreach ($news as $k => $v) {
837 if ($a_group_posting_sequence && $last_aggregation_forum > 0 &&
838 $last_aggregation_forum != $v["context_obj_id"]) {
839 $forums[$last_aggregation_forum] = null;
840 }
841
842 if ($v["context_obj_type"] === "frm") {
843 if (!isset($forums[$v["context_obj_id"]])) {
844 // $forums[forum_id] = news_id;
845 $forums[$v["context_obj_id"]] = $k;
846 $last_aggregation_forum = $v["context_obj_id"];
847 } else {
848 $to_del[] = $k;
849 }
850
851 $news[$k]["no_context_title"] = true;
852
853 // aggregate every forum into it's "k" news
854 $news[$forums[$news[$k]["context_obj_id"]]]["aggregation"][$k]
855 = $news[$k];
856 $news[$k]["agg_ref_id"]
857 = $news[$k]["ref_id"];
858 $news[$k]["content"] = "";
859 $news[$k]["content_long"] = "";
860 }
861 }
862
863 // delete double entries
864 foreach ($to_del as $k) {
865 unset($news[$k]);
866 }
867 //var_dump($news[14]["aggregation"]);
868
869 return $news;
870 }
871
875 protected function aggregateFiles(
876 array $news,
877 int $a_ref_id
878 ): array {
879 $first_file = "";
880 $to_del = [];
881 foreach ($news as $k => $v) {
882 // aggregate file related news
883 if ($v["context_obj_type"] === "file") {
884 if ($first_file === "") {
885 $first_file = $k;
886 } else {
887 $to_del[] = $k;
888 }
889 $news[$first_file]["aggregation"][$k] = $v;
890 $news[$first_file]["agg_ref_id"] = $a_ref_id;
891 $news[$first_file]["ref_id"] = $a_ref_id;
892 }
893 }
894
895 foreach ($to_del as $v) {
896 unset($news[$v]);
897 }
898
899 return $news;
900 }
901
902
907 protected function getAggregatedChildNewsData(
908 int $a_ref_id,
909 bool $a_only_public = false,
910 int $a_time_period = 0,
911 bool $a_prevent_aggregation = false,
912 string $a_starting_date = "",
913 bool $a_no_auto_generated = false
914 ): array {
915 $tree = $this->tree;
916 $ilAccess = $this->access;
917 $ref_id = [];
918 // get news of parent object
919 $data = $this->getNewsForRefId(
920 $a_ref_id,
921 $a_only_public,
922 true,
923 $a_time_period,
924 true,
925 false,
926 false,
927 $a_no_auto_generated
928 );
929 foreach ($data as $k => $v) {
930 $data[$k]["ref_id"] = $a_ref_id;
931 }
932
933 // get childs
934 $nodes = $tree->getChilds($a_ref_id);
935
936 // no check, for which of the objects any news are available
937 $obj_ids = [];
938 foreach ($nodes as $node) {
939 $obj_ids[] = $node["obj_id"];
940 }
941 $news_obj_ids = self::filterObjIdsPerNews($obj_ids, $a_time_period, $a_starting_date);
942 //$news_obj_ids = $obj_ids;
943
944 // get news for all subtree nodes
945 $contexts = [];
946 foreach ($nodes as $node) {
947 // only go on, if news are available
948 if (!in_array($node["obj_id"], $news_obj_ids)) {
949 continue;
950 }
951
952 if (!$a_only_public && !$ilAccess->checkAccess("read", "", (int) $node["child"])) {
953 continue;
954 }
955 $ref_id[$node["obj_id"]] = $node["child"];
956 $contexts[] = [
957 "obj_id" => $node["obj_id"],
958 "obj_type" => $node["type"]
959 ];
960 }
961
962 $news = $this->queryNewsForMultipleContexts(
963 $contexts,
964 $a_only_public,
965 $a_time_period,
966 $a_starting_date,
967 $a_no_auto_generated
968 );
969 foreach ($news as $k => $v) {
970 $news[$k]["ref_id"] = $ref_id[$v["context_obj_id"]];
971 }
972 $data = self::mergeNews($data, $news);
973
974 // sort and return
975 $data = ilArrayUtil::sortArray($data, "creation_date", "desc", false, true);
976
977 if (!$a_prevent_aggregation) {
978 $data = $this->aggregateFiles($data, $a_ref_id);
979 }
980
981 return $data;
982 }
983
987 public function setContext(
988 int $a_obj_id,
989 string $a_obj_type,
990 int $a_sub_obj_id = 0,
991 string $a_sub_obj_type = ""
992 ): void {
993 $this->setContextObjId($a_obj_id);
994 $this->setContextObjType($a_obj_type);
995 $this->setContextSubObjId($a_sub_obj_id);
996 $this->setContextSubObjType($a_sub_obj_type);
997 }
998
1003 protected static function handleTimePeriod($a_time_period): string
1004 {
1005 // time period is number of days
1006 if (is_numeric($a_time_period)) {
1007 if ($a_time_period > 0) {
1008 return date('Y-m-d H:i:s', time() - ($a_time_period * 24 * 60 * 60));
1009 }
1010 }
1011 // time period is datetime
1012 elseif (preg_match("/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/", $a_time_period)) {
1013 return $a_time_period;
1014 }
1015 return "";
1016 }
1017
1023 public function queryNewsForContext(
1024 bool $a_for_rss_use = false,
1025 $a_time_period = 0,
1026 string $a_starting_date = "",
1027 bool $a_no_auto_generated = false,
1028 bool $a_oldest_first = false,
1029 int $a_limit = 0
1030 ): array {
1031 $ilDB = $this->db;
1032 $ilUser = $this->user;
1033
1034 $and = "";
1035 if ($a_time_period > 0) {
1036 $limit_ts = self::handleTimePeriod($a_time_period);
1037 $and = " AND creation_date >= " . $ilDB->quote($limit_ts, "timestamp") . " ";
1038 }
1039
1040 if ($a_starting_date !== "") {
1041 $and .= " AND creation_date > " . $ilDB->quote($a_starting_date, "timestamp") . " ";
1042 }
1043
1044 if ($a_no_auto_generated) {
1045 $and .= " AND priority = 1 AND content_type = " . $ilDB->quote("text", "text") . " ";
1046 }
1047
1048 // this is changed with 4.1 (news table for lm pages)
1049 if ($this->getContextSubObjId() > 0) {
1050 $and .= " AND context_sub_obj_id = " . $ilDB->quote($this->getContextSubObjId(), "integer") .
1051 " AND context_sub_obj_type = " . $ilDB->quote($this->getContextSubObjType(), "text");
1052 }
1053
1054 $ordering = ($a_oldest_first)
1055 ? " creation_date ASC, id ASC "
1056 : " creation_date DESC, id DESC ";
1057
1058 if ($a_for_rss_use && self::getPrivateFeedId() === 0) {
1059 $query = "SELECT * " .
1060 "FROM il_news_item " .
1061 " WHERE " .
1062 "context_obj_id = " . $ilDB->quote($this->getContextObjId(), "integer") .
1063 " AND context_obj_type = " . $ilDB->quote($this->getContextObjType(), "text") .
1064 $and .
1065 " ORDER BY " . $ordering;
1066 } elseif (self::getPrivateFeedId() > 0) {
1067 $query = "SELECT il_news_item.* " .
1068 ", il_news_read.user_id user_read " .
1069 "FROM il_news_item LEFT JOIN il_news_read " .
1070 "ON il_news_item.id = il_news_read.news_id AND " .
1071 " il_news_read.user_id = " . $ilDB->quote(self::getPrivateFeedId(), "integer") .
1072 " WHERE " .
1073 "context_obj_id = " . $ilDB->quote($this->getContextObjId(), "integer") .
1074 " AND context_obj_type = " . $ilDB->quote($this->getContextObjType(), "text") .
1075 $and .
1076 " ORDER BY " . $ordering;
1077 } else {
1078 $query = "SELECT il_news_item.* " .
1079 ", il_news_read.user_id as user_read " .
1080 "FROM il_news_item LEFT JOIN il_news_read " .
1081 "ON il_news_item.id = il_news_read.news_id AND " .
1082 " il_news_read.user_id = " . $ilDB->quote($ilUser->getId(), "integer") .
1083 " WHERE " .
1084 "context_obj_id = " . $ilDB->quote($this->getContextObjId(), "integer") .
1085 " AND context_obj_type = " . $ilDB->quote($this->getContextObjType(), "text") .
1086 $and .
1087 " ORDER BY " . $ordering;
1088 }
1089 //echo $query;
1090 $set = $ilDB->query($query);
1091 $result = [];
1092 while ($rec = $ilDB->fetchAssoc($set)) {
1093 if ($a_limit > 0 && count($result) >= $a_limit) {
1094 continue;
1095 }
1096 if (!$a_for_rss_use || (self::getPrivateFeedId() > 0) || ($rec["visibility"] === NEWS_PUBLIC ||
1097 ((int) $rec["priority"] === 0 &&
1099 "news",
1100 "public_notifications",
1101 0,
1102 (int) $rec["context_obj_id"]
1103 )))) {
1104 $result[$rec["id"]] = $rec;
1105 }
1106 }
1107
1108 // do we get data for rss and may the time limit by an issue?
1109 // do a second query without time limit.
1110 // this is not very performant, but I do not have a better
1111 // idea. The keep_rss_min setting is currently (Jul 2012) only set
1112 // by mediacasts
1113 if ($a_time_period && $a_for_rss_use) {
1114 $keep_rss_min = ilBlockSetting::_lookup(
1115 "news",
1116 "keep_rss_min",
1117 0,
1118 $this->getContextObjId()
1119 );
1120 if ($keep_rss_min > 0) {
1121 return $this->queryNewsForContext(
1122 true,
1123 0,
1124 $a_starting_date,
1125 $a_no_auto_generated,
1126 $a_oldest_first,
1127 (int) $keep_rss_min
1128 );
1129 }
1130 }
1131
1132 return $result;
1133 }
1134
1140 public static function queryNewsByIds(array $a_news_ids): array
1141 {
1142 global $DIC;
1143 $ilDB = $DIC->database();
1144 $news = [];
1145 $set = $ilDB->query("SELECT * FROM il_news_item " .
1146 " WHERE " . $ilDB->in("id", $a_news_ids, false, "integer"));
1147 while ($rec = $ilDB->fetchAssoc($set)) {
1148 $news[$rec["id"]] = $rec;
1149 }
1150 return $news;
1151 }
1152
1159 array $objects,
1160 $a_time_period = 1
1161 ): array {
1162 $ilDB = $this->db;
1163
1164 $all = [];
1165
1166 $this->log->debug("time period: " . $a_time_period);
1167 $limit_ts = self::handleTimePeriod($a_time_period);
1168
1169 // are there any news items for relevant objects and?
1170 $query = $ilDB->query($q = "SELECT id,context_obj_id,context_obj_type" .
1171 " FROM il_news_item" .
1172 " WHERE " . $ilDB->in("context_obj_id", array_keys($objects), false, "integer") .
1173 " AND creation_date >= " . $ilDB->quote($limit_ts, "timestamp"));
1174 $this->log->debug($q);
1175 while ($rec = $ilDB->fetchAssoc($query)) {
1176 if ($objects[$rec["context_obj_id"]]["type"] == $rec["context_obj_type"]) {
1177 $all[] = (int) $rec["id"];
1178 }
1179 }
1180
1181 return $all;
1182 }
1183
1189 array $a_contexts,
1190 bool $a_for_rss_use = false,
1191 $a_time_period = 0,
1192 string $a_starting_date = "",
1193 bool $a_no_auto_generated = false,
1194 int $a_user_id = null,
1195 int $a_limit = 0,
1196 array $a_exclude = []
1197 ): array {
1198 $ilDB = $this->db;
1199 $ilUser = $this->user;
1200
1201 $and = "";
1202 if ($a_time_period > 0) {
1203 $limit_ts = self::handleTimePeriod($a_time_period);
1204 $and = " AND creation_date >= " . $ilDB->quote($limit_ts, "timestamp") . " ";
1205 }
1206
1207 if ($a_starting_date !== "") {
1208 $and .= " AND creation_date > " . $ilDB->quote($a_starting_date, "timestamp") . " ";
1209 }
1210
1211 if ($a_no_auto_generated) {
1212 $and .= " AND priority = 1 AND content_type = " . $ilDB->quote("text", "text") . " ";
1213 }
1214
1215 if ($a_limit > 0) {
1216 $ilDB->setLimit($a_limit, 0);
1217 }
1218
1219 if (is_array($a_exclude) && count($a_exclude) > 0) {
1220 $and .= " AND " . $ilDB->in("id", $a_exclude, true, "integer") . " ";
1221 }
1222
1223 $ids = [];
1224 $type = [];
1225
1226 foreach ($a_contexts as $cont) {
1227 $ids[] = $cont["obj_id"];
1228 $type[$cont["obj_id"]] = $cont["obj_type"];
1229 }
1230
1231 if ($a_for_rss_use && self::getPrivateFeedId() === 0) {
1232 $query = "SELECT * " .
1233 "FROM il_news_item " .
1234 " WHERE " .
1235 $ilDB->in("context_obj_id", $ids, false, "integer") . " " .
1236 $and .
1237 " ORDER BY creation_date DESC ";
1238 } elseif (self::getPrivateFeedId() > 0) {
1239 $query = "SELECT il_news_item.* " .
1240 ", il_news_read.user_id as user_read " .
1241 "FROM il_news_item LEFT JOIN il_news_read " .
1242 "ON il_news_item.id = il_news_read.news_id AND " .
1243 " il_news_read.user_id = " . $ilDB->quote(self::getPrivateFeedId(), "integer") .
1244 " WHERE " .
1245 $ilDB->in("context_obj_id", $ids, false, "integer") . " " .
1246 $and .
1247 " ORDER BY creation_date DESC ";
1248 } else {
1249 if ($a_user_id) {
1250 $user_id = $a_user_id;
1251 } else {
1252 $user_id = $ilUser->getId();
1253 }
1254 $query = "SELECT il_news_item.* " .
1255 ", il_news_read.user_id as user_read " .
1256 "FROM il_news_item LEFT JOIN il_news_read " .
1257 "ON il_news_item.id = il_news_read.news_id AND " .
1258 " il_news_read.user_id = " . $ilDB->quote($user_id, "integer") .
1259 " WHERE " .
1260 $ilDB->in("context_obj_id", $ids, false, "integer") . " " .
1261 $and .
1262 " ORDER BY creation_date DESC ";
1263 }
1264
1265 $set = $ilDB->query($query);
1266 $result = [];
1267 while ($rec = $ilDB->fetchAssoc($set)) {
1268 if ($type[$rec["context_obj_id"]] == $rec["context_obj_type"]) {
1269 if (!$a_for_rss_use || self::getPrivateFeedId() > 0 || ($rec["visibility"] === NEWS_PUBLIC ||
1270 ((int) $rec["priority"] === 0 &&
1272 "news",
1273 "public_notifications",
1274 0,
1275 (int) $rec["context_obj_id"]
1276 )))) {
1277 $result[$rec["id"]] = $rec;
1278 }
1279 }
1280 }
1281
1282 return $result;
1283 }
1284
1285
1290 public static function _setRead(
1291 int $a_user_id,
1292 int $a_news_id
1293 ): void {
1294 global $DIC;
1295
1296 $ilDB = $DIC->database();
1297 $ilAppEventHandler = $DIC["ilAppEventHandler"];
1298
1299 $ilDB->replace(
1300 "il_news_read",
1301 [
1302 "user_id" => ["integer", $a_user_id],
1303 "news_id" => ["integer", $a_news_id]
1304 ],
1305 []
1306 );
1307
1308 $ilAppEventHandler->raise(
1309 "Services/News",
1310 "readNews",
1311 ["user_id" => $a_user_id, "news_ids" => [$a_news_id]]
1312 );
1313 }
1314
1319 public static function _setUnread(
1320 int $a_user_id,
1321 int $a_news_id
1322 ): void {
1323 global $DIC;
1324
1325 $ilDB = $DIC->database();
1326 $ilAppEventHandler = $DIC["ilAppEventHandler"];
1327
1328 $ilDB->manipulate("DELETE FROM il_news_read (user_id, news_id) VALUES (" .
1329 " WHERE user_id = " . $ilDB->quote($a_user_id, "integer") .
1330 " AND news_id = " . $ilDB->quote($a_news_id, "integer"));
1331
1332 $ilAppEventHandler->raise(
1333 "Services/News",
1334 "unreadNews",
1335 ["user_id" => $a_user_id, "news_ids" => [$a_news_id]]
1336 );
1337 }
1338
1343 public static function mergeNews(
1344 array $n1,
1345 array $n2
1346 ): array {
1347 foreach ($n2 as $id => $news) {
1348 $n1[$id] = $news;
1349 }
1350
1351 return $n1;
1352 }
1353
1358 public static function _getDefaultVisibilityForRefId(int $a_ref_id): string
1359 {
1360 global $DIC;
1361
1362 $tree = $DIC->repositoryTree();
1363
1364 $news_set = new ilSetting("news");
1365 $default_visibility = ($news_set->get("default_visibility") != "")
1366 ? $news_set->get("default_visibility")
1367 : "users";
1368
1369 if ($tree->isInTree($a_ref_id)) {
1370 $path = $tree->getPathFull($a_ref_id);
1371
1372 foreach ($path as $key => $row) {
1373 if (!in_array($row["type"], ["root", "cat", "crs", "fold", "grp"], true)) {
1374 continue;
1375 }
1376
1377 $visibility = ilBlockSetting::_lookup(
1378 "news",
1379 "default_visibility",
1380 0,
1381 (int) $row["obj_id"]
1382 );
1383
1384 if ($visibility != "") {
1385 $default_visibility = $visibility;
1386 }
1387 }
1388 }
1389
1390 return $default_visibility;
1391 }
1392
1393
1398 public function delete(): void
1399 {
1400 $ilDB = $this->db;
1401
1402 // delete il_news_read entries
1403 $ilDB->manipulate("DELETE FROM il_news_read " .
1404 " WHERE news_id = " . $ilDB->quote($this->getId(), "integer"));
1405
1406 // delete multimedia object
1407 $mob = $this->getMobId();
1408
1409 // delete
1410 $query = "DELETE FROM il_news_item" .
1411 " WHERE id = " . $ilDB->quote($this->getId(), "integer");
1412 $ilDB->manipulate($query);
1413
1414 // delete mob after news, to have a "mob usage" of 0
1415 if ($mob > 0 && ilObject::_exists($mob)) {
1416 $mob = new ilObjMediaObject($mob);
1417 $mob->delete();
1418 }
1419 }
1420
1426 public static function getNewsOfContext(
1427 int $a_context_obj_id,
1428 string $a_context_obj_type,
1429 int $a_context_sub_obj_id = 0,
1430 string $a_context_sub_obj_type = ""
1431 ): array {
1432 global $DIC;
1433
1434 $ilDB = $DIC->database();
1435 $and = "";
1436
1437 if ($a_context_obj_id === 0 || $a_context_obj_type === "") {
1438 return [];
1439 }
1440
1441 if ($a_context_sub_obj_id > 0) {
1442 $and = " AND context_sub_obj_id = " . $ilDB->quote($a_context_sub_obj_id, "integer") .
1443 " AND context_sub_obj_type = " . $ilDB->quote($a_context_sub_obj_type, "text");
1444 }
1445
1446 // get news records
1447 $query = "SELECT id FROM il_news_item" .
1448 " WHERE context_obj_id = " . $ilDB->quote($a_context_obj_id, "integer") .
1449 " AND context_obj_type = " . $ilDB->quote($a_context_obj_type, "text") .
1450 $and;
1451
1452 $news_set = $ilDB->query($query);
1453
1454 $news_arr = [];
1455 while ($news = $ilDB->fetchAssoc($news_set)) {
1456 $news_arr[] = new ilNewsItem((int) $news["id"]);
1457 }
1458 return $news_arr;
1459 }
1460
1465 public static function deleteNewsOfContext(
1466 int $a_context_obj_id,
1467 string $a_context_obj_type,
1468 int $a_context_sub_obj_id = 0,
1469 string $a_context_sub_obj_type = ""
1470 ): void {
1471 foreach (self::getNewsOfContext(
1472 $a_context_obj_id,
1473 $a_context_obj_type,
1474 $a_context_sub_obj_id,
1475 $a_context_sub_obj_type
1476 ) as $n) {
1477 $n->delete();
1478 }
1479 }
1480
1485 public static function _lookupTitle(int $a_news_id): string
1486 {
1487 global $DIC;
1488
1489 $ilDB = $DIC->database();
1490
1491 $query = "SELECT title FROM il_news_item WHERE id = " .
1492 $ilDB->quote($a_news_id, "integer");
1493 $set = $ilDB->query($query);
1494 $rec = $ilDB->fetchAssoc($set);
1495 return $rec["title"] ?? '';
1496 }
1497
1502 public static function _lookupVisibility(int $a_news_id): string
1503 {
1504 global $DIC;
1505
1506 $ilDB = $DIC->database();
1507
1508 $query = "SELECT visibility FROM il_news_item WHERE id = " .
1509 $ilDB->quote($a_news_id, "integer");
1510 $set = $ilDB->query($query);
1511 $rec = $ilDB->fetchAssoc($set);
1512
1513 return $rec["visibility"] ?? NEWS_USERS;
1514 }
1515
1520 public static function _lookupMobId(int $a_news_id): int
1521 {
1522 global $DIC;
1523
1524 $ilDB = $DIC->database();
1525
1526 $query = "SELECT mob_id FROM il_news_item WHERE id = " .
1527 $ilDB->quote($a_news_id, "integer");
1528 $set = $ilDB->query($query);
1529 $rec = $ilDB->fetchAssoc($set);
1530 return (int) ($rec["mob_id"] ?? 0);
1531 }
1532
1539 public static function filterObjIdsPerNews(
1540 array $a_obj_ids,
1541 $a_time_period = 0,
1542 string $a_starting_date = "",
1543 string $a_ending_date = '',
1544 bool $ignore_period = false
1545 ): array {
1546 global $DIC;
1547
1548 $ilDB = $DIC->database();
1549
1550 $and = "";
1551 if ($a_time_period > 0) {
1552 $limit_ts = self::handleTimePeriod($a_time_period);
1553 $and = " AND creation_date >= " . $ilDB->quote($limit_ts, "timestamp") . " ";
1554 }
1555
1556 if ($a_starting_date !== "") {
1557 $and .= " AND creation_date >= " . $ilDB->quote($a_starting_date, "timestamp");
1558 }
1559
1560 $query = "SELECT DISTINCT(context_obj_id) AS obj_id FROM il_news_item" .
1561 " WHERE " . $ilDB->in("context_obj_id", $a_obj_ids, false, "integer") . " " . $and;
1562 //" WHERE context_obj_id IN (".implode(ilUtil::quoteArray($a_obj_ids),",").")".$and;
1563
1564 $set = $ilDB->query($query);
1565 $objs = [];
1566 while ($rec = $ilDB->fetchAssoc($set)) {
1567 $objs[] = $rec["obj_id"];
1568 }
1569
1570 return $objs;
1571 }
1572
1576 public static function determineNewsTitleByNewsId(
1577 int $a_news_id,
1578 int $a_agg_ref_id = 0,
1579 array $a_aggregation = []
1580 ): string {
1581 global $DIC;
1582
1583 $ilDB = $DIC->database();
1584
1585 $query = "SELECT context_obj_type, content_is_lang_var, title FROM il_news_item WHERE id = " .
1586 $ilDB->quote($a_news_id, "integer");
1587 $set = $ilDB->query($query);
1588 $rec = $ilDB->fetchAssoc($set);
1589
1590 return self::determineNewsTitle(
1591 $rec["context_obj_type"],
1592 $rec["title"],
1593 $rec["content_is_lang_var"],
1594 $a_agg_ref_id,
1595 $a_aggregation
1596 );
1597 }
1598
1603 public static function determineNewsTitle(
1604 string $a_context_obj_type,
1605 string $a_title,
1606 bool $a_content_is_lang_var,
1607 int $a_agg_ref_id = 0,
1608 array $a_aggregation = []
1609 ): string {
1610 global $DIC;
1611
1612 $lng = $DIC->language();
1613 $obj_definition = $DIC["objDefinition"];
1614 $tit = "";
1615
1616 if ($a_agg_ref_id > 0) {
1617 $cnt = count($a_aggregation);
1618
1619 // forums
1620 if ($a_context_obj_type === "frm") {
1621 if ($cnt > 1) {
1622 return sprintf($lng->txt("news_x_postings"), $cnt);
1623 }
1624
1625 return $lng->txt("news_1_postings");
1626 }
1627
1628 // files
1629 $up_cnt = $cr_cnt = 0;
1630 foreach ($a_aggregation as $item) {
1631 if ($item["title"] === "file_updated") {
1632 $up_cnt++;
1633 } else {
1634 $cr_cnt++;
1635 }
1636 }
1637 $sep = "";
1638 if ($cr_cnt === 1) {
1639 $tit = $lng->txt("news_1_file_created");
1640 $sep = "<br />";
1641 } elseif ($cr_cnt > 1) {
1642 $tit = sprintf($lng->txt("news_x_files_created"), $cr_cnt);
1643 $sep = "<br />";
1644 }
1645 if ($up_cnt === 1) {
1646 $tit .= $sep . $lng->txt("news_1_file_updated");
1647 } elseif ($up_cnt > 1) {
1648 $tit .= $sep . sprintf($lng->txt("news_x_files_updated"), $up_cnt);
1649 }
1650 return $tit;
1651 }
1652
1653 if ($a_content_is_lang_var) {
1654 if ($obj_definition->isPlugin($a_context_obj_type)) {
1655 return ilObjectPlugin::lookupTxtById($a_context_obj_type, $a_title);
1656 }
1657 return $lng->txt($a_title);
1658 }
1659
1660 return $a_title;
1661 }
1662
1667 public static function determineNewsContent(
1668 string $a_context_obj_type,
1669 string $a_content,
1670 bool $a_is_lang_var
1671 ): string {
1672 global $DIC;
1673
1674 $lng = $DIC->language();
1675 $obj_definition = $DIC["objDefinition"];
1676
1677 if ($a_is_lang_var) {
1678 if ($obj_definition->isPlugin($a_context_obj_type)) {
1679 return ilObjectPlugin::lookupTxtById($a_context_obj_type, $a_content);
1680 }
1681 $lng->loadLanguageModule($a_context_obj_type);
1682 return $lng->txt($a_content);
1683 }
1684
1685 return $a_content;
1686 }
1687
1692 public static function getFirstNewsIdForContext(
1693 int $a_context_obj_id,
1694 string $a_context_obj_type,
1695 int $a_context_sub_obj_id = 0,
1696 string $a_context_sub_obj_type = ""
1697 ): int {
1698 global $DIC;
1699
1700 $ilDB = $DIC->database();
1701
1702 // Determine how many rows should be deleted
1703 $query = "SELECT id " .
1704 "FROM il_news_item " .
1705 "WHERE " .
1706 "context_obj_id = " . $ilDB->quote($a_context_obj_id, "integer") .
1707 " AND context_obj_type = " . $ilDB->quote($a_context_obj_type, "text") .
1708 " AND context_sub_obj_id = " . $ilDB->quote($a_context_sub_obj_id, "integer") .
1709 " AND " . $ilDB->equals("context_sub_obj_type", $a_context_sub_obj_type, "text", true);
1710
1711 $set = $ilDB->query($query);
1712 $rec = $ilDB->fetchAssoc($set);
1713
1714 return (int) ($rec["id"] ?? 0);
1715 }
1716
1721 public static function getLastNewsIdForContext(
1722 int $a_context_obj_id,
1723 string $a_context_obj_type,
1724 int $a_context_sub_obj_id = 0,
1725 string $a_context_sub_obj_type = "",
1726 bool $a_only_today = false
1727 ): int {
1728 global $DIC;
1729
1730 $ilDB = $DIC->database();
1731
1732 // Determine how many rows should be deleted
1733 $query = "SELECT id, update_date " .
1734 "FROM il_news_item " .
1735 "WHERE " .
1736 "context_obj_id = " . $ilDB->quote($a_context_obj_id, "integer") .
1737 " AND context_obj_type = " . $ilDB->quote($a_context_obj_type, "text") .
1738 " AND context_sub_obj_id = " . $ilDB->quote($a_context_sub_obj_id, "integer") .
1739 " AND " . $ilDB->equals("context_sub_obj_type", $a_context_sub_obj_type, "text", true) .
1740 " ORDER BY update_date DESC";
1741
1742 $ilDB->setLimit(1, 0);
1743 $set = $ilDB->query($query);
1744 $id = 0;
1745 if ($rec = $ilDB->fetchAssoc($set)) {
1746 $id = (int) $rec["id"];
1747 if ($a_only_today) {
1748 $now = ilUtil::now();
1749 if (strpos($rec["update_date"], substr($now, 0, 10)) !== 0) {
1750 $id = 0;
1751 }
1752 }
1753 }
1754
1755 return $id;
1756 }
1757
1758
1763 public static function _lookupMediaObjectUsages(int $a_mob_id): array
1764 {
1765 global $DIC;
1766
1767 $ilDB = $DIC->database();
1768
1769 $query = "SELECT id " .
1770 "FROM il_news_item " .
1771 "WHERE " .
1772 " mob_id = " . $ilDB->quote($a_mob_id, "integer");
1773
1774 $usages = [];
1775 $set = $ilDB->query($query);
1776 while ($rec = $ilDB->fetchAssoc($set)) {
1777 $usages[$rec["id"]] = ["type" => "news", "id" => $rec["id"]];
1778 }
1779
1780 return $usages;
1781 }
1782
1787 public static function _lookupContextObjId(int $a_news_id): int
1788 {
1789 global $DIC;
1790
1791 $ilDB = $DIC->database();
1792
1793 $query = "SELECT context_obj_id " .
1794 "FROM il_news_item " .
1795 "WHERE " .
1796 " id = " . $ilDB->quote($a_news_id, "integer");
1797 $set = $ilDB->query($query);
1798 $rec = $ilDB->fetchAssoc($set);
1799
1800 return $rec["context_obj_id"];
1801 }
1802
1806 public static function _lookupDefaultPDPeriod(): int
1807 {
1808 $news_set = new ilSetting("news");
1809 $per = $news_set->get("pd_period");
1810 if ((int) $per === 0) {
1811 $per = 30;
1812 }
1813
1814 return $per;
1815 }
1816
1820 public static function _lookupUserPDPeriod(int $a_user_id): int
1821 {
1822 $news_set = new ilSetting("news");
1823 $allow_shorter_periods = $news_set->get("allow_shorter_periods");
1824 $allow_longer_periods = $news_set->get("allow_longer_periods");
1825 $default_per = self::_lookupDefaultPDPeriod();
1826
1828 "pdnews",
1829 "news_pd_period",
1830 $a_user_id,
1831 0
1832 );
1833
1834 // news period information
1835 if ($per <= 0 ||
1836 (!$allow_shorter_periods && ($per < $default_per)) ||
1837 (!$allow_longer_periods && ($per > $default_per))
1838 ) {
1839 $per = $default_per;
1840 }
1841
1842 return (int) $per;
1843 }
1844
1848 public static function _lookupRSSPeriod(): int
1849 {
1850 $news_set = new ilSetting("news");
1851 $rss_period = $news_set->get("rss_period");
1852 if ((int) $rss_period === 0) { // default to two weeks
1853 $rss_period = 14;
1854 }
1855 return $rss_period;
1856 }
1857
1861 public static function setPrivateFeedId(int $a_userId): void
1862 {
1863 self::$privFeedId = $a_userId;
1864 }
1865
1869 public static function getPrivateFeedId(): int
1870 {
1871 return self::$privFeedId;
1872 }
1873
1878 public function deliverMobFile(
1879 string $a_purpose = "Standard",
1880 bool $a_increase_download_cnt = false
1881 ): bool {
1882 $mob = $this->getMobId();
1883 $mob = new ilObjMediaObject($mob);
1884 $mob_dir = ilObjMediaObject::_getDirectory($mob->getId());
1885
1886 // check purpose
1887 if (!$mob->hasPurposeItem($a_purpose)) {
1888 return false;
1889 }
1890
1891 $m_item = $mob->getMediaItem($a_purpose);
1892 if ($m_item->getLocationType() !== "Reference") {
1893 $file = $mob_dir . "/" . $m_item->getLocation();
1894 if (file_exists($file) && is_file($file)) {
1895 if ($a_increase_download_cnt) {
1896 $this->increaseDownloadCounter();
1897 }
1898 ilFileDelivery::deliverFileLegacy($file, $m_item->getLocation(), "", false, false, false);
1899 return true;
1900 }
1901
1902 $this->main_tpl->setOnScreenMessage('failure', "File not found!", true);
1903 return false;
1904 }
1905
1906 if ($a_increase_download_cnt) {
1907 $this->increaseDownloadCounter();
1908 }
1909
1910 ilUtil::redirect($m_item->getLocation());
1911 }
1912
1917 public function increaseDownloadCounter(): void
1918 {
1919 $ilDB = $this->db;
1920
1921 $cnt = $this->getMobDownloadCounter();
1922 $cnt++;
1923 $this->setMobDownloadCounter($cnt);
1924 $ilDB->manipulate(
1925 "UPDATE il_news_item SET " .
1926 " mob_cnt_download = " . $ilDB->quote($cnt, "integer") .
1927 " WHERE id = " . $ilDB->quote($this->getId(), "integer")
1928 );
1929 }
1930
1936 public function increasePlayCounter(): void
1937 {
1938 $ilDB = $this->db;
1939
1940 $cnt = $this->getMobPlayCounter();
1941 $cnt++;
1942 $this->setMobPlayCounter($cnt);
1943 $ilDB->manipulate(
1944 "UPDATE il_news_item SET " .
1945 " mob_cnt_play = " . $ilDB->quote($cnt, "integer") .
1946 " WHERE id = " . $ilDB->quote($this->getId(), "integer")
1947 );
1948 }
1949
1954 public static function prepareNewsDataFromCache(array $a_cres): array
1955 {
1956 global $DIC;
1957
1958 $ilDB = $DIC->database();
1959
1960 $data = $a_cres;
1961 $news_ids = array_keys($data);
1962 $set = $ilDB->query("SELECT id FROM il_news_item " .
1963 " WHERE " . $ilDB->in("id", $news_ids, false, "integer"));
1964 $existing_ids = [];
1965 while ($rec = $ilDB->fetchAssoc($set)) {
1966 $existing_ids[] = (int) $rec["id"];
1967 }
1968 //var_dump($existing_ids);
1969 $existing_news = [];
1970 foreach ($data as $k => $v) {
1971 if (in_array($k, $existing_ids)) {
1972 $existing_news[$k] = $v;
1973 }
1974 }
1975
1976 return $existing_news;
1977 }
1978}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
const NEWS_AUDIO
const NEWS_TEXT
const NEWS_WARNING
const NEWS_USERS
const NEWS_HTML
const NEWS_MESSAGE
const NEWS_NOTICE
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const NEWS_PUBLIC
static sortArray(array $array, string $a_array_sortby_key, string $a_array_sortorder="asc", bool $a_numeric=false, bool $a_keep_keys=false)
static _lookup(string $a_type, string $a_setting, int $a_user=0, int $a_block_id=0)
Lookup setting from database.
static _lookupContainerSetting(int $a_id, string $a_keyword, string $a_default_value=null)
Class ilCtrl provides processing control methods.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
language handling
Component logger with individual log levels by component id.
A news item can be created by different sources.
static _setUnread(int $a_user_id, int $a_news_id)
Set item unread.
ilDBInterface $db
static _lookupUserPDPeriod(int $a_user_id)
static determineNewsTitle(string $a_context_obj_type, string $a_title, bool $a_content_is_lang_var, int $a_agg_ref_id=0, array $a_aggregation=[])
Determine title for news item entry.
setContentType(string $a_content_type="text")
static getFirstNewsIdForContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="")
Get first new id of news set related to a certain context.
static int $privFeedId
string $context_obj_type
static getPrivateFeedId()
static _lookupRSSPeriod()
setId(int $a_id)
update(bool $a_as_new=false)
Update item in database.
setPriority(int $a_priority=1)
read()
Read item from database.
static handleTimePeriod($a_time_period)
Convert time period for DB-queries.
static getNewsOfContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="")
Get all news of a context.
setUserId(int $a_user_id)
static mergeNews(array $n1, array $n2)
Merges two sets of news.
static _getNewsItemsOfUser(int $a_user_id, bool $a_only_public=false, bool $a_prevent_aggregation=false, int $a_per=0, array &$a_cnt=[])
Get all news items for a user.
ilLanguage $lng
static _lookupMobId(int $a_news_id)
Lookup mob id.
setMobDownloadCounter(int $a_val)
string $update_date
setContextObjType(string $a_context_obj_type)
setContextSubObjId(int $a_context_sub_obj_id)
static prepareNewsDataFromCache(array $a_cres)
Prepare news data from cache.
setContentIsLangVar(bool $a_content_is_lang_var=false)
static filterObjIdsPerNews(array $a_obj_ids, $a_time_period=0, string $a_starting_date="", string $a_ending_date='', bool $ignore_period=false)
Checks whether news are available for.
__construct(int $a_id=0)
setContent(string $a_content)
setContentTextIsLangVar(bool $a_val=false)
increasePlayCounter()
Increase play counter.
static setPrivateFeedId(int $a_userId)
increaseDownloadCounter()
Increase download counter.
queryNewsForContext(bool $a_for_rss_use=false, $a_time_period=0, string $a_starting_date="", bool $a_no_auto_generated=false, bool $a_oldest_first=false, int $a_limit=0)
Query news for a context.
string $context_sub_obj_type
bool $content_is_lang_var
static deleteNewsOfContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="")
Delete all news of a context.
static _setRead(int $a_user_id, int $a_news_id)
Set item read.
aggregateForums(array $news, bool $a_group_posting_sequence=false)
aggregateFiles(array $news, int $a_ref_id)
setMobId(int $a_mob_id)
setContext(int $a_obj_id, string $a_obj_type, int $a_sub_obj_id=0, string $a_sub_obj_type="")
Set context for news.
static _lookupMediaObjectUsages(int $a_mob_id)
Lookup media object usage(s)
string $creation_date
static _lookupVisibility(int $a_news_id)
Lookup News Visibility.
setContentHtml(bool $a_val)
getAggregatedChildNewsData(int $a_ref_id, bool $a_only_public=false, int $a_time_period=0, bool $a_prevent_aggregation=false, string $a_starting_date="", bool $a_no_auto_generated=false)
Get news aggregation for child objects (e.g.
queryNewsForMultipleContexts(array $a_contexts, bool $a_for_rss_use=false, $a_time_period=0, string $a_starting_date="", bool $a_no_auto_generated=false, int $a_user_id=null, int $a_limit=0, array $a_exclude=[])
static _lookupContextObjId(int $a_news_id)
Context Object ID.
ilObjectDataCache $obj_data_cache
setPlaytime(string $a_playtime)
ilObjUser $user
static _getDefaultVisibilityForRefId(int $a_ref_id)
Get default visibility for reference id.
static _lookupTitle(int $a_news_id)
Lookup News Title.
setMobPlayCounter(int $a_val)
static queryNewsByIds(array $a_news_ids)
Query news data by news ids.
static _lookupDefaultPDPeriod()
static determineNewsTitleByNewsId(int $a_news_id, int $a_agg_ref_id=0, array $a_aggregation=[])
Determine title for news item entry.
string $content_long
static determineNewsContent(string $a_context_obj_type, string $a_content, bool $a_is_lang_var)
Determine new content.
bool $content_text_is_lang_var
deliverMobFile(string $a_purpose="Standard", bool $a_increase_download_cnt=false)
Deliver mob file.
setLimitation(bool $a_limitation)
Set Limitation for number of items.
setVisibility(string $a_visibility="users")
string $content_type
checkNewsExistsForObjects(array $objects, $a_time_period=1)
setUpdateUserId(int $a_val)
ilAccessHandler $access
setContextSubObjType(?string $a_context_sub_obj_type)
setContextObjId(int $a_context_obj_id)
getAggregatedNewsData(int $a_ref_id, bool $a_only_public=false, $a_time_period=0, bool $a_prevent_aggregation=false, string $a_starting_date="", bool $a_no_auto_generated=false, int $a_user_id=null, int $a_limit=0, array $a_exclude=[])
Get news aggregation (e.g.
setTitle(string $a_title)
getNewsForRefId(int $a_ref_id, bool $a_only_public=false, bool $a_stopnesting=false, $a_time_period=0, bool $a_prevent_aggregation=true, bool $a_forum_group_sequences=false, bool $a_no_auto_generated=false, bool $a_ignore_date_filter=false, int $a_user_id=null, int $a_limit=0, array $a_excluded=[])
Get News For Ref Id.
static getLastNewsIdForContext(int $a_context_obj_id, string $a_context_obj_type, int $a_context_sub_obj_id=0, string $a_context_sub_obj_type="", bool $a_only_today=false)
Get last news id of news set related to a certain context.
string $visibility
setContentLong(string $a_content_long)
setCreationDate(string $a_creation_date)
setUpdateDate(string $a_update_date)
ilGlobalTemplateInterface $main_tpl
static _getDirectory(int $a_mob_id)
Get absolute directory.
User class.
static _lookupPref(int $a_usr_id, string $a_keyword)
static preloadData(array $ref_ids)
Preload data to internal cache.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static lookupTxtById(string $plugin_id, string $lang_var)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupType(int $id, bool $reference=false)
static _getAllReferences(int $id)
get all reference ids for object ID
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _lookupObjId(int $ref_id)
static _getMembershipByType(int $a_usr_id, array $a_type, bool $a_only_member_role=false)
get membership by type Get course or group membership
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
isInTree(?int $a_node_id)
get all information of a node.
getPathFull(int $a_endnode_id, int $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
getNodeData(int $a_node_id, ?int $a_tree_pk=null)
get all information of a node.
getChilds(int $a_node_id, string $a_order="", string $a_direction="ASC")
get child nodes of given node
getSubTree(array $a_node, bool $a_with_data=true, array $a_type=[])
get all nodes in the subtree under specified node
static now()
Return current timestamp in Y-m-d H:i:s format.
static redirect(string $a_script)
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$ref_id
Definition: ltiauth.php:67
$path
Definition: ltiservices.php:32
$i
Definition: metadata.php:41
string $key
Consumer key/client ID value.
Definition: System.php:193
$query
$type
$lng