Api::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 3
crap 2
1
<?php
2
3
/*
4
 * This file is part of the PhpMob package.
5
 *
6
 * (c) Ishmael Doss <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace PhpMob\Omise;
15
16
use PhpMob\Omise\Client\HttpClientInterface;
17
use PhpMob\Omise\Domain\Error;
18
use PhpMob\Omise\Exception\InvalidRequestArgumentException;
19
use PhpMob\Omise\Exception\InvalidResponseException;
20
use PhpMob\Omise\Hydrator\Hydration;
21
use PhpMob\Omise\Hydrator\HydrationInterface;
22
use Psr\Http\Message\ResponseInterface;
23
use Symfony\Component\OptionsResolver\OptionsResolver;
24
25
/**
26
 * @author Ishmael Doss <[email protected]>
27
 */
28
abstract class Api
29
{
30
    /**
31
     * @var bool
32
     */
33
    protected $isSensitive = false;
34
35
    /**
36
     * @var string
37
     */
38
    protected $countryCode = 'th';
39
40
    /**
41
     * @var HttpClientInterface
42
     */
43
    protected $httpClient;
44
45
    /**
46
     * @var array
47
     */
48
    protected $options;
49
50
    /**
51
     * @var HydrationInterface
52
     */
53
    private $hydration;
54
55 62
    /**
56
     * @param HttpClientInterface $httpClient
57 62
     * @param array $options
58
     * @param HydrationInterface $hydration
59 62
     */
60 62
    public function __construct(HttpClientInterface $httpClient, array $options, HydrationInterface $hydration = null)
61
    {
62 62
        $this->httpClient = $httpClient;
63 62
64 62
        $resolver = new OptionsResolver();
65 62
        $this->configureOptions($resolver);
66
67
        $this->options = $resolver->resolve($options);
68
        $this->hydration = $hydration ?: new Hydration();
69
        $this->isSensitive = $this->options['sensitive'];
70 62
        $this->countryCode = $this->options['country_code'];
71
    }
72 62
73
    /**
74 62
     * @param OptionsResolver $resolver
75 62
     */
76 62
    protected function configureOptions(OptionsResolver $resolver)
77
    {
78 62
        $resolver->setRequired(['secret_key', 'public_key', 'sandbox']);
79 62
80
        $resolver->setAllowedTypes('secret_key', 'string');
81
        $resolver->setAllowedTypes('public_key', 'string');
82
        $resolver->setAllowedTypes('sandbox', 'boolean');
83
84 51
        $resolver->setDefault('sensitive', $this->isSensitive);
85
        $resolver->setDefault('country_code', $this->countryCode);
86 51
    }
87
88
    /**
89
     * @return string
90
     */
91
    protected function getAuthorizationKey()
92 51
    {
93
        return 'Basic ' . base64_encode($this->options[$this->isSensitive ? 'public_key' : 'secret_key'] . ':');
94 51
    }
95
96
    /**
97
     * @return string
98
     */
99
    protected function getApiServer()
100
    {
101
        return $this->isSensitive ? OmiseApi::OMISE_VAULT_ENDPOINT : OmiseApi::OMISE_ENDPOINT;
102
    }
103
104
    /**
105
     * @param string $method
106
     * @param string $path
107 51
     * @param array $data
108
     * @param array $headers
109 51
     *
110
     * @return mixed|Model
111 51
     *
112 19
     * @throws InvalidResponseException
113 19
     */
114
    protected function doRequest($method, $path, array $data = [], array $headers = [])
115
    {
116 51
        $headers = array_merge(['Authorization' => $this->getAuthorizationKey()], $headers);
117 51
118
        if ('GET' !== strtoupper($method)) {
119 51
            $data = array_merge($data, ['livemode' => !$this->options['sandbox']]);
120
            $headers = array_merge(['Content-Type' => 'application/json; charset=utf-8'], $headers);
121
        }
122
123
        $uri = preg_replace('/([^:])(\/{2,})/', '$1/', $this->getApiServer() . $path);
124
        $response = $this->httpClient->send($method, $uri, $data, $headers);
125
126
        return $this->hydrateResponse($response);
127
    }
128
129 51
    /**
130
     * @param ResponseInterface $response
131 51
     *
132
     * @return mixed|Model
133
     *
134 51
     * @throws InvalidResponseException
135
     */
136
    protected function hydrateResponse(ResponseInterface $response)
137
    {
138
        $content = $response->getBody()->getContents();
139
140
        // non api error, mock server error.
141
        if (empty($content) && $response->getStatusCode() >= 400) {
142
            $content = json_encode(
143
                [
144 51
                    'object' => 'error',
145
                    'code' => 'http_error_' . $response->getStatusCode(),
146 51
                    'message' => $response->getReasonPhrase(),
147
                ]
148
            );
149
        }
150 51
151
        $result = $this->hydration->hydrate($content);
152
153
        if ($result instanceof Error) {
154
            throw new InvalidResponseException($result);
155
        }
156
157
        return $result;
158
    }
159 39
160
    /**
161 39
     * @param mixed $id
162 11
     * @param string $message
163
     *
164 28
     * @throws InvalidRequestArgumentException
165
     */
166
    protected static function assertNotEmpty($id, $message = 'Id can not be empty.')
167
    {
168
        if (empty($id)) {
169
            throw new InvalidRequestArgumentException($message);
170
        }
171
    }
172
}
173