UrlGenerator::generate()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 12
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 24
rs 9.8666
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cakasim\Payone\Sdk\Redirect\UrlGenerator;
6
7
use Cakasim\Payone\Sdk\Config\ConfigExceptionInterface;
8
use Cakasim\Payone\Sdk\Config\ConfigInterface;
9
use Cakasim\Payone\Sdk\Redirect\Token\Format\EncoderExceptionInterface;
10
use Cakasim\Payone\Sdk\Redirect\Token\Format\EncoderInterface;
11
use Cakasim\Payone\Sdk\Redirect\Token\TokenFactoryInterface;
12
use Psr\Http\Message\UriFactoryInterface;
13
14
class UrlGenerator implements UrlGeneratorInterface
15
{
16
    /**
17
     * The name of the token query parameter which will be used
18
     * if the token value placeholder is not in use.
19
     */
20
    protected const TOKEN_PARAMETER_NAME = 't';
21
22
    /**
23
     * The pattern to search in the redirect URL which will
24
     * be replaced by the token value.
25
     */
26
    protected const TOKEN_PLACEHOLDER_PATTERN = '/\$TOKEN/i';
27
28
    /**
29
     * @var ConfigInterface The SDK config.
30
     */
31
    protected $config;
32
33
    /**
34
     * @var TokenFactoryInterface The redirect token factory.
35
     */
36
    protected $tokenFactory;
37
38
    /**
39
     * @var EncoderInterface The token encoder.
40
     */
41
    protected $encoder;
42
43
    /**
44
     * @var UriFactoryInterface The PSR-7 URI factory.
45
     */
46
    protected $uriFactory;
47
48
    /**
49
     * Constructs the URL generator.
50
     *
51
     * @param ConfigInterface $config The SDK config.
52
     * @param TokenFactoryInterface $tokenFactory The redirect token factory.
53
     * @param EncoderInterface $encoder The token encoder.
54
     * @param UriFactoryInterface $uriFactory The PSR-7 URI factory.
55
     */
56
    public function __construct(
57
        ConfigInterface $config,
58
        TokenFactoryInterface $tokenFactory,
59
        EncoderInterface $encoder,
60
        UriFactoryInterface $uriFactory
61
    ) {
62
        $this->config = $config;
63
        $this->tokenFactory = $tokenFactory;
64
        $this->encoder = $encoder;
65
        $this->uriFactory = $uriFactory;
66
    }
67
68
    /**
69
     * @inheritDoc
70
     */
71
    public function generate(array $data): string
72
    {
73
        try {
74
            $url = $this->config->get('redirect.url');
75
        } catch (ConfigExceptionInterface $e) {
76
            throw new UrlGeneratorException("Failed to generate the redirect URL.", 0, $e);
77
        }
78
79
        $token = $this->tokenFactory->createToken($data);
80
81
        try {
82
            $token = $this->encoder->encode($token);
83
        } catch (EncoderExceptionInterface $e) {
84
            throw new UrlGeneratorException("Failed to generate the redirect URL, could not encode the token.", 0, $e);
85
        }
86
87
        // Try to replace the token placeholder.
88
        // Return the URL if the placeholder was replaced.
89
        if ($this->replaceTokenPlaceholder($url, $token)) {
90
            return $url;
91
        }
92
93
        // Append the token parameter to the URL.
94
        return $this->appendDefaultTokenParameter($url, $token);
95
    }
96
97
    /**
98
     * Replaces the token parameter if a placeholder if used.
99
     *
100
     * @param string $url The URL.
101
     * @param string $token The token value.
102
     * @return bool True if the token placeholder was replaced.
103
     */
104
    protected function replaceTokenPlaceholder(string &$url, string $token): bool
105
    {
106
        $count = 0;
107
        $url = preg_replace(static::TOKEN_PLACEHOLDER_PATTERN, $token, $url, -1, $count);
108
109
        return $count > 0;
110
    }
111
112
    /**
113
     * Appends the default token query parameter (if possible).
114
     * If the token parameter already exists, it will not be modified.
115
     *
116
     * @param string $url The URL to which the token will be appended.
117
     * @param string $token The token to append.
118
     * @return string The URL with appended token parameter.
119
     */
120
    protected function appendDefaultTokenParameter(string $url, string $token): string
121
    {
122
        // Make PSR-7 URI from provided URL and read the query string.
123
        $uri = $this->uriFactory->createUri($url);
124
        $query = $uri->getQuery();
125
126
        // Parse the query string.
127
        $queryData = [];
128
        parse_str($query, $queryData);
129
130
        // Return untouched URL if the token parameter already exists.
131
        if (isset($queryData[static::TOKEN_PARAMETER_NAME])) {
132
            return $url;
133
        }
134
135
        // Set token parameter.
136
        $queryData[static::TOKEN_PARAMETER_NAME] = $token;
137
138
        // Build the query string.
139
        $query = http_build_query($queryData);
140
141
        return (string) $uri->withQuery($query);
142
    }
143
}
144