Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 149
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
OlzRolePageParams
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
OlzRolePage
0.00% covered (danger)
0.00%
0 / 149
0.00% covered (danger)
0.00%
0 / 3
420
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
 searchSqlWhenHasAccess
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 getHtmlWhenHasAccess
0.00% covered (danger)
0.00%
0 / 132
0.00% covered (danger)
0.00%
0 / 1
342
1<?php
2
3namespace Olz\Roles\Components\OlzRolePage;
4
5use Olz\Components\Common\OlzRootComponent;
6use Olz\Components\Page\OlzFooter\OlzFooter;
7use Olz\Components\Page\OlzHeader\OlzHeader;
8use Olz\Entity\Roles\Role;
9use Olz\Users\Components\OlzUserInfoModal\OlzUserInfoModal;
10use Olz\Utils\HttpParams;
11
12/** @extends HttpParams<array{von?: ?string}> */
13class OlzRolePageParams extends HttpParams {
14}
15
16/** @extends OlzRootComponent<array<string, mixed>> */
17class OlzRolePage extends OlzRootComponent {
18    public function hasAccess(): bool {
19        return true;
20    }
21
22    public function searchSqlWhenHasAccess(array $terms): string|array|null {
23        $code_href = $this->envUtils()->getCodeHref();
24        $where = implode(' AND ', array_map(function ($term) {
25            return <<<ZZZZZZZZZZ
26                (
27                    r.username LIKE '%{$term}%'
28                    OR r.old_username LIKE '%{$term}%'
29                    OR r.name LIKE '%{$term}%'
30                    OR r.description LIKE '%{$term}%'
31                )
32                ZZZZZZZZZZ;
33        }, $terms));
34        return <<<ZZZZZZZZZZ
35            SELECT
36                CONCAT('{$code_href}verein/', r.username) AS link,
37                '{$code_href}assets/icns/link_role_16.svg' AS icon,
38                NULL AS date,
39                CONCAT('Ressort: ', IF(rpp.name IS NULL, '', CONCAT(rpp.name, ' &gt; ')), IF(rp.name IS NULL, '', CONCAT(rp.name, ' &gt; ')), r.name) AS title,
40                CONCAT(IFNULL(r.username, ''), ' ', IFNULL(r.old_username, ''), ' ', IFNULL(r.description, '')) AS text,
41                1.0 AS time_relevance
42            FROM roles r
43                LEFT JOIN roles rp ON (rp.id = r.parent_role)
44                LEFT JOIN roles rpp ON (rpp.id = rp.parent_role)
45            WHERE
46                r.on_off = '1'
47                AND {$where}
48            ZZZZZZZZZZ;
49    }
50
51    public function getHtmlWhenHasAccess(mixed $args): string {
52        $this->httpUtils()->validateGetParams(OlzRolePageParams::class);
53        $is_member = $this->authUtils()->hasPermission('member');
54        $entityManager = $this->dbUtils()->getEntityManager();
55        $code_href = $this->envUtils()->getCodeHref();
56        $role_repo = $entityManager->getRepository(Role::class);
57        $role_username = $args['ressort'];
58        $role_repo = $entityManager->getRepository(Role::class);
59        $role = $role_repo->findOneBy(['username' => $role_username, 'on_off' => 1]);
60
61        if (!$role) {
62            $this->httpUtils()->dieWithHttpError(404);
63            throw new \Exception('should already have failed');
64        }
65
66        // TODO: Remove again, after all ressort descriptions have been updated.
67        // This is just temporary logic!
68        $no_robots = ($role->getGuide() === '');
69
70        $role_description = $role->getDescription();
71        $end_of_first_line = strpos($role_description, "\n");
72        $first_line = $end_of_first_line
73            ? substr($role_description, 0, $end_of_first_line)
74            : $role_description;
75        $description_html = $this->htmlUtils()->renderMarkdown($first_line);
76        $role_short_description = strip_tags($description_html);
77
78        $role_id = $role->getId();
79        $role_name = $role->getName();
80        $role_description = $role->getDescription();
81        $parent_role_id = $role->getParentRoleId();
82        $parent_role = $role_repo->findOneBy(['id' => $parent_role_id]);
83        $can_have_child_roles = $role->getCanHaveChildRoles();
84
85        $parent_chain = [];
86        $parent = $role;
87        while ($parent) {
88            $parent_id = $parent->getParentRoleId();
89            if ($parent_id) {
90                $parent = $role_repo->findOneBy(['id' => $parent_id]);
91                array_unshift($parent_chain, $parent);
92            } else {
93                $parent = null;
94            }
95        }
96
97        $out = OlzHeader::render([
98            'back_link' => "{$code_href}verein",
99            'title' => $role_name,
100            'description' => "{$role_short_description} - Ressort {$role_name} der OL Zimmerberg.",
101            'norobots' => $no_robots,
102            'canonical_url' => "{$code_href}verein/{$role_username}",
103        ]);
104
105        $out .= "<div class='content-full olz-role-page'>";
106        $out .= "<nav aria-label='breadcrumb'>";
107        $out .= "<ol class='breadcrumb'>";
108        $out .= "<li class='breadcrumb-item'><a href='{$code_href}verein'>OL Zimmerberg</a></li>";
109        foreach ($parent_chain as $breadcrumb) {
110            $username = $breadcrumb?->getUsername();
111            $name = $breadcrumb?->getName();
112            $out .= "<li class='breadcrumb-item'><a href='{$code_href}verein/{$username}'>{$name}</a></li>";
113        }
114        $out .= "<li class='breadcrumb-item active' aria-current='page'>{$role_name}</li>";
115        $out .= "</ol>";
116        $out .= "</nav>";
117
118        $edit_admin = '';
119        $add_membership_admin = '';
120        $add_child_role_admin = '';
121        $is_parent_superior = $this->authUtils()->hasRoleEditPermission($parent_role_id);
122        $is_parent_owner = $parent_role && $this->entityUtils()->canUpdateOlzEntity($parent_role, null, 'roles');
123        $can_parent_edit = $is_parent_superior || $is_parent_owner;
124        $is_superior = $this->authUtils()->hasRoleEditPermission($role_id);
125        $is_owner = $this->entityUtils()->canUpdateOlzEntity($role, null, 'roles');
126        $can_edit = $is_superior || $is_owner;
127        if ($can_edit) {
128            $json_id = json_encode($role_id);
129            $json_can_parent_edit = json_encode(boolval($can_parent_edit));
130            $edit_admin = <<<ZZZZZZZZZZ
131                <div>
132                    <button
133                        id='edit-role-button'
134                        class='btn btn-primary'
135                        onclick='return olz.editRole({$json_id}{$json_can_parent_edit})'
136                    >
137                        <img src='{$code_href}assets/icns/edit_white_16.svg' class='noborder' />
138                        Bearbeiten
139                    </button>
140                </div>
141                ZZZZZZZZZZ;
142            $add_membership_admin = <<<ZZZZZZZZZZ
143                <div>
144                    <button
145                        id='add-role-user-button'
146                        class='btn btn-primary'
147                        onclick='return olz.addRoleUser({$json_id})'
148                    >
149                        <img src='{$code_href}assets/icns/new_white_16.svg' class='noborder' />
150                        Neuer Verantwortlicher
151                    </button>
152                </div>
153                ZZZZZZZZZZ;
154            if ($can_have_child_roles) {
155                $add_child_role_admin = <<<ZZZZZZZZZZ
156                    <div>
157                        <button
158                            id='add-sub-role-button'
159                            class='btn btn-primary'
160                            onclick='return olz.addChildRole({$json_id})'
161                        >
162                            <img src='{$code_href}assets/icns/new_white_16.svg' class='noborder' />
163                            Neues Unter-Ressort
164                        </button>
165                    </div>
166                    ZZZZZZZZZZ;
167            }
168        }
169
170        $out .= "<div>{$edit_admin}</div>";
171        $description_html = $this->htmlUtils()->renderMarkdown($role->getDescription());
172        $description_html = $role->replaceImagePaths($description_html);
173        $description_html = $role->replaceFilePaths($description_html);
174        $out .= $description_html;
175
176        $assignees = $role->getUsers();
177        $num_assignees = count($assignees);
178        $out .= "<br/><h2>Verantwortlich</h2>";
179        if ($num_assignees === 0) {
180            $out .= "<p><i>Keine Ressort-Verantwortlichen</i></p>";
181            $out .= $add_membership_admin;
182        } else {
183            $out .= "<div class='role-assignees'>";
184            foreach ($assignees as $assignee) {
185                $out .= "<div class='assignee'>";
186                if ($is_superior || $is_owner) {
187                    $json_role_id = json_encode(intval($role_id));
188                    $json_user_id = json_encode(intval($assignee->getId()));
189                    $out .= <<<ZZZZZZZZZZ
190                            <button
191                                id='delete-role-user-button'
192                                class='btn btn-sm btn-danger'
193                                onclick='return olz.deleteRoleUser({$json_role_id}{$json_user_id})'
194                            >
195                                <img src='{$code_href}assets/icns/delete_white_16.svg' class='noborder' />
196                            </button>
197                        ZZZZZZZZZZ;
198                }
199                $out .= OlzUserInfoModal::render([
200                    'user' => $assignee,
201                    'mode' => 'name_picture',
202                ]);
203                $out .= "</div>";
204            }
205            $out .= $add_membership_admin;
206            $out .= "</div>";
207        }
208
209        $child_roles = $role_repo->findBy([
210            'parent_role' => $role_id,
211            'on_off' => 1,
212        ], ['position_within_parent' => 'ASC']);
213        $num_child_roles = count($child_roles);
214        $out .= "<br/><h2>Unter-Ressorts</h2>";
215        if ($num_child_roles === 0) {
216            $out .= "<p id='sub-roles'><i>Keine Unter-Ressorts</i></p>";
217        } else {
218            $out .= "<ul id='sub-roles' class='no-style'>";
219            foreach ($child_roles as $child_role) {
220                $child_role_name = $child_role->getName();
221                $child_role_username = $child_role->getUsername();
222                $out .= "<li><a href='{$code_href}verein/{$child_role_username}' class='linkint'><b>{$child_role_name}</b></a></li>";
223            }
224            $out .= "</ul>";
225            $out .= $add_child_role_admin;
226        }
227
228        if ($is_member) {
229            $guide_html = $this->htmlUtils()->renderMarkdown($role->getGuide());
230            $guide_html = $role->replaceImagePaths($guide_html);
231            $guide_html = $role->replaceFilePaths($guide_html);
232            $out .= "<br/><br/><h2>Aufgaben (nur für OLZ-Mitglieder sichtbar)</h2>";
233            $out .= $guide_html;
234        }
235
236        $out .= "</div>";
237        $out .= OlzFooter::render();
238
239        return $out;
240    }
241}