Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 140
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
OlzUserDetail
0.00% covered (danger)
0.00%
0 / 140
0.00% covered (danger)
0.00%
0 / 4
1190
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 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHtmlWhenHasAccess
0.00% covered (danger)
0.00%
0 / 130
0.00% covered (danger)
0.00%
0 / 1
756
 prettyPrintPermissionMap
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace Olz\Users\Components\OlzUserDetail;
4
5use Olz\Components\Common\OlzRootComponent;
6use Olz\Components\Page\OlzFooter\OlzFooter;
7use Olz\Components\Page\OlzHeader\OlzHeader;
8use Olz\Entity\ForwardedEmail;
9use Olz\Entity\Roles\Role;
10use Olz\Entity\Users\User;
11use Olz\Repository\Roles\PredefinedRole;
12use Olz\Roles\Components\OlzRoleInfoModal\OlzRoleInfoModal;
13
14/** @extends OlzRootComponent<array<string, mixed>> */
15class OlzUserDetail extends OlzRootComponent {
16    public function hasAccess(): bool {
17        return true;
18    }
19
20    public function searchSqlWhenHasAccess(array $terms): string|array|null {
21        return null;
22    }
23
24    public function getHtmlWhenHasAccess(mixed $args): string {
25        $code_href = $this->envUtils()->getCodeHref();
26        $user_repo = $this->entityManager()->getRepository(User::class);
27        $user = $user_repo->findOneBy(['id' => $args['id']]);
28        if (!$user) {
29            $this->httpUtils()->dieWithHttpError(404);
30            throw new \Exception('should already have failed');
31        }
32
33        $user_id = $user->getId() ?? -1;
34        $parent_id = $user->getParentUserId() ?? -1;
35        $auth_user_id = $this->authUtils()->getCurrentAuthUser()?->getId();
36        $is_root = $this->authUtils()->hasPermission('all');
37        if (!$is_root && $user_id !== $auth_user_id && $parent_id !== $auth_user_id) {
38            $this->httpUtils()->dieWithHttpError(403);
39            throw new \Exception('should already have failed');
40        }
41
42        $role_repo = $this->entityManager()->getRepository(Role::class);
43        $sysadmin_role = $role_repo->getPredefinedRole(PredefinedRole::Sysadmin);
44
45        $out = OlzHeader::render([
46            'back_link' => "{$code_href}verein",
47            'title' => $user->getFullName(),
48            'description' => "{$user->getFullName()} - Profil.",
49            'norobots' => true,
50        ]);
51
52        $out .= "<div class='content-full olz-user-detail'>";
53
54        $image_paths = $this->authUtils()->getUserAvatar($user);
55        $image_src_html = $this->htmlUtils()->getImageSrcHtml($image_paths);
56        $img_html = "<img {$image_src_html} alt='' class='image'>";
57
58        $auth_user_id = $this->session()->get('auth_user_id');
59        $is_parent = $auth_user_id && intval($user->getParentUserId()) === intval($auth_user_id);
60        $is_self = $auth_user_id && intval($user->getId()) === intval($auth_user_id);
61        $has_permissions = $this->authUtils()->hasPermission('users');
62        $can_edit = $is_parent || $is_self || $has_permissions;
63        $edit_admin = '';
64        $edit_password = '';
65        if ($can_edit) {
66            $json_id = json_encode($user->getId());
67            $edit_admin = <<<ZZZZZZZZZZ
68                <div>
69                    <button
70                        id='edit-user-button'
71                        class='btn btn-primary'
72                        onclick='return olz.editUser({$json_id})'
73                    >
74                        <img src='{$code_href}assets/icns/edit_white_16.svg' class='noborder' />
75                        Bearbeiten
76                    </button>
77                </div>
78                ZZZZZZZZZZ;
79            $edit_password = <<<'ZZZZZZZZZZ'
80                     <button
81                        class='btn btn-secondary'
82                        onclick='return olz.initOlzChangePasswordModal()'
83                        id='change-password-button'
84                    >
85                        Passwort ändern
86                    </button>
87                ZZZZZZZZZZ;
88        }
89
90        $street = $user->getStreet() ?? '(Keine Adresse)';
91        $postal_code = $user->getPostalCode() ?? '(Keine PLZ)';
92        $city = $user->getCity() ?? '(Kein Ort)';
93        $region = $user->getRegion() ?? 'Keine Region';
94        $country_code = $user->getCountryCode() ?? 'Kein Land';
95        $birthdate = $user->getBirthdate()?->format('d.m.Y') ?? '(Unbekannt)';
96        $phone = $user->getPhone() ?? '(Unbekannt)';
97
98        if (
99            !$user->getParentUserId()
100            && !$user->isEmailVerified()
101            && !$this->authUtils()->hasPermission('verified_email', $user)
102        ) {
103            if ($user->getEmailVerificationToken()) {
104                $out .= <<<'ZZZZZZZZZZ'
105                    <div class='alert alert-danger' role='alert'>
106                        Deine E-Mail-Adresse ist noch nicht bestätigt. Bitte prüfe deine Inbox (und dein Spam-Postfach) auf unsere Bestätigungs-E-Mail (Betreff: "[OLZ] E-Mail bestätigen").
107                        <a
108                            href='#'
109                            onclick='olz.initOlzVerifyUserEmailModal()'
110                            id='verify-user-email-link'
111                        >
112                            Erneut senden
113                        </a>
114                    </div>
115                    ZZZZZZZZZZ;
116            } else {
117                $out .= <<<'ZZZZZZZZZZ'
118                    <div class='alert alert-danger' role='alert'>
119                        Deine E-Mail-Adresse ist noch nicht bestätigt.
120                        <a
121                            href='#'
122                            onclick='olz.initOlzVerifyUserEmailModal()'
123                            id='verify-user-email-link'
124                        >
125                            Jetzt bestätigen
126                        </a>
127                    </div>
128                    ZZZZZZZZZZ;
129            }
130        }
131
132        $out .= <<<ZZZZZZZZZZ
133            <div class='edit-user-container'>{$edit_admin}</div>
134            <div class='image-container'>{$img_html}</div>
135            <h1 class='name-container'>{$user->getFullName()}</h1>
136            <div class='info-container username'>Benutzername: {$user->getUsername()}</div>
137            ZZZZZZZZZZ;
138        if ($can_edit) {
139            $out .= <<<ZZZZZZZZZZ
140                <div class='info-container address'>
141                    <div>{$street}</div>
142                    <div>{$postal_code} {$city} ({$region}{$country_code})</div>
143                </div>
144                <div class='info-container birthdate'>Geburtsdatum: {$birthdate}</div>
145                <div class='info-container phone'>Telephon: {$phone}</div>
146                ZZZZZZZZZZ;
147        }
148
149        $has_official_email = $this->authUtils()->hasPermission('user_email', $user);
150        $email_html = '';
151        if ($has_official_email) {
152            $host = $this->envUtils()->getEmailForwardingHost();
153            $olz_email = "{$user->getUsername()}@{$host}";
154            $email = $user->getEmail() ? $olz_email : null;
155            $email_html = "<div class='info-container'>Du hast eine <b>offizielle</b> OLZ E-Mail-Adresse: <b>{$olz_email}</b></div>";
156            if ($user->getOldUsername()) {
157                $old_olz_email = "{$user->getOldUsername()}@{$host}";
158                $email_html .= "<div class='info-container'>Du hast ausserdem eine <b>alte</b> offizielle OLZ E-Mail-Adresse: <b>{$old_olz_email}</b> <i>(nicht mehr benutzen!)</i></div>";
159            }
160            $email_html .= "<div class='info-container'>Die E-Mails <b>werden weitergeleitet</b> an: <b>{$user->getEmail()}</b></div>";
161            $email_html .= "<h3>Kürzlich weitergeleitete E-Mails</h3>";
162            $email_html .= "<table class='forwarded-emails'><tr><th>Datum</th><th>Absender</th><th>Betreff</th></tr>";
163            $forwarded_email_repo = $this->entityManager()->getRepository(ForwardedEmail::class);
164            $forwarded_emails = $forwarded_email_repo->findBy(['recipient_user' => $user], ['forwarded_at' => 'DESC']);
165            foreach ($forwarded_emails as $forwarded_email) {
166                $email_html .= <<<ZZZZZZZZZZ
167                    <tr>
168                        <td>{$forwarded_email->getForwardedAt()?->format('d.m.Y H:i')}</td>
169                        <td>{$forwarded_email->getSenderAddress()}</td>
170                        <td>{$forwarded_email->getSubject()}</td>
171                    </tr>
172                    ZZZZZZZZZZ;
173            }
174            $email_html .= "</table>";
175        } else {
176            $email = $user->getEmail();
177            $email_html = "<div class='info-container'>Du hast <b>keine offizielle</b> OLZ E-Mail-Adresse.</div>";
178            $sysadmin_modal = $sysadmin_role ? OlzRoleInfoModal::render(['role' => $sysadmin_role]) : '"Website"';
179            $email_html .= "<div class='info-container'>Bei Fragen: kontaktiere das Ressort {$sysadmin_modal}.</div>";
180        }
181        if ($email) {
182            $email_out = $this->htmlUtils()->replaceEmailAdresses($email);
183            $out .= "<div class='info-container email'>{$email_out}</div>";
184        }
185        $out .= $edit_password;
186
187        $out .= <<<ZZZZZZZZZZ
188            <h2>Berechtigungen</h2>
189            <div class='info-container'>Persönliche Berechtigungen: <b>{$this->prettyPrintPermissionMap($user->getPermissionMap())}</b></div>
190            ZZZZZZZZZZ;
191        foreach ($user->getRoles() as $role) {
192            $role_modal = OlzRoleInfoModal::render(['role' => $role]);
193            $out .= "<div class='info-container'>Berechtigungen im Rahmen von {$role_modal}: <b>{$this->prettyPrintPermissionMap($role->getPermissionMap())}</b></div>";
194        }
195
196        $out .= <<<ZZZZZZZZZZ
197            <h2>E-Mail Weiterleitung</h2>
198            {$email_html}
199            ZZZZZZZZZZ;
200
201        if ($can_edit) {
202            $out .= "<h2>Familie</h2>";
203            $child_users = $user_repo->findBy(['parent_user' => $user->getId()]);
204            if ($child_users) {
205                $out .= "<ul class='info-container'>";
206                foreach ($child_users as $child_user) {
207                    $out .= "<li>Familienmitglied <a href='{$code_href}benutzer/{$child_user->getId()}'>{$child_user->getFullName()}</a></li>";
208                }
209                $out .= "</ul>";
210            }
211            if ($user->getParentUserId()) {
212                $parent_user = $user_repo->findOneBy(['id' => $user->getParentUserId()]);
213                $out .= "<div class='info-container'>Familienmitglied von <a href='{$code_href}benutzer/{$parent_user?->getId()}'>{$parent_user?->getFullName()}</a></div>";
214                if ($child_users) {
215                    $this->log()->warning("User {$user->getId()} has parent and children.");
216                }
217            } else {
218                $json_id = json_encode($user->getId());
219                $out .= <<<ZZZZZZZZZZ
220                    <div>
221                        <button
222                            id='add-child-user-button'
223                            class='btn btn-secondary'
224                            onclick='return olz.addChildUser({$json_id})'
225                        >
226                            <img src='{$code_href}assets/icns/new_white_16.svg' class='noborder' />
227                            Familienmitglied hinzufügen
228                        </button>
229                    </div>
230                    ZZZZZZZZZZ;
231            }
232        }
233        $out .= "</div>";
234
235        $out .= OlzFooter::render();
236
237        return $out;
238    }
239
240    /** @param array<string, bool> $permissions_map */
241    protected function prettyPrintPermissionMap(array $permissions_map): string {
242        $out = '';
243        foreach ($permissions_map as $permission => $is_given) {
244            if (!$is_given) {
245                continue;
246            }
247            if ($out !== '') {
248                $out .= ', ';
249            }
250            $out .= $permission;
251        }
252        return $out !== '' ? $out : '(keine Berechtigungen)';
253    }
254}