WeatherModel::getDate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Anax\Weather;
4
5
// use Anax\Route\Exception\ForbiddenException;
6
// use Anax\Route\Exception\NotFoundException;
7
// use Anax\Route\Exception\InternalErrorException;
8
9
/**
10
 * Model class witch main responsability is handeling data for /vader
11
 *
12
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
13
 */
14
class WeatherModel
15
{
16
    /**
17
     * @var string $apiKey initializes the key
18
     */
19
    protected $apiKey;
20
21
    /**
22
     * Sets the api key.
23
     *
24
     * @return void
25
     */
26 4
    public function __construct()
27
    {
28 4
        $prep = require ANAX_INSTALL_PATH . "/config/keys.php";
29 4
        $this->apiKey = $prep["darksky"];
30 4
    }
31
32
    /**
33
     * Gets the weekly weather.
34
     *
35
     * @param array $coords contains the values longitude and latitude.
36
     *
37
     * @return array with the weekly weather data.
38
     */
39 2
    public function getData(array $coords) : array
40
    {
41 2
        if (!isset($coords[0]['lat']) || !isset($coords[0]['lon'])) {
42 1
            return [];
43
        }
44
45 1
        $accessKey = $this->apiKey;
46 1
        $location = $coords[0]['lat'] . ',' . $coords[0]['lon'];
47
48 1
        $chA = curl_init(
49
            'https://api.darksky.net/forecast/'.
50 1
            $accessKey . '/' . $location.
51 1
            '?exclude=minutely,hourly,currently,alerts,flags&extend=daily&lang=sv&units=auto'
52
        );
53 1
        curl_setopt($chA, CURLOPT_RETURNTRANSFER, true);
54 1
        $json = curl_exec($chA);
55 1
        curl_close($chA);
56
57 1
        $apiRes = json_decode($json, true);
58 1
        return [$apiRes];
59
    }
60
61
    /**
62
     * Gets todays date and subtract the number of days sent in
63
     *
64
     * @param string|int $nrOfDays the number of days
65
     *
66
     * @return string the date in unix format
67
     */
68 1
    public function getDate($nrOfDays) : string
69
    {
70 1
        $myDate = new \Datetime();
71 1
        $myDate->sub(new \DateInterval('P'. (intval($nrOfDays) + 1) .'D'));
72 1
        return $myDate->format('U');
73
    }
74
75
    /**
76
     * Takes a location and turns it into coordinates.
77
     *
78
     * @param string $adrs the location, can be anything like Zip, adress and so on
79
     *
80
     * @return array with longitude and latitude values NOTE: will be empty if nothing is found
81
     */
82 2
    public function geocode(string $adrs) : array
83
    {
84 2
        $city = urlencode($adrs);
85
86
        // Just a random email query (not returning anything wihtout it ??)
87 2
        $url = "https://nominatim.openstreetmap.org/?format=json&addressdetails=1&q={$city}&limit=1&[email protected]";
88
        
89 2
        $chA = curl_init($url);
90 2
        curl_setopt($chA, CURLOPT_RETURNTRANSFER, true);
91 2
        $json = curl_exec($chA);
92 2
        curl_close($chA);
93
94 2
        $apiRes = json_decode($json, true) ?? [];
95 2
        return $apiRes;
96
    }
97
98
    /**
99
     * Preforms a multi curl to get the previus weather
100
     *
101
     * @param string|int    $nrOfDays amount of previus days
102
     * @param string        $adrs the position
103
     *
104
     * @return array with all the weather details for each day
105
     */
106 2
    public function multiCurl($nrOfDays, string $adrs) : array
107
    {
108 2
        $urls = $this->getUrls($nrOfDays, $adrs);
109
110 2
        if ($urls == [[]] || $urls == []) {
111 1
            return [[]];
112
        }
113
114 1
        $multi = curl_multi_init();
115 1
        $handles = [];
116 1
        $htmls = [];
117
118 1
        foreach ($urls as $url) {
119 1
            $ch = curl_init($url);
120 1
            curl_setopt($ch, CURLOPT_HEADER, false);
121 1
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
122
123 1
            curl_multi_add_handle($multi, $ch);
124 1
            $handles[$url] = $ch;
125
        }
126
127 1
        $this->startMultiCurl($multi);
128
129 1
        foreach ($handles as $channel) {
130 1
            $html = curl_multi_getcontent($channel);
131 1
            $htmls[] = json_decode($html, true);
132 1
            curl_multi_remove_handle($multi, $channel);
133
        }
134
135 1
        curl_multi_close($multi);
136
137 1
        return $htmls;
138
    }
139
140
    /**
141
     * Continueation for $this->multiCurl
142
     */
143 1
    public function startMultiCurl($multi)
144
    {
145
        do {
146 1
            $mrc = curl_multi_exec($multi, $active);
147 1
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
148
149 1
        while ($active && $mrc == CURLM_OK) {
150 1
            if (curl_multi_select($multi) == -1) {
151 1
                usleep(100);
152
            }
153
            do {
154 1
                $mrc = curl_multi_exec($multi, $active);
155 1
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
156
        }
157 1
    }
158
159
    /**
160
     * Returns the api key for DarkS.N
161
     *
162
     * @return string api key
163
     */
164 1
    private function getKey() : string
165
    {
166 1
        return $this->apiKey;
167
    }
168
169
    /**
170
     * Returns a list of urls
171
     *
172
     * @param string|int $nrOfDays the total amount of days (MAX 30)
173
     * @param string $adrs the given adress/location
174
     *
175
     * @return array a list of urls to curl
176
     */
177 2
    private function getUrls($nrOfDays, string $adrs) : array
178
    {
179 2
        $coords = $this->geocode($adrs);
180 2
        $nrOfDays = ($nrOfDays > 30) ? 30 : $nrOfDays;
181
182 2
        if ($coords == []) {
183 1
            return [[]];
184
        }
185
186 1
        $urls = [];
187 1
        $accessKey = $this->getKey();
188 1
        $location = $coords[0]['lat'] . ',' . $coords[0]['lon'];
189
190 1
        for ($i = 0; $i < $nrOfDays; $i++) {
191 1
            $time = $this->getDate("$i");
192 1
            $urls[] = 'https://api.darksky.net/forecast/'.$accessKey.'/'.$location.','.$time.'?exclude=minutely,hourly,currently,alerts,flags&extend=daily&lang=sv&units=auto';
193
        }
194
195 1
        return $urls;
196
    }
197
    /**
198
     * Method to test dipendency injection
199
     * Might aswell be ignored
200
     *
201
     * @return string the title for a view
202
     */
203 1
    public function hello() : string
204
    {
205 1
        return 'Väder app (Test - Taget från $di->get("weather"))';
206
    }
207
}
208