Overview

Classes

  • weather
  • Overview
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * Weather widget class
  5:  * All Documentation included in this document.
  6:  * For further developer note please see the Weather.php class
  7:  * 
  8:  * @version 1.0.1
  9:  * @author Samy Massoud <samymassoud@gmail.com>
 10:  * @link  http://www.deploy2cloud.com/demo/weather
 11:  * 
 12:  * @tutorial 
 13:  * This class main functionality is to provide weather wedget to use it easily and smoothly.
 14:  * You can use this class with almost zero configuration , or configure it as far as you need !
 15:  * 
 16:  * When i started to write this class i put in mind to make it easy,clean and professional as much as i can.
 17:  * 
 18:  * To start using this class just do the following
 19:  *  1- include attached weather.css file in your page.
 20:  *  2- Make sure that you have embedded jquery version greater than 1.6 
 21:  *  3- Include this class in your page and Make object from this class with required city
 22:  *     $weather = new weather ("Cairo,EG");
 23:  *     echo $weather->get_weather ();
 24:  * And you will get a copy from this widget with cairo weather !
 25:  * 
 26:  * To start using this class as codeigniter library
 27:  *  1- include attached weather.css file in your page.
 28:  *  2- Make sure that you have embedded jquery version greater than 1.6 
 29:  *  3- Move weather.php to application/libraries folder
 30:  *     and you can load library by adding it to autoload.php or use
 31:  *     $this->load->library ('weather');
 32:  *     and at any place in your application (Controller or view)
 33:  *     $this->weather->set_city ('Cairo,EG');
 34:  *     echo $this->weather->get_weather ();
 35:  * And you will get a copy from this widget with cairo weather !
 36:  * 
 37:  * 
 38:  */
 39: class weather {
 40: 
 41:     /**
 42:      * Available themes for weather class
 43:      * @var array 
 44:      */
 45:     private $themes = array(
 46:     'blue' => 'theme-blue',
 47:     'darkblue' => 'theme-darkblue',
 48:     'green' => 'theme-green',
 49:     'black' => 'theme-black',
 50:     'darkred' => 'theme-darkred'
 51:     );
 52: 
 53:     /**
 54:      * Default theme , or user selected theme
 55:      * @var string 
 56:      */
 57:     private $theme = "theme-darkblue";
 58: 
 59:     /**
 60:      * Weather api link and weather forecast link
 61:      * @var string 
 62:      */
 63:     private $weather_api = "http://api.openweathermap.org/data/2.5/weather?units=metric&";
 64:     private $forecast_api = "http://api.openweathermap.org/data/2.5/forecast/daily/?cnt=4&units=metric&mode=json&";
 65: 
 66:     /**
 67:      * City identifires , used to select city by name,id or lat. and lon.
 68:      * @var string
 69:      */
 70:     private $city = "";
 71:     private $city_id = "";
 72:     private $city_lat = "";
 73:     private $city_lon = "";
 74: 
 75:     /**
 76:      * Selected temperature measurement
 77:      * @var string 
 78:      */
 79:     private $temp_metric = "c";
 80: 
 81:     /**
 82:      * Output type it can be empty or row for php array
 83:      * @var string 
 84:      */
 85:     private $output = "";
 86: 
 87:     /**
 88:      * Cache folder , this is the dfault folder , user can change it using configuration
 89:      * @var string 
 90:      */
 91:     private $cache_folder = "./cache/";
 92: 
 93:     /**
 94:      * Enable or disable cache
 95:      * @var bool 
 96:      */
 97:     private $cache = false;
 98: 
 99:     /**
100:      * cache lifetime (By seconds)
101:      * @var integer 
102:      */
103:     private $cache_time = 600;
104: 
105:     /**
106:      * Widget dimention this is default values 
107:      * @var integer 
108:      */
109:     private $width = 270;
110:     private $height = 248;
111: 
112:     /**
113:      * weather info after processing it
114:      * @var array
115:      */
116:     private $weather_info = array();
117: 
118:     /**
119:      * Widget  languages,it can be extended by coping
120:      * for example 'En' array and translate it to any other language
121:      * @var array 
122:      */
123:     private $languages = array(
124:     'en' => array(
125:         'cannot_access' => "Can't Access Weather API",
126:         'invalid_city_info' => "Please select valid city information",
127:         'show_next_days' => "Show weather next three days",
128:         'back_to_weather' => "Back to current weather details",
129:         'weather' => 'Weather',
130:         'weather_desc' => "Weather description",
131:         'wind' => 'Wind',
132:         'wind_degree' => 'Wind degree',
133:         'humidity' => 'Humidity',
134:         'pressure' => 'Pressure',
135:         'hi' => 'HI',
136:         'lo' => 'LO'
137:     ),
138:     'it' => array(
139:         'cannot_access' => "Impossibile accedere Meteo",
140:         'invalid_city_info' => "Si prega di selezionare le informazioni citt� valida",
141:         'show_next_days' => "Mostra previsioni prossimi tre giorni",
142:         'back_to_weather' => "Torna a correnti dettagli meteo",
143:         'weather' => 'Meteo',
144:         'weather_desc' => "descrizione Meteo",
145:         'wind' => 'vento',
146:         'wind_degree' => 'grado Vento',
147:         'humidity' => 'umidit�',
148:         'pressure' => 'pressione',
149:         'hi' => 'alto',
150:         'lo' => 'basso'
151:     ),
152:     'fr' => array(
153:         'cannot_access' => "Impossible d'acc�der � l'API M�t�o",
154:         'invalid_city_info' => "S'il vous pla�t s�lectionner l'information de la ville valide",
155:         'show_next_days' => "Montrez temps trois prochains jours",
156:         'back_to_weather' => "Retour aux d�tails m�t�orologiques actuelles",
157:         'weather' => 'm�t�o',
158:         'weather_desc' => "Description m�t�o",
159:         'wind' => 'vent',
160:         'wind_degree' => 'Degr� de Vent',
161:         'humidity' => 'humidit�',
162:         'pressure' => 'pression',
163:         'hi' => 'haut',
164:         'lo' => 'faible'
165:     )
166:     );
167:     //Available API Languages ' don't modify
168:     private $api_lang = array('en', 'it', 'ru', 'fr', 'ua', 'de', 'pt', 'ro', 'pl', 'fi', 'nl', 'sp', 'bg', 'se', 'zh_tw', 'zh_cn', 'tr');
169: 
170:     /**
171:      * Selected language for api and widget
172:      * @var string
173:      */
174:     private $lang = 'en';
175:     private $lang_api = 'en';
176: 
177:     /**
178:      * Construct weather widget you can provide any configration you want 
179:      * Click right # to see more
180:      * @example  $config = array ('theme' => 'blue',
181:      *          'city' => 'cairo,eg',
182:      *          'temp_metrics' => 'f');
183:      * $weather = new weather ($config);
184:      * 
185:      * @param type array
186:      */
187:     public function __construct($config = null) {
188:     if (is_array($config)) {
189:         foreach ($config as $key => $value) {
190:         //Set Theme
191:         if ($key == "theme" && isset($this->themes[$value])) {
192:             $this->theme = $this->themes[$value];
193:         }
194: 
195:         //Set City Name
196:         if ($key == 'city') {
197:             $this->city = $value;
198:                      $this->file_name =  $this->city;
199:         }
200:         if ($key == 'city_id') {
201:             $this->city_id = $value;
202:                      $this->file_name =  $this->city_id;
203:         }
204:         if ($key == 'city_lat') {
205:             $this->city_lat = $value;
206:                      $this->file_name =  $this->city_lat;
207:         }
208:         if ($key == 'city_lon') {
209:             $this->city_lon = $value;
210:                      $this->file_name .=  '_'.$this->city_lon;
211:         }
212: 
213:         //Set Tempereature Metrics
214:         if ($key == 'temp_metrics' && ($value == "c" || $value == 'f')) {
215:             $this->temp_metric = $value;
216:         }
217: 
218:         if ($key == "lang" && (isset($this->languages[$value]) || in_array($value, $this->api_lang))) {
219:             if (isset($this->languages[$value])) {
220:             $this->lang = $value;
221:             }
222: 
223:             if (in_array($value, $this->api_lang)) {
224:             $this->lang_api = $value;
225:             }
226:         }
227:         //Set Output
228:         if ($key == "output" && ($value == "row")) {
229:             $this->output = "row";
230:         }
231:         }
232:     } else {
233:         $this->city = $config; //City Name
234:     }
235:     }
236: 
237:     // Start Setter Functions
238: 
239:     /**
240:      * set city by it's name or id or lat. and lon.
241:      * @param type string
242:      * @param type integer
243:      * @param type decimal
244:      * @param type decimal
245:      */
246:     public function set_city($name = null, $id = null, $lat = null, $lon = null) {
247:     if ($name) {
248:         $this->city = $name;
249:         $this->city_id = null;
250:         $this->city_lat = null;
251:         $this->city_lon = null;
252:             $this->file_name =  $this->city;
253:     }
254: 
255:     if ($id) {
256:         $this->city_id = $id;
257:         $this->city = null;
258:         $this->city_lat = null;
259:         $this->city_lon = null;
260:             $this->file_name = $this->city_id;
261:     }
262: 
263:     if ($lat && $lon) {
264:         $this->city_lat = $lat;
265:             $this->city_lon = $lon;
266:         $this->city_id = null;
267:         $this->city = null;
268:             $this->file_name =  $this->city_lat."_".$this->city_lon;
269:     }
270: 
271:     
272:     }
273: 
274:     /**
275:      * Set Theme
276:      * 
277:      * @param type string
278:      */
279:     public function set_theme($theme) {
280:     if (isset($this->themes[$theme])) {
281:         $this->theme = $this->themes[$theme];
282:     }
283:     }
284: 
285:     /**
286:      * Set temp. metrics
287:      * @param type char
288:      */
289:     public function set_temp_metrics($metrics = 'c') {
290:     if ($metrics == 'c' || $metrics == 'f')
291:         $this->temp_metric = $metrics;
292:     }
293: 
294:     /**
295:      * Set language
296:      * @param type string
297:      */
298:     public function set_lang($lang) {
299:     if (isset($this->languages[$lang])) {
300:         $this->lang = $lang;
301:     }
302: 
303:     if (in_array($lang, $this->api_lang)) {
304:         $this->lang_api = $lang;
305:     }
306:     }
307: 
308:     /**
309:      * Set widget dimention
310:      * @param type integer
311:      * @param type integer
312:      */
313:     public function set_dimention($width, $height) {
314:     if ($width > 270)
315:         $this->width = $width;
316:     if ($height > 248)
317:         $this->height = $height;
318:     }
319: 
320:     /**
321:      * Set output type accept empty string or word 'row'
322:      * @param type string
323:      */
324:     public function set_output($out = "") {
325:     if ($out == "row") {
326:         $this->output = "row";
327:     }
328:     }
329: 
330:     /**
331:      * set cache time and folder and this will enable cache
332:      * you have to provide cache time greater than 0 second
333:      * and cache folder name is optional , if you didn't provide it 
334:      * it will use default cache folder
335:      * @param type integer
336:      * @param type string
337:      */
338:     public function set_cache($cache_time, $cache_folder = false) {
339:     if ($cache_time > 0) {
340:         $this->cache = TRUE;
341:         $this->cache_time = $cache_time;
342:         if ($cache_folder)
343:         $this->cache_folder = $cache_folder;
344:     }
345:     }
346: 
347:     /**
348:      * Stop caching
349:      */
350:     public function disable_cache() {
351:     $this->cache = FALSE;
352:     }
353: 
354:     /**
355:      * get weather widget or row array according to your config
356:      * $this->weather_info['rain'] array is available if any rain data available
357:      * AND it's array:)
358:      * Thank's for Ray <ray@tzweather.org>
359:      * @return type
360:      */
361:     public function get_weather() {
362:     if (!$this->city && !$this->city_id && (!$this->city_lat && !$this->city_lon))
363:         return $this->languages[$this->lang]['invalid_city_info'];
364:     //City Detrmine method
365:     $search_q = "";
366:     if ($this->city) {
367:         $search_q = "q=" . $this->city;
368:     } elseif ($this->city_id) {
369:         $search_q = "id=" . $this->city_id;
370:     } else {
371:         $search_q = "lat=" . $this->city_lat . "&lon=" . $this->city_lon;
372:     }
373: 
374:     $read_cache = $this->read_wether();
375: 
376:     if ($read_cache) {
377:         $weather = true;
378:     } else {
379:         $weather = @file_get_contents($this->weather_api . $search_q . '&lang=' . $this->lang_api);
380:     }
381:         
382:     if ($weather) {
383:         if (!$read_cache) {
384:         $weather_forecast = @file_get_contents($this->forecast_api . $search_q . '&lang=' . $this->lang_api);
385:         $weather = json_decode($weather);
386:         $weather_forecast = json_decode($weather_forecast);
387:         //print_r($weather_forecast);
388: 
389:         if (isset($weather->message))
390:             return ($weather->message);
391:         //Extract Weather
392:         $this->extract_weather($weather, $weather_forecast);
393:         }
394: 
395:         if ($this->output == "row") {
396:         return $this->weather_info;
397:         }
398:         //Else return markup
399:         return $this->markup();
400:     } else {
401:         return $this->languages[$this->lang]['cannot_access'];
402:     }
403:     }
404: 
405:     //Private Methods
406:     /**
407:      * extract weather to weather info
408:      * @param type object
409:      * @param type object
410:      */
411:     private function extract_weather($weather, $weather_forecast) {
412:     //Normal Weather data
413:     $this->weather_info['place'] = $weather->name . (($weather->name) ? ',' : '' ) . $weather->sys->country;
414:     $this->weather_info['icon'] = $weather->weather[0]->icon;
415:     $this->weather_info['weather_main'] = $weather->weather[0]->main;
416:     $this->weather_info['weather_description'] = $weather->weather[0]->description;
417:     $this->weather_info['temp_c'] = round($weather->main->temp, 1);
418:     $this->weather_info['temp_c_accurate'] = ($weather->main->temp);
419:     $this->weather_info['temp_f'] = round((9 / 5) * $weather->main->temp, 1) + 32;
420:     $this->weather_info['temp_f_accurate'] = ((9 / 5) * $weather->main->temp) + 32;
421:     $this->weather_info['temp'] = (($this->temp_metric == 'c') ? $this->weather_info['temp_c'] : $this->weather_info['temp_f']);
422:     $this->weather_info['symbol'] = (($this->temp_metric == 'c') ? 'C' : 'F');
423:     $this->weather_info['humidity'] = $weather->main->humidity;
424:     $this->weather_info['wind_speed'] = $weather->wind->speed;
425:         $this->weather_info['rain'] = (isset($weather->rain)) ? (array)$weather->rain : false;
426:     //Aditinal info
427:     $this->weather_info['wind_degree'] = $weather->wind->deg;
428:     $this->weather_info['pressure'] = $weather->main->pressure;
429:     $this->weather_info['lat'] = $weather->coord->lat;
430:     $this->weather_info['lon'] = $weather->coord->lon;
431: 
432:     //Forecast Data For Next Three days
433:     $forecaster = array();
434:     for ($i = 1; $i <= 3; $i++) {
435:         $forecaster[$i]['day'] = date('D', $weather_forecast->list[$i]->dt);
436:         $forecaster[$i]['month'] = date('M d', $weather_forecast->list[$i]->dt);
437:         $forecaster[$i]['min_temp_c'] = round($weather_forecast->list[$i]->temp->min, 1);
438:         $forecaster[$i]['min_temp_f'] = round((9 / 5) * $weather_forecast->list[$i]->temp->min, 1) + 32;
439:         $forecaster[$i]['max_temp_c'] = round($weather_forecast->list[$i]->temp->max, 1);
440:         $forecaster[$i]['max_temp_f'] = round((9 / 5) * $weather_forecast->list[$i]->temp->max, 1) + 32;
441:         $forecaster[$i]['temp_max'] = (($this->temp_metric == 'c') ? $forecaster[$i]['max_temp_c'] : $forecaster[$i]['max_temp_f']);
442:         $forecaster[$i]['temp_min'] = (($this->temp_metric == 'c') ? $forecaster[$i]['min_temp_c'] : $forecaster[$i]['min_temp_f']);
443:         $forecaster[$i]['symbol'] = (($this->temp_metric == 'c') ? 'C' : 'F');
444:         $forecaster[$i]['weather_main'] = $weather_forecast->list[$i]->weather[0]->main;
445:         $forecaster[$i]['icon'] = $weather_forecast->list[$i]->weather[0]->icon;
446:     }
447:     //Append To weather info 
448:     $this->weather_info['forecast'] = $forecaster;
449: 
450:     //IF Cache enabled,save data to file
451:     if ($this->cache) {
452:         $this->save_weather($this->weather_info);
453:     }
454:     }
455: 
456:     /**
457:      * save weather to cache
458:      * @param type array
459:      */
460:     private function save_weather($weather) {
461:     $weather_json = json_encode($weather);
462:     $file = $this->cache_folder . $this->file_name . '.txt';
463:     $handle = @fopen($file, 'w');
464:     if ($handle) {
465:         fwrite($handle, $weather_json);
466:         fclose($handle);
467:     }
468:     }
469: 
470:     /**
471:      * load weather from cache
472:      * @return boolean
473:      */
474:     private function read_wether() {
475:     $file = $this->cache_folder . $this->file_name . '.txt';
476:     if (file_exists($file)) {
477:         if (((time() - $this->cache_time) > filemtime($file)) || !$this->cache)
478:         return false; //This file is not fresh or cache disabled
479:         $handle = @fopen($file, 'r');
480:         if ($handle) {
481:         $json_weather = fread($handle, filesize($file));
482:         $this->weather_info = json_decode($json_weather, true);
483:         /** CHECK FOR METRICS AND FIX IT * */
484:         if ($this->temp_metric == "c") {
485:             $this->weather_info['temp'] = $this->weather_info['temp_c'];
486:             $this->weather_info['symbol'] = 'C';
487: 
488:             for ($i = 1; $i <= 3; $i++) {
489:             $this->weather_info['forecast'][$i]['temp_min'] = $this->weather_info['forecast'][$i]['min_temp_c'];
490:             $this->weather_info['forecast'][$i]['temp_max'] = $this->weather_info['forecast'][$i]['max_temp_c'];
491:             $this->weather_info['forecast'][$i]['symbol'] = 'C';
492:             }
493:         } else {
494:             $this->weather_info['temp'] = $this->weather_info['temp_f'];
495:             $this->weather_info['symbol'] = 'F';
496:             for ($i = 1; $i <= 3; $i++) {
497:             $this->weather_info['forecast'][$i]['temp_min'] = $this->weather_info['forecast'][$i]['min_temp_f'];
498:             $this->weather_info['forecast'][$i]['temp_max'] = $this->weather_info['forecast'][$i]['max_temp_f'];
499:             $this->weather_info['forecast'][$i]['symbol'] = 'F';
500:             }
501:         }
502: 
503:         fclose($handle);
504:         return true;
505:         }
506:     }
507: 
508:     return false;
509:     }
510: 
511:     /**
512:      * Get weather markup(Widget)
513:      * @return string
514:      */
515:     private function markup() {
516:     $next_weather = $this->languages[$this->lang]['show_next_days'];
517:     $back_weather = $this->languages[$this->lang]['back_to_weather'];
518:     $markup = '<div class="widget" style="width:' . $this->width . 'px;height:' . $this->height . 'px"> 
519:            <div class="upper">
520:            <div class="degree-box">
521:            <div class="temp">
522:            <h2 class="title"><span class="update">' . $this->weather_info['temp'] . '<sup>o</sup>' . $this->weather_info['symbol'] . '</span></h2></div>
523:            <div class="place update ' . $this->theme . '-place">' . $this->weather_info['place'] . '</div></div>
524:            <div id="change-weather" onclick="change_weather($(this))" show-ul="weather-forecast"  class="change-weather next-icon" title="' . $next_weather . '"></div>
525:            </div>
526:            <div class="clear"></div>
527:            <div class="lower ' . $this->theme . '-lower">
528:             
529:            <ul id="weather-info" class="infos-w">
530:            <li class="info-w weather"><h2 class="title"><span class="weather-bg" title="' . $this->languages[$this->lang]['weather'] . '"></span></h2>
531:             <span class="update">' . $this->weather_info['weather_main'] . '</span>
532:            <h2 class="title"><span><img title="' . $this->languages[$this->lang]['weather_desc'] . '" src="http://openweathermap.org/img/w/' . $this->weather_info['icon'] . '.png" /></span></h2>
533:                <span class="update">' . $this->weather_info['weather_description'] . '</span></li>
534:            <li class="info-w wind"><h2 class="title"><span class="wind-bg" title="' . $this->languages[$this->lang]['wind'] . '"></span></h2>
535:                <span class="update">' . $this->weather_info['wind_speed'] . 'm/s</span>
536:            <h2><span class="wind-degree" title="' . $this->languages[$this->lang]['wind_degree'] . '"></span></h2><p class="update">' . $this->weather_info['wind_degree'] . '<sup>o</sup></p></li>
537:            <li class="info-w"><h2 class="title"><span class="humidity" title="' . $this->languages[$this->lang]['humidity'] . '"></span></h2>
538:            <p class="update">' . $this->weather_info['humidity'] . '%</p>
539:            <h2><span class="pressure" title="' . $this->languages[$this->lang]['pressure'] . '"></span> </h2><p class="update">' . $this->weather_info['pressure'] . ' hPa</p></li></ul>';
540: 
541: 
542:     $inner_li = "";
543:     foreach ($this->weather_info['forecast'] as $weather) {
544:         $inner_li .= '<li class="info-w"><h2 class="title">' . $weather['day'] . '</h2><h3>' . $weather['month'] . '</h3>
545:            <span class="main update">
546:            <img title="' . $weather['weather_main'] . '" src="http://openweathermap.org/img/w/' . $weather['icon'] . '" /></span>
547:            <br/><span class="des update">' . $this->languages[$this->lang]['hi'] . ': ' . $weather['temp_max'] . '<sup>o</sup>' . $weather['symbol'] . '<br/>
548:             ' . $this->languages[$this->lang]['lo'] . ': ' . $weather['temp_min'] . '<sup>o</sup>' . $weather['symbol'] . '</span></li>';
549:     }
550: 
551:     $markup .= '<ul style="display:none"  id="weather-forecast" class="infos-w">' . $inner_li . '</ul></div></div>';
552: 
553:     //JAVASCRIPT
554:     $markup .= '<script type="text/javascript">
555:         function change_weather (sender){
556:         var elm = sender.attr("show-ul");
557:         var next_elm = "";
558:         
559:         if(elm == "weather-forecast"){
560:             next_elm = "weather-info";
561:             sender.removeClass("next-icon");
562:             sender.addClass("back-icon");
563:             sender.prop("title","' . $back_weather . '");
564:         }
565:         else {
566:             next_elm = "weather-forecast";
567:             sender.removeClass("back-icon");
568:             sender.addClass("next-icon");
569:             sender.prop("title","' . $next_weather . '");
570:         }
571:         
572:         //Set element next item
573:         sender.attr("show-ul",next_elm);
574:         sender.parent().parent().find("#"+next_elm).slideUp("slow");
575:         sender.parent().parent().find("#"+elm).slideDown("slow");
576:         }
577:     </script>';
578:     return $markup;
579:     }
580: 
581: }
weather_class API documentation generated by ApiGen 2.8.0