Passed
Push — develop ( f66d95...f9d2ce )
by Paul
13:45
created

SanitizeUserName::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules\Sanitizers;
4
5
use GeminiLabs\SiteReviews\Helpers\Cast;
6
7
class SanitizeUserName extends StringSanitizer
8
{
9
    public array $args;
10
    public $value;
11
    public array $values;
12
13 35
    public function __construct($value, array $args = [], array $values = [])
14
    {
15 35
        $args = array_pad($args, 2, ''); // minimum of 2 args
16 35
        $this->args = $args;
17 35
        $this->value = $this->userValue($value);
18 35
        $this->values = $values;
19
    }
20
21 35
    public function run(): string
22
    {
23 35
        $value = $this->sanitizeValue($this->value()); // allow any valid name value
24 35
        if (defined('WP_IMPORTING')) {
25
            return $value;
26
        }
27 35
        if ('' !== $value) { // allow "0"
28 23
            return $value;
29
        }
30 22
        $fallback = Cast::toString($this->args[0]); // try the fallback value
31 22
        if ('current_user' === $fallback) {
32 10
            $fallback = $this->userValue(wp_get_current_user());
33
        }
34 22
        return $this->sanitizeValue($fallback);
35
    }
36
37
    /**
38
     * \p{L} = any kind of letter from any language.
39
     * \p{M} = any character intended to be combined with another character (e.g. accents, umlauts, enclosing boxes, etc.).
40
     * \p{N} = any kind of numeric character in any script.
41
     * \p{Pf} = any kind of closing quote.
42
     *
43
     * @see https://www.regular-expressions.info/unicode.html
44
     */
45 35
    protected function sanitizeValue(string $value): string
46
    {
47 35
        if ('' === $value) {
48 22
            return $value;
49
        }
50 26
        $name = strstr($value, '@', true) ?: $value; // prevent exposing user email
51 26
        $name = $this->kses($name);
52 26
        $name = html_entity_decode($name, ENT_QUOTES, 'UTF-8'); // &amp;lt => &lt;
53 26
        $name = wp_specialchars_decode($name); // &lt; => <
54 26
        $name = wp_strip_all_tags($name);
55 26
        $name = preg_replace('/%([a-fA-F0-9][a-fA-F0-9])/', '', $name); // Remove percent-encoded characters.
56 26
        $name = preg_replace('/&.+?;/', '', $name); // Remove HTML entities.
57 26
        $name = preg_replace('/[^\p{L}\p{M}\p{N}\p{Pf}\'\.\,\- ]/u', '', $name);
58 26
        $name = sanitize_text_field($name); // Remove extra whitespace.
59 26
        return $name;
60
    }
61
62
    /**
63
     * @param mixed $user
64
     */
65 35
    protected function userValue($user): string
66
    {
67 35
        if (!is_object($user)) {
68 27
            return Cast::toString($user);
69
        }
70 22
        if ($user instanceof \WP_User && !$user->exists()) {
71 20
            return '';
72
        }
73 4
        $displayName = $user->display_name ?? '';
74 4
        $userNicename = $user->user_nicename ?? '';
75 4
        $userLogin = $user->user_login ?? '';
76 4
        return $displayName ?: $userNicename ?: $userLogin;
77
    }
78
}
79