Completed
Push — master ( 3150c4...4cbb1c )
by
unknown
02:06
created

src/WooCommerce/HttpClient/OAuth.php (1 issue)

assigning incompatible types to properties.

Bug Documentation Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * WooCommerce oAuth1.0
4
 *
5
 * @category HttpClient
6
 * @package  Automattic/WooCommerce
7
 */
8
9
namespace Automattic\WooCommerce\HttpClient;
10
11
/**
12
 * oAuth1.0 class.
13
 *
14
 * @package Automattic/WooCommerce
15
 */
16
class OAuth
17
{
18
19
    /**
20
     * OAuth signature method algorithm.
21
     */
22
    const HASH_ALGORITHM = 'SHA256';
23
24
    /**
25
     * API endpoint URL.
26
     *
27
     * @var string
28
     */
29
    protected $url;
30
31
    /**
32
     * Consumer key.
33
     *
34
     * @var string
35
     */
36
    protected $consumerKey;
37
38
    /**
39
     * Consumer secret.
40
     *
41
     * @var string
42
     */
43
    protected $consumerSecret;
44
45
    /**
46
     * API version.
47
     *
48
     * @var array
49
     */
50
    protected $apiVersion;
51
52
    /**
53
     * Request method.
54
     *
55
     * @var string
56
     */
57
    protected $method;
58
59
    /**
60
     * Request parameters.
61
     *
62
     * @var array
63
     */
64
    protected $parameters;
65
66
    /**
67
     * Timestamp.
68
     *
69
     * @var string
70
     */
71
    protected $timestamp;
72
73
    /**
74
     * Initialize oAuth class.
75
     *
76
     * @param string $url            Store URL.
77
     * @param string $consumerKey    Consumer key.
78
     * @param string $consumerSecret Consumer Secret.
79
     * @param string $method         Request method.
80
     * @param string $apiVersion     API version.
81
     * @param array  $parameters     Request parameters.
82
     * @param string $timestamp      Timestamp.
83
     */
84
    public function __construct($url, $consumerKey, $consumerSecret, $apiVersion, $method, $parameters = [], $timestamp = '')
85
    {
86
        $this->url            = $url;
87
        $this->consumerKey    = $consumerKey;
88
        $this->consumerSecret = $consumerSecret;
89
        $this->apiVersion     = $apiVersion;
0 ignored issues
show
Documentation Bug introduced by
It seems like $apiVersion of type string is incompatible with the declared type array of property $apiVersion.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
90
        $this->method         = $method;
91
        $this->parameters     = $parameters;
92
        $this->timestamp      = $timestamp;
93
    }
94
95
    /**
96
     * Normalize strings.
97
     *
98
     * @param string $string String to be normalized.
99
     *
100
     * @return string
101
     */
102
    protected function normalizeString($string)
103
    {
104
        return \str_replace('%', '%25', \rawurlencode(\rawurldecode($string)));
105
    }
106
107
    /**
108
     * Normalize parameters.
109
     *
110
     * @param array $parameters Parameters to normalize.
111
     *
112
     * @return array
113
     */
114
    protected function normalizeParameters($parameters)
115
    {
116
        $normalized = [];
117
118
        foreach ($parameters as $key => $value) {
119
            // Percent symbols (%) must be double-encoded.
120
            $key   = $this->normalizeString($key);
121
            $value = $this->normalizeString($value);
122
123
            $normalized[$key] = $value;
124
        }
125
126
        return $normalized;
127
    }
128
129
    /**
130
     * Process filters.
131
     *
132
     * @param array $parameters Request parameters.
133
     *
134
     * @return array
135
     */
136
    protected function processFilters($parameters)
137
    {
138
        if (isset($parameters['filter'])) {
139
            $filters = $parameters['filter'];
140
            unset($parameters['filter']);
141
            foreach ($filters as $filter => $value) {
142
                $parameters['filter[' . $filter . ']'] = $value;
143
            }
144
        }
145
146
        return $parameters;
147
    }
148
149
    /**
150
     * Get secret.
151
     *
152
     * @return string
153
     */
154
    protected function getSecret()
155
    {
156
        $secret = $this->consumerSecret;
157
158
        // Fix secret for v3 or later.
159
        if (!\in_array($this->apiVersion, ['v1', 'v2'])) {
160
            $secret .= '&';
161
        }
162
163
        return $secret;
164
    }
165
166
    /**
167
     * Generate oAuth1.0 signature.
168
     *
169
     * @param array $parameters Request parameters including oauth.
170
     *
171
     * @return string
172
     */
173
    protected function generateOauthSignature($parameters)
174
    {
175
        $baseRequestUri = \rawurlencode($this->url);
176
177
        // Extract filters.
178
        $parameters = $this->processFilters($parameters);
179
180
        // Normalize parameter key/values and sort them.
181
        $parameters = $this->normalizeParameters($parameters);
182
        \uksort($parameters, 'strcmp');
183
184
        // Set query string.
185
        $query = [];
186
        foreach ($parameters as $key => $value) {
187
            $query[] = $key . '%3D' . $value; // Join with equals sign.
188
        }
189
190
        $queryString  = \implode('%26', $query); // Join with ampersand.
191
        $stringToSign = $this->method . '&' . $baseRequestUri . '&' . $queryString;
192
        $secret       = $this->getSecret();
193
194
        return \base64_encode(\hash_hmac(self::HASH_ALGORITHM, $stringToSign, $secret, true));
195
    }
196
197
    /**
198
     * Sort parameters.
199
     *
200
     * @param array $parameters Parameters to sort in byte-order.
201
     *
202
     * @return array
203
     */
204
    protected function getSortedParameters($parameters)
205
    {
206
        \uksort($parameters, 'strcmp');
207
208
        foreach ($parameters as $key => $value) {
209
            if (\is_array($value)) {
210
                \uksort($parameters[$key], 'strcmp');
211
            }
212
        }
213
214
        return $parameters;
215
    }
216
217
    /**
218
     * Get oAuth1.0 parameters.
219
     *
220
     * @return string
221
     */
222
    public function getParameters()
223
    {
224
        $parameters = \array_merge($this->parameters, [
225
            'oauth_consumer_key'     => $this->consumerKey,
226
            'oauth_timestamp'        => $this->timestamp,
227
            'oauth_nonce'            => \sha1(\microtime()),
228
            'oauth_signature_method' => 'HMAC-' . self::HASH_ALGORITHM,
229
        ]);
230
231
        // The parameters above must be included in the signature generation.
232
        $parameters['oauth_signature'] = $this->generateOauthSignature($parameters);
233
234
        return $this->getSortedParameters($parameters);
235
    }
236
}
237