Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 125
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
OlzNewsListParams
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
OlzNewsList
0.00% covered (danger)
0.00%
0 / 125
0.00% covered (danger)
0.00%
0 / 4
812
0.00% covered (danger)
0.00%
0 / 1
 hasAccess
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSearchTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSearchResultsWhenHasAccess
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHtmlWhenHasAccess
0.00% covered (danger)
0.00%
0 / 122
0.00% covered (danger)
0.00%
0 / 1
650
1<?php
2
3namespace Olz\News\Components\OlzNewsList;
4
5use Olz\Apps\OlzApps;
6use Olz\Components\Common\OlzRootComponent;
7use Olz\Components\Page\OlzFooter\OlzFooter;
8use Olz\Components\Page\OlzHeader\OlzHeader;
9use Olz\Entity\News\NewsEntry;
10use Olz\Entity\Roles\Role;
11use Olz\Entity\Users\User;
12use Olz\News\Components\OlzNewsFilter\OlzNewsFilter;
13use Olz\News\Components\OlzNewsListItem\OlzNewsListItem;
14use Olz\Utils\HttpParams;
15
16/** @extends HttpParams<array{
17 *   filter?: ?string,
18 *   seite?: ?numeric-string,
19 *   von?: ?string,
20 * }> */
21class OlzNewsListParams extends HttpParams {
22}
23
24/** @extends OlzRootComponent<array<string, mixed>> */
25class OlzNewsList extends OlzRootComponent {
26    public function hasAccess(): bool {
27        return true;
28    }
29
30    public function getSearchTitle(): string {
31        return 'TODO';
32    }
33
34    public function getSearchResultsWhenHasAccess(array $terms): array {
35        return [];
36    }
37
38    public static string $title = "News";
39    public static string $description = "Aktuelle Beiträge, Berichte von Anlässen und weitere Neuigkeiten von der OL Zimmerberg.";
40
41    public static int $page_size = 25;
42
43    public function getHtmlWhenHasAccess(mixed $args): string {
44        $params = $this->httpUtils()->validateGetParams(OlzNewsListParams::class);
45        $db = $this->dbUtils()->getDb();
46        $entityManager = $this->dbUtils()->getEntityManager();
47        $code_href = $this->envUtils()->getCodeHref();
48
49        $news_utils = $this->newsUtils();
50        $current_filter = $news_utils->deserialize($params['filter'] ?? $this->session()->get('news_filter') ?? '');
51        $page_number = intval($params['seite'] ?? $this->session()->get('news_page') ?? 1);
52        $page_index = $page_number - 1;
53
54        $valid_filter = $news_utils->getValidFilter($current_filter);
55        $serialized_filter = $news_utils->serialize($valid_filter);
56
57        if (
58            !$news_utils->isValidFilter($current_filter)
59            || ($params['filter'] ?? '') !== $serialized_filter
60            || ($params['seite'] ?? '') !== "{$page_number}"
61        ) {
62            $is_backfill = empty($params['filter']) || empty($params['seite']);
63            $this->httpUtils()->redirect(
64                "{$code_href}news?filter={$serialized_filter}&seite={$page_number}",
65                $is_backfill ? 308 : 410,
66            );
67        }
68
69        $this->session()->set('news_filter', $serialized_filter);
70        $this->session()->set('news_page', "{$page_number}");
71
72        $news_list_title = $news_utils->getTitleFromFilter($valid_filter);
73        $out = OlzHeader::render([
74            'title' => $news_list_title,
75            'description' => self::$description, // TODO: Filter-specific description?
76            'canonical_url' => "{$code_href}news?filter={$serialized_filter}&seite={$page_number}",
77        ]);
78
79        $out .= "<div class='content-right'>";
80        $out .= "<h2 class='optional'>Filter</h2>";
81        $out .= OlzNewsFilter::render(['currentFilter' => $valid_filter]);
82        $out .= "</div>";
83        $out .= "<div class='content-middle olz-news-list-middle'>";
84
85        $is_logged_in = $this->authUtils()->hasPermission('any');
86        $has_blog = $this->authUtils()->hasPermission('kaderblog');
87        $has_roles = !empty($this->authUtils()->getAuthenticatedRoles());
88        $json_mode = htmlentities(json_encode($has_roles ? ($has_blog ? 'account_with_all' : 'account_with_aktuell') : ($has_blog ? 'account_with_blog' : 'account')) ?: '');
89        $class = $is_logged_in ? ' create-news-container' : ' dropdown-toggle';
90        $properties = $is_logged_in
91            ? <<<ZZZZZZZZZZ
92                onclick='return olz.initOlzEditNewsModal({$json_mode})'
93                ZZZZZZZZZZ
94            : <<<'ZZZZZZZZZZ'
95                type='button'
96                data-bs-toggle='dropdown'
97                aria-expanded='false'
98                ZZZZZZZZZZ;
99        if (!$is_logged_in) {
100            $out .= "<div class='dropdown create-news-container'>";
101        }
102        $out .= <<<ZZZZZZZZZZ
103            <button
104                id='create-news-button'
105                class='btn btn-secondary{$class}'
106                {$properties}
107            >
108                <img src='{$code_href}assets/icns/new_white_16.svg' class='noborder' />
109                Neuer Eintrag
110            </button>
111            ZZZZZZZZZZ;
112        if (!$is_logged_in) {
113            $out .= <<<'ZZZZZZZZZZ'
114                <div
115                    class='dropdown-menu dropdown-menu-end'
116                    aria-labelledby='create-news-button'
117                >
118                    <li><button
119                        class='dropdown-item'
120                        onclick='return olz.initOlzLoginModal({})'
121                    >
122                        Login
123                    </button></li>
124                    <li><hr class="dropdown-divider"></li>
125                    <li><div class='dropdown-item disabled should-login'>
126                        <b>Achtung</b>: Bild-Upload und nachträgliches Bearbeiten des Eintrags nur mit Login möglich!
127                    </div></li>
128                    <li><button
129                        id='create-anonymous-button'
130                        class='dropdown-item'
131                        onclick='return olz.initOlzEditNewsModal(&quot;anonymous&quot;)'
132                    >
133                        Forumseintrag ohne Login
134                    </button></li>
135                </div>
136                ZZZZZZZZZZ;
137            $out .= "</div>";
138        }
139
140        $newsletter_link = '';
141        $newsletter_app = OlzApps::getApp('Newsletter');
142        if ($newsletter_app) {
143            $newsletter_link = <<<ZZZZZZZZZZ
144                <a href='{$code_href}{$newsletter_app->getHref()}' class='newsletter-link'>
145                    <img
146                        src='{$newsletter_app->getIcon()}'
147                        alt='newsletter'
148                        class='newsletter-link-icon'
149                        title='Newsletter abonnieren!'
150                    />
151                </a>
152                ZZZZZZZZZZ;
153        } else {
154            $this->log()->error('Newsletter App does not exist!');
155        }
156        $out .= "<h1>{$news_list_title} {$newsletter_link}</h1>";
157
158        $filter_where = $news_utils->getSqlFromFilter($valid_filter);
159        $first_index = $page_index * $this::$page_size;
160        $sql = <<<ZZZZZZZZZZ
161            SELECT
162                COUNT(n.id) as count
163            FROM news n
164            WHERE
165                {$filter_where}
166                AND n.on_off='1'
167            ORDER BY published_date DESC, published_time DESC
168            ZZZZZZZZZZ;
169        // @phpstan-ignore-next-line
170        $count = intval($db->query($sql)->fetch_assoc()['count']);
171        $num_pages = intval($count / $this::$page_size) + 1;
172
173        $sql = <<<ZZZZZZZZZZ
174            SELECT
175                id,
176                owner_user_id,
177                owner_role_id,
178                published_date,
179                published_time,
180                format,
181                author_user_id,
182                author_role_id,
183                author_name,
184                author_email,
185                title,
186                teaser,
187                content,
188                image_ids
189            FROM news n
190            WHERE
191                {$filter_where}
192                AND n.on_off='1'
193            ORDER BY published_date DESC, published_time DESC
194            LIMIT {$first_index}{$this::$page_size}
195            ZZZZZZZZZZ;
196        $res = $db->query($sql);
197
198        $user_repo = $entityManager->getRepository(User::class);
199        $role_repo = $entityManager->getRepository(Role::class);
200
201        $page_content = '';
202        // @phpstan-ignore-next-line
203        for ($index = 0; $index < $res->num_rows; $index++) {
204            // @phpstan-ignore-next-line
205            $row = $res->fetch_assoc();
206
207            // TODO: Directly use doctrine to run the DB query.
208            // @phpstan-ignore-next-line
209            $owner_user = $row['owner_user_id'] ?
210                $user_repo->findOneBy(['id' => $row['owner_user_id']]) : null;
211            $owner_role = $row['owner_role_id'] ?
212                $role_repo->findOneBy(['id' => $row['owner_role_id']]) : null;
213            $author_user = $row['author_user_id'] ?
214                $user_repo->findOneBy(['id' => $row['author_user_id']]) : null;
215            $author_role = $row['author_role_id'] ?
216                $role_repo->findOneBy(['id' => $row['author_role_id']]) : null;
217
218            $news_entry = new NewsEntry();
219            $news_entry->setOwnerUser($owner_user);
220            $news_entry->setOwnerRole($owner_role);
221            // @phpstan-ignore-next-line
222            $news_entry->setPublishedDate(new \DateTime($row['published_date']));
223            // @phpstan-ignore-next-line
224            $news_entry->setFormat($row['format']);
225            $news_entry->setAuthorUser($author_user);
226            $news_entry->setAuthorRole($author_role);
227            // @phpstan-ignore-next-line
228            $news_entry->setAuthorName($row['author_name']);
229            // @phpstan-ignore-next-line
230            $news_entry->setAuthorEmail($row['author_email']);
231            // @phpstan-ignore-next-line
232            $news_entry->setTitle($row['title']);
233            // @phpstan-ignore-next-line
234            $news_entry->setTeaser($row['teaser']);
235            // @phpstan-ignore-next-line
236            $news_entry->setContent($row['content']);
237            $news_entry->setId(intval($row['id']));
238            // @phpstan-ignore-next-line
239            $news_entry->setImageIds($row['image_ids'] ? json_decode($row['image_ids'], true) : null);
240
241            $page_content .= OlzNewsListItem::render([
242                'json_mode' => $json_mode,
243                'news_entry' => $news_entry,
244            ]);
245        }
246        if ($page_content === '') {
247            $page_content = "<div class='no-entries'>Keine Einträge. Bitte Filter anpassen.</div>";
248        }
249        $out .= $page_content;
250        if ($num_pages > 1) {
251            $pages = '';
252            for ($page_number = 1; $page_number <= $num_pages; $page_number++) {
253                $is_current_page = $page_number === $page_index + 1;
254                $page_link_class = $is_current_page ? ' active' : '';
255                $pages .= <<<ZZZZZZZZZZ
256                    <li class='page-item'>
257                        <a
258                            class='page-link{$page_link_class}'
259                            href='?filter={$serialized_filter}&seite={$page_number}'
260                        >
261                            {$page_number}
262                        </a>
263                    </li>
264                    ZZZZZZZZZZ;
265            }
266            $out .= "<nav><ul class='no-style pagination justify-content-center'>{$pages}</ul></nav>";
267        }
268
269        $out .= "</div>";
270
271        $out .= OlzFooter::render();
272
273        return $out;
274    }
275}