1 <?php
2
3 4 5 6 7 8 9
10 class PageInformerWeather extends Extension {
11
12 13 14
15 protected static $api_base_url = "http://www.eurometeo.ru/";
16
17 18 19
20 protected static $city_id = 'russia/kareliya/petrozavodsk';
21
22 23 24
25 protected static $expire = 7200;
26
27 28 29
30 protected static $ImageSrc = 'informer_weather/images';
31
32 33 34
35 protected static $ImageExt = '.png';
36
37 38 39
40 protected static $hours_to_show = array(4, 16);
41
42 43 44 45
46 protected static $rp5_eurometeo = array(
47 6601 => 'russia/kareliya/petrozavodsk',
48 1461 => 'russia/kareliya/belomorskiy-rayon/belomorsk',
49 75485 => 'russia/leningradskaya-oblast/podporozhskiy-rayon/podporozhe',
50 4967 => 'russia/leningradskaya-oblast/lodeynopolskiy-rayon/lodeynoe-pole',
51 6942 => 'russia/kareliya/pudozhskiy-rayon/pudozh',
52 );
53
54 55 56
57 protected $weather = false;
58
59 60 61
62 protected $cityName = array();
63
64 protected $cityId = false;
65
66 67 68 69 70 71
72 public static function SetCityId($id) {
73 if (preg_match('/^\d+$/', $id)) {
74 if (!isset(self::$rp5_eurometeo[$id])) die("Invalid old rp5 city id: '$id'");
75 $id = self::$rp5_eurometeo[$id];
76 }
77 self::$city_id = $id;
78 }
79
80 81 82 83 84 85
86 public static function SetExpire($hours) {
87 self::$expire = $hours * 3600;
88 }
89
90 91 92 93 94 95
96 public static function SetImagePath($path) {
97 self::$ImageSrc = $path;
98 }
99
100 101 102 103 104 105
106 public static function SetImageExt($ext) {
107 if (strpos($ext, '.') === false)
108 $ext = '.' . $ext;
109 self::$ImageExt = $ext;
110 }
111
112 113 114 115 116
117 public static function ShowFullDay($val=true) {
118 self::$hours_to_show = ($val) ? array(4, 10, 16, 22) : array(4, 16);
119 }
120
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
151 public function WeatherInfo($days=2, $cityId = false) {
152 if ($days > 3)
153 $days = 3;
154
155 if (!$cityId)
156 $cityId = self::$city_id;
157
158 if ($cityId != $this->cityId) {
159 $this->cityId = $cityId;
160 $this->weather = false;
161 }
162
163 if (!$this->_getWeather())
164 return false;
165
166 $res = new DataObjectSet();
167 $i = 0;
168 foreach ($this->weather->GroupBy('Day') as $day => $data) {
169 $dt = new Date();
170 $dt->setValue($day);
171 $res->push(new ArrayData(array(
172 'CityName0' => $this->cityName[0],
173 'CityName1' => $this->cityName[1],
174 'Date' => $dt,
175 'Items' => $data
176 )));
177 $i++;
178 if ($i >= $days) break;
179 }
180 return $res;
181 }
182
183 184 185 186 187
188 public function CityID() {
189 return self::$city_id;
190 }
191
192 193 194 195 196
197 public function CityLink() {
198 return self::$api_base_url . self::$city_id . '/';
199 }
200
201 202 203 204 205 206 207
208 public function CityName($index = 0) {
209 if (isset($this->cityName[$index]))
210 return $this->cityName[$index];
211
212 return false;
213 }
214
215 216 217 218 219 220 221 222
223 private function _getWeather() {
224
225 if ($this->weather)
226 return true;
227
228
229 $cache_path = TEMP_FOLDER . '/cache_weather_' . md5($this->cityId . join(':', self::$hours_to_show)) . '_' . i18n::get_locale();
230 if (@file_exists($cache_path)) {
231 $buffer = unserialize(file_get_contents($cache_path));
232 $this->weather = $buffer['weather'];
233 $this->cityName = $buffer['cityName'];
234 unset($buffer);
235 }
236 else {
237 $this->weather = new DataObjectSet();
238 }
239
240
241 if($this->weather->Count() > 0 && !isset($_GET['flush']) && @file_exists($cache_path) && @filemtime($cache_path) + self::$expire > time()) {
242 return true;
243 }
244
245
246 $now = date('Y-m-d');
247 while ($this->weather->Count()) {
248 $row = $this->weather->First();
249 if ($row->Date->Format('Y-m-d') == $now)
250 break;
251 $this->weather->remove($row);
252 }
253
254
255 $server = new RestfulService(self::$api_base_url, self::$expire);
256 try {
257 $conn = $server->request($this->cityId . '/export/xml/data/');
258 if (!$conn)
259 throw new Exception("Can't connect to: ". $this->cityId . '/export/xml/data/');
260
261 $data = $server->getValues($conn->getBody(), 'city', 'step');
262 $this->cityName[0] = $server->getValue($conn->getBody(), 'city', 'cityname');
263 $this->cityName[1] = $server->getValue($conn->getBody(), 'city', 'cityname2');
264 } catch (Exception $e) {
265
266 $this->weather = false;
267 return false;
268 }
269
270 if (!$data) {
271 $this->weather = false;
272 return false;
273 }
274
275
276 foreach ($data as $row) {
277 $dt = new SS_Datetime();
278 $dt->setValue($row->datetime);
279 if (array_search($dt->Format('G'), self::$hours_to_show) === false) continue;
280
281 $item = array(
282 'ID' => strtotime($row->datetime),
283 'Date' => $dt,
284 'CloudCover' => round($row->cloudcover),
285 'CloudLevel' => $this->_cloudCover2Level($row->cloudcover),
286 'Pressure' => round($row->pressure),
287 'Temperature' => round($row->temperature),
288 'Humidity' => round($row->humidity),
289 'Precipitation' => $row->precipitation,
290 'FallsType' => $this->_fallsType($row->temperature, $row->precipitation),
291 'Drops' => $this->_dropsLevel($row->precipitation),
292 'FallsLevel' => $this->_fallsLevel($row->precipitation),
293 'WindDirection' => $this->_windDirection($row->winddir, $row->windspeed),
294 'WindVelocity' => round($row->windspeed),
295 'WindGust' => round($row->windgust),
296 );
297
298 $item['FallsName'] = $this->_fallsName($item['FallsType']);
299
300 $item['Hour'] = date('G', $item['ID']);
301 $item['DayTimeName'] = _t('WEATHER.DAYTIME_'.$item['Hour'], $item['Hour']);
302 $item['Day'] = date('Y-m-d', $item['ID']);
303 $item['CloudName'] = $this->_cloudName($item['CloudLevel'], $item['CloudCover']);
304 $item['CloudImageUrl'] = $this->_getCloudImage($item['CloudLevel'], $item['Hour']);
305 $item['FallsImageUrl'] = $this->_getFallsImage($item['FallsType'], $item['FallsLevel']);
306
307 $this->weather->push(new ArrayData($item), $item['ID']);
308 }
309
310 if (!$this->weather->Count()) {
311 $this->weather = false;
312 return false;
313 }
314
315 file_put_contents($cache_path, serialize(array(
316 'weather' => $this->weather,
317 'cityName' => $this->cityName,
318 )));
319 return true;
320 }
321
322 323 324 325 326 327
328 private function _cloudCover2Level($percent) {
329 if ($percent > 84)
330 return 7;
331 return floor($percent / 12);
332 }
333
334 335 336 337 338 339 340
341 protected function _dropsLevel($falls) {
342 if ($falls == 0) return '0';
343 if ($falls <= 0.5) return 0.5;
344 if ($falls <= 1) return 1;
345 if ($falls <= 1.5) return 2;
346 if ($falls <= 2) return 3;
347 if ($falls <= 2.5) return 4;
348 if ($falls <= 3) return 5;
349 if ($falls <= 3.5) return 6;
350 if ($falls <= 4) return 7;
351 return 8;
352 }
353
354 355 356 357 358 359 360
361 protected function _fallsLevel($falls) {
362 if ($falls == 0) return '0';
363 if ($falls <= 1) return 1;
364 if ($falls <= 1.5) return 2;
365 if ($falls <= 2) return 3;
366 if ($falls <= 2.5) return 4;
367 if ($falls <= 3) return 5;
368 if ($falls <= 3.5) return 6;
369 if ($falls <= 4) return 7;
370 return 8;
371 }
372
373 374 375 376 377 378 379
380 protected function _windDirection($dir, $speed) {
381 $code = 'NONE';
382 if ($speed > 0.2) {
383 if ($dir < 22.5) $code = 'N';
384 elseif ($dir < 67.5) $code = 'NE';
385 elseif ($dir < 112.5) $code = 'E';
386 elseif ($dir < 157.5) $code = 'SE';
387 elseif ($dir < 202.5) $code = 'S';
388 elseif ($dir < 247.5) $code = 'SW';
389 elseif ($dir < 292.5) $code = 'W';
390 elseif ($dir < 337.5) $code = 'NW';
391 else $code = 'N';
392 }
393
394 return _t('WEATHER.WIND_DIRECTION_'.$code, $code);
395 }
396
397 398 399 400 401 402 403 404
405 protected function _fallsType($temp, $falls) {
406 if ($falls == 0 ) return 0;
407 if ($temp > 1) return 1;
408 if ($temp < -1) return 3;
409 return 2;
410 }
411
412 413 414 415 416 417
418 protected function _fallsName($type) {
419 return _t('WEATHER.FALLS_TYPE_'.$type, $type);
420 }
421
422 423 424 425 426 427 428
429 protected function _cloudName($level, $percent) {
430 return _t('WEATHER.CLOUD_LEVEL_'.$level, sprintf('%d %%', $percent));
431 }
432
433 434 435 436 437 438 439
440 protected function _getCloudImage($level, $hour) {
441 return self::$ImageSrc . '/c' . (($hour > 8 && $hour < 20) ? 'd' : 'n') . $level . self::$ImageExt;
442 }
443
444 445 446 447 448 449 450
451 protected function _getFallsImage($type, $level) {
452 return self::$ImageSrc . '/o' . $type . 'd' . $level . self::$ImageExt;
453 }
454 }
455
456
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-