Completed
Push — master ( fa72c9...1b6f39 )
by Oleksandr
02:59
created

CurrentWeatherData::validateCountryCode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Savchenko\Bundle\OpenWeatherMapBundle\Api;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\ClientException;
7
use GuzzleHttp\Exception\GuzzleException;
8
use Psr\Http\Message\ResponseInterface;
9
use Savchenko\Bundle\OpenWeatherMapBundle\Exception\BadRequestException;
10
use Savchenko\Bundle\OpenWeatherMapBundle\Exception\InvalidCountryCodeException;
11
use Symfony\Component\Intl\Intl;
12
13
/**
14
 * Get current weather data information
15
 *
16
 * @author Oleksandr Savchenko
17
 */
18
class CurrentWeatherData
19
{
20
    /**
21
     * @var string OpenWeatherMap API key
22
     */
23
    private $apiKey;
24
25
    /**
26
     * @var Client
27
     */
28
    private $client;
29
30 11
    public function __construct(string $apiKey, Client $client)
31
    {
32 11
        $this->apiKey = $apiKey;
33 11
        $this->client = $client;
34 11
    }
35
36
    /**
37
     * Send request to OpenWeatherMap API endpoint
38
     *
39
     * @param array $params query parameters
40
     * @return ResponseInterface
41
     * @throws BadRequestException
42
     * @throws GuzzleException
43
     */
44 9
    private function sendRequest(array $params) : ResponseInterface {
45 9
        $params = array_merge(['appid' => $this->apiKey], $params);
46
47
        try {
48 9
            $response = $this->client->get('', [
49 9
                'query' => $params,
50
            ]);
51
        }
52 3
        catch (ClientException $exception) {
53 3
            switch ($exception->getCode()) {
54
                case 401:
55 1
                    throw new BadRequestException('You doesn\'t set APPID parameter or it has incorrect value');
56 1
                case 403:
57 1
                    throw new BadRequestException('Data available only on commercial terms');
58
                default:
59 1
                    throw $exception;
60
            }
61
        }
62
63 6
        return $response;
64
    }
65
66
    /**
67
     * Validate country code
68
     *
69
     * @param string $countryCode country code in ISO 3166-1 alpha-2 format
70
     * @return bool
71
     * @throws InvalidCountryCodeException
72
     */
73 4
    private function validateCountryCode(string $countryCode) :bool
74
    {
75 4
        if (Intl::getRegionBundle()->getCountryName($countryCode) === null) {
76 2
            throw new InvalidCountryCodeException('You should provide ISO 3166-1 alpha-2 country code');
77
        }
78
79 2
        return true;
80
    }
81
82
    /**
83
     * Call by city name or city name and country code
84
     *
85
     * @param string $cityName
86
     * @param string $countryCode optional country code in ISO 3166-1 alpha-2 format
87
     * @return \stdClass
88
     * @throws GuzzleException on request exception
89
     * @throws BadRequestException
90
     * @throws InvalidCountryCodeException on incorrect country code
91
     */
92 6
    public function loadByCityName(string $cityName, string $countryCode = null) : \stdClass
93
    {
94 6
        return json_decode(
95 6
            $this->sendRequest(['q' => $this->addCountryCodeToBase($cityName, $countryCode)])->getBody()
96
        );
97
    }
98
99
    /**
100
     * Call by city id
101
     *
102
     * @param string $cityCode
103
     * @return \stdClass
104
     * @throws GuzzleException on request exception
105
     * @throws BadRequestException
106
     */
107 1
    public function loadByCityId(string $cityCode) : \stdClass
108
    {
109 1
        return json_decode($this->sendRequest(['id' => $cityCode])->getBody());
110
    }
111
112
    /**
113
     * Call by geographic coordinates
114
     *
115
     * @param float $lat location latitude 
116
     * @param float $lon location longitude
117
     * @return \stdClass
118
     * @throws GuzzleException on request exception
119
     * @throws BadRequestException
120
     */
121 1
    public function loadByGeographicCoordinates(float $lat, float $lon) : \stdClass
122
    {
123 1
        return json_decode($this->sendRequest(['lat' => $lat, 'lon' => $lon])->getBody());
124
    }
125
126
    /**
127
     * Call by city name or city name and country code
128
     *
129
     * @param string $zipCode zip code
130
     * @param string $countryCode optional country code in ISO 3166-1 alpha-2 format
131
     * @return \stdClass
132
     * @throws GuzzleException on request exception
133
     * @throws BadRequestException
134
     * @throws InvalidCountryCodeException on incorrect country code
135
     */
136 3
    public function loadByZipCode(string $zipCode, string $countryCode = null) : \stdClass
137
    {
138 3
        return json_decode(
139 3
            $this->sendRequest(['zip' => $this->addCountryCodeToBase($zipCode, $countryCode)])->getBody()
140
        );
141
    }
142
143
    /**
144
     * Add country code to city name or zip code
145
     *
146
     * @param string $base
147
     * @param string|null $countryCode
148
     * @return string
149
     * @throws InvalidCountryCodeException
150
     */
151 9
    private function addCountryCodeToBase(string $base, string $countryCode = null) : string
152
    {
153 9
        if ($countryCode !== null) {
154 4
            $this->validateCountryCode($countryCode);
155
156 2
            $base .= ',' . $countryCode;
157
        }
158
159 7
        return $base;
160
    }
161
}