19declare(strict_types=1);
40 protected readonly
Factory $factory
46 $query =
"SELECT * FROM il_news_item WHERE id = %s";
49 return $result->numRows()
50 ? $this->
factory->newsItem($this->db->fetchAssoc($result))
60 if (empty($news_ids)) {
65 return array_map(fn($row) => $this->
factory->newsItem($row), $this->db->fetchAll($result));
74 $obj_ids = array_map(fn($context) => $context->getObjId(), $contexts);
78 $query =
"SELECT DISTINCT (context_obj_id) AS obj_id FROM il_news_item WHERE ";
82 $query .=
" AND creation_date >= %s";
88 $query .=
" AND id NOT IN ({$this->buildExcludeByDateQuery($criteria->getStartDates())})";
91 $result = $this->db->queryF($query, $types, $values);
92 $needed_obj_ids = array_column($this->db->fetchAll($result),
'obj_id',
'obj_id');
94 return array_filter($contexts, fn($context) => isset($needed_obj_ids[$context->getObjId()]));
103 public function loadLazyItems(array $news_ids, array $group_context_types): array
105 if (empty($news_ids)) {
111 $additional_obj_ids = [];
113 foreach ($this->db->fetchAll($result) as $row) {
114 $news_item = $this->
factory->newsItem($row);
116 if (in_array($news_item->getContextObjType(), $group_context_types)) {
117 $additional_obj_ids[] = $news_item->getContextObjId();
120 $news_items[] = $news_item;
123 if (empty($additional_obj_ids)) {
131 $result = $this->db->query($query);
135 array_map(fn($row) => $this->
factory->newsItem($row), $this->db->fetchAll($result))
142 SELECT il_news_item.*,
144 (SELECT ref_id FROM object_reference WHERE object_reference.obj_id = il_news_item.context_obj_id LIMIT 1),
149 if ($news_ids !==
null) {
161 if (empty($contexts)) {
165 $obj_ids = array_map(fn($context) => $context->getObjId(), $contexts);
166 $result = $this->db->queryF(...$this->
buildBatchQuery($obj_ids, $criteria));
171 while ($row = $this->db->fetchAssoc($result)) {
172 $items[] = $this->
factory->newsItem($row);
173 $user_read[$row[
'id']] = isset($row[
'user_read']) && $row[
'user_read'] !== 0;
178 $collection->setUserReadStatus($criteria->
getReadUserId(), $user_read);
189 if (empty($contexts)) {
193 $obj_ids = array_map(fn($context) => $context->getObjId(), $contexts);
194 $result = $this->db->queryF(...$this->
buildBatchQuery($obj_ids, $criteria,
true));
198 while ($row = $this->db->fetchAssoc($result)) {
199 $items[] = $row[
'id'];
200 $user_read[$row[
'id']] = isset($row[
'user_read']) && $row[
'user_read'] !== 0;
205 $collection->setUserReadStatus($criteria->
getReadUserId(), $user_read);
218 foreach ($contexts as $context) {
219 $context_map[$context->getObjId()] = $context;
223 $query =
"SELECT context_obj_id, count(context_obj_id) as count FROM il_news_item WHERE {$in_clause} GROUP BY context_obj_id";
224 $result = $this->db->query($query);
227 foreach ($this->db->fetchAll($result) as $row) {
229 $context_map[$row[
'context_obj_id']],
244 $columns = [
'il_news_item.id'];
248 'COALESCE((SELECT ref_id FROM object_reference WHERE object_reference.obj_id = il_news_item.context_obj_id LIMIT 1), 0) AS ref_id'
254 throw new \InvalidArgumentException(
"Read user id is required for read status");
257 $columns[] =
'il_news_read.user_id AS user_read';
258 $joins .=
'LEFT JOIN il_news_read ON il_news_item.id = il_news_read.news_id AND il_news_read.user_id = %s ';
264 $query =
"SELECT " . join(
', ', $columns) .
" FROM il_news_item {$joins} WHERE "
268 $query .=
" AND creation_date >= %s";
274 $query .=
" AND priority = 1 AND content_type = 'text'";
279 $query .=
" AND n.priority {$operator} %s";
285 $query .=
" AND visibility = '" .
NEWS_PUBLIC .
"'";
289 $query .=
" AND id NOT IN ({$this->buildExcludeByDateQuery($criteria->getStartDates())})";
292 $query .=
" ORDER BY creation_date DESC";
294 return [$query, $types, $values];
303 foreach ($start_dates as $obj_id => $date) {
304 $conditions[] =
" (context_obj_id = {$obj_id} AND creation_date < '{$date->format('Y-m-d H:i:s')}') ";
307 return "SELECT id FROM il_news_item WHERE" . implode(
'OR', $conditions);
313 if (is_numeric($time_period) && $time_period > 0) {
314 return date(
'Y-m-d H:i:s', time() - ($time_period * 24 * 60 * 60));
318 if (preg_match(
"/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/", $time_period)) {
Factory for creating News DTOs from database results (arrays)
This class is a special implementation of a NewsCollection that is designed to load the complete News...
Optimized News Collection with memory-efficient data structures to support large news feeds.
News Context DTO represents a context where news items can be associated with.
News Criteria DTO for querying news items supports caching, JSON serialization, and validation.
News Item DTO for transfer of news items.
News Repository provides basic CRUD operations and optimized database access for news operations with...
buildFindQuery(?array $news_ids=null)
countByContextsBatch(array $contexts)
filterContext(array $contexts, NewsCriteria $criteria)
findByContextsBatchLazy(array $contexts, NewsCriteria $criteria)
buildExcludeByDateQuery(array $start_dates)
__construct(protected readonly \ilDBInterface $db, protected readonly Factory $factory)
static parseTimePeriod(string|int $time_period)
findByIds(array $news_ids)
loadLazyItems(array $news_ids, array $group_context_types)
buildBatchQuery(array $obj_ids, NewsCriteria $criteria, bool $only_id=false)
findByContextsBatch(array $contexts, NewsCriteria $criteria)