Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
TrimInput
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
2 / 2
8
100.00% covered (success)
100.00%
1 / 1
 process
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 trimArrayValues
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Middleware;
6
7use Psr\Http\Message\ResponseInterface;
8use Psr\Http\Message\ServerRequestInterface;
9use Psr\Http\Server\MiddlewareInterface;
10use Psr\Http\Server\RequestHandlerInterface;
11
12/**
13 * Request middleware that trims all string values of PUT and POST requests.
14 * Some fields such as passwords are excluded.
15 */
16class TrimInput implements MiddlewareInterface
17{
18    /**
19     * @var array<string> List of field names to exclude from trim
20     */
21    private const TRIM_EXCLUDE_LIST = [
22        'password',
23        'password2',
24        'new_password',
25        'new_password2',
26        'new_pw',
27        'new_pw2',
28        'password_confirmation',
29    ];
30
31    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
32    {
33        if (in_array($request->getMethod(), ['PUT', 'POST']) && is_array($request->getParsedBody())) {
34            $trimmedParsedBody = $this->trimArrayValues($request->getParsedBody());
35            $request = $request->withParsedBody($trimmedParsedBody);
36        }
37
38        return $handler->handle($request);
39    }
40
41    /**
42     * @template AK array key type
43     * @template AV array value type
44     * @param array<AK, AV> $array
45     * @return array<AK, AV>
46     */
47    private function trimArrayValues(array $array): array
48    {
49        $result = [];
50
51        foreach ($array as $key => $value) {
52            if (is_array($value)) {
53                // recurse trim
54                $result[$key] = $this->trimArrayValues($value);
55                continue;
56            }
57
58            if (is_string($value) && !in_array($key, self::TRIM_EXCLUDE_LIST)) {
59                // trim only non-excluded string values
60                $result[$key] = trim($value);
61                continue;
62            }
63
64            $result[$key] = $value;
65        }
66
67        return $result;
68    }
69}