WeatherReport   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 248
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 79
c 1
b 0
f 0
dl 0
loc 248
ccs 82
cts 82
cp 1
rs 10
wmc 17

10 Methods

Rating   Name   Duplication   Size   Complexity  
A setApikey() 0 3 1
A buildWeatherHistoryUrls() 0 17 2
A getCurrentWeatherByCoord() 0 34 2
A getWeatherForecast() 0 21 2
A formatWeatherData() 0 21 3
A buildUrl() 0 5 1
A setSiteUrl() 0 3 1
A setCurrentDateTime() 0 3 2
A getWeatherHistory() 0 19 2
A getDatetime() 0 3 1
1
<?php
2
3
namespace Nihl\WeatherReport;
4
5
use Anax\Commons\ContainerInjectableInterface;
6
use Anax\Commons\ContainerInjectableTrait;
7
8
/**
9
 * Class module for weather report service
10
 */
11
class WeatherReport implements ContainerInjectableInterface
12
{
13
    use ContainerInjectableTrait;
14
15
    /**
16
     * @var String  $siteUrl            URL to fetch weather data
17
     * @var String  $apikey             Apikey for access
18
     * @var Integer $currentDateTime    Datetime of current time.
19
     */
20
    private $siteUrl;
21
    private $apikey;
22
    private $currentDateTime;
23
24
25
26
    /**
27
     * Set base url
28
     *
29
     * @param String $url
30
     */
31 30
    public function setSiteUrl(string $url)
32
    {
33 30
        $this->siteUrl = $url;
34 30
    }
35
36
37
38
    /**
39
     * Set apikey
40
     *
41
     * @param String $apikey
42
     */
43 29
    public function setApikey(string $apikey)
44
    {
45 29
        $this->apikey = $apikey;
46 29
    }
47
48
49
    /**
50
     * Set current timestamp
51
     *
52
     */
53 30
    public function setCurrentDateTime(object $dt = null)
54
    {
55 30
        $this->currentDateTime = $dt instanceof \Datetime ? $dt : new \Datetime();
56 30
    }
57
58
59
60
    /**
61
     * Get current timestamp
62
     *
63
     * @return Datetime
0 ignored issues
show
Bug introduced by
The type Nihl\WeatherReport\Datetime was not found. Did you mean Datetime? If so, make sure to prefix the type with \.
Loading history...
64
     */
65 6
    public function getDatetime()
66
    {
67 6
        return $this->currentDateTime ?? new \Datetime();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->currentDateTime ?? new Datetime() also could return the type Datetime which is incompatible with the documented return type Nihl\WeatherReport\Datetime.
Loading history...
68
    }
69
70
71
72
    /**
73
     * Build url strings, extending http_build_query
74
     *
75
     * @param String    $baseUrl    Url to use
76
     * @param Array     $queries    Array with queries
77
     * @param String    $path       [Optional] Path to api
78
     *
79
     * @return String
80
     */
81 17
    public function buildUrl(string $baseUrl, array $queries, string $path = "")
82
    {
83 17
        $queryString = http_build_query($queries);
84
85 17
        return $baseUrl . $path . "?$queryString";
86
    }
87
88
89
90
    /**
91
     * Creates an array of URLs to use with openweathermap.org
92
     * eg. http://api.openweathermap.org/data/2.5/onecall/timemachine?lat=$lat&lon=$lon&appid=$apikey&dt=$dt->getTimestamp()
93
     *
94
     * @param Float     $lat    Latitude
95
     * @param Float     $lon    Longitude
96
     * @param Object    $dt     Datetime of request
97
     * @param String    $apikey Apikey to access data
98
     *
99
     * @return Array    $urls   Array of strings
100
     */
101 6
    public function buildWeatherHistoryUrls(float $lat, float $lon, object $dt, string $apikey)
102
    {
103
        $queries = [
104 6
            "lat" => $lat,
105 6
            "lon" => $lon,
106 6
            "lang" => "se",
107 6
            "units" => "metric",
108 6
            "appid" => $apikey
109
        ];
110
111 6
        $urls = array();
112 6
        for ($i = 0; $i < 5; $i++) {
113 6
            $dt->modify("-1 day");
114 6
            $queries["dt"] = $dt->getTimestamp();
115 6
            $urls[] = $this->buildUrl($this->siteUrl, $queries, "/onecall/timemachine");
116
        }
117 6
        return $urls;
118
    }
119
120
    /**
121
     * Formats data from openweathermap
122
     *
123
     * @param  Array    $data       Data to be formatted
124
     * @param  String   $format     Changes how data is formatted
125
     *
126
     * @return Array    $formattedData
127
     */
128 12
    public function formatWeatherData(array $data, string $format)
129
    {
130
        $formattedData = [
131 12
            "dt" => date('D j M', $data["dt"]),
132 12
            "humidity" => $data["humidity"],
133 12
            "weather" => $data["weather"][0]["description"],
134 12
            "sunrise" => date("H:i", $data["sunrise"]),
135 12
            "sunset" => date("H:i", $data["sunset"])
136
        ];
137
138 12
        if ($format == "forecast") {
139 6
            $formattedData["min"] = $data["temp"]["min"];
140 6
            $formattedData["max"] = $data["temp"]["max"];
141
        }
142
143 12
        if ($format == "history") {
144 6
            $formattedData["temp"] = $data["temp"];
145 6
            $formattedData["feels_like"] = $data["feels_like"];
146
        }
147
148 12
        return $formattedData;
149
    }
150
151
152
153
    /**
154
     * Make 5 curl requests to a weather api to get weather data from the last five days
155
     *
156
     * @param Float     $lat    Latitude of position
157
     * @param Float     $lon    Longitude of position
158
     *
159
     * @return Array            Array of data
160
     */
161 5
    public function getWeatherHistory($lat = null, $lon = null)
162
    {
163
        // Inject curl
164 5
        $curl = $this->di->get("curl");
165
166
        // Get current datetime
167 5
        $dt = $this->getDatetime();
168
169
        // Build urls
170 5
        $urls = $this->buildWeatherHistoryUrls($lat, $lon, $dt, $this->apikey);
0 ignored issues
show
Bug introduced by
It seems like $lat can also be of type null; however, parameter $lat of Nihl\WeatherReport\Weath...ildWeatherHistoryUrls() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

170
        $urls = $this->buildWeatherHistoryUrls(/** @scrutinizer ignore-type */ $lat, $lon, $dt, $this->apikey);
Loading history...
Bug introduced by
It seems like $lon can also be of type null; however, parameter $lon of Nihl\WeatherReport\Weath...ildWeatherHistoryUrls() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

170
        $urls = $this->buildWeatherHistoryUrls($lat, /** @scrutinizer ignore-type */ $lon, $dt, $this->apikey);
Loading history...
171 5
        $data = $curl->doMultiRequest($urls);
172
173
        // Format data to get desired output
174 5
        $formattedData = [];
175 5
        foreach ($data as $day) {
176 5
            array_unshift($formattedData, $this->formatWeatherData($day["current"], "history"));
177
        }
178
179 5
        return $formattedData;
180
    }
181
182
183
184
    /**
185
     * Get weather forecast of the coming week
186
     *
187
     * @param float     $lat    Latitude of position
188
     * @param float     $lon    Longitude of position
189
     *
190
     * @return array            Array of data
191
     */
192 5
    public function getWeatherForecast($lat = null, $lon = null)
193
    {
194 5
        $curl = $this->di->get("curl");
195
196
        $queries = [
197 5
            "lat" => $lat,
198 5
            "lon" => $lon,
199 5
            "exclude" => "minutely,hourly,current",
200 5
            "lang" => "se",
201 5
            "units" => "metric",
202 5
            "appid" => $this->apikey
203
        ];
204
205
        // Create url and make curl request
206 5
        $url = $this->buildUrl($this->siteUrl, $queries, "/onecall");
207 5
        $data = json_decode($curl->doRequest($url), true);
208
209 5
        foreach ($data["daily"] as $day) {
210 5
            $formattedData[] = $this->formatWeatherData($day, "forecast");
211
        }
212 5
        return $formattedData;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $formattedData seems to be defined by a foreach iteration on line 209. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
213
    }
214
215
216
217
    /**
218
     * Get current weather using coord
219
     *
220
     * @param float     $lat    Latitude of position
221
     * @param float     $lon    Longitude of position
222
     *
223
     * @return array            Array of data
224
     */
225 13
    public function getCurrentWeatherByCoord($lat = null, $lon = null)
226
    {
227 13
        $curl = $this->di->get("curl");
228
229
        $queries = [
230 13
            "lat" => $lat,
231 13
            "lon" => $lon,
232 13
            "lang" => "se",
233 13
            "units" => "metric",
234 13
            "appid" => $this->apikey
235
        ];
236
237
        // Create url and make curl request
238 13
        $url = $this->buildUrl($this->siteUrl, $queries, "/weather");
239 13
        $data = json_decode($curl->doRequest($url), true);
240
        // Check if data response is ok and format data
241
        // else return data
242 13
        if ($data["cod"] != 200) {
243 4
            return $data;
244
        }
245
246
        $formattedData = [
247 9
            "cod" => $data["cod"],
248 9
            "dt" => date('D j M', $data["dt"]),
249 9
            "name" => $data["name"],
250 9
            "temp" => $data["main"]["temp"],
251 9
            "feels_like" => $data["main"]["feels_like"],
252 9
            "humidity" => $data["main"]["humidity"],
253 9
            "weather" => $data["weather"][0]["description"],
254 9
            "sunrise" => date("H:i", $data["sys"]["sunrise"]),
255 9
            "sunset" => date("H:i", $data["sys"]["sunset"]),
256
        ];
257
258 9
        return $formattedData;
259
    }
260
}
261