Completed
Pull Request — master (#58)
by
unknown
03:04
created

OpenWeatherMap::getApiKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * OpenWeatherMap-PHP-API — A php api to parse weather data from http://www.OpenWeatherMap.org .
4
 *
5
 * @license MIT
6
 *
7
 * Please see the LICENSE file distributed with this source code for further
8
 * information regarding copyright and licensing.
9
 *
10
 * Please visit the following links to read about the usage policies and the license of
11
 * OpenWeatherMap before using this class:
12
 *
13
 * @see http://www.OpenWeatherMap.org
14
 * @see http://www.OpenWeatherMap.org/terms
15
 * @see http://openweathermap.org/appid
16
 */
17
18
namespace Cmfcmf;
19
20
use Cmfcmf\OpenWeatherMap\AbstractCache;
21
use Cmfcmf\OpenWeatherMap\CurrentWeather;
22
use Cmfcmf\OpenWeatherMap\Exception as OWMException;
23
use Cmfcmf\OpenWeatherMap\Fetcher\CurlFetcher;
24
use Cmfcmf\OpenWeatherMap\Fetcher\FetcherInterface;
25
use Cmfcmf\OpenWeatherMap\Fetcher\FileGetContentsFetcher;
26
use Cmfcmf\OpenWeatherMap\WeatherForecast;
27
use Cmfcmf\OpenWeatherMap\WeatherHistory;
28
29
/**
30
 * Main class for the OpenWeatherMap-PHP-API. Only use this class.
31
 *
32
 * @api
33
 */
34
class OpenWeatherMap
35
{
36
    /**
37
     * @var string The basic api url to fetch weather data from.
38
     */
39
    private $weatherUrl = 'http://api.openweathermap.org/data/2.5/weather?';
40
41
    /**
42
     * @var string The basic api url to fetch weekly forecast data from.
43
     */
44
    private $weatherHourlyForecastUrl = 'http://api.openweathermap.org/data/2.5/forecast?';
45
46
    /**
47
     * @var string The basic api url to fetch daily forecast data from.
48
     */
49
    private $weatherDailyForecastUrl = 'http://api.openweathermap.org/data/2.5/forecast/daily?';
50
51
    /**
52
     * @var string The basic api url to fetch history weather data from.
53
     */
54
    private $weatherHistoryUrl = 'http://api.openweathermap.org/data/2.5/history/city?';
55
56
    /**
57
     * The copyright notice. This is no official text, this hint was created regarding to http://openweathermap.org/copyright.
58
     *
59
     * @var string
60
     */
61
    const COPYRIGHT = 'Weather data from <a href="http://www.openweathermap.org">OpenWeatherMap.org</a>';
62
63
    /**
64
     * @var \Cmfcmf\OpenWeatherMap\AbstractCache|bool The cache class.
65
     */
66
    private $cacheClass = false;
67
68
    /**
69
     * @var int
70
     */
71
    private $seconds;
72
73
    /**
74
     * @var bool
75
     */
76
    private $wasCached = false;
77
78
    /**
79
     * @var FetcherInterface The url fetcher.
80
     */
81
    private $fetcher;
82
83
    /**
84
     * @var string
85
     */
86
    private $apiKey = '';
87
88
    /**
89
     * Constructs the OpenWeatherMap object.
90
     *
91
     * @param null|string           $appid      The API key. Defaults to null.
0 ignored issues
show
Bug introduced by
There is no parameter named $appid. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
92
     * @param null|FetcherInterface $fetcher    The interface to fetch the data from OpenWeatherMap. Defaults to
93
     *                                          CurlFetcher() if cURL is available. Otherwise defaults to
94
     *                                          FileGetContentsFetcher() using 'file_get_contents()'.
95
     * @param bool|string           $cacheClass If set to false, caching is disabled. Otherwise this must be a class
96
     *                                          extending AbstractCache. Defaults to false.
97
     * @param int                   $seconds    How long weather data shall be cached. Default 10 minutes.
98
     *
99
     * @throws \Exception If $cache is neither false nor a valid callable extending Cmfcmf\OpenWeatherMap\Util\Cache.
100
     *
101
     * @api
102
     */
103
    public function __construct($fetcher = null, $cacheClass = false, $seconds = 600)
104
    {
105
        if ($cacheClass !== false && !($cacheClass instanceof AbstractCache)) {
106
            throw new \Exception('The cache class must implement the FetcherInterface!');
107
        }
108
        if (!is_numeric($seconds)) {
109
            throw new \Exception('$seconds must be numeric.');
110
        }
111
        if (!isset($fetcher)) {
112
            $fetcher = (function_exists('curl_version')) ? new CurlFetcher() : new FileGetContentsFetcher();
113
        }
114
        if ($seconds == 0) {
115
            $cacheClass = false;
116
        }
117
118
        $this->cacheClass = $cacheClass;
119
        $this->seconds = $seconds;
0 ignored issues
show
Documentation Bug introduced by
It seems like $seconds can also be of type double or string. However, the property $seconds is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
120
        $this->fetcher = $fetcher;
121
    }
122
123
     /**
124
      * Sets the API Key.
125
      *
126
      * @param	string	API key for the OpenWeatherMap account making the connection.
127
      *
128
      * @api
129
      */
130
     public function setApiKey($appid)
131
     {
132
         $this->apiKey = $appid;
133
     }
134
135
    /**
136
      * Returns the API Key.
137
      *
138
      * @return string
139
      *
140
      * @api
141
      */
142
     public function getApiKey()
143
     {
144
         return $this->apiKey;
145
     }
146
147
    /**
148
     * Returns the current weather at the place you specified as an object.
149
     *
150
     * @param array|int|string $query The place to get weather information for. For possible values see below.
151
     * @param string           $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
152
     * @param string           $lang  The language to use for descriptions, default is 'en'. For possible values see below.
153
     * @param string           $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
154
     *
155
     * @throws OpenWeatherMap\Exception  If OpenWeatherMap returns an error.
156
     * @throws \InvalidArgumentException If an argument error occurs.
157
     *
158
     * @return CurrentWeather The weather object.
159
     *
160
     * There are three ways to specify the place to get weather information for:
161
     * - Use the city name: $query must be a string containing the city name.
162
     * - Use the city id: $query must be an integer containing the city id.
163
     * - Use the coordinates: $query must be an associative array containing the 'lat' and 'lon' values.
164
     *
165
     * Available languages are (as of 17. July 2013):
166
     * - English - en
167
     * - Russian - ru
168
     * - Italian - it
169
     * - Spanish - sp
170
     * - Ukrainian - ua
171
     * - German - de
172
     * - Portuguese - pt
173
     * - Romanian - ro
174
     * - Polish - pl
175
     * - Finnish - fi
176
     * - Dutch - nl
177
     * - French - fr
178
     * - Bulgarian - bg
179
     * - Swedish - se
180
     * - Chinese Traditional - zh_tw
181
     * - Chinese Simplified - zh_cn
182
     * - Turkish - tr
183
     *
184
     * @api
185
     */
186
    public function getWeather($query, $units = 'imperial', $lang = 'en', $appid = '')
187
    {
188
        // Disable default error handling of SimpleXML (Do not throw E_WARNINGs).
189
        libxml_use_internal_errors(true);
190
        libxml_clear_errors();
191
192
        $answer = $this->getRawWeatherData($query, $units, $lang, $appid, 'xml');
193
194
        try {
195
            $xml = new \SimpleXMLElement($answer);
196
        } catch (\Exception $e) {
197
            // Invalid xml format. This happens in case OpenWeatherMap returns an error.
198
            // OpenWeatherMap always uses json for errors, even if one specifies xml as format.
199
            $error = json_decode($answer, true);
200 View Code Duplication
            if (isset($error['message'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
                throw new OWMException($error['message'], $error['cod']);
202
            } else {
203
                throw new OWMException('Unknown fatal error: OpenWeatherMap returned the following json object: '.$answer);
204
            }
205
        }
206
207
        return new CurrentWeather($xml, $units);
208
    }
209
210
    /**
211
     * Returns the current weather at the place you specified as an object.
212
     *
213
     * @param array|int|string $query The place to get weather information for. For possible values see below.
214
     * @param string           $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
215
     * @param string           $lang  The language to use for descriptions, default is 'en'. For possible values see below.
216
     * @param string           $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
217
     * @param int              $days  For how much days you want to get a forecast. Default 1, maximum: 16.
218
     *
219
     * @throws OpenWeatherMap\Exception  If OpenWeatherMap returns an error.
220
     * @throws \InvalidArgumentException If an argument error occurs.
221
     *
222
     * @return WeatherForecast The WeatherForecast object.
223
     *
224
     * There are three ways to specify the place to get weather information for:
225
     * - Use the city name: $query must be a string containing the city name.
226
     * - Use the city id: $query must be an integer containing the city id.
227
     * - Use the coordinates: $query must be an associative array containing the 'lat' and 'lon' values.
228
     *
229
     * Available languages are (as of 17. July 2013):
230
     * - English - en
231
     * - Russian - ru
232
     * - Italian - it
233
     * - Spanish - sp
234
     * - Ukrainian - ua
235
     * - German - de
236
     * - Portuguese - pt
237
     * - Romanian - ro
238
     * - Polish - pl
239
     * - Finnish - fi
240
     * - Dutch - nl
241
     * - French - fr
242
     * - Bulgarian - bg
243
     * - Swedish - se
244
     * - Chinese Traditional - zh_tw
245
     * - Chinese Simplified - zh_cn
246
     * - Turkish - tr
247
     *
248
     * @api
249
     */
250
    public function getWeatherForecast($query, $units = 'imperial', $lang = 'en', $appid = '', $days = 1)
251
    {
252
        // Disable default error handling of SimpleXML (Do not throw E_WARNINGs).
253
        libxml_use_internal_errors(true);
254
        libxml_clear_errors();
255
256
        if ($days <= 5) {
257
            $answer = $this->getRawHourlyForecastData($query, $units, $lang, $appid, 'xml');
258
        } elseif ($days <= 16) {
259
            $answer = $this->getRawDailyForecastData($query, $units, $lang, $appid, 'xml', $days);
260
        } else {
261
            throw new \InvalidArgumentException('Error: forecasts are only available for the next 16 days. $days must be lower than 17.');
262
        }
263
264
        try {
265
            $xml = new \SimpleXMLElement($answer);
266
        } catch (\Exception $e) {
267
            // Invalid xml format. This happens in case OpenWeatherMap returns an error.
268
            // OpenWeatherMap always uses json for errors, even if one specifies xml as format.
269
            $error = json_decode($answer, true);
270 View Code Duplication
            if (isset($error['message'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
                throw new OWMException($error['message'], $error['cod']);
272
            } else {
273
                throw new OWMException('Unknown fatal error: OpenWeatherMap returned the following json object: '.$answer);
274
            }
275
        }
276
277
        return new WeatherForecast($xml, $units, $days);
278
    }
279
280
    /**
281
     * Returns the weather history for the place you specified as an object.
282
     *
283
     * @param array|int|string $query      The place to get weather information for. For possible values see below.
284
     * @param \DateTime        $start
285
     * @param int              $endOrCount
286
     * @param string           $type
287
     * @param string           $units      Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
288
     * @param string           $lang       The language to use for descriptions, default is 'en'. For possible values see below.
289
     * @param string           $appid      Your app id, default ''. See http://openweathermap.org/appid for more details.
290
     *
291
     * @throws OpenWeatherMap\Exception  If OpenWeatherMap returns an error.
292
     * @throws \InvalidArgumentException If an argument error occurs.
293
     *
294
     * @return WeatherHistory The WeatherHistory object.
295
     *
296
     * There are three ways to specify the place to get weather information for:
297
     * - Use the city name: $query must be a string containing the city name.
298
     * - Use the city id: $query must be an integer containing the city id.
299
     * - Use the coordinates: $query must be an associative array containing the 'lat' and 'lon' values.
300
     *
301
     * Available languages are (as of 17. July 2013):
302
     * - English - en
303
     * - Russian - ru
304
     * - Italian - it
305
     * - Spanish - sp
306
     * - Ukrainian - ua
307
     * - German - de
308
     * - Portuguese - pt
309
     * - Romanian - ro
310
     * - Polish - pl
311
     * - Finnish - fi
312
     * - Dutch - nl
313
     * - French - fr
314
     * - Bulgarian - bg
315
     * - Swedish - se
316
     * - Chinese Traditional - zh_tw
317
     * - Chinese Simplified - zh_cn
318
     * - Turkish - tr
319
     *
320
     * @api
321
     */
322
    public function getWeatherHistory($query, \DateTime $start, $endOrCount = 1, $type = 'hour', $units = 'imperial', $lang = 'en', $appid = '')
323
    {
324 View Code Duplication
        if (!in_array($type, array('tick', 'hour', 'day'))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
325
            throw new \InvalidArgumentException('$type must be either "tick", "hour" or "day"');
326
        }
327
328
        $xml = json_decode($this->getRawWeatherHistory($query, $start, $endOrCount, $type, $units, $lang, empty($appid) ? $this->apiKey : $appid), true);
329
330
        if ($xml['cod'] != 200) {
331
            throw new OWMException($xml['message'], $xml['cod']);
332
        }
333
334
        return new WeatherHistory($xml, $query);
335
    }
336
337
    /**
338
     * @deprecated Use {@link self::getRawWeatherData()} instead.
339
     */
340
    public function getRawData($query, $units = 'imperial', $lang = 'en', $appid = '', $mode = 'xml')
341
    {
342
        return $this->getRawWeatherData($query, $units, $lang, $appid, $mode);
343
    }
344
345
    /**
346
     * Directly returns the xml/json/html string returned by OpenWeatherMap for the current weather.
347
     *
348
     * @param array|int|string $query The place to get weather information for. For possible values see below.
349
     * @param string           $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
350
     * @param string           $lang  The language to use for descriptions, default is 'en'. For possible values see below.
351
     * @param string           $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
352
     * @param string           $mode  The format of the data fetched. Possible values are 'json', 'html' and 'xml' (default).
353
     *
354
     * @return string Returns false on failure and the fetched data in the format you specified on success.
355
     *
356
     * Warning If an error occurred, OpenWeatherMap returns data in json format ALWAYS
357
     *
358
     * There are three ways to specify the place to get weather information for:
359
     * - Use the city name: $query must be a string containing the city name.
360
     * - Use the city id: $query must be an integer containing the city id.
361
     * - Use the coordinates: $query must be an associative array containing the 'lat' and 'lon' values.
362
     *
363
     * Available languages are (as of 17. July 2013):
364
     * - English - en
365
     * - Russian - ru
366
     * - Italian - it
367
     * - Spanish - sp
368
     * - Ukrainian - ua
369
     * - German - de
370
     * - Portuguese - pt
371
     * - Romanian - ro
372
     * - Polish - pl
373
     * - Finnish - fi
374
     * - Dutch - nl
375
     * - French - fr
376
     * - Bulgarian - bg
377
     * - Swedish - se
378
     * - Chinese Traditional - zh_tw
379
     * - Chinese Simplified - zh_cn
380
     * - Turkish - tr
381
     *
382
     * @api
383
     */
384
    public function getRawWeatherData($query, $units = 'imperial', $lang = 'en', $appid = '', $mode = 'xml')
385
    {
386
        $url = $this->buildUrl($query, $units, $lang, $appid, $mode, $this->weatherUrl);
387
388
        return $this->cacheOrFetchResult($url);
389
    }
390
391
    /**
392
     * Directly returns the xml/json/html string returned by OpenWeatherMap for the hourly forecast.
393
     *
394
     * @param array|int|string $query The place to get weather information for. For possible values see below.
395
     * @param string           $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
396
     * @param string           $lang  The language to use for descriptions, default is 'en'. For possible values see below.
397
     * @param string           $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
398
     * @param string           $mode  The format of the data fetched. Possible values are 'json', 'html' and 'xml' (default).
399
     *
400
     * @return string Returns false on failure and the fetched data in the format you specified on success.
401
     *
402
     * Warning If an error occurred, OpenWeatherMap returns data in json format ALWAYS
403
     *
404
     * There are three ways to specify the place to get weather information for:
405
     * - Use the city name: $query must be a string containing the city name.
406
     * - Use the city id: $query must be an integer containing the city id.
407
     * - Use the coordinates: $query must be an associative array containing the 'lat' and 'lon' values.
408
     *
409
     * Available languages are (as of 17. July 2013):
410
     * - English - en
411
     * - Russian - ru
412
     * - Italian - it
413
     * - Spanish - sp
414
     * - Ukrainian - ua
415
     * - German - de
416
     * - Portuguese - pt
417
     * - Romanian - ro
418
     * - Polish - pl
419
     * - Finnish - fi
420
     * - Dutch - nl
421
     * - French - fr
422
     * - Bulgarian - bg
423
     * - Swedish - se
424
     * - Chinese Traditional - zh_tw
425
     * - Chinese Simplified - zh_cn
426
     * - Turkish - tr
427
     *
428
     * @api
429
     */
430
    public function getRawHourlyForecastData($query, $units = 'imperial', $lang = 'en', $appid = '', $mode = 'xml')
431
    {
432
        $url = $this->buildUrl($query, $units, $lang, $appid, $mode, $this->weatherHourlyForecastUrl);
433
434
        return $this->cacheOrFetchResult($url);
435
    }
436
437
    /**
438
     * Directly returns the xml/json/html string returned by OpenWeatherMap for the daily forecast.
439
     *
440
     * @param array|int|string $query The place to get weather information for. For possible values see below.
441
     * @param string           $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
442
     * @param string           $lang  The language to use for descriptions, default is 'en'. For possible values see below.
443
     * @param string           $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
444
     * @param string           $mode  The format of the data fetched. Possible values are 'json', 'html' and 'xml' (default)
445
     * @param int              $cnt   How many days of forecast shall be returned? Maximum (and default): 16
446
     *
447
     * @throws \InvalidArgumentException If $cnt is higher than 16.
448
     *
449
     * @return string Returns false on failure and the fetched data in the format you specified on success.
450
     *
451
     * Warning If an error occurred, OpenWeatherMap returns data in json format ALWAYS
452
     *
453
     * There are three ways to specify the place to get weather information for:
454
     * - Use the city name: $query must be a string containing the city name.
455
     * - Use the city id: $query must be an integer containing the city id.
456
     * - Use the coordinates: $query must be an associative array containing the 'lat' and 'lon' values.
457
     *
458
     * Available languages are (as of 17. July 2013):
459
     * - English - en
460
     * - Russian - ru
461
     * - Italian - it
462
     * - Spanish - sp
463
     * - Ukrainian - ua
464
     * - German - de
465
     * - Portuguese - pt
466
     * - Romanian - ro
467
     * - Polish - pl
468
     * - Finnish - fi
469
     * - Dutch - nl
470
     * - French - fr
471
     * - Bulgarian - bg
472
     * - Swedish - se
473
     * - Chinese Traditional - zh_tw
474
     * - Chinese Simplified - zh_cn
475
     * - Turkish - tr
476
     *
477
     * @api
478
     */
479
    public function getRawDailyForecastData($query, $units = 'imperial', $lang = 'en', $appid = '', $mode = 'xml', $cnt = 16)
480
    {
481
        if ($cnt > 16) {
482
            throw new \InvalidArgumentException('$cnt must be 16 or below!');
483
        }
484
        $url = $this->buildUrl($query, $units, $lang, $appid, $mode, $this->weatherDailyForecastUrl)."&cnt=$cnt";
485
486
        return $this->cacheOrFetchResult($url);
487
    }
488
489
    /**
490
     * Directly returns the xml/json/html string returned by OpenWeatherMap for the daily forecast.
491
     *
492
     * @param array|int|string $query      The place to get weather information for. For possible values see below.
493
     * @param \DateTime        $start      The \DateTime object of the date to get the first weather information from.
494
     * @param \DateTime|int    $endOrCount Can be either a \DateTime object representing the end of the period to
495
     *                                     receive weather history data for or an integer counting the number of
496
     *                                     reports requested.
497
     * @param string           $type       The period of the weather history requested. Can be either be either "tick",
498
     *                                     "hour" or "day".
499
     * @param string           $units      Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
500
     * @param string           $lang       The language to use for descriptions, default is 'en'. For possible values see below.
501
     * @param string           $appid      Your app id, default ''. See http://openweathermap.org/appid for more details.
502
     *
503
     * @throws \InvalidArgumentException
504
     *
505
     * @return string Returns false on failure and the fetched data in the format you specified on success.
506
     *
507
     * Warning If an error occurred, OpenWeatherMap returns data in json format ALWAYS
508
     *
509
     * There are three ways to specify the place to get weather information for:
510
     * - Use the city name: $query must be a string containing the city name.
511
     * - Use the city id: $query must be an integer containing the city id.
512
     * - Use the coordinates: $query must be an associative array containing the 'lat' and 'lon' values.
513
     *
514
     * Available languages are (as of 17. July 2013):
515
     * - English - en
516
     * - Russian - ru
517
     * - Italian - it
518
     * - Spanish - sp
519
     * - Ukrainian - ua
520
     * - German - de
521
     * - Portuguese - pt
522
     * - Romanian - ro
523
     * - Polish - pl
524
     * - Finnish - fi
525
     * - Dutch - nl
526
     * - French - fr
527
     * - Bulgarian - bg
528
     * - Swedish - se
529
     * - Chinese Traditional - zh_tw
530
     * - Chinese Simplified - zh_cn
531
     * - Turkish - tr
532
     *
533
     * @api
534
     */
535
    public function getRawWeatherHistory($query, \DateTime $start, $endOrCount = 1, $type = 'hour', $units = 'imperial', $lang = 'en', $appid = '')
536
    {
537 View Code Duplication
        if (!in_array($type, array('tick', 'hour', 'day'))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
538
            throw new \InvalidArgumentException('$type must be either "tick", "hour" or "day"');
539
        }
540
541
        $queryUrl = $this->weatherHistoryUrl.$this->buildQueryUrlParameter($query)."&start={$start->format('U')}";
542
543
        if ($endOrCount instanceof \DateTime) {
544
            $queryUrl .= "&end={$endOrCount->format('U')}";
545
        } elseif (is_numeric($endOrCount) && $endOrCount > 0) {
546
            $queryUrl .= "&cnt=$endOrCount";
547
        } else {
548
            throw new \InvalidArgumentException('$endOrCount must be either a \DateTime or a positive integer.');
549
        }
550
        $queryUrl .= "&type=$type&units=$units&lang=$lang&APPID=";
551
552
        $queryUrl .= empty($appid) ? $this->apiKey : $appid;
553
554
        return $this->cacheOrFetchResult($queryUrl);
555
    }
556
557
    /**
558
     * Fetches the result or delivers a cached version of the result.
559
     *
560
     * @param $url
561
     *
562
     * @return string
563
     *
564
     * @internal
565
     */
566
    private function cacheOrFetchResult($url)
567
    {
568
        if ($this->cacheClass !== false) {
569
            /** @var \Cmfcmf\OpenWeatherMap\AbstractCache $cache */
570
            $cache = $this->cacheClass;
571
            $cache->setSeconds($this->seconds);
572
            $this->wasCached = false;
573
            if ($cache->isCached($url)) {
574
                $this->wasCached = true;
575
576
                return $cache->getCached($url);
577
            }
578
            $result = $this->fetcher->fetch($url);
579
            $cache->setCached($url, $result);
580
        } else {
581
            $result = $this->fetcher->fetch($url);
582
        }
583
584
        return $result;
585
    }
586
587
    /**
588
     * Build the url to fetch weather data from.
589
     *
590
     * @param        $query
591
     * @param        $units
592
     * @param        $lang
593
     * @param        $appid
594
     * @param        $mode
595
     * @param string $url   The url to prepend.
596
     *
597
     * @return bool|string The fetched url, false on failure.
598
     *
599
     * @internal
600
     */
601
    private function buildUrl($query, $units, $lang, $appid, $mode, $url)
602
    {
603
        $queryUrl = $this->buildQueryUrlParameter($query);
604
605
        $url = $url."$queryUrl&units=$units&lang=$lang&mode=$mode&APPID=";
606
        $url .= empty($appid) ? $this->apiKey : $appid;
607
608
        return $url;
609
    }
610
611
    /**
612
     * Builds the query string for the url.
613
     *
614
     * @param $query
615
     *
616
     * @return string The built query string for the url.
617
     *
618
     * @throws \InvalidArgumentException If the query parameter is invalid.
619
     *
620
     * @internal
621
     */
622
    private function buildQueryUrlParameter($query)
623
    {
624
        switch ($query) {
625
            case is_array($query) && isset($query['lat']) && isset($query['lon']) && is_numeric($query['lat']) && is_numeric($query['lon']):
626
                return "lat={$query['lat']}&lon={$query['lon']}";
627
            case is_numeric($query):
628
                return "id=$query";
629
            case is_string($query):
630
                return 'q='.urlencode($query);
631
            default:
632
                throw new \InvalidArgumentException('Error: $query has the wrong format. See the documentation of OpenWeatherMap::getRawData() to read about valid formats.');
633
        }
634
    }
635
636
    /**
637
     * Returns whether or not the last result was fetched from the cache.
638
     *
639
     * @return bool true if last result was fetched from cache, otherwise false.
640
     */
641
    public function wasCached()
642
    {
643
        return $this->wasCached;
644
    }
645
}
646