WeatherModelTrait::setDarkskyKey()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Showing off a standard class with methods and properties.
4
 */
5
namespace Erjh17\CallUrlModel;
6
7
/**
8
 * A trait implementing WeatherModelTrait.
9
 */
10
trait WeatherModelTrait
11
{
12
    /**
13
     * Class handling logic for fetching and parsing weather data from API calls.
14
     *
15
     * @var int        $ip  The ip address.
16
     * @var string     $message  The message.
17
     * @var boolean    $valid  If the ip address is valid.
18
     * @var string     $host  The ip adress' host.
19
     */
20
21
    private $position;
22
    private $darkSkyUrl;
23
    private $currently;
24
    private $hourly;
25
    private $daily;
26
    private $pastDays;
27
    private $darkskykey;
28
29
    public static $dateFormat = "%e %B %Y";
30
    public static $timeFormat = "%R";
31
    public static $dayFormat = "%A";
32
33
    abstract public function getInfo();
34
    abstract public function getGeoInfo();
35
    abstract public function pushInfo($result, $keys);
36
    abstract public function getZoomLevel();
37
    abstract public function setErrorMessage($msg);
38
    abstract public function fillInfo($result, $keys);
39
40
    /**
41
     * Sets darkskykey property.
42
     *
43
     * @param string $url darksky url.
44
     */
45 27
    public function setDarkskyUrl($url)
46
    {
47 27
        $this->darkSkyUrl = $url;
48 27
    }
49
50
    /**
51
     * Sets darkskykey property.
52
     *
53
     * @param string $key darksky key.
54
     */
55 27
    public function setDarkskyKey($key)
56
    {
57 27
        $this->darkskykey = $key;
58 27
    }
59
60
    /**
61
     * Get darkskykey property.
62
     *
63
     * @return string $key darksky key.
64
     */
65 4
    public function getDarkskyKey()
66
    {
67 4
        return $this->darkskykey;
68
    }
69
70
    /**
71
     * Returns specific fetched key properties.
72
     *
73
     * @return array Weather data
74
     */
75 7
    public function getWeatherInfo()
76
    {
77 7
        if ($this->currently !== null) {
78 3
            return array_merge(
79 3
                $this->getInfo(),
80 3
                $this->getGeoInfo(),
81
                array(
82 3
                    "pos" => $this->ipAddress,
83 3
                    "positionName" => $this->getPosition(),
84 3
                    "currently" => $this->currently(),
85 3
                    "hours" => $this->hourly(),
86 3
                    "days" => $this->daily(),
87 3
                    "pastDays" => $this->pastDays(),
88 3
                    "script" => $this->generateScript()
89
                )
90
            );
91
        } else {
92 4
            return array_merge(
93 4
                $this->getInfo(),
94
                array(
95 4
                    "pos" => $this->ipAddress
96
                )
97
            );
98
        }
99
    }
100
101
    /**
102
     * Sets the position property according to available properties.
103
     *
104
     * @return string Position string
105
     */
106 3
    public function getPosition()
107
    {
108 3
        $positionName = $this->ipAddress;
109 3
        if ($this->city) {
110 1
            $placeNames = array($this->city);
111 1
            if ($this->country_name) {
112 1
                array_push($placeNames, $this->country_name);
113
            }
114 1
            $positionName = implode(", ", $placeNames);
115 2
        } elseif ($this->latitude && $this->longitude) {
116 2
            $positionName = $this->latitude . ", " . $this->longitude;
117
        }
118 3
        return $positionName;
119
    }
120
121
    /**
122
     * Parses and returns the weather data for the current day
123
     *
124
     * @return array Parsed weather data.
125
     */
126 3
    public function currently()
127
    {
128 3
        $currently = [];
129 3
        setlocale(LC_ALL, 'sv_SV');
130 3
        if ($this->currently && $this->currently["time"]) {
131 3
            $currently = $this->pushInfo(
132 3
                $this->currently,
133
                [
134 3
                    "weekday",
135
                    "date",
136
                    "timeofday",
137
                    "icon",
138
                    "temperature",
139
                    "apparentTemperature",
140
                    "summary",
141
                    "windSpeed",
142
                    "precipProbability",
143
                    "pressure"
144
                ]
145
            );
146
147 3
            $time = $this->currently["time"];
148 3
            $localdate = strftime(self::$dateFormat, $time);
149 3
            $localtime = strftime(self::$timeFormat, $time);
150 3
            $weekday = strftime(self::$dayFormat, $time);
151
152 3
            $currently["weekday"] = ucfirst($weekday);
153 3
            $currently["date"] = ucfirst($localdate);
154 3
            $currently["timeofday"] = ucfirst($localtime);
155
        }
156 3
        return $currently;
157
    }
158
159
160 3
    public function generateScript()
161
    {
162 3
        $zoomLevel = $this->getZoomLevel();
163
164 3
        $latitude = str_replace(",", ".", $this->latitude);
165 3
        $longitude = str_replace(",", ".", $this->longitude);
166 3
        $zLevel = $zoomLevel["zoomLevel"];
167 3
        $radius = $zoomLevel["radius"];
168
        $script = "    window.addEventListener('load', function() {".
169 3
            "        window.initMap($longitude, $latitude, $zLevel, $radius);".
170 3
            "        var skycons = new Skycons({'color': 'white'});";
171 3
        $icon = $this->currently['icon'];
172 3
        $script .= "        skycons.add('icon1', '$icon');";
173 3
        foreach ($this->daily["data"] as $day) {
174 3
            $time = $day['time'];
175 3
            $icon = $day['icon'];
176 3
            $script .= "skycons.add('icon$time', '$icon');";
177
        }
178
        $script .= "        skycons.play();".
179 3
        "    });";
180 3
        return $script;
181
    }
182
183
    /**
184
     * Parses and returns the weather data for coming hours
185
     *
186
     * @return array Parsed weather data.
187
     */
188 3
    public function hourly()
189
    {
190 3
        $hourly = [];
191 3
        if ($this->hourly && isset($this->hourly["data"])) {
192 3
            $this->hourly["data"] = array_slice($this->hourly["data"], 0, 12);
193 3
            $hours = count($this->hourly["data"]);
194 3
            for ($i=0; $i < $hours; $i++) {
195 3
                setlocale(LC_ALL, 'sv_SV');
196 3
                $time = $this->hourly["data"][$i]["time"];
197 3
                if ($time) {
198 3
                    $this->parseDate("hourly", $i, $time);
199 3
                    $weekday = strftime(self::$dayFormat, $time);
200 3
                    $weeknr = strftime("%w", $time);
201
202 3
                    $hourly["days"][$weeknr]["hours"][$i] = $this->pushInfo(
203 3
                        $this->hourly["data"][$i],
204
                        [
205 3
                            "icon",
206
                            "timeofday",
207
                            "summary",
208
                            "temperature",
209
                            "apparentTemperature",
210
                            "date",
211
                            "weekday",
212
                            "timeofday"
213
                        ]
214
                    );
215 3
                    $hourly["days"][$weeknr]["day"] = ucfirst($weekday);
216
                }
217
            }
218
        }
219 3
        return $hourly;
220
    }
221
222
    /**
223
     * Parses and returns the weather data for the past days
224
     *
225
     * @return array Parsed weather data.
226
     */
227 3
    public function pastDays()
228
    {
229 3
        $pastDays = [];
230
231 3
        if ($this->pastDays["data"]) {
232 3
            setlocale(LC_ALL, 'sv_SV');
233 3
            $pastDayCount = count($this->pastDays["data"]);
234 3
            for ($i=0; $i < $pastDayCount; $i++) {
235 3
                $pastDaysTime = $this->pastDays["data"][$i]["time"];
236 3
                if ($pastDaysTime) {
237 3
                    $this->parseDate("pastDays", $i, $pastDaysTime);
238 3
                    $pastDays[$i] = $this->pushInfo(
239 3
                        $this->pastDays["data"][$i],
240
                        [
241 3
                            "icon",
242
                            "weekday",
243
                            "date",
244
                            "summary",
245
                            "temperatureMax",
246
                            "apparentTemperatureMax",
247
                            "temperatureMin",
248
                            "apparentTemperatureMin",
249
                            "time"
250
                        ]
251
                    );
252
                }
253
            }
254
        }
255 3
        return $pastDays;
256
    }
257
258
    /**
259
     * Parses weather data and creates date and time data and returns them.
260
     *
261
     * @param string  $arr  string representing the property
262
     *                      to be called from '$this'
263
     * @param integer $i    array index in target data object
264
     * @param int     $time Unix time integer
265
     *
266
     * @return void
267
     */
268 3
    public function parseDate($arr, $i, $time)
269
    {
270 3
        $localdate = strftime(self::$dateFormat, $time);
271 3
        $localtime = strftime(self::$timeFormat, $time);
272 3
        $weekday = strftime(self::$dayFormat, $time);
273 3
        $this->$arr["data"][$i]["date"] = $localdate;
274 3
        $this->$arr["data"][$i]["weekday"] = ucfirst($weekday);
275 3
        $this->$arr["data"][$i]["timeofday"] = $localtime;
276 3
        $this->$arr["days"][strftime("%w", $time)]["hours"][$i] = $this->$arr["data"][$i];
277 3
        $this->$arr["days"][strftime("%w", $time)]["day"] = ucfirst($weekday);
278 3
    }
279
280
    /**
281
     * Parses and returns the weather data for the coming days
282
     *
283
     * @return array Parsed weather data.
284
     */
285 3
    public function daily()
286
    {
287 3
        $days = [];
288 3
        if ($this->daily) {
289 3
            setlocale(LC_ALL, 'sv_SV');
290 3
            $comingDays = array_slice($this->daily["data"], 1, 30);
291 3
            foreach ($comingDays as $i => $data) {
292 3
                if ($data["time"]) {
293 3
                    $this->parseDate("daily", $i, $data["time"]);
294 3
                    $days[$i] = $this->pushInfo(
295 3
                        $this->daily["data"][$i],
296
                        [
297 3
                            "weekday",
298
                            "date",
299
                            "icon",
300
                            "summary",
301
                            "temperatureMax",
302
                            "apparentTemperatureMax",
303
                            "temperatureMin",
304
                            "apparentTemperatureMin",
305
                            "time"
306
                        ]
307
                    );
308
                }
309
            }
310
        }
311 3
        return $days;
312
    }
313
314
    /**
315
     * Creates array containing dates ranging 30 days back
316
     *
317
     * @return array Dates
318
     */
319 4
    public function calculateTimeMachine()
320
    {
321 4
        $days = array();
322 4
        for ($i=1; $i < 31; $i++) {
323 4
            $date = date('c', strtotime("-$i days"));
324 4
            array_push($days, strtotime($date));
325
        }
326 4
        return $days;
327
    }
328
329
    /**
330
     * Creates the arguments to go into the batch call
331
     *
332
     * @return array Array containing urls, parameters and query strings
333
     */
334 4
    public function buildArgs()
335
    {
336 4
        $time = $this->calculateTimeMachine();
337
338 4
        $urls = array($this->darkSkyUrl);
339
        $params = array(
340 4
            array($this->getDarkskyKey(), $this->latitude . "," . $this->longitude)
341
        );
342
        $queries = array(
343 4
            array("lang" => "sv", "units" => "si")
344
        );
345
346
        // var_dump($this->darkSkyUrl);
347
348 4
        foreach ($time as $day) {
349 4
            array_push($urls, $this->darkSkyUrl);
350 4
            array_push(
351 4
                $params,
352
                array(
353 4
                    $this->getDarkskyKey(),
354 4
                    $this->latitude . "," . $this->longitude . "," . $day
355
                )
356
            );
357 4
            array_push(
358 4
                $queries,
359
                array(
360 4
                    "lang" => "sv",
361
                    "units" => "si",
362
                    "exclude" => "currently,flags,hourly"
363
                )
364
            );
365
        }
366
        return [
367 4
            "urls" => $urls,
368 4
            "params" => $params,
369 4
            "queries" => $queries
370
        ];
371
    }
372
373
    /**
374
     * Batch API-calls to get weather data
375
     *
376
     * @return array Weather data
377
     */
378 7
    public function fetchWeatherInfo()
379
    {
380 7
        if ($this->latitude && $this->latitude) {
381 4
            $cUrl = $this->di->get("callurl");
382 4
            $args = $this->buildArgs();
383 4
            $apiResult = $cUrl->fetchConcurrently(
384 4
                $args["urls"],
385 4
                $args["params"],
386 4
                $args["queries"]
387
            );
388
389 4
            if (isset($apiResult[0]["error"])) {
390 1
                $this->setErrorMessage("DarkSkyError: " . $apiResult[0]['error']);
391
            }
392
393 4
            $pastDays = array("data" => []);
394
395 4
            $resultCount = count($apiResult);
396
397 4
            for ($i=1; $i<$resultCount; $i++) {
398 4
                if ($apiResult[$i] && isset($apiResult[$i]["daily"]["data"][0])) {
399 3
                    array_push($pastDays["data"], $apiResult[$i]["daily"]["data"][0]);
400
                }
401
            }
402
403
            // var_dump($apiResult);
404
405 4
            if ($apiResult[0]) {
406 4
                $this->fillInfo(
407 4
                    array_merge($apiResult[0], array("pastDays" => $pastDays)),
408
                    [
409 4
                        "currently",
410
                        "hourly",
411
                        "daily",
412
                        "pastDays"
413
                    ]
414
                );
415
            } else {
416
                $this->setErrorMessage("DarkSkyError: daily usage limit exceeded");
417
            }
418
        }
419 7
        return $this->getWeatherInfo();
420
    }
421
}
422