Passed
Push — master ( 306745...84d474 )
by Paul
16:41 queued 07:55
created

Sanitizer::sanitizeSlug()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Helper;
6
use GeminiLabs\SiteReviews\Helpers\Arr;
7
use GeminiLabs\SiteReviews\Helpers\Cast;
8
use GeminiLabs\SiteReviews\Helpers\Str;
9
use GeminiLabs\SiteReviews\Modules\Multilingual;
10
11
class Sanitizer
12
{
13
    const JSON_ERROR_CODES = [
14
        JSON_ERROR_DEPTH => 'JSON Error: The maximum stack depth has been exceeded',
15
        JSON_ERROR_STATE_MISMATCH => 'JSON Error: Invalid or malformed JSON',
16
        JSON_ERROR_CTRL_CHAR => 'JSON Error: Control character error, possibly incorrectly encoded',
17
        JSON_ERROR_SYNTAX => 'JSON Error: Syntax error',
18
        JSON_ERROR_UTF8 => 'JSON Error: Malformed UTF-8 characters, possibly incorrectly encoded',
19
        JSON_ERROR_RECURSION => 'JSON Error: One or more recursive references in the value to be encoded',
20
        JSON_ERROR_INF_OR_NAN => 'JSON Error: One or more NAN or INF values in the value to be encoded',
21
        JSON_ERROR_UNSUPPORTED_TYPE => 'JSON Error: A value of a type that cannot be encoded was given',
22
        JSON_ERROR_INVALID_PROPERTY_NAME => 'JSON Error: A property name that cannot be encoded was given',
23
        JSON_ERROR_UTF16 => 'JSON Error: Malformed UTF-16 characters, possibly incorrectly encoded',
24
    ];
25
26
    /**
27
     * @var array
28
     */
29
    public $sanitizers;
30
31
    /**
32
     * @var array
33
     */
34
    public $values;
35
36 40
    public function __construct(array $values = [], array $sanitizers = [])
37
    {
38 40
        $this->sanitizers = $this->buildSanitizers(Arr::consolidate($sanitizers));
39 40
        $this->values = Arr::consolidate($values);
40 40
    }
41
42
    /**
43
     * @return array|bool|string
44
     */
45 40
    public function run()
46
    {
47 40
        $result = $this->values;
48 40
        foreach ($this->values as $key => $value) {
49 40
            if (array_key_exists($key, $this->sanitizers)) {
50 40
                $result[$key] = call_user_func([$this, $this->sanitizers[$key]], $value);
51
            }
52
        }
53 40
        return $result;
54
    }
55
56
    /**
57
     * @param mixed $value
58
     * @return array
59
     */
60 17
    public function sanitizeArray($value)
61
    {
62 17
        return Arr::consolidate($value);
63
    }
64
65
    /**
66
     * @param mixed $value
67
     * @return int[]
68
     */
69 25
    public function sanitizeArrayInt($value)
70
    {
71 25
        return Arr::uniqueInt(Cast::toArray($value));
72
    }
73
74
    /**
75
     * @param mixed $value
76
     * @return string[]
77
     */
78 1
    public function sanitizeArrayString($value)
79
    {
80 1
        $sanitized = array_filter(Cast::toArray($value), 'is_string');
81
        array_walk($sanitized, function (&$value) {
82 1
            $value = $this->sanitizeText($value);
83 1
        });
84 1
        return $sanitized;
85
    }
86
87
    /**
88
     * @param mixed $value
89
     * @return bool
90
     */
91 16
    public function sanitizeBool($value)
92
    {
93 16
        return Cast::toBool($value);
94
    }
95
96
    /**
97
     * If date is invalid then return an empty string.
98
     * @param mixed $value
99
     * @param string $fallback
100
     * @return string
101
     */
102 24
    public function sanitizeDate($value, $fallback = '')
103
    {
104 24
        $date = strtotime(trim(Cast::toString($value)));
105 24
        if (false !== $date) {
106 15
            return wp_date('Y-m-d H:i:s', $date);
107
        }
108 24
        return $fallback;
109
    }
110
111
    /**
112
     * @param mixed $value
113
     * @return string
114
     */
115 25
    public function sanitizeEmail($value)
116
    {
117 25
        return sanitize_email(trim(Cast::toString($value)));
118
    }
119
120
    /**
121
     * @param mixed $value
122
     * @return string
123
     */
124 9
    public function sanitizeId($value)
125
    {
126 9
        require_once ABSPATH.WPINC.'/pluggable.php';
127 9
        $value = sanitize_key($this->sanitizeText($value));
128 9
        $value = substr($value, 0, 32); // limit the id to 32 characters
129 9
        if (empty($value)) {
130 9
            $value = glsr()->prefix.substr(wp_hash(serialize($this->values), 'nonce'), -12, 8);
131
        }
132 9
        return $value;
133
    }
134
135
    /**
136
     * @param mixed $value
137
     * @return int
138
     */
139 16
    public function sanitizeInt($value)
140
    {
141 16
        return Cast::toInt($value);
142
    }
143
144
    /**
145
     * @param mixed $value
146
     * @return array
147
     */
148
    public function sanitizeJson($value)
149
    {
150
        $result = '';
151
        if (is_scalar($value) && !Helper::isEmpty($value)) {
152
            $result = trim((string) $value);
153
            $result = htmlspecialchars_decode($result);
154
            $result = json_decode($result, true);
155
            $error = json_last_error();
156
            if (array_key_exists($error, static::JSON_ERROR_CODES)) {
157
                glsr_log()->error(static::JSON_ERROR_CODES[$error])->debug($value);
158
            }
159
        }
160
        return wp_unslash(Arr::consolidate($result));
161
    }
162
163
    /**
164
     * This allows lowercase alphannumeric and underscore characters
165
     * @param mixed $value
166
     * @return string
167
     */
168 25
    public function sanitizeKey($value)
169
    {
170 25
        $value = sanitize_key($this->sanitizeText($value));
171 25
        return substr(Str::snakeCase($value), 0, 32); // limit the key to 32 characters
172
    }
173
174
    /**
175
     * This allows lowercase alpha and underscore characters
176
     * @param mixed $value
177
     * @return string
178
     */
179 22
    public function sanitizeName($value)
180
    {
181 22
        $value = Str::snakeCase($this->sanitizeText($value));
182 22
        return preg_replace('/[^a-z_]/', '', $value);
183
    }
184
185
    /**
186
     * @param mixed $value
187
     * @return int|string
188
     */
189 1
    public function sanitizeNumeric($value)
190
    {
191 1
        return is_numeric($value) ? Cast::toInt($value) : '';
192
    }
193
194
    /**
195
     * @param mixed $value
196
     * @return int[]
197
     */
198 24
    public function sanitizePostIds($value)
199
    {
200 24
        $postIds = Cast::toArray($value);
201 24
        foreach ($postIds as &$postId) {
202 4
            if ($sanitizedId = Helper::getPostId($postId)) {
203 4
                $postId = $sanitizedId;
204
            }
205
        }
206 24
        return Arr::uniqueInt($postIds);
207
    }
208
209
    /**
210
     * @param mixed $value
211
     * @return string
212
     */
213 1
    public function sanitizeSlug($value)
214
    {
215 1
        return sanitize_title($this->sanitizeText($value));
216
    }
217
218
    /**
219
     * @param mixed $value
220
     * @return int[]
221
     */
222 24
    public function sanitizeTermIds($value)
223
    {
224 24
        $termIds = Cast::toArray($value);
225 24
        foreach ($termIds as &$termId) {
226 4
            if ($sanitizedId = Helper::getTermTaxonomyId($termId)) {
227 4
                $termId = $sanitizedId;
228
            }
229
        }
230 24
        return Arr::uniqueInt($termIds);
231
    }
232
233
    /**
234
     * @param mixed $value
235
     * @return string
236
     */
237 30
    public function sanitizeText($value)
238
    {
239 30
        return sanitize_text_field(trim(Cast::toString($value)));
240
    }
241
242
    /**
243
     * @param mixed $value
244
     * @return string
245
     */
246
    public function sanitizeTextHtml($value)
247
    {
248
        $allowedHtmlPost = wp_kses_allowed_html('post');
249
        $allowedHtml = [
250
            'a' => glsr_get($allowedHtmlPost, 'a'),
251
            'em' => glsr_get($allowedHtmlPost, 'em'),
252
            'strong' => glsr_get($allowedHtmlPost, 'strong'),
253
        ];
254
        $allowedHtml = glsr()->filterArray('sanitize/allowed-html', $allowedHtml, $this);
255
        return wp_kses(trim(Cast::toString($value)), $allowedHtml);
256
    }
257
258
    /**
259
     * @param mixed $value
260
     * @return string
261
     */
262 16
    public function sanitizeTextMultiline($value)
263
    {
264 16
        return sanitize_textarea_field(trim(Cast::toString($value)));
265
    }
266
267
    /**
268
     * Returns slashed data!
269
     * @param mixed $value
270
     * @return string
271
     */
272
    public function sanitizeTextPost($value)
273
    {
274
        return wp_filter_post_kses(trim(Cast::toString($value)));
275
    }
276
277
    /**
278
     * @param mixed $value
279
     * @return string
280
     */
281 16
    public function sanitizeUrl($value)
282
    {
283 16
        $value = trim(Cast::toString($value));
284 16
        if (!Str::startsWith('http://, https://', $value)) {
285 16
            $value = Str::prefix($value, 'https://');
286
        }
287 16
        $url = esc_url_raw($value);
288 16
        if (mb_strtolower($value) === mb_strtolower($url) && filter_var($url, FILTER_VALIDATE_URL) !== false) {
289 15
            return $url;
290
        }
291 16
        return '';
292
    }
293
294
    /**
295
     * @param mixed $value
296
     * @return string
297
     */
298 15
    public function sanitizeUserEmail($value)
299
    {
300 15
        $user = wp_get_current_user();
301 15
        $value = $this->sanitizeEmail($value);
302 15
        if ($user->exists() && !glsr()->retrieveAs('bool', 'import', false)) {
303 2
            return Helper::ifEmpty($value, $user->user_email);
304
        }
305 15
        return $value;
306
    }
307
308
    /**
309
     * @param mixed $value
310
     * @return int
311
     */
312 15
    public function sanitizeUserId($value)
313
    {
314 15
        $user = get_user_by('ID', Cast::toInt($value));
315 15
        if (false !== $user) {
316 2
            return (int) $user->ID;
317
        }
318 15
        if (glsr()->retrieveAs('bool', 'import', false)) {
319
            return 0;
320
        }
321 15
        return get_current_user_id();
322
    }
323
324
    /**
325
     * @param mixed $value
326
     * @return int[]
327
     */
328 24
    public function sanitizeUserIds($value)
329
    {
330 24
        $userIds = Cast::toArray($value);
331 24
        foreach ($userIds as &$userId) {
332 5
            if ($sanitizedId = Helper::getUserId($userId)) {
333 5
                $userId = $sanitizedId;
334
            }
335
        }
336 24
        return Arr::uniqueInt($userIds);
337
    }
338
339
    /**
340
     * @param mixed $value
341
     * @return string
342
     */
343 15
    public function sanitizeUserName($value)
344
    {
345 15
        $user = wp_get_current_user();
346 15
        $value = $this->sanitizeText($value);
347 15
        if ($user->exists() && !glsr()->retrieveAs('bool', 'import', false)) {
348 2
            return Helper::ifEmpty($value, $user->display_name);
349
        }
350 15
        return $value;
351
    }
352
353
    /**
354
     * @return array
355
     */
356 40
    protected function buildSanitizers(array $sanitizers)
357
    {
358 40
        foreach ($sanitizers as $key => &$type) {
359 40
            $method = Helper::buildMethodName($type, 'sanitize');
360 40
            $type = method_exists($this, $method)
361 40
                ? $method
362 40
                : 'sanitizeText';
363
        }
364 40
        return $sanitizers;
365
    }
366
}
367