Api   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 7
dl 0
loc 148
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A execute() 0 16 3
A getClient() 0 6 1
A createHandler() 0 28 5
A generateUserAgent() 0 4 1
A __construct() 0 4 1
A baseUrl() 0 4 1
A _get() 0 4 1
A cacheValue() 0 8 3
1
<?php
2
3
/*
4
 * Part of the Saudi Address API PHP package.
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * Licensed under the MIT.
9
 *
10
 * This source file is subject to the MIT License that is
11
 * bundled with this package in the LICENSE file.
12
 *
13
 * @package    Saudi Address
14
 * @version    1.3
15
 * @author     Ali Alharthi
16
 * @license    MIT
17
 * @copyright  (c) 2020, Ali Alharthi
18
 * @link       https://aalharthi.sa
19
 */
20
21
namespace AliAlharthi\SaudiAddress\Api;
22
23
use AliAlharthi\SaudiAddress\ConfigInterface;
24
use AliAlharthi\SaudiAddress\Exception\Handler;
25
use GuzzleHttp\Client;
26
use GuzzleHttp\Exception\ClientException;
27
use GuzzleHttp\Exception\ConnectException;
28
use GuzzleHttp\Exception\TransferException;
29
use GuzzleHttp\HandlerStack;
30
use GuzzleHttp\Middleware;
31
use Psr\Http\Message\RequestInterface;
32
use Psr\Http\Message\ResponseInterface;
33
use RuntimeException;
34
35
abstract class Api implements ApiInterface
36
{
37
    const API_BASE_URL = 'https://apina.address.gov.sa/NationalAddress/';
38
    const USER_AGENT_SUFFIX = "alharthi-saudi-address-api-php-client/";
39
    const IN_CHARACTER_ENCODING = 'windows-1256';
40
    const OUT_CHARACTER_ENCODING = 'UTF-8';
41
42
    /**
43
     * The Config repository instance.
44
     *
45
     * @var \AliAlharthi\SaudiAddress\ConfigInterface
46
     */
47
    protected $config;
48
49
    /**
50
     * Constructor.
51
     *
52
     * @param   \AliAlharthi\SaudiAddress\ConfigInterface  $config
53
     */
54
    public function __construct(ConfigInterface $config)
55
    {
56
        $this->config = $config;
57
    }
58
59
    /**
60
     * Returns the Saudi National Address API endpoint.
61
     *
62
     * @return  string
63
     */
64
    public function baseUrl()
65
    {
66
        return self::API_BASE_URL;
67
    }
68
69
    /**
70
     * Execute a get request.
71
     *
72
     * @param   string  $url
73
     * @param   string  $lang
74
     * @param   array   $parameters
75
     * @param   bool    $encode
76
     * @return  null|array
77
     */
78
    public function _get($url = null, $lang = 'A', $parameters = [], $encode = true)
79
    {
80
        return $this->execute('get', $url, $lang, $parameters, $encode);
81
    }
82
83
    /**
84
     * Execute a request.
85
     *
86
     * @param   string  $httpMethod
87
     * @param   string  $url
88
     * @param   string  $lang
89
     * @param   array   $parameters
90
     * @param   bool    $encode
91
     * @return  null|array
92
     * @throws  AliAlharthi\SaudiAddress\Exception\Handler
93
     */
94
    public function execute($httpMethod, $url, $lang = 'A', array $parameters = [], $encode = true)
95
    {
96
        try {
97
            $parameters['format'] = 'json';
98
            $parameters['language'] = $lang;
99
            $parameters = http_build_query($parameters);
100
            $response = $this->getClient()->{$httpMethod}($url, ['query' => $parameters]);
101
102
            return ($encode) ?
103
                json_decode(iconv(self::IN_CHARACTER_ENCODING, self::OUT_CHARACTER_ENCODING, ($response->getBody())), true) :
104
                json_decode($response->getBody(), true);
105
106
        } catch (ClientException $e) {
107
            new Handler($e);
108
        }
109
    }
110
111
    /**
112
     * Returns an Http client instance.
113
     *
114
     * @return  \GuzzleHttp\Client
115
     */
116
    protected function getClient()
117
    {
118
        return new Client([
119
            'base_uri' => $this->baseUrl(), 'handler' => $this->createHandler()
120
        ]);
121
    }
122
123
    /**
124
     * Create the client handler.
125
     *
126
     * @return  \GuzzleHttp\HandlerStack
127
     * @throws  \RuntimeException
128
     */
129
    protected function createHandler()
130
    {
131
        if (! $this->config->getApiKey()) {
132
            throw new RuntimeException('The Saudi National Address API key is not defined.');
133
        }
134
135
        $stack = HandlerStack::create();
136
137
        $stack->push(Middleware::mapRequest(function (RequestInterface $request) {
138
            $config = $this->config;
139
140
            $request = $request->withHeader('api_key', $config->getApiKey());
141
142
            $request = $request->withHeader('User-Agent', $this->generateUserAgent());
143
144
            $request = $request->withHeader('accept', 'application/json');
145
146
            return $request;
147
        }));
148
149
        $stack->push(Middleware::retry(function ($retries, RequestInterface $request, ResponseInterface $response = null, TransferException $exception = null) {
150
            return $retries < 3 && ($exception instanceof ConnectException || ($response && $response->getStatusCode() >= 500));
151
        }, function ($retries) {
152
            return (int) pow(2, $retries) * 1000;
153
        }));
154
155
        return $stack;
156
    }
157
158
    /**
159
     * Generates the main user agent string.
160
     *
161
     * @return  string
162
     */
163
    protected function generateUserAgent()
164
    {
165
        return self::USER_AGENT_SUFFIX . $this->config->getVersion();
166
    }
167
168
    /**
169
     * Return a value from cache.
170
     *
171
     * @param   string  $file
172
     * @return  array|null
173
     */
174
    protected function cacheValue($file)
175
    {
176
        if ($this->config->getCache() && file_exists($file)) {
177
            return unserialize(file_get_contents($file));
178
        }
179
180
        return null;
181
    }
182
}
183