These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * webtrees: online genealogy |
||
4 | * Copyright (C) 2018 webtrees development team |
||
5 | * This program is free software: you can redistribute it and/or modify |
||
6 | * it under the terms of the GNU General Public License as published by |
||
7 | * the Free Software Foundation, either version 3 of the License, or |
||
8 | * (at your option) any later version. |
||
9 | * This program is distributed in the hope that it will be useful, |
||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
12 | * GNU General Public License for more details. |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
15 | */ |
||
16 | namespace Fisharebest\Webtrees; |
||
17 | |||
18 | use DateTimeZone; |
||
19 | use Fisharebest\Webtrees\Controller\PageController; |
||
20 | use Fisharebest\Webtrees\Functions\FunctionsEdit; |
||
21 | |||
22 | /** @global Tree $WT_TREE */ |
||
23 | global $WT_TREE; |
||
24 | |||
25 | require 'includes/session.php'; |
||
26 | |||
27 | // Need to be logged in |
||
28 | if (!Auth::check()) { |
||
29 | header('Location: index.php'); |
||
30 | |||
31 | return; |
||
32 | } |
||
33 | |||
34 | // Extract form variables |
||
35 | $action = Filter::post('action', 'update|delete', ''); |
||
36 | $username = Filter::post('username'); |
||
37 | $real_name = Filter::post('real-name'); |
||
38 | $password_1 = Filter::post('password-1', WT_REGEX_PASSWORD); |
||
39 | $password_2 = Filter::post('password-2', WT_REGEX_PASSWORD); |
||
40 | $email = Filter::post('email'); |
||
41 | $root_id = Filter::post('root-id', WT_REGEX_XREF); |
||
42 | $theme = Filter::post('theme', implode('|', array_keys(Theme::themeNames())), ''); |
||
43 | $language = Filter::post('language', null, ''); |
||
44 | $time_zone = Filter::post('time-zone', null, 'UTC'); |
||
45 | $contact_method = Filter::post('contact-method', null, ''); |
||
46 | $visible_online = Filter::postBool('visible-online'); |
||
47 | |||
48 | // Respond to form action |
||
49 | if ($action !== '' && Filter::checkCsrf()) { |
||
50 | switch ($action) { |
||
51 | case 'update': |
||
52 | if ($username !== Auth::user()->getUserName() && User::findByUserName($username)) { |
||
53 | FlashMessages::addMessage(I18N::translate('Duplicate username. A user with that username already exists. Please choose another username.')); |
||
54 | } elseif ($email !== Auth::user()->getEmail() && User::findByEmail($email)) { |
||
55 | FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); |
||
56 | } else { |
||
57 | // Change username |
||
58 | if ($username !== Auth::user()->getUserName()) { |
||
59 | Log::addAuthenticationLog('User ' . Auth::user()->getUserName() . ' renamed to ' . $username); |
||
60 | Auth::user()->setUserName($username); |
||
61 | } |
||
62 | |||
63 | // Change password |
||
64 | if ($password_1 !== '' && $password_1 === $password_2) { |
||
65 | Auth::user()->setPassword($password_1); |
||
66 | } |
||
67 | |||
68 | // Change other settings |
||
69 | Auth::user() |
||
70 | ->setRealName($real_name) |
||
71 | ->setEmail($email) |
||
72 | ->setPreference('language', $language) |
||
73 | ->setPreference('TIMEZONE', $time_zone) |
||
74 | ->setPreference('contactmethod', $contact_method) |
||
75 | ->setPreference('visibleonline', $visible_online ? '1' : '0'); |
||
76 | |||
77 | Auth::user()->setPreference('theme', $theme); |
||
78 | |||
79 | $WT_TREE->setUserPreference(Auth::user(), 'rootid', $root_id); |
||
80 | } |
||
81 | break; |
||
82 | |||
83 | case 'delete': |
||
84 | // An administrator can only be deleted by another administrator |
||
85 | if (!Auth::user()->getPreference('canadmin')) { |
||
86 | $currentUser = Auth::user(); |
||
87 | Auth::logout(); |
||
88 | $currentUser->delete(); |
||
89 | } |
||
90 | break; |
||
91 | } |
||
92 | |||
93 | header('Location: edituser.php'); |
||
94 | |||
95 | return; |
||
96 | } |
||
97 | |||
98 | $controller = new PageController; |
||
99 | $controller |
||
100 | ->setPageTitle(I18N::translate('My account')) |
||
101 | ->pageHeader(); |
||
102 | |||
103 | $my_individual_record = Individual::getInstance($WT_TREE->getUserPreference(Auth::user(), 'gedcomid'), $WT_TREE); |
||
104 | $default_individual = Individual::getInstance($WT_TREE->getUserPreference(Auth::user(), 'rootid'), $WT_TREE); |
||
105 | |||
106 | // Form validation |
||
107 | ?> |
||
108 | <script> |
||
109 | function checkform(frm) { |
||
110 | if (frm.form_pass1.value!=frm.form_pass2.value) { |
||
111 | alert("<?= I18N::translate('The passwords do not match.') ?>"); |
||
112 | frm.form_pass1.focus(); |
||
113 | return false; |
||
114 | } |
||
115 | if (frm.form_pass1.value.length > 0 && frm.form_pass1.value.length < 6) { |
||
116 | alert("<?= I18N::translate('Passwords must contain at least 6 characters.') ?>"); |
||
117 | frm.form_pass1.focus(); |
||
118 | return false; |
||
119 | } |
||
120 | return true; |
||
121 | } |
||
122 | </script> |
||
123 | |||
124 | <h2><?= $controller->getPageTitle() ?></h2> |
||
125 | |||
126 | <form name="editform" method="post" onsubmit="return checkform(this);"> |
||
127 | <input type="hidden" name="action" value="update"> |
||
128 | <?= Filter::getCsrf() ?> |
||
129 | |||
130 | <div class="row form-group"> |
||
131 | <label class="col-sm-3 col-form-label" for="username"> |
||
132 | <?= I18N::translate('Username') ?> |
||
133 | </label> |
||
134 | <div class="col-sm-9"> |
||
135 | <input type="text" class="form-control" id="username" name="username" value="<?= e(Auth::user()->getUserName()) ?>" dir="auto" aria-describedby="username-description" required> |
||
136 | <p class="small text-muted" id="username-description"> |
||
137 | <?= I18N::translate('Usernames are case-insensitive and ignore accented letters, so that āchloeā, āchloĆ«ā, and āChloeā are considered to be the same.') ?> |
||
138 | </p> |
||
139 | </div> |
||
140 | </div> |
||
141 | |||
142 | <div class="row form-group"> |
||
143 | <label class="col-sm-3 col-form-label" for="real-name"> |
||
144 | <?= I18N::translate('Real name') ?> |
||
145 | </label> |
||
146 | <div class="col-sm-9"> |
||
147 | <input type="text" class="form-control" id="real-name" name="real-name" value="<?= e(Auth::user()->getRealName()) ?>" dir="auto" aria-describedby="real-name-description" required> |
||
148 | <p class="small text-muted" id="username-description"> |
||
149 | <?= I18N::translate('This is your real name, as you would like it displayed on screen.') ?> |
||
150 | </p> |
||
151 | </div> |
||
152 | </div> |
||
153 | |||
154 | <div class="row form-group"> |
||
155 | <label class="col-sm-3 col-form-label" for="gedcom-id"> |
||
156 | <?= I18N::translate('Individual record') ?> |
||
157 | </label> |
||
158 | <div class="col-sm-9"> |
||
159 | <select class="form-control" id="gedcom-id" aria-describedby="gedcom-id-description" disabled> |
||
160 | <?php if ($my_individual_record instanceof Individual): ?> |
||
161 | <option value=""><?= $my_individual_record->getFullName() ?></option> |
||
162 | <?php else: ?> |
||
163 | <option value=""><?= I18N::translateContext('unknown people', 'Unknown') ?></option> |
||
164 | <?php endif ?> |
||
165 | </select> |
||
166 | <p class="small text-muted" id="gedcom-id-description"> |
||
167 | <?= I18N::translate('This is a link to your own record in the family tree. If this is the wrong individual, contact an administrator.') ?> |
||
168 | </p> |
||
169 | </div> |
||
170 | </div> |
||
171 | |||
172 | <div class="row form-group"> |
||
173 | <label class="col-sm-3 col-form-label" for="root-id"> |
||
174 | <?= I18N::translate('Default individual') ?> |
||
175 | </label> |
||
176 | <div class="col-sm-9"> |
||
177 | <?= FunctionsEdit::formControlIndividual($default_individual, ['id' => 'root-id', 'name' => 'root-id', 'aria-describedby' => 'root-id-description']) ?> |
||
0 ignored issues
–
show
|
|||
178 | <p class="small text-muted" id="root-id-description"> |
||
179 | <?= I18N::translate('This individual will be selected by default when viewing charts and reports.') ?> |
||
180 | </p> |
||
181 | </div> |
||
182 | </div> |
||
183 | |||
184 | <div class="row form-group"> |
||
185 | <label class="col-sm-3 col-form-label" for="password-1"> |
||
186 | <?= I18N::translate('Password') ?> |
||
187 | </label> |
||
188 | <div class="col-sm-9"> |
||
189 | <input class="form-control" type="password" id="password-1" name="password-1" aria-describedby="password-1-description" autocomplete="new-password"> |
||
190 | <p class="small text-muted" id="password-1-description"> |
||
191 | <?= I18N::translate('Passwords must be at least 6 characters long and are case-sensitive, so that āsecretā is different from āSECRETā.') ?> |
||
192 | <br> |
||
193 | <?= I18N::translate('Leave the password blank if you want to keep the current password.') ?> |
||
194 | </p> |
||
195 | </div> |
||
196 | </div> |
||
197 | |||
198 | <div class="row form-group"> |
||
199 | <label class="col-sm-3 col-form-label" for="password-2"> |
||
200 | <?= I18N::translate('Confirm password') ?> |
||
201 | </label> |
||
202 | <div class="col-sm-9"> |
||
203 | <input class="form-control" type="password" id="password-2" name="password-2" aria-describedby="password-2-description" autocomplete="new-password"> |
||
204 | <p class="small text-muted" id="password-2-description"> |
||
205 | <?= I18N::translate('Type your password again, to make sure you have typed it correctly.') ?> |
||
206 | </p> |
||
207 | </div> |
||
208 | </div> |
||
209 | |||
210 | <div class="row form-group"> |
||
211 | <label class="col-sm-3 col-form-label" for="language"> |
||
212 | <?= I18N::translate('Language') ?> |
||
213 | </label> |
||
214 | <div class="col-sm-9"> |
||
215 | <?= Bootstrap4::select(FunctionsEdit::optionsInstalledLanguages(), Auth::user()->getPreference('language'), ['id' => 'language', 'name' => 'language']) ?> |
||
216 | </div> |
||
217 | </div> |
||
218 | |||
219 | <div class="row form-group"> |
||
220 | <label class="col-sm-3 col-form-label" for="time-zone"> |
||
221 | <?= I18N::translate('Time zone') ?> |
||
222 | </label> |
||
223 | <div class="col-sm-9"> |
||
224 | <?= Bootstrap4::select(array_combine(DateTimeZone::listIdentifiers(), DateTimeZone::listIdentifiers()), Auth::user()->getPreference('TIMEZONE', 'UTC'), ['id' => 'time-zone', 'name', 'time-zone', 'aria-describedby' => 'time-zone-description']) ?> |
||
225 | <p class="small text-muted" id="time-zone-description"> |
||
226 | <?= I18N::translate('The time zone is required for date calculations, such as knowing todayās date.') ?> |
||
227 | </p> |
||
228 | </div> |
||
229 | </div> |
||
230 | |||
231 | <div class="row form-group"> |
||
232 | <label class="col-sm-3 col-form-label" for="email"> |
||
233 | <?= I18N::translate('Email address') ?> |
||
234 | </label> |
||
235 | <div class="col-sm-9"> |
||
236 | <input class="form-control" type="email" id="email" name="email" value="<?= e(Auth::user()->getEmail()) ?>" aria-describedby="email-description"> |
||
237 | <p class="small text-muted" id="email-description"> |
||
238 | <?= I18N::translate('This email address will be used to send password reminders, website notifications, and messages from other family members who are registered on the website.') ?> |
||
239 | </p> |
||
240 | </div> |
||
241 | </div> |
||
242 | |||
243 | <?php if (Site::getPreference('ALLOW_USER_THEMES') === '1'): ?> |
||
244 | <div class="row form-group"> |
||
245 | <label class="col-sm-3 col-form-label" for="theme"> |
||
246 | <?= I18N::translate('Theme') ?> |
||
247 | </label> |
||
248 | <div class="col-sm-9"> |
||
249 | <select class="form-control" id="theme" name="theme" aria-describedby="theme-description"> |
||
250 | <option value=""> |
||
251 | <?= e(/* I18N: default option in list of themes */ I18N::translate('<default theme>')) ?> |
||
252 | </option> |
||
253 | <?php foreach (Theme::themeNames() as $theme_id => $theme_name): ?> |
||
254 | <option value="<?= $theme_id ?>" <?= $theme_id === Auth::user()->getPreference('theme') ? 'selected' : '' ?>> |
||
0 ignored issues
–
show
|
|||
255 | <?= $theme_name ?> |
||
256 | </option> |
||
257 | <?php endforeach ?> |
||
258 | </select> |
||
259 | <p class="small text-muted" id="theme-description"> |
||
260 | <?= /* I18N: Help text for the "Default theme" site configuration setting */ I18N::translate('You can change the appearance of webtrees using āthemesā. Each theme has a different style, layout, color scheme, etc.') ?> |
||
261 | </p> |
||
262 | </div> |
||
263 | </div> |
||
264 | <?php endif ?> |
||
265 | |||
266 | <div class="row form-group"> |
||
267 | <label class="col-sm-3 col-form-label" for="contact-method"> |
||
268 | <?= I18N::translate('Contact method') ?> |
||
269 | </label> |
||
270 | <div class="col-sm-9"> |
||
271 | <?= Bootstrap4::select(FunctionsEdit::optionsContactMethods(), Auth::user()->getPreference('contactmethod'), ['id' => 'contact-method', 'name' => 'contact-method', 'aria-describedby' => 'contact-method-description']) ?> |
||
272 | <p class="small text-muted" id="contact-method-description"> |
||
273 | <?= I18N::translate('Site members can send each other messages. You can choose to how these messages are sent to you, or choose not receive them at all.') ?> |
||
274 | </p> |
||
275 | </div> |
||
276 | </div> |
||
277 | |||
278 | <fieldset class="form-group"> |
||
279 | <div class="row"> |
||
280 | <legend class="col-sm-3 col-form-label"> |
||
281 | <?= I18N::translate('Visible online') ?> |
||
282 | </legend> |
||
283 | <div class="col-sm-9"> |
||
284 | <?= Bootstrap4::checkbox(I18N::translate('Visible to other users when online'), false, ['name' => 'visible-online', 'checked' => (bool) Auth::user()->getPreference('visibleonline'), 'aria-describedby' => 'visible-online-description']) ?> |
||
0 ignored issues
–
show
array('name' => 'visible...le-online-description') is of type array<string,string|bool...describedby":"string"}> , but the function expects a array<integer,string> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
285 | <p class="small text-muted" id="visible-online-description"> |
||
286 | <?= I18N::translate('You can choose whether to appear in the list of users who are currently signed-in.') ?> |
||
287 | </p> |
||
288 | </div> |
||
289 | </div> |
||
290 | </fieldset> |
||
291 | |||
292 | <div class="row form-group"> |
||
293 | <div class="col-sm-9 offset-sm-3"> |
||
294 | <input class="btn btn-primary" type="submit" value="<?= I18N::translate('save') ?>"> |
||
295 | </div> |
||
296 | </div> |
||
297 | </form> |
||
298 | |||
299 | <?php if (!Auth::user()->getPreference('canadmin')): ?> |
||
300 | <form method="post"> |
||
301 | <input type="hidden" name="action" value="delete"> |
||
302 | <?= Filter::getCsrf() ?> |
||
303 | <div class="row form-group"> |
||
304 | <div class="col-sm-9 offset-sm-3"> |
||
305 | <input class="btn btn-danger" type="submit" value="<?= I18N::translate('Delete your account') ?>" data-confirm="<?= I18N::translate('Are you sure you want to delete ā%sā?', e(Auth::user()->getUserName())) ?>" onclick="return confirm(this.dataset.confirm);"> |
||
306 | </div> |
||
307 | </div> |
||
308 | </form> |
||
309 | <?php endif ?> |
||
310 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.