Passed
Push — master ( 590e2f...306c91 )
by
unknown
16:33 queued 08:00
created

user::shownDataLicenseMail()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 4
c 1
b 1
f 0
nc 2
nop 0
dl 0
loc 6
rs 9.4285
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 14 and the first side effect is on line 11.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/***************************************************************************
3
 *  For license information see doc/license.txt
4
 *
5
 *  Unicode Reminder メモ
6
 *
7
 *   get/set has to be commited with save
8
 *   add/remove etc. is executed instantly
9
 ***************************************************************************/
10
11
require_once __DIR__ . '/cracklib.inc.php';
12
require_once __DIR__ . '/../translate.class.php';
13
14
class user
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
Coding Style introduced by
Class name must begin with a capital letter
Loading history...
15
{
16
    public $nUserId = 0;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line before member var; 0 found
Loading history...
17
18
    public $reUser;
19
    public $reUserStat;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line before member var; 0 found
Loading history...
20
21
    /**
22
     * @param string $email
23
     *
24
     * @return null|user
0 ignored issues
show
introduced by
Invalid class name "user"
Loading history...
25
     */
26
    public static function fromEMail($email)
27
    {
28
        $userId = sql_value("SELECT `user_id` FROM `user` WHERE `email`='&1'", 0, $email);
29
        if ($userId == 0) {
30
            return null;
31
        }
32
33
        return new user($userId);
0 ignored issues
show
introduced by
Expected self::, got user::
Loading history...
34
    }
35
36
    /**
37
     * @param string $username
38
     *
39
     * @return null|user
0 ignored issues
show
introduced by
Invalid class name "user"
Loading history...
40
     */
41
    public static function fromUsername($username)
42
    {
43
        $userId = sql_value("SELECT `user_id` FROM `user` WHERE `username`='&1'", 0, $username);
44
        if ($userId == 0) {
45
            return null;
46
        }
47
48
        return new user($userId);
0 ignored issues
show
introduced by
Expected self::, got user::
Loading history...
49
    }
50
51
    public function __construct($nNewUserId = ID_NEW)
52
    {
53
        global $opt;
54
55
        $this->reUser = new rowEditor('user');
56
        $this->reUser->addPKInt('user_id', null, false, RE_INSERT_AUTOINCREMENT);
57
        $this->reUser->addString('username', '', false);
58
        $this->reUser->addString('password', null, true);
59
        $this->reUser->addString('email', null, true);
60
        $this->reUser->addString('email_problems', 0, false);
61
        $this->reUser->addDate('last_email_problem', null, true);
62
        $this->reUser->addInt('mailing_problems', 0, false);
63
        $this->reUser->addFloat('latitude', 0, false);
64
        $this->reUser->addFloat('longitude', 0, false);
65
        $this->reUser->addDate('last_modified', time(), true, RE_INSERT_IGNORE);
66
        $this->reUser->addBoolean('is_active_flag', false, false);
67
        $this->reUser->addString('last_name', '', false);
68
        $this->reUser->addString('first_name', '', false);
69
        $this->reUser->addString('country', null, true);
70
        $this->reUser->addBoolean('accept_mailing', 1, false);
71
        $this->reUser->addBoolean('pmr_flag', false, false);
72
        $this->reUser->addString('new_pw_code', null, true);
73
        $this->reUser->addDate('new_pw_date', null, true);
74
        $this->reUser->addDate('date_created', time(), true, RE_INSERT_IGNORE);
75
        $this->reUser->addString('new_email_code', null, true);
76
        $this->reUser->addDate('new_email_date', null, true);
77
        $this->reUser->addString('new_email', null, true);
78
        $this->reUser->addString('uuid', '', false, RE_INSERT_AUTOUUID);
79
        $this->reUser->addBoolean('permanent_login_flag', false, false);
80
        $this->reUser->addInt('watchmail_mode', 1, false);
81
        $this->reUser->addInt('watchmail_hour', 0, false);
82
        $this->reUser->addDate('watchmail_nextmail', time(), false);
83
        $this->reUser->addInt('watchmail_day', 0, false);
84
        $this->reUser->addString('activation_code', '', false);
85
        $this->reUser->addBoolean('no_htmledit_flag', false, false);
86
        $this->reUser->addBoolean('usermail_send_addr', false, false);
87
        $this->reUser->addInt('notify_radius', 0, false);
88
        $this->reUser->addInt('notify_oconly', 1, false);
89
        $this->reUser->addString('language', null, true);
90
        $this->reUser->addInt('admin', 0, false);
91
        $this->reUser->addInt('data_license', $opt['logic']['license']['newusers'], false);
92
        $this->reUser->addInt('node', 0, false);
93
94
        $this->reUserStat = new rowEditor('stat_user');
95
        $this->reUserStat->addPKInt('user_id', null, false, RE_INSERT_AUTOINCREMENT);
96
        $this->reUserStat->addInt('found', 0, false);
97
        $this->reUserStat->addInt('notfound', 0, false);
98
        $this->reUserStat->addInt('note', 0, false);
99
        $this->reUserStat->addInt('hidden', 0, false);
100
101
        $this->nUserId = $nNewUserId + 0;
102
103
        if ($nNewUserId == ID_NEW) {
104
            $this->reUser->addNew(null);
105
        } else {
106
            $this->reUser->load($this->nUserId);
107
            $this->reUserStat->load($this->nUserId);
108
        }
109
    }
110
111
    public function exist()
112
    {
113
        return $this->reUser->exist();
114
    }
115
116
    /**
117
     * @param string $username
118
     *
119
     * @return bool
120
     */
121
    public static function existUsername($username)
122
    {
123
        return (sql_value("SELECT COUNT(*) FROM `user` WHERE `username`='&1'", 0, $username) != 0);
0 ignored issues
show
introduced by
Language constructs must not be followed by parenthesesis.
Loading history...
124
    }
125
126
    /**
127
     * @param string $email
128
     *
129
     * @return bool
130
     */
131
    public static function existEMail($email)
132
    {
133
        return (sql_value("SELECT COUNT(*) FROM `user` WHERE `email`='&1'", 0, $email) != 0);
0 ignored issues
show
introduced by
Language constructs must not be followed by parenthesesis.
Loading history...
134
    }
135
136
    public function getUserId()
137
    {
138
        return $this->nUserId;
139
    }
140
141
    public function getUsername()
142
    {
143
        return $this->reUser->getValue('username');
144
    }
145
146 View Code Duplication
    public function setUsername($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
    {
148
        if (!mb_ereg_match(REGEX_USERNAME, $value)) {
149
            return false;
150
        }
151
152
        if (is_valid_email_address($value)) {
153
            return false;
154
        }
155
156
        return $this->reUser->setValue('username', $value);
157
    }
158
159
    public function getUsernameChanged()
160
    {
161
        return $this->reUser->getChanged('username');
162
    }
163
164
    public function getEMail()
165
    {
166
        return $this->reUser->getValue('email');
167
    }
168
169
    public function setEMail($value)
170
    {
171
        if (!is_valid_email_address($value)) {
172
            return false;
173
        }
174
175
        return $this->reUser->setValue('email', $value);
176
    }
177
178
    public function getPassword()
179
    {
180
        return $this->reUser->getValue('password');
181
    }
182
183
    public function setPassword($password)
184
    {
185
        if (!mb_ereg_match(REGEX_PASSWORD, $password)) {
186
            return false;
187
        }
188
189
        if (cracklib_checkpw(
190
            $password,
191
            [
192
                'open',
193
                'caching',
194
                'cache',
195
                $this->getUsername(),
196
                $this->getFirstName(),
197
                $this->getLastName()
198
            ]
199
        ) === false) {
200
            return false;
201
        }
202
203
        $encryptedPassword = crypt::encryptPassword($password);
204
205
        return $this->reUser->setValue('password', $encryptedPassword);
206
    }
207
208
    public function getFirstName()
209
    {
210
        return $this->reUser->getValue('first_name');
211
    }
212
213
    public function setFirstName($value)
214
    {
215
        if ($value != '') {
216
            if (!mb_ereg_match(REGEX_FIRST_NAME, $value)) {
217
                return false;
218
            }
219
        }
220
221
        return $this->reUser->setValue('first_name', $value);
222
    }
223
224
    public function getLastName()
225
    {
226
        return $this->reUser->getValue('last_name');
227
    }
228
229
    public function setLastName($value)
230
    {
231
        if ($value != '') {
232
            if (!mb_ereg_match(REGEX_LAST_NAME, $value)) {
233
                return false;
234
            }
235
        }
236
237
        return $this->reUser->setValue('last_name', $value);
238
    }
239
240
    public function getCountry()
241
    {
242
        return countriesList::getCountryLocaleName($this->reUser->getValue('country'));
243
    }
244
245
    public function getCountryCode()
246
    {
247
        return $this->reUser->getValue('country');
248
    }
249
250 View Code Duplication
    public function setCountryCode($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
251
    {
252
        if ($value !== null && (sql_value("SELECT COUNT(*) FROM countries WHERE short='&1'", 0, $value) == 0)) {
253
            return false;
254
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
255
            return $this->reUser->setValue('country', $value);
256
        }
257
    }
258
259
    public function getLanguageCode()
260
    {
261
        return $this->reUser->getValue('language');
262
    }
263
264 View Code Duplication
    public function setLanguageCode($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
265
    {
266
        if ($value !== null && (sql_value("SELECT COUNT(*) FROM languages WHERE short='&1'", 0, $value) == 0)) {
267
            return false;
268
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
269
            return $this->reUser->setValue('language', $value);
270
        }
271
    }
272
273
    public function getLatitude()
274
    {
275
        return $this->reUser->getValue('latitude');
276
    }
277
278 View Code Duplication
    public function setLatitude($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
279
    {
280
        if (($value + 0) > 90 || ($value + 0) < - 90) {
0 ignored issues
show
introduced by
A unary operator statement must not be followed by a space
Loading history...
281
            return false;
282
        }
283
284
        return $this->reUser->setValue('latitude', $value + 0);
285
    }
286
287
    public function getLongitude()
288
    {
289
        return $this->reUser->getValue('longitude');
290
    }
291
292 View Code Duplication
    public function setLongitude($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
293
    {
294
        if (($value + 0) > 180 || ($value + 0) < - 180) {
0 ignored issues
show
introduced by
A unary operator statement must not be followed by a space
Loading history...
295
            return false;
296
        }
297
298
        return $this->reUser->setValue('longitude', $value + 0);
299
    }
300
301
    public function getNotifyRadius()
302
    {
303
        return $this->reUser->getValue('notify_radius');
304
    }
305
306 View Code Duplication
    public function setNotifyRadius($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
307
    {
308
        if (($value + 0) < 0 || ($value + 0) > 150) {
309
            return false;
310
        }
311
312
        return $this->reUser->setValue('notify_radius', $value + 0);
313
    }
314
315
    public function getNotifyOconly()
316
    {
317
        return $this->reUser->getValue('notify_oconly') != 0;
318
    }
319
320
    public function setNotifyOconly($value)
321
    {
322
        return $this->reUser->setValue('notify_oconly', $value ? 1 : 0);
323
    }
324
325
    public function getPermanentLogin()
326
    {
327
        return $this->reUser->getValue('permanent_login_flag');
328
    }
329
330
    public function setPermanentLogin($value)
331
    {
332
        return $this->reUser->setValue('permanent_login_flag', $value);
333
    }
334
335
    public function getAccMailing()
336
    {
337
        return $this->reUser->getValue('accept_mailing');
338
    }
339
340
    public function setAccMailing($value)
341
    {
342
        return $this->reUser->setValue('accept_mailing', $value);
343
    }
344
345
    public function getUsermailSendAddress()
346
    {
347
        return $this->reUser->getValue('usermail_send_addr');
348
    }
349
350
    public function setUsermailSendAddress($value)
351
    {
352
        return $this->reUser->setValue('usermail_send_addr', $value);
353
    }
354
355
    public function getNoHTMLEditor()
356
    {
357
        return $this->reUser->getValue('no_htmledit_flag');
358
    }
359
360
    public function setNoHTMLEditor($value)
361
    {
362
        return $this->reUser->setValue('no_htmledit_flag', $value);
363
    }
364
365
    public function getUsePMR()
366
    {
367
        return $this->reUser->getValue('pmr_flag');
368
    }
369
370
    public function setUsePMR($value)
371
    {
372
        return $this->reUser->setValue('pmr_flag', $value);
373
    }
374
375
    public function getIsActive()
376
    {
377
        return $this->reUser->getValue('is_active_flag');
378
    }
379
380
    public function setIsActive($value)
381
    {
382
        return $this->reUser->setValue('is_active_flag', $value);
383
    }
384
385
    public function getActivationCode()
386
    {
387
        return $this->reUser->getValue('activation_code');
388
    }
389
390
    public function setActivationCode($value)
391
    {
392
        return $this->reUser->setValue('activation_code', $value);
393
    }
394
395
    public function getNewPWCode()
396
    {
397
        return $this->reUser->getValue('new_pw_code');
398
    }
399
400
    public function setNewPWCode($value)
401
    {
402
        return $this->reUser->setValue('new_pw_code', $value);
403
    }
404
405
    public function getNewPWDate()
406
    {
407
        return $this->reUser->getValue('new_pw_date');
408
    }
409
410
    public function setNewPWDate($value)
411
    {
412
        return $this->reUser->setValue('new_pw_date', $value);
413
    }
414
415
    public function getNewEMailCode()
416
    {
417
        return $this->reUser->getValue('new_email_code');
418
    }
419
420
    public function setNewEMailCode($value)
421
    {
422
        return $this->reUser->setValue('new_email_code', $value);
423
    }
424
425
    public function getNewEMailDate()
426
    {
427
        return $this->reUser->getValue('new_email_date');
428
    }
429
430
    public function setNewEMailDate($value)
431
    {
432
        return $this->reUser->setValue('new_email_date', $value);
433
    }
434
435
    public function getNewEMail()
436
    {
437
        return $this->reUser->getValue('new_email');
438
    }
439
440 View Code Duplication
    public function setNewEMail($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
441
    {
442
        if ($value !== null) {
443
            if (!is_valid_email_address($value)) {
444
                return false;
445
            }
446
447
            if (user::existEMail($value)) {
0 ignored issues
show
introduced by
Expected self::, got user::
Loading history...
448
                return false;
449
            }
450
        }
451
452
        return $this->reUser->setValue('new_email', $value);
453
    }
454
455
    public function getWatchmailMode()
456
    {
457
        return $this->reUser->getValue('watchmail_mode');
458
    }
459
460
    public function setWatchmailMode($value)
461
    {
462
        $this->setWatchmailNext('0000-00-00 00:00:00');
463
464
        return $this->reUser->setValue('watchmail_mode', $value);
465
    }
466
467
    public function getWatchmailHour()
468
    {
469
        return $this->reUser->getValue('watchmail_hour');
470
    }
471
472
    public function setWatchmailHour($value)
473
    {
474
        $this->setWatchmailNext('0000-00-00 00:00:00');
475
476
        return $this->reUser->setValue('watchmail_hour', $value);
477
    }
478
479
    public function getWatchmailDay()
480
    {
481
        return $this->reUser->getValue('watchmail_day');
482
    }
483
484
    public function setWatchmailDay($value)
485
    {
486
        $this->setWatchmailNext('0000-00-00 00:00:00');
487
488
        return $this->reUser->setValue('watchmail_day', $value);
489
    }
490
491
    public function getWatchmailNext()
492
    {
493
        return $this->reUser->getValue('watchmail_nextmail');
494
    }
495
496
    public function setWatchmailNext($value)
497
    {
498
        return $this->reUser->setValue('watchmail_nextmail', $value);
499
    }
500
501
    public function getStatFound()
502
    {
503
        if ($this->reUserStat->exist()) {
504
            return $this->reUserStat->getValue('found');
505
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
506
            return 0;
507
        }
508
    }
509
510
    public function getStatNotFound()
511
    {
512
        if ($this->reUserStat->exist()) {
513
            return $this->reUserStat->getValue('notfound');
514
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
515
            return 0;
516
        }
517
    }
518
519
    public function getStatNote()
520
    {
521
        if ($this->reUserStat->exist()) {
522
            return $this->reUserStat->getValue('note');
523
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
524
            return 0;
525
        }
526
    }
527
528
    public function getStatHidden()
529
    {
530
        if ($this->reUserStat->exist()) {
531
            return $this->reUserStat->getValue('hidden');
532
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
533
            return 0;
534
        }
535
    }
536
537
    public function getDateRegistered()
538
    {
539
        return $this->reUser->getValue('date_created');
540
    }
541
542
    public function getUUID()
543
    {
544
        return $this->reUser->getValue('uuid');
545
    }
546
547
    public function getLastModified()
548
    {
549
        return $this->reUser->getValue('last_modified');
550
    }
551
552
    public function getDateCreated()
553
    {
554
        return $this->reUser->getValue('date_created');
555
    }
556
557
    public function getAdmin()
558
    {
559
        return $this->reUser->getValue('admin');
560
    }
561
562
    public function getNode()
563
    {
564
        return $this->reUser->getValue('node');
565
    }
566
567
    public function setNode($value)
568
    {
569
        return $this->reUser->setValue('node', $value);
570
    }
571
572
    public function getAnyChanged()
573
    {
574
        return $this->reUser->getAnyChanged();
575
    }
576
577
    // return if successfull (with insert)
578
    public function save()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
579
    {
580
        $bNeedStatpicClear = $this->reUser->getChanged('username');
0 ignored issues
show
Unused Code introduced by
$bNeedStatpicClear is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
581
582
        sql_slave_exclude();
583
        if ($this->reUser->save()) {
584
            if ($this->getUserId() == ID_NEW) {
585
                $this->nUserId = $this->reUser->getValue('user_id');
586
            }
587
            $this->getStatpic()->invalidate();
588
589
            return true;
590
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
591
            return false;
592
        }
593
    }
594
595
    public function getStatpic()
596
    {
597
        return new statpic($this->nUserId);
598
    }
599
600
    public static function createCode()
601
    {
602
        return mb_strtoupper(mb_substr(md5(uniqid('')), 0, 13));
603
    }
604
605
    public function requestNewPWCode()
606
    {
607
        global $translate;
608
609
        if (!$this->exist()) {
610
            return false;
611
        }
612
613
        $email = $this->getEMail();
614
        if ($email === null || $email == '') {
615
            return false;
616
        }
617
618
        if (!$this->getIsActive()) {
619
            return false;
620
        }
621
622
        $this->setNewPWCode($this->createCode());
623
        if (!$this->reUser->saveField('new_pw_code')) {
624
            return false;
625
        }
626
627
        $this->setNewPWDate(time());
628
        if (!$this->reUser->saveField('new_pw_date')) {
629
            return false;
630
        }
631
632
        // send confirmation
633
        $mail = new mail();
634
        $mail->name = 'newpw';
635
        $mail->to = $email;
636
        $mail->subject = $translate->t('New password code', '', basename(__FILE__), __LINE__);
637
        $mail->assign('code', $this->getNewPWCode());
638
        $mail->send();
639
640
        return true;
641
    }
642
643
    public function clearNewPWCode()
644
    {
645
        $this->setNewPWCode(null);
646
        if (!$this->reUser->saveField('new_pw_code')) {
647
            return false;
648
        }
649
650
        $this->setNewPWDate(null);
651
        if (!$this->reUser->saveField('new_pw_date')) {
652
            return false;
653
        }
654
655
        return true;
656
    }
657
658
    public function requestNewEMail($email)
659
    {
660
        global $translate;
661
662
        if (!$this->exist()) {
663
            return false;
664
        }
665
666
        if (mb_strtolower($this->getEMail()) == mb_strtolower($email)) {
667
            return false;
668
        }
669
670
        if ($this->getEMail() === null || $this->getEMail() == '') {
671
            return false;
672
        }
673
674
        if (!$this->getIsActive()) {
675
            return false;
676
        }
677
678
        $this->setNewEMailCode($this->createCode());
679
        if (!$this->reUser->saveField('new_email_code')) {
680
            return false;
681
        }
682
683
        $this->setNewEMailDate(time());
684
        if (!$this->reUser->saveField('new_email_date')) {
685
            return false;
686
        }
687
688
        $this->setNewEMail($email);
689
        if (!$this->reUser->saveField('new_email')) {
690
            return false;
691
        }
692
693
        // send confirmation
694
        $mail = new mail();
695
        $mail->name = 'newemail';
696
        $mail->to = $email;
697
        $mail->subject = $translate->t('New email code', '', basename(__FILE__), __LINE__);
698
        $mail->assign('code', $this->getNewEMailCode());
699
        $mail->send();
700
701
        return true;
702
    }
703
704
    public function clearNewEMailCode()
705
    {
706
        $this->setNewEMailCode(null);
707
        if (!$this->reUser->saveField('new_email_code')) {
708
            return false;
709
        }
710
711
        $this->setNewEMailDate(null);
712
        if (!$this->reUser->saveField('new_email_date')) {
713
            return false;
714
        }
715
716
        $this->setNewEMail(null);
717
        if (!$this->reUser->saveField('new_email')) {
718
            return false;
719
        }
720
721
        return true;
722
    }
723
724
    public function remindEMail()
725
    {
726
        global $translate;
727
728
        if (!$this->exist()) {
729
            return false;
730
        }
731
732
        $email = $this->getEMail();
733
        if ($email === null || $email == '') {
734
            return false;
735
        }
736
737
        if (!$this->getIsActive()) {
738
            return false;
739
        }
740
741
        // send confirmation
742
        $mail = new mail();
743
        $mail->name = 'remindemail';
744
        $mail->to = $email;
745
        $mail->subject = $translate->t('Reminder to your E-Mail-Address', '', basename(__FILE__), __LINE__);
746
        $mail->assign('username', $this->getUsername());
747
        $mail->assign('email', $email);
748
        $mail->send();
749
750
        return true;
751
    }
752
753
    public function sendRegistrationCode()
754
    {
755
        global $opt, $translate;
756
757
        $countriesList = new countriesList();
758
759
        $mail = new mail();
760
        $mail->name = 'register';
761
        $mail->to = $this->getEMail();
762
        $mail->subject = $translate->t('Registration confirmation', '', basename(__FILE__), __LINE__);
763
        $mail->assign('domain', $opt['page']['domain']);
764
        $mail->assign('activation_page', $opt['page']['absolute_url'] . 'activation.php');
765
        $mail->assign('short_activation_page', $opt['page']['absolute_url'] . 'a.php');
766
        $mail->assign('username', $this->getUsername());
767
        $mail->assign('userid', $this->getUserId());
768
        $mail->assign('last_name', $this->getLastName());
769
        $mail->assign('first_name', $this->getFirstName());
770
        $mail->assign('country', $countriesList->getCountryLocaleName($this->getCountryCode()));
771
        $mail->assign('code', $this->getActivationCode());
772
773
        if ($mail->send()) {
774
            return true;
775
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
776
            return false;
777
        }
778
    }
779
780
    public function sendEMail($nFromUserId, $sSubject, $sText, $bSendEMailAddress)
0 ignored issues
show
Coding Style introduced by
sendEMail uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
781
    {
782
        global $opt, $translate;
783
784
        if ($this->exist() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
785
            return false;
786
        }
787
788
        if ($this->getIsActive() == false) {
789
            return false;
790
        }
791
792
        if ($this->getEMail() === null || $this->getEMail() == '') {
793
            return false;
794
        }
795
796
        if ($sSubject == '') {
797
            return false;
798
        }
799
800
        if ($sText == '') {
801
            return false;
802
        }
803
804
        if (mb_strpos($sSubject, "\n") !== false) {
805
            $sSubject = mb_substr($sSubject, 0, mb_strpos($sSubject, "\n"));
806
        }
807
        $sSubject = mb_trim($sSubject);
808
809
        $fromUser = new user($nFromUserId);
0 ignored issues
show
introduced by
Expected self::, got user::
Loading history...
810
        if ($fromUser->exist() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
811
            return false;
812
        }
813
        if ($fromUser->getIsActive() == false) {
814
            return false;
815
        }
816
        if ($fromUser->getEMail() === null || $fromUser->getEMail() == '') {
817
            return false;
818
        }
819
820
        $language = $this->getLanguageCode();
821
        if (!$language) {
822
            $language = $opt['template']['locale'];
823
        }
824
825
        // ok, we can send ...
826
        $mail = new mail();
827
        $mail->name = 'usercontactmail';
828
        $mail->to = $this->getEMail();
829
        $mail->recipient_locale = $this->getLanguageCode();
830
831
        $mail->from = $opt['mail']['usermail'];
832
833
        if ($bSendEMailAddress == true) {
834
            $mail->replyTo = $fromUser->getEMail();
835
            $mail->returnPath = $fromUser->getEMail();
836
        }
837
838
        $mail->subject = $translate->t('E-Mail from', '', basename(__FILE__), __LINE__, '', 1, $language) . ' ' . $fromUser->getUsername() . ': ' . $sSubject;
839
        $mail->assign('usersubject', $sSubject);
840
        $mail->assign('text', $sText);
841
        $mail->assign('username', $this->getUsername());
842
        $mail->assign('sendemailaddress', $bSendEMailAddress);
843
        $mail->assign('fromusername', $fromUser->getUsername());
844
        $mail->assign('fromuserid', $fromUser->getUserId());
845
        $mail->assign('fromuseremail', $fromUser->getEMail());
846
847
        if ($mail->send($opt['page']['default_absolute_url'])) {
848
            // send copy to fromUser
849
            $mail->assign('copy', true);
850
            $mail->to = $fromUser->getEMail();
851
            $mail->send();
852
853
            // log
854
            sql(
855
                "INSERT INTO `email_user` (`ipaddress`, `from_user_id`, `from_email`, `to_user_id`, `to_email`)
856
                 VALUES ('&1', '&2', '&3', '&4', '&5')",
857
                $_SERVER["REMOTE_ADDR"],
858
                $fromUser->getUserId(),
859
                $fromUser->getEMail(),
860
                $this->getUserId(),
861
                $this->getEMail()
862
            );
863
864
            return true;
865
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
866
            return false;
867
        }
868
    }
869
870 View Code Duplication
    public function canDisable()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
871
    {
872
        global $login;
873
        $login->verify();
874
875
        if ($login->userid != $this->nUserId && ($login->admin & ADMIN_USER) != ADMIN_USER) {
876
            return false;
877
        }
878
879
        if ($this->getIsActive() != 0) {
880
            return true;
881
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
882
            return false;
883
        }
884
    }
885
886
    public function disable()
887
    {
888
        global $login, $translate;
889
890
        if ($this->canDisable() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
891
            return false;
892
        }
893
894
        // write old record to log
895
        $backup = array();
896
        $backup['username'] = $this->getUsername();
897
        $backup['email'] = $this->getEMail();
898
        $backup['last_name'] = $this->getLastName();
899
        $backup['first_name'] = $this->getFirstName();
900
        $backup['country'] = $this->getCountryCode();
901
        $backup['latitude'] = $this->getLatitude();
902
        $backup['longitude'] = $this->getLongitude();
903
904
        sql(
905
            "INSERT INTO `logentries` (`module`, `eventid`, `userid`, `objectid1`, `objectid2`, `logtext`, `details`)
906
             VALUES ('user', 6, '&1', '&2', '&3', '&4', '&5')",
907
            $login->userid,
908
            $this->nUserId,
909
            0,
910
            'User ' . sql_escape($this->getUsername()) . ' disabled',
911
            serialize($backup)
912
        );
913
914
        // delete private and system data
915
        sql(
916
            "UPDATE `user` SET `password`=NULL, `email`=NULL, `last_name`='', `first_name`='',
917
                               `country`=NULL, `latitude`=0, `longitude`=0, `is_active_flag`=0, `activation_code`='',
918
                               `new_pw_code`=NULL, `new_pw_date`=NULL, `new_email`=NULL, `new_email_code`=NULL,
919
                               `new_email_date`=NULL, `email_problems`=0, `first_email_problem`=NULL,
920
                               `last_email_problem`=NULL
921
             WHERE `user_id`='&1'",
922
            $this->nUserId
923
        );
924
925
        // non-private data which need not to be deleted:
926
        //
927
        //   - Statpic and profile description texts - published under the data license
928
        //   - profile settings: accept_mailing, pmr_flag, permanent_login_flag, notify_radius,
929
        //                       user_options entries
930
        //   - watch and ignore lists
931
        //   - adoptions: may still be executed if offered to another user
932
933
        // Handling of cache lists is unclear. They may be deleted by the Opencaching team
934
        // if not considered useful.
935
936
        // lock the user's caches
937
        $error = false;
938
        $rs = sql("SELECT `cache_id` FROM `caches` WHERE `user_id`='&1' AND `status` IN (1,2,3)", $this->nUserId);
939
        while (($rCache = sql_fetch_assoc($rs)) && !$error) {
940
            $error = true;
941
            $cache = new cache($rCache['cache_id']);
942
            if ($cache->setStatus(6) && $cache->save()) {
943
                $log = cachelog::createNew($rCache['cache_id'], $login->userid, true);
0 ignored issues
show
Unused Code introduced by
The call to cachelog::createNew() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
944
                if ($log !== false) {
945
                    $log->setType(cachelog::LOGTYPE_LOCKED, true);
946
                    $log->setOcTeamComment(true);
947
                    $log->setDate(date('Y-m-d'));
948
                    $log->setText($translate->t(
949
                        'The user account has been disabled.',
950
                        '',
951
                        '',
952
                        0,
953
                        '',
954
                        1,
955
                        $cache->getDefaultDescLanguage()
956
                    ));
957
                    $log->setTextHtml(false);
958
                    if ($log->save()) {
959
                        $error = false;
960
                    }
961
                }
962
            }
963
            echo "\n";
964
        }
965
        sql_free_result($rs);
966
967
        return !$error;
968
    }
969
970
971 View Code Duplication
    public function canDisableDueLicense()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
972
    {
973
        global $login;
974
        $login->verify();
975
976
        if ($login->userid != $this->nUserId && ($login->admin & ADMIN_USER) != ADMIN_USER) {
977
            return false;
978
        } else {
0 ignored issues
show
introduced by
Unneeded T_ELSE detected.
Loading history...
979
            return true;
980
        }
981
    }
982
983
    /**
0 ignored issues
show
Coding Style Documentation introduced by
Doc comment for parameter "$old_disabled" missing
Loading history...
984
     * disables user (if not disabled), removes all licensed content from db and
985
     * replaces every picture with a dummy one
986
     *
987
     * @return string error message, if anything went wrong, true otherwise
988
     *
989
     * old_disabled: the user was disabled already before license transition
990
     *               and therefore could not accept/decline the license
991
     */
992
    public function disduelicense($old_disabled = false)
0 ignored issues
show
introduced by
Doc Block params do not match method signature
Loading history...
993
    {
994
995
        // get translation-object
996
        global $translate;
997
998
        // check if disabled, disable if not
999
        if (!$this->canDisableDueLicense()) {
1000
            return 'this user must not be disabled';
1001
        }
1002
1003
        if (!$old_disabled) {
1004
            if ($this->canDisable()) {
1005
                if (!$this->disable()) {
1006
                    return 'disable user failed';
1007
                }
1008
            }
1009
        }
1010
1011
        // remember that data license was declined
1012
        sql(
1013
            "UPDATE user SET data_license='&2' WHERE user_id='&1'",
1014
            $this->getUserId(),
1015
            $old_disabled ? NEW_DATA_LICENSE_PASSIVELY_DECLINED : NEW_DATA_LICENSE_ACTIVELY_DECLINED
1016
        );
1017
1018
        /*
1019
         * set all cache_desc and hint to '', save old texts
1020
         */
1021
        // check if there are caches
1022
        $num_caches = sql_value(
1023
            "SELECT COUNT(*) FROM `caches` WHERE `user_id`='&1'",
1024
            0,
1025
            $this->getUserId()
1026
        );
1027
        if ($num_caches > 0) {
1028
            $cache_descs = array();
1029
            $rs = sql(
1030
                "SELECT `id`, `language`, `desc`, `hint` " .
1031
                "FROM `cache_desc`,`caches` " .
1032
                "WHERE `caches`.`cache_id`=`cache_desc`.`cache_id` " .
1033
                "AND `caches`.`user_id`='&1'",
1034
                $this->getUserId()
1035
            );
1036
            while ($cache_desc = sql_fetch_array($rs, MYSQL_ASSOC)) {
0 ignored issues
show
Unused Code introduced by
The call to sql_fetch_array() has too many arguments starting with MYSQL_ASSOC.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1037
                $cache_descs[] = $cache_desc;
1038
            }
1039
            sql_free_result($rs);
1040
1041
            // walk through cache_descs and set message for each language
1042
            foreach ($cache_descs as $desc) {
1043
                // save text - added 2013/03/18 to be enable restoring data on reactivation
1044
                // of accounts that were disabled before license transition
1045 View Code Duplication
                if ($desc['desc'] != "") {
1046
                    sql(
1047
                        "INSERT IGNORE INTO `saved_texts` (`object_type`, `object_id`, `subtype`, `text`)
1048
                         VALUES ('&1', '&2', '&3', '&4')",
1049
                        OBJECT_CACHEDESC,
1050
                        $desc['id'],
1051
                        1,
1052
                        $desc['desc']
1053
                    );
1054
                }
1055 View Code Duplication
                if ($desc['hint'] != "") {
1056
                    sql(
1057
                        "INSERT IGNORE INTO `saved_texts` (`object_type`, `object_id`, `subtype`, `text`)
1058
                         VALUES ('&1', '&2', '&3', '&4')",
1059
                        OBJECT_CACHEDESC,
1060
                        $desc['id'],
1061
                        2,
1062
                        $desc['hint']
1063
                    );
1064
                }
1065
1066
                if ($desc['desc'] != "") {
1067
                    if ($old_disabled) {
1068
                        $descmsg = $translate->t("cache description was removed because the owner's account was inactive when the <a href='articles.php?page=impressum#datalicense'>new content license</a> was launched", '', basename(__FILE__), __LINE__, '', 1, $desc['language']);
1069
                    } else {
1070
                        $descmsg = $translate->t('cache description was removed because owner declined content license', '', basename(__FILE__), __LINE__, '', 1, $desc['language']);
1071
                    }
1072
                } else {
1073
                    $descmsg = "";
1074
                }
1075
1076
                sql(
1077
                    "UPDATE `cache_desc` " .
1078
                    "SET `desc`='&1',`hint`='&2' " .
1079
                    "WHERE `id`='&3'",
1080
                    "<em>" . $descmsg . "</em>",
1081
                    '',
1082
                    $desc['id']
1083
                );
1084
            }
1085
1086
            // replace pictures
1087
            $errmesg = $this->replace_pictures(OBJECT_CACHE);
1088
            if ($errmesg !== true) {
1089
                return "removing cache pictures: $errmesg";
1090
            }
1091
        }
1092
1093
        // delete additional waypoint texts
1094
        $rs = sql(
1095
            "SELECT `id`, `description` FROM `coordinates`
1096
             WHERE `type`='&1'
1097
             AND `cache_id` IN (SELECT `cache_id` FROM `caches` WHERE `user_id`='&2')",
1098
            COORDINATE_WAYPOINT,
1099
            $this->getUserId()
1100
        );
1101
        while ($wp = sql_fetch_assoc($rs)) {
1102
            if ($wp['description'] != "") {
1103
                sql(
1104
                    "INSERT IGNORE INTO `saved_texts` (`object_type`, `object_id`, `subtype`, `text`)
1105
                     VALUES ('&1', '&2', '&3', '&4')",
1106
                    OBJECT_WAYPOINT,
1107
                    $wp['id'],
1108
                    0,
1109
                    $wp['description']
1110
                );
1111
            }
1112
1113
            sql("UPDATE `coordinates` SET `description`='' WHERE `id`='&1'", $wp['id']);
1114
        }
1115
        sql_free_result($rs);
1116
1117
        /*
1118
         * set all cache_logs '', save old texts and delete pictures
1119
         */
1120
        $rs = sql("SELECT `id`, `text` FROM `cache_logs` WHERE `user_id`='&1'", $this->getUserId());
1121
        while ($log = sql_fetch_array($rs, MYSQL_ASSOC)) {
0 ignored issues
show
Unused Code introduced by
The call to sql_fetch_array() has too many arguments starting with MYSQL_ASSOC.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1122
            // save text - added 2013/03/18 to be enable restoring data on reactivation
1123
            // of accounts that were disabled before license transition
1124
            sql(
1125
                "INSERT IGNORE INTO `saved_texts` (`object_type`, `object_id`, `subtype`, `text`)
1126
                 VALUES ('&1', '&2', '&3', '&4')",
1127
                OBJECT_CACHELOG,
1128
                $log['id'],
1129
                0,
1130
                $log['text']
1131
            );
1132
1133
            // set text ''
1134
            sql("UPDATE `cache_logs` SET `text`='' WHERE `id`='&1'", $log['id']);
1135
1136
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1137
            // replace pictures
1138
            $errmesg = $this->replace_pictures(OBJECT_CACHELOG);
1139
            if ($errmesg !== true)
1140
                return "removing log pictures: $errmesg";
1141
            */
1142
1143
            // delete log pictures
1144
            $rsp = sql(
1145
                "SELECT `id` FROM `pictures`
1146
                 WHERE `object_type`='&1' AND `object_id`='&2'",
1147
                OBJECT_CACHELOG,
1148
                $log['id']
1149
            );
1150
            while ($pic = sql_fetch_assoc($rsp)) {
1151
                $picture = new picture($pic['id']);
1152
                $picture->delete();
1153
            }
1154
            sql_free_result($rsp);
1155
        }
1156
        sql_free_result($rs);
1157
1158
        // discard achived logs' texts
1159
        sql("UPDATE `cache_logs_archived` SET `text`='' WHERE `user_id`='&1'", $this->getUserId());
1160
1161
        // success
1162
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type documented by user::disduelicense of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
1163
    }
1164
1165
    /**
1166
     * replaces all pictures of $this-user with a dummy for the given object-type
1167
     *
1168
     * @param int $object_type object_types-id from table object_types
0 ignored issues
show
Coding Style introduced by
Expected "integer" but found "int" for parameter type
Loading history...
Coding Style introduced by
Parameter comment must start with a capital letter
Loading history...
Coding Style Documentation introduced by
Parameter comment must end with a full stop
Loading history...
1169
     *
1170
     * @return bool true, if replacement worked, false otherwise
1171
     */
1172
    public function replace_pictures($object_type)
0 ignored issues
show
Coding Style introduced by
Method name "user::replace_pictures" is not in camel caps format
Loading history...
1173
    {
1174
        // get optionsarray
1175
        global $opt;
1176
1177
        // load bmp-support
1178
        require_once $opt['rootpath'] . 'lib2/imagebmp.inc.php';
1179
1180
        // paths cleared by trailing '/'
1181
        if (substr($opt['logic']['pictures']['dir'], - 1) != '/') {
0 ignored issues
show
introduced by
A unary operator statement must not be followed by a space
Loading history...
1182
            $picpath = $opt['logic']['pictures']['dir'];
1183
        } else {
1184
            $picpath = substr($opt['logic']['pictures']['dir'], 0, - 1);
0 ignored issues
show
introduced by
A unary operator statement must not be followed by a space
Loading history...
1185
        }
1186
1187
        $thumbpath = "$picpath/thumbs";
1188
1189
        $pdummy = isset($opt['logic']['pictures']['dummy']);
1190 View Code Duplication
        if ($pdummy && isset($opt['logic']['pictures']['dummy']['bgcolor']) && is_array($opt['logic']['pictures']['dummy']['bgcolor'])) {
1191
            $dummybg = $opt['logic']['pictures']['dummy']['bgcolor'];
1192
        } else {
1193
            $dummybg = [
1194
                255,
1195
                255,
1196
                255
1197
            ];
1198
        }
1199
1200 View Code Duplication
        if ($pdummy && isset($opt['logic']['pictures']['dummy']['text'])) {
1201
            $dummytext = $opt['logic']['pictures']['dummy']['text'];
1202
        } else {
1203
            $dummytext = '';
1204
        }
1205
1206 View Code Duplication
        if ($pdummy && isset($opt['logic']['pictures']['dummy']['textcolor']) && is_array($opt['logic']['pictures']['dummy']['textcolor'])) {
1207
            $dummytextcolor = $opt['logic']['pictures']['dummy']['textcolor'];
1208
        } else {
1209
            $dummytextcolor = array(
1210
                0,
1211
                0,
1212
                0
1213
            );
1214
        }
1215
1216
        $tmh = 0;
0 ignored issues
show
Unused Code introduced by
$tmh is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1217
        $tmw = 0;
0 ignored issues
show
Unused Code introduced by
$tmw is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1218
1219
        /*
1220
         * check log or cache
1221
         */
1222
        if ($object_type == OBJECT_CACHE) {// get filenames of the pictures of $this' caches
1223
            $rs = sql(
1224
                "SELECT `pictures`.`url` " .
1225
                "FROM `pictures`,`caches` " .
1226
                "WHERE `caches`.`cache_id`=`pictures`.`object_id`" .
1227
                " AND `pictures`.`object_type`='&1' AND `caches`.`user_id`='&2'",
1228
                OBJECT_CACHE,
1229
                $this->getUserId()
1230
            );
1231
        } elseif ($object_type == OBJECT_CACHELOG) {// get filenames of the pictures of $this' logs
1232
            $rs = sql(
1233
                "SELECT `pictures`.`url` " .
1234
                "FROM `pictures`,`cache_logs` " .
1235
                "WHERE `cache_logs`.`id`=`pictures`.`object_id`" .
1236
                " AND `pictures`.`object_type`='&1' AND `cache_logs`.`user_id`='&2'",
1237
                OBJECT_CACHELOG,
1238
                $this->getUserId()
1239
            );
1240
        }
1241
1242
        // set thumb-dimensions
1243
        $tmh = $opt['logic']['pictures']['thumb_max_height'];
1244
        $tmw = $opt['logic']['pictures']['thumb_max_width'];
1245
1246
        $filenames = array();
1247
        while ($url = sql_fetch_array($rs, MYSQL_NUM)) {
0 ignored issues
show
Bug introduced by
The variable $rs does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Unused Code introduced by
The call to sql_fetch_array() has too many arguments starting with MYSQL_NUM.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1248
            $filenames[] = substr($url['url'], - 40);
0 ignored issues
show
introduced by
A unary operator statement must not be followed by a space
Loading history...
1249
        }
1250
1251
        // free result
1252
        sql_free_result($rs);
1253
1254
        /*
1255
         * walk through filenames and replace original
1256
         */
1257
        // check if there is something to replace
1258
        if (count($filenames) > 0) {
1259
            foreach ($filenames as $fn) {
1260
                // get uuid and extension
1261
                $uuid = substr($fn, 0, 36);
1262
                $ext = substr($fn, - 3);
0 ignored issues
show
introduced by
A unary operator statement must not be followed by a space
Loading history...
1263
                $thumb_dir1 = substr($uuid, 0, 1);
1264
                $thumb_dir2 = substr($uuid, 1, 1);
1265
1266
                // read original size
1267
                if (file_exists("$picpath/$fn")) {
1268
                    list($w, $h, $t, $attr) = getimagesize("$picpath/$fn");
0 ignored issues
show
Unused Code introduced by
The assignment to $t is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $attr is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1269
                } else {
1270
                    $w = 600;
1271
                    $h = 480;
1272
                }
1273
1274
                // create new image
1275
                $im = imagecreatetruecolor($w, $h);
1276
                // allocate colors
1277
                $col_bg = imagecolorallocate($im, $dummybg[0], $dummybg[1], $dummybg[2]);
1278
                $col_text = imagecolorallocate($im, $dummytextcolor[0], $dummytextcolor[1], $dummytextcolor[2]);
1279
1280
                // fill bg
1281
                imagefill($im, 0, 0, $col_bg);
1282
1283
                // check for replacement-image
1284
                if ($pdummy && isset($opt['logic']['pictures']['dummy']['replacepic'])
1285
                    && $opt['logic']['pictures']['dummy']['replacepic'] != $opt['rootpath'] . 'images/'
1286
                    && file_exists($opt['logic']['pictures']['dummy']['replacepic'])
1287
                ) {
1288
                    // get dimensions of the replacement
1289
                    list($rw, $rh, $rt, $rattr) = getimagesize($opt['logic']['pictures']['dummy']['replacepic']);
0 ignored issues
show
Unused Code introduced by
The assignment to $rt is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $rattr is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1290
                    $rwh = 0;
0 ignored issues
show
Unused Code introduced by
$rwh is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1291
                    if ($rw > $rh) {
1292
                        $rwh = $rh;
1293
                    } else {
1294
                        $rwh = $rw;
1295
                    }
1296
1297
                    // check dimensions of original and set replacement size
1298
                    $rsize = 0;
0 ignored issues
show
Unused Code introduced by
$rsize is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1299
                    if ($w > $h) {
1300
                        if (($h * 0.85) > $rwh) {
1301
                            $rsize = $rwh;
1302
                        } else {
1303
                            $rsize = $h * 0.9;
1304
                        }
1305
                    } else {
1306
                        if (($w * 0.85) > $rwh) {
1307
                            $rsize = $rwh;
1308
                        } else {
1309
                            $rsize = $w * 0.9;
1310
                        }
1311
                    }
1312
                    $dx = ($w - $rsize) / 2;
1313
                    $dy = ($h - $rsize) / 2;
1314
1315
                    // get replacement image
1316
                    $rext = substr($opt['logic']['pictures']['dummy']['replacepic'], - 3);
0 ignored issues
show
introduced by
A unary operator statement must not be followed by a space
Loading history...
1317
                    $rim = null;
1318
                    if ($rext == 'jpg') {
1319
                        $rim = imagecreatefromjpeg($opt['logic']['pictures']['dummy']['replacepic']);
1320 View Code Duplication
                    } elseif ($rext == 'png') {
1321
                        $rim = imagecreatefrompng($opt['logic']['pictures']['dummy']['replacepic']);
1322
                    } elseif ($rext == 'gif') {
1323
                        $rim = imagecreatefromgif($opt['logic']['pictures']['dummy']['replacepic']);
1324 View Code Duplication
                    } elseif ($rext == 'bmp') {
1325
                        $rim = imagecreatefrombmp($opt['logic']['pictures']['dummy']['replacepic']);
1326
                    }
1327
1328
                    // copy image
1329
                    if (!is_null($rim)) {
0 ignored issues
show
introduced by
is_null() found, should be strict === null check.
Loading history...
1330
                        imagecopyresampled($im, $rim, $dx, $dy, 0, 0, $rsize, $rsize, $rw, $rh);
1331
                    }
1332
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1333
                } else {
1334
                    // set text
1335
                    if ($dummytext != '') {
1336
                        imagestring($im, 1, 10, $h / 2, $dummytext, $col_text);
1337
                    } else {
1338
                        imageline($im, 0, 0, $w, $h, 0xff0000);
1339
                        imageline($im, 0, $h, $w, 0, 0xff0000);
1340
                    }
1341
                }
1342
1343
                // save dummy
1344
                if ($ext == 'jpg') {
1345
                    if (!imagejpeg($im, "$picpath/$fn", 75)) {
1346
                        return "save dummy failed [$ext]";
1347
                    }
1348
                } elseif ($ext == 'png') {
1349
                    if (!imagepng($im, "$picpath/$fn", 4)) {
1350
                        return "save dummy failed [$ext]";
1351
                    }
1352
                } elseif ($ext == 'gif') {
1353
                    if (!imagegif($im, "$picpath/$fn")) {
1354
                        return "save dummy failed [$ext]";
1355
                    }
1356
                } elseif ($ext == 'bmp') {
1357
                    if (!imagebmp($im, "$picpath/$fn")) {
1358
                        return "save dummy failed [$ext]";
1359
                    }
1360
                } else {
1361
                    return "save dummy failed [$ext], unknown extension";
1362
                }
1363
1364
                // set thumb-dimensions
1365
                if (($h > $tmh) || ($w > $tmw)) {
1366
                    if ($h > $w) {
1367
                        $th = $tmh;
1368
                        $tw = $w * ($th / $h);
1369
                    } else {
1370
                        $tw = $tmw;
1371
                        $th = $h * ($tw / $w);
1372
                    }
1373
                } else {
1374
                    $tw = $w;
1375
                    $th = $h;
1376
                }
1377
1378
                // copy dummy
1379
                $tim = imagecreatetruecolor($tw, $th);
1380
                imagecopyresampled($tim, $im, 0, 0, 0, 0, $tw, $th, $w, $h);
1381
1382
                // check directories or create them
1383 View Code Duplication
                if (!file_exists("$thumbpath/$thumb_dir1")) {
1384
                    if (!mkdir("$thumbpath/$thumb_dir1")) {
1385
                        return 'mkdir in thumbpath failed';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return 'mkdir in thumbpath failed'; (string) is incompatible with the return type documented by user::replace_pictures of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
1386
                    }
1387
                }
1388 View Code Duplication
                if (!file_exists("$thumbpath/$thumb_dir1/$thumb_dir2")) {
1389
                    if (!mkdir("$thumbpath/$thumb_dir1/$thumb_dir2")) {
1390
                        return 'mkdir in thumbpath failed';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return 'mkdir in thumbpath failed'; (string) is incompatible with the return type documented by user::replace_pictures of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
1391
                    }
1392
                }
1393
1394
                // save thumb
1395
                if ($ext == 'jpg') {
1396
                    if (!imagejpeg($tim, "$thumbpath/$thumb_dir1/$thumb_dir2/$fn", 75)) {
1397
                        return "save thumb failed [$ext]";
1398
                    }
1399 View Code Duplication
                } elseif ($ext == 'png') {
1400
                    if (!imagepng($tim, "$thumbpath/$thumb_dir1/$thumb_dir2/$fn", 4)) {
1401
                        return "save thumb failed [$ext]";
1402
                    }
1403
                } elseif ($ext == 'gif') {
1404
                    if (!imagegif($tim, "$thumbpath/$thumb_dir1/$thumb_dir2/$fn")) {
1405
                        return "save thumb failed [$ext]";
1406
                    }
1407 View Code Duplication
                } elseif ($ext == 'bmp') {
1408
                    if (!imagebmp($tim, "$thumbpath/$thumb_dir1/$thumb_dir2/$fn")) {
1409
                        return "save thumb failed [$ext]";
1410
                    }
1411
                } else {
1412
                    return "save thumb failed [$ext], unknown extension";
1413
                }
1414
            }
1415
        }
1416
1417
        // success
1418
        return true;
1419
    }
1420
1421
    public function canDelete()
1422
    {
1423
        global $login;
1424
        $login->verify();
1425
1426
        if ($login->userid != $this->nUserId && ($login->admin & ADMIN_USER) != ADMIN_USER) {
1427
            return false;
1428
        }
1429
1430
        return
1431
            sql_value("SELECT COUNT(*) FROM `caches` WHERE `user_id`='&1'", 0, $this->nUserId)
1432
            + sql_value("SELECT COUNT(*) FROM `cache_logs` WHERE `user_id`='&1'", 0, $this->nUserId)
1433
            + sql_value("SELECT COUNT(*) FROM `cache_logs_archived` WHERE `user_id`='&1'", 0, $this->nUserId)
1434
            + sql_value("SELECT COUNT(*) FROM `cache_reports` WHERE `userid`='&1'", 0, $this->nUserId)
1435
            == 0;
1436
    }
1437
1438
    public function delete()
1439
    {
1440
        global $login;
1441
1442
        if ($this->canDelete() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1443
            return false;
1444
        }
1445
1446
        // write old record to log
1447
        $backup = array();
1448
        $backup['username'] = $this->getUsername();
1449
        $backup['email'] = $this->getEMail();
1450
        $backup['last_name'] = $this->getLastName();
1451
        $backup['first_name'] = $this->getFirstName();
1452
1453
        sql(
1454
            "INSERT INTO `logentries` (`module`, `eventid`, `userid`, `objectid1`, `objectid2`, `logtext`, `details`)
1455
             VALUES ('user', 7, '&1', '&2', '&3', '&4', '&5')",
1456
            $login->userid,
1457
            $this->nUserId,
1458
            0,
1459
            'User ' . sql_escape($this->getUsername()) . ' deleted',
1460
            serialize($backup)
1461
        );
1462
1463
        sql("set @allowdelete=1");
1464
        sql("DELETE FROM `user` WHERE `user_id`='&1'", $this->nUserId);
1465
        // all data in depending tables is cleared via trigger
1466
1467
        $this->reload();
1468
1469
        return true;
1470
    }
1471
1472
    // email bounce processing
1473
    public function addEmailProblem($licensemail = false)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
1474
    {
1475
        // mailing_problems is a bit-flag field to remember nondelivered, important mailings
1476
        if ($licensemail) {
1477
            if (!$this->reUser->setValue('mailing_problems', $this->reUser->getValue('mailing_problems') | 1)) {
1478
                return false;
1479
            }
1480
        }
1481
1482
        return $this->reUser->setValue('email_problems', $this->getEmailProblems() + 1) &&
1483
        $this->reUser->setValue('last_email_problem', date('Y-m-d H:i:s')) &&
1484
        $this->save();
1485
    }
1486
1487
    public function getEmailProblems()
1488
    {
1489
        // see also common.inc.php "SELECT `email_problems`"
1490
        return $this->reUser->getValue('email_problems');
1491
    }
1492
1493
    public function getDataLicense()
1494
    {
1495
        return $this->reUser->getValue('data_license');
1496
    }
1497
1498
    public function getLicenseDeclined()
1499
    {
1500
        return $this->getDataLicense() == NEW_DATA_LICENSE_ACTIVELY_DECLINED ||
1501
        $this->getDataLicense() == NEW_DATA_LICENSE_PASSIVELY_DECLINED;
1502
    }
1503
1504
    public function missedDataLicenseMail()
1505
    {
1506
        return $this->reUser->getValue('mailing_problems') & 1;
1507
    }
1508
1509
    function shownDataLicenseMail()
0 ignored issues
show
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for shownDataLicenseMail.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1510
    {
1511
        return
1512
            $this->reUser->setValue('mailing_problems', $this->reUser->getValue('mailing_problems') & ~1)
1513
            && $this->save();
1514
    }
1515
1516
    public function confirmEmailAddress()
1517
    {
1518
        return $this->reUser->setValue('email_problems', 0) && $this->save();
1519
    }
1520
1521
    public function reload()
1522
    {
1523
        $this->reUser->reload();
1524
        $this->reUserStat->reload();
1525
    }
1526
1527
    public function getGivenRatings()
1528
    {
1529
        // get number of cache ratings for this user
1530
        return sql_value(
1531
            "
1532
                            SELECT COUNT(`user_id`)
1533
                            FROM `cache_rating`
1534
                            WHERE `user_id`='&1'",
1535
            0,
1536
            $this->getUserId()
1537
        );
1538
    }
1539
1540
    public function getMaxRatings()
1541
    {
1542
        global $opt;
1543
1544
        // get number of possible rates
1545
        return floor($this->getStatFound() * $opt['logic']['rating']['percentageOfFounds'] / 100);
1546
    }
1547
1548
    public function allowRatings()
1549
    {
1550
        // new ratings allowed, if "given ratings" < "max ratings"
1551
        return ($this->getGivenRatings() < $this->getMaxRatings());
0 ignored issues
show
introduced by
Language constructs must not be followed by parenthesesis.
Loading history...
1552
    }
1553
1554
    public function foundsUntilNextRating()
1555
    {
1556
        global $opt;
1557
1558
        return ($opt['logic']['rating']['percentageOfFounds'] - ($this->getStatFound() % $opt['logic']['rating']['percentageOfFounds']));
0 ignored issues
show
introduced by
Language constructs must not be followed by parenthesesis.
Loading history...
1559
    }
1560
1561
    public function showStatFounds()
1562
    {
1563
        // wether to show the number of founds on log page
1564
        // TODO: make customisable in user profile, see #241
1565
        return false;
1566
    }
1567
1568
    public function guessLanguage()
1569
    {
1570
        global $opt;
1571
1572
        $language = false;
1573
1574
        // If the user has selected a country and a translation is available for
1575
        // that country's primary language, use this language.
1576
1577
        $country = $this->getCountryCode();
1578
        if ($country) {
1579
            foreach ($opt['locale'] as $code => $props) {
1580
                if ($props['mostly_translated'] && in_array($country, $props['primary_lang_of'])) {
1581
                    $language = $code;
1582
                }
1583
            }
1584
        }
1585
1586
        if (!$language) {
1587
            // If the user has logged caches with at least three descriptions,
1588
            // at least 65% of those descriptions have the same language,
1589
            // and a translation is available for that language, use it.
1590
1591
            $rs = sql(
1592
                "
1593
                SELECT COUNT(*) AS `count`, `cache_desc`.`language`
1594
                FROM `cache_logs`
1595
                JOIN `cache_desc` ON `cache_desc`.`cache_id`=`cache_logs`.`cache_id`
1596
                WHERE `cache_logs`.`user_id`='&1'
1597
                GROUP BY `cache_desc`.`language`
1598
                ORDER BY `count` DESC",
1599
                $this->nUserId
1600
            );
1601
            $total = 0;
1602
            while ($r = sql_fetch_assoc($rs)) {
1603
                if ($total == 0) {
1604
                    $first = $r;
1605
                }
1606
                $total += $r['count'];
1607
            }
1608
            sql_free_result($rs);
1609
1610
            if ($total >= 3 && $first['count'] / $total >= 0.65) {
1611
                if (isset($opt['locale'][$first['language']])
1612
                    && $opt['locale'][$first['language']]['mostly_translated']
1613
                ) {
1614
                    $language = $first['language'];
0 ignored issues
show
Bug introduced by
The variable $first does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1615
                }
1616
            }
1617
        }
1618
1619
        return $language;
1620
    }
1621
}
1622