Passed
Push — master ( 3c8625...c93166 )
by Divine Niiquaye
12:46
created

Helper::getParameterValue()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 8
eloc 20
nc 8
nop 3
dl 0
loc 34
ccs 0
cts 21
cp 0
crap 72
rs 8.4444
c 2
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Biurad opensource projects.
7
 *
8
 * PHP version 7.4 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 *
17
 */
18
19
namespace Biurad\Security;
20
21
use Biurad\Http\Request;
22
use Biurad\Security\Handler\RememberMeHandler;
23
use Psr\Http\Message\ServerRequestInterface;
24
use Symfony\Component\HttpFoundation\Cookie;
25
use Symfony\Component\HttpFoundation\Session\SessionInterface;
26
use Symfony\Component\PropertyAccess\Exception\AccessException;
27
use Symfony\Component\PropertyAccess\PropertyAccess;
28
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
29
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
30
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
31
32
/**
33
 * @author Divine Niiquaye Ibok <[email protected]>
34
 */
35
class Helper
36
{
37
    private static PropertyAccessorInterface $propertyAccessor;
38
39
    /**
40
     * Determine the targeted url from request, session or referer header.
41
     */
42
    public static function determineTargetUrl(
43
        ServerRequestInterface $request,
44
        SessionInterface $session = null,
45
        string $parameter = '_target_path',
46
        bool $fromReferer = false
47
    ): ?string {
48
        if ($targetUrl = self::getParameterValue($request, $parameter)) {
49
            goto targetUrl;
50
        }
51
52
        if (null === $session && ($request instanceof Request && $request->getRequest()->hasSession())) {
53
            $session = $request->getRequest()->getSession();
54
        }
55
56
        if (null !== $session && $targetUrl = $session->get($parameter)) {
57
            $session->remove($parameter);
58
        }
59
60
        targetUrl:
61
        if ($fromReferer && $targetUrl = ($targetUrl ?? $request->getHeaderLine('Referer'))) {
62
            if (false !== $pos = \strpos($targetUrl, '?')) {
63
                $targetUrl = \substr($targetUrl, 0, $pos);
64
            }
65
66
            return $targetUrl;
67
        }
68
69
        return $targetUrl ?: null;
70
    }
71
72
    /**
73
     * Returns a request "parameter" value.
74
     *
75
     * Paths like foo[bar] will be evaluated to find deeper items in nested data structures.
76
     *
77
     * @param ServerRequestInterface|\stdClass $data
78
     *
79
     * @throws \InvalidArgumentException when the given path is malformed
80
     *
81
     * @return mixed
82
     */
83
    public static function getParameterValue(object $data, string $path, PropertyAccessorInterface $propertyAccessor = null)
84
    {
85
        if ($data instanceof ServerRequestInterface) {
86
            $getter = static function (string $value) use ($data) {
87
                if ($data instanceof Request) {
88
                    $requestedValue = $data->getRequest()->get($value);
89
                } else {
90
                    $requestedValue = $data->getAttributes()[$value] ?? $data->getQueryParams()[$value] ?? null;
91
                }
92
93
                if (null === $requestedValue) {
94
                    $data = (array) ($data->getParsedBody() ?? \json_decode(((string) $data->getBody()) ?: '', true));
95
                    $requestedValue = $data[$value] ?? null;
96
                }
97
98
                return $requestedValue;
99
            };
100
101
            if (false === $pos = \strpos($path, '[')) {
102
                return $getter($path);
103
            }
104
105
            if (null === $data = $getter(\substr($path, 0, $pos))) {
106
                return null;
107
            }
108
            $path = \substr($path, $pos);
109
        }
110
111
        try {
112
            self::$propertyAccessor ??= $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
113
114
            return self::$propertyAccessor->getValue($data, $path);
115
        } catch (AccessException $e) {
116
            return null;
117
        }
118
    }
119
120
    /**
121
     * Fetch the form data from the request.
122
     *
123
     * @param array<int,string> $parameterKeys
124
     *
125
     * @return array<int,mixed>
126
     */
127
    public static function getParameterValues(ServerRequestInterface $request, array $parameterKeys, PropertyAccessorInterface $propertyAccessor = null): array
128
    {
129
        if (empty($parameterKeys)) {
130
            return [];
131
        }
132
133
        foreach ($parameterKeys as $offset => $key) {
134
            unset($parameterKeys[$offset]);
135
            $parameterKeys[$key] = self::getParameterValue($request, $key, $propertyAccessor);
136
        }
137
138
        return $parameterKeys;
139
    }
140
141
    /**
142
     * Creates remember me cookies from token.
143
     *
144
     * @return array<int,Cookie>
145
     */
146
    public static function createRememberMeCookie(?TokenInterface $fromToken, ServerRequestInterface $request): array
147
    {
148
        if (null === $fromToken || !$fromToken->hasAttribute($cookieR = RememberMeHandler::REMEMBER_ME)) {
149
            return [];
150
        }
151
152
        $cookieId = RememberMeHandler::USERS_ID;
153
        $cookieUserId = \rawurldecode($request->getCookieParams()[$cookieId] ?? '');
154
155
        if (!\str_contains($cookieUserId, $userId = $fromToken->getUserIdentifier())) {
156
            $cookieUserId = empty($cookieUserId) ? $userId : $cookieUserId . '|' . $userId;
157
        }
158
159
        if (!\is_array($tokenCookies = $fromToken->getAttribute($cookieR))) {
160
            $tokenCookies = [$tokenCookies];
161
        }
162
163
        $tokenCookies[] = new Cookie($cookieId, $cookieUserId, $tokenCookies[0]->getExpiresTime());
164
165
        return $tokenCookies;
166
    }
167
}
168