Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 119 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
OlzTermineListParams | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | n/a |
0 / 0 |
|||
OlzTermineList | |
0.00% |
0 / 119 |
|
0.00% |
0 / 4 |
552 | |
0.00% |
0 / 1 |
getSearchTitle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSearchResults | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getHtml | |
0.00% |
0 / 114 |
|
0.00% |
0 / 1 |
380 | |||
getMonth | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | // ============================================================================= |
4 | // Zeigt geplante und vergangene Termine an. |
5 | // ============================================================================= |
6 | |
7 | namespace Olz\Termine\Components\OlzTermineList; |
8 | |
9 | use Olz\Components\Common\OlzEditableText\OlzEditableText; |
10 | use Olz\Components\Common\OlzRootComponent; |
11 | use Olz\Components\Page\OlzFooter\OlzFooter; |
12 | use Olz\Components\Page\OlzHeader\OlzHeader; |
13 | use Olz\Entity\Termine\Termin; |
14 | use Olz\Entity\Termine\TerminLabel; |
15 | use Olz\Termine\Components\OlzTermineFilter\OlzTermineFilter; |
16 | use Olz\Termine\Components\OlzTermineListItem\OlzTermineListItem; |
17 | use Olz\Utils\HttpParams; |
18 | |
19 | /** @extends HttpParams<array{filter?: ?string, von?: ?string}> */ |
20 | class OlzTermineListParams extends HttpParams { |
21 | } |
22 | |
23 | /** @extends OlzRootComponent<array<string, mixed>> */ |
24 | class OlzTermineList extends OlzRootComponent { |
25 | public function getSearchTitle(): string { |
26 | return 'Termin-Listen'; |
27 | } |
28 | |
29 | public function getSearchResults(array $terms): array { |
30 | return []; |
31 | } |
32 | |
33 | public static string $title = "Termine"; |
34 | public static string $description = "Orientierungslauf-Wettkämpfe, OL-Wochen, OL-Weekends, Trainings und Vereinsanlässe der OL Zimmerberg."; |
35 | |
36 | public function getHtml(mixed $args): string { |
37 | /** @return array{filter?: ?string} */ |
38 | $params = $this->httpUtils()->validateGetParams(OlzTermineListParams::class); |
39 | $db = $this->dbUtils()->getDb(); |
40 | $code_href = $this->envUtils()->getCodeHref(); |
41 | |
42 | $current_filter = json_decode($params['filter'] ?? '{}', true); |
43 | $termine_utils = $this->termineUtils()->loadTypeOptions(); |
44 | |
45 | if (!$termine_utils->isValidFilter($current_filter)) { |
46 | $valid_filter = $termine_utils->getValidFilter($current_filter); |
47 | $enc_json_filter = urlencode(json_encode($valid_filter) ?: '{}'); |
48 | $this->httpUtils()->redirect("{$code_href}termine?filter={$enc_json_filter}", 308); |
49 | } |
50 | |
51 | $termine_list_title = $termine_utils->getTitleFromFilter($current_filter); |
52 | $enc_json_filter = urlencode(json_encode($current_filter) ?: '{}'); |
53 | |
54 | $out = OlzHeader::render([ |
55 | 'title' => $termine_list_title, |
56 | 'description' => self::$description, // TODO: Filter-specific description? |
57 | 'canonical_url' => "{$code_href}termine?filter={$enc_json_filter}", |
58 | ]); |
59 | |
60 | $admin_menu_out = ''; |
61 | $has_termine_permissions = $this->authUtils()->hasPermission('termine'); |
62 | if ($has_termine_permissions) { |
63 | $admin_menu_out = <<<ZZZZZZZZZZ |
64 | <div class='termine-list-admin-menu'> |
65 | <span class='entry'> |
66 | <a href='{$code_href}termine/orte' class='linkmap'> |
67 | Termin-Orte |
68 | </a> |
69 | </span> |
70 | <span class='entry'> |
71 | <a href='{$code_href}termine/vorlagen' class='linkint'> |
72 | Termin-Vorlagen |
73 | </a> |
74 | </span> |
75 | </div> |
76 | ZZZZZZZZZZ; |
77 | } |
78 | $filter_out = OlzTermineFilter::render(); |
79 | $downloads_links_out = OlzEditableText::render(['snippet_id' => 2]); |
80 | $newsletter_out = OlzEditableText::render(['snippet_id' => 3]); |
81 | $out .= <<<ZZZZZZZZZZ |
82 | <div class='content-right'> |
83 | {$admin_menu_out} |
84 | <h2 class='optional'>Filter</h2> |
85 | {$filter_out} |
86 | <div class='optional'> |
87 | <h2>Downloads und Links</h2> |
88 | {$downloads_links_out} |
89 | </div> |
90 | <div class='optional'> |
91 | <h2>Newsletter</h2> |
92 | {$newsletter_out} |
93 | </div> |
94 | </div> |
95 | <div class='content-middle olz-termine-list-middle'> |
96 | ZZZZZZZZZZ; |
97 | |
98 | $has_access = $this->authUtils()->hasPermission('termine'); |
99 | if ($has_access) { |
100 | $out .= <<<ZZZZZZZZZZ |
101 | <button |
102 | id='create-termin-button' |
103 | class='btn btn-secondary create-termin-container' |
104 | onclick='return olz.initOlzEditTerminModal()' |
105 | > |
106 | <img src='{$code_href}assets/icns/new_white_16.svg' class='noborder' /> |
107 | Neuer Termin |
108 | </button> |
109 | ZZZZZZZZZZ; |
110 | } |
111 | |
112 | $termin_repo = $this->entityManager()->getRepository(Termin::class); |
113 | $termin_label_repo = $this->entityManager()->getRepository(TerminLabel::class); |
114 | $termin_label = $termin_label_repo->findOneBy(['ident' => $current_filter['typ']]); |
115 | $edit_admin = ''; |
116 | if ($termin_label) { |
117 | $has_termine_permissions = $this->authUtils()->hasPermission('termine'); |
118 | if ($has_termine_permissions) { |
119 | $json_id = json_encode($termin_label->getId()); |
120 | $edit_admin = <<<ZZZZZZZZZZ |
121 | <button |
122 | id='edit-termin-label-button' |
123 | class='btn btn-secondary-outline btn-sm' |
124 | onclick='return olz.termineListEditTerminLabel({$json_id})' |
125 | > |
126 | <img src='{$code_href}assets/icns/edit_16.svg' class='noborder' /> |
127 | </button> |
128 | ZZZZZZZZZZ; |
129 | } |
130 | } |
131 | $out .= "<h1>{$termine_list_title}{$edit_admin}</h1>"; |
132 | $details = $termin_label?->getDetails(); |
133 | if ($details) { |
134 | $details_html = $this->htmlUtils()->renderMarkdown($details); |
135 | $details_html = $termin_label->replaceImagePaths($details_html); |
136 | $details_html = $termin_label->replaceFilePaths($details_html); |
137 | $out .= $details_html; |
138 | } |
139 | |
140 | // ------------------------------------------------------------- |
141 | // VORSCHAU - LISTE |
142 | $inner_date_filter = $termine_utils->getSqlDateRangeFilter($current_filter, 't'); |
143 | $inner_sql_where = <<<ZZZZZZZZZZ |
144 | (t.on_off = '1') |
145 | AND ({$inner_date_filter}) |
146 | ZZZZZZZZZZ; |
147 | $type_filter = $termine_utils->getSqlTypeFilter($current_filter, 'c'); |
148 | $outer_date_filter = $termine_utils->getSqlDateRangeFilter($current_filter, 'c'); |
149 | $outer_sql_where = "({$type_filter}) AND ({$outer_date_filter})"; |
150 | |
151 | $sql = <<<ZZZZZZZZZZ |
152 | SELECT * FROM (( |
153 | SELECT |
154 | 'termin' as item_type, |
155 | t.owner_user_id as owner_user_id, |
156 | t.start_date as start_date, |
157 | t.start_time as start_time, |
158 | t.end_date as end_date, |
159 | t.end_time as end_time, |
160 | t.title as title, |
161 | t.text as text, |
162 | t.id as id, |
163 | ( |
164 | SELECT GROUP_CONCAT(l.ident ORDER BY l.position ASC SEPARATOR ' ') |
165 | FROM |
166 | termin_label_map tl |
167 | JOIN termin_labels l ON (l.id = tl.label_id) |
168 | WHERE tl.termin_id = t.id |
169 | GROUP BY t.id |
170 | ) as typ, |
171 | t.on_off as on_off, |
172 | t.newsletter as newsletter, |
173 | t.xkoord as xkoord, |
174 | t.ykoord as ykoord, |
175 | t.go2ol as go2ol, |
176 | t.solv_uid as solv_uid, |
177 | t.last_modified_by_user_id as last_modified_by_user_id, |
178 | t.image_ids as image_ids, |
179 | t.location_id as location_id |
180 | FROM termine t |
181 | WHERE ({$inner_sql_where}) |
182 | ) UNION ALL ( |
183 | SELECT |
184 | 'deadline' as item_type, |
185 | t.owner_user_id as owner_user_id, |
186 | DATE(t.deadline) as start_date, |
187 | TIME(t.deadline) as start_time, |
188 | NULL as end_date, |
189 | NULL as end_time, |
190 | CONCAT('Meldeschluss für ', t.title) as title, |
191 | '' as text, |
192 | t.id as id, |
193 | 'meldeschluss' as typ, |
194 | t.on_off as on_off, |
195 | NULL as newsletter, |
196 | NULL as xkoord, |
197 | NULL as ykoord, |
198 | t.go2ol as go2ol, |
199 | t.solv_uid as solv_uid, |
200 | t.last_modified_by_user_id as last_modified_by_user_id, |
201 | t.image_ids as image_ids, |
202 | NULL as location_id |
203 | FROM termine t |
204 | WHERE (t.deadline IS NOT NULL) AND ({$inner_sql_where}) |
205 | )) AS c |
206 | WHERE ({$outer_sql_where}) |
207 | ORDER BY c.start_date ASC |
208 | ZZZZZZZZZZ; |
209 | |
210 | $result = $db->query($sql); |
211 | $today = $this->dateUtils()->getCurrentDateInFormat('Y-m-d'); |
212 | $meldeschluss_label = new TerminLabel(); |
213 | $meldeschluss_label->setIdent('meldeschluss'); |
214 | $meldeschluss_label->setIcon(null); |
215 | $last_date = null; |
216 | // @phpstan-ignore-next-line |
217 | while ($row = $result->fetch_assoc()) { |
218 | $this_date = $row['start_date']; |
219 | // @phpstan-ignore-next-line |
220 | $this_month_start = $this->getMonth($this_date).'-01'; |
221 | |
222 | if ($today < $this_month_start && $today > $last_date) { |
223 | $out .= "<div class='bar today'>Heute</div>"; |
224 | } |
225 | // @phpstan-ignore-next-line |
226 | if ($this->getMonth($this_date) !== $this->getMonth($last_date)) { |
227 | // @phpstan-ignore-next-line |
228 | $pretty_month = $this->dateUtils()->olzDate("MM jjjj", $this_date); |
229 | $out .= "<h3 class='bar green'>{$pretty_month}</h3>"; |
230 | } |
231 | if ($today <= $this_date && $today > $last_date && $today >= $this_month_start) { |
232 | $out .= "<div class='bar today'>Heute</div>"; |
233 | } |
234 | $labels = [$meldeschluss_label]; |
235 | if ($row['item_type'] === 'termin') { |
236 | $termin = $termin_repo->findOneBy(['id' => $row['id']]); |
237 | $labels = [...($termin?->getLabels() ?? [])]; |
238 | } |
239 | |
240 | $out .= OlzTermineListItem::render([ |
241 | 'id' => $row['id'], |
242 | 'owner_user_id' => $row['owner_user_id'], |
243 | 'start_date' => $row['start_date'], |
244 | 'start_time' => $row['start_time'], |
245 | 'end_date' => $row['end_date'], |
246 | 'end_time' => $row['end_time'], |
247 | 'title' => $row['title'], |
248 | 'text' => $row['text'], |
249 | 'solv_uid' => $row['solv_uid'], |
250 | 'labels' => $labels, |
251 | // @phpstan-ignore-next-line |
252 | 'image_ids' => $row['image_ids'] ? json_decode($row['image_ids'], true) : null, |
253 | 'location_id' => $row['location_id'], |
254 | ]); |
255 | |
256 | $last_date = $this_date; |
257 | } |
258 | if ($last_date === null) { |
259 | $out .= "<div class='no-entries'>Keine Einträge. Bitte Filter anpassen.</div>"; |
260 | } |
261 | $out .= "</div>"; |
262 | |
263 | $out .= OlzFooter::render(); |
264 | |
265 | return $out; |
266 | } |
267 | |
268 | protected function getMonth(?string $date): ?string { |
269 | if ($date === null) { |
270 | return null; |
271 | } |
272 | return substr($date, 0, 7); |
273 | } |
274 | } |