5 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * @author Robert Basic * @email dpfreak@gmail.com * @link http://vtssu.rs/~kazil/ * @copyright 2008 Robert Basic * @package myWeather * @version 0.0.1 */ class myWeather { /** * The URL from witch the information is gathered * * @var string */ var $url = "http://weather.weatherbug.com/Serbia%20and%20Montenegro/{city}-weather/local-forecast/detailed-forecast.html?zcode=z6286"; /** * The cURL status code * * @var integer */ var $curl_status_code = 0; /** * Array of cities for which weather information can be gathered * * @var array */ var $cities = array("Subotica","Belgrade","Novi Sad"); /** * The city for which the weather information is gathered * * @var string */ var $city = ""; /** * How many days to show in the forecast? Max is 7 * * @var integer */ var $number_of_days_for_forecast = 7; /** * Array with the forecast details (day, date, image, high, low, description) * * @var array */ var $forecast = array(); /** * Should it translate to Serbian? * * @var bool */ var $translate = true; /** * Array with the translation text (must be filled at time, 'cause "new" words can show up) * * @var array */ var $translate_text = array( "Weather forcast for" => "Vremenska prognoza za", "Monday" => "Ponedeljak", "Tuesday" => "Utorak", "Wednesday" => "Sreda", "Thursday" => "Cetvrtak", "Friday" => "Petak", "Saturday" => "Subota", "Sunday" => "Nedelja", "Hi" => "Najvi�a dnevna", "Lo" => "Najni�a dnevna", "Afternoon clouds" => "Popodne naoblacenje", "Morning clouds" => "Ujutro naoblacenje", "Showers early" => "Ujutro pljusak", "Sprinkles early" => "Ujutro ki�ica", "Sprinkles late" => "Uvece ki�ica", "Hot" => "Toplo", "Mostly cloudy" => "Uglavnom oblacno", "Mostly sunny" => "Uglavnom suncano", "Mild" => "Umereno", "Pleasantly warm" => "Prijatno toplo", "Pleasantly warm, Dry" => "Prijatno toplo, suvo", "More sun than clouds" => "Vi�e sunca nego oblaka", "Numerous showers" => "Brojni pljuskovi", "Temperature of" => "Temperatura", "Winds" => "Vetar ce duvati brzinom od", "Humidity will be" => "Vla�nost vazduha ce biti", "There is a" => "�ansa za padavine je" ); /** * Date formats in which the parsed date can be transformed to * * @var array */ var $date_formats = array("sr" => "d.m.Y."); /** * Convert to this date format * * @var string */ var $date_format = "sr"; /** * The name of the cache file (to put into, or to get out from) * Naming: content_randomNumber_unixTimeStamp.html * * @var string */ var $cache_file; /** * Folder for the cache. Default is html * * @var string */ var $cache_folder; /** * How long should the cache live? Default is 7200 seconds (2 hours) * * @var integer */ var $cache_lifetime = 7200; /** * Get the information from the cache file? * * @var bool */ var $from_cache = false; /** * Constructor * * @param string $city * @param integer $number_of_days_for_forecast * @param string $cache_folder * @param string $date_format * @param bool $translate */ function __construct($city = "Belgrade",$number_of_days_for_forecast = 7,$cache_folder = "html",$date_format = "sr",$translate = true) { // If no cURL functions available, it should die(); if(function_exists("curl_init") === FALSE){ echo "No cURL functions available!"; exit; } (in_array($city,$this->cities)) ? $this->city = $city : $this->city = "Belgrade"; if($number_of_days_for_forecast < 1) $number_of_days_for_forecast = 1; elseif($number_of_days_for_forecast > 7) $number_of_days_for_forecast = 7; $this->number_of_days_for_forecast = $number_of_days_for_forecast; $this->cache_folder = $cache_folder; (in_array($date_format,$this->date_formats)) ? $this->date_format = $date_format : $this->date_format = "sr"; $this->translate = $translate; // Check if cache is young enough or exists $this->checkCache(); // If not from cache if(!$this->from_cache){ $this->clearCache(); $this->setCityInUrl(); $this->createHtmlFile(); $this->getDataFromUrl(); } // Get the data from the cache file if($this->curl_status_code == 200 || $this->from_cache){ $this->getDataFromHtmlFile(); } // if there is forecast to show, show it if(count($this->forecast) > 0){ $this->showForecast(); } } /** * Show the forecast. Needs some Javascript/CSS tuning. * */ private function showForecast() { $box = "\n"; $box .= "
\n"; $box .= "\t

".$this->translate_text['Weather forcast for'].": $this->city

\n"; foreach($this->forecast as $forecast){ $box .= "
\n\t".$this->translate($forecast['day'],1). " :: " . $this->translate($forecast['date'],2) . "\n
\n"; $box .= "
\n\t".$forecast['image']."\n
\n"; $box .= "
\n\t".$this->translate($forecast['high'],3)."
".$this->translate($forecast['low'],3)."\n
\n"; $box .= "
\n\t".$this->translate($forecast['description'],4)."\n
\n"; } $box .= "
\n"; echo $box; } /** * Translate the forecast. If they change how the info is showing up, this'll need a full rewrite :-/ * * @param string $string * @param integer $type */ private function translate($string, $type = 1) { // Do not translate if($this->translate === false) return $string; switch($type){ case 1:{ // An ordinary sentence to translate (ie. "Sunny", "Hot", "Raining" etc...) if(array_key_exists($string,$this->translate_text)) return $this->translate_text[$string]; else return $string; } break; case 2:{ // Translate the date return date($this->date_formats[$this->date_format],strtotime($string)); } break; case 3:{ // Translate the high/low temperatures $string = explode(":",$string); list($text, $temperature) = $string; if(array_key_exists($text,$this->translate_text)) $text = $this->translate_text[$text]; return $text .": ". trim($temperature) ."C"; } break; case 4:{ // Translate sentences with variable data in them. (ie. "Temperature of 24�C", "There is a 37% chance of precipitation." etc) $sentences = explode(".",$string); // We go sentence by sentence for($i=0;$itranslate_text)){ // If an ordinary translation... $sentences[$i] = $this->translate_text[$sentences[$i]]; } else{ //First type of sentences... if(preg_match("'(?<=Temperature \s of \s) \d .*'ixs",$sentences[$i],$temp_degree) && array_key_exists("Temperature of",$this->translate_text)){ preg_match("'(?:Temperature \s of)'ixs",$sentences[$i],$temp_text); $sentences[$i] = $this->translate_text[$temp_text[0]] . " " . $temp_degree[0]; } // Second type of sentences elseif(preg_match("'(?<=Winds \s) \d .*'ixs",$sentences[$i],$wind_speed_direction) && array_key_exists("Winds",$this->translate_text)){ preg_match("'(?:Winds)'ixs",$sentences[$i],$wind_text); $from = array("E","W","N","S","NE","NW","SE","SW","ENE","WNW","ESE","WSW","NNE","NNW","SSE","SSW"); $to = array("I","Z","S","J","SI","SZ","JI","JZ","ISI","ZSZ","IJI","ZJZ","SSI","SSZ","JJI","JJZ"); $wind_speed_direction[0] = str_replace($from,$to,$wind_speed_direction[0]); $sentences[$i] = $this->translate_text[$wind_text[0]] . " " . $wind_speed_direction[0]; } //Third type of sentences elseif(preg_match("'(?<=Humidity \s will \s be \s) \d{2,3}.'ixs",$sentences[$i],$humidity_percent) && array_key_exists("Humidity will be",$this->translate_text)){ preg_match("'(?:Humidity \s will \s be)'ixs",$sentences[$i],$humidity_text); $sentences[$i] = $this->translate_text[$humidity_text[0]] . " " . $humidity_percent[0]; } // Fourth type of sentences elseif(preg_match("'(?<=There \s is \s a \s) \d{1,2}.'ixs",$sentences[$i],$precipitation_percent) && array_key_exists("There is a",$this->translate_text)){ preg_match("'(?:There \s is \s a)'ixs",$sentences[$i],$precipitation_text); $sentences[$i] = $this->translate_text[$precipitation_text[0]] . " " . $precipitation_percent[0]; } } } return implode(". ",$sentences); // Glue the sentences back together... } break; default:{ if(array_key_exists($string,$this->translate_text)) return $this->translate_text[$string]; else return $string; } break; } } /** * Get the data from the URL. Uses cURL library * * @param string $string * @param integer $type */ private function getDataFromUrl() { // Init $ch = curl_init($this->url); // Open up the cache file for writing $fh = fopen($this->cache_file, "wb+"); // The output of curl goes into the cache file curl_setopt($ch, CURLOPT_FILE, $fh); // Execute curl curl_exec($ch); // Get the status code $this->curl_status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //Close... curl_close($ch); fclose($fh); } /** * Check the cache, if the cache file is young enough * */ private function checkCache() { $files = scandir($this->cache_folder); $files = implode(",",$files); preg_match_all('/(?<=content\_)\w{1,}/i',$files,$matches); $matches = $matches[0]; $file_ts = array(); // the timestamp that is glued to the file name $file_rnd = array(); // the random number that is glued to the file name for($i=0;$i $val){ $diff = $now - $val; if($diff < $this->cache_lifetime){ // if it's young enough $this->from_cache = true; $this->cache_file = $this->cache_folder . "/" . "content_" . $file_rnd[$key] . "_" . $val . ".html"; } else{ $this->from_cache = false; } } } /** * Clear the cache folder, we don't want old files hangin' around... * */ private function clearCache() { $files = scandir($this->cache_folder); foreach($files as $file){ if($file != "." || $file != "..") @unlink("html/$file"); } } /** * Get the data from the html (cache) file * */ private function getDataFromHtmlFile() { $file_content = file_get_contents($this->cache_file); if($file_content != ""){ $this->getForecast($file_content); } } /** * Gets the forecast information from the html (cache) file * It's done in several stages, this way was easier... * */ private function getForecast(&$file_content) { $forecast = array(); for($i=0;$i<$this->number_of_days_for_forecast;$i++){ $j=$i+1; // For the last day it's a bit different regex $regex_1st_part = "'
(.*?)"; ($i==6) ? $regex_2nd_part = "
'ixs" : $regex_2nd_part = "
'ixs"; $regex = $regex_1st_part . $regex_2nd_part; preg_match($regex,$file_content,$forecast[$i]); } foreach($forecast as $key => $val){ $forecast[$key] = $forecast[$key][1]; } $tmp_forecast = array(); foreach($forecast as $key => $val){ // Get the day preg_match("'
(.*?)
'ixs",$val,$tmp_forecast['day'][$key]); // Get the date preg_match("'
(.*?)
'ixs",$val,$tmp_forecast['date'][$key]); // Get the image preg_match("'
(.*?)
'ixs",$val,$tmp_forecast['image'][$key]); // Get the high preg_match("'
(.*?)
'ixs",$val,$tmp_forecast['high'][$key]); // Get the low preg_match("'
(.*?)
'ixs",$val,$tmp_forecast['low'][$key]); // Get the whole text preg_match("'
(.*?)
'ixs",$val,$tmp_forecast['description'][$key]); } for($i=0;$iforecast[$i]['day'] = $tmp_forecast['day'][$i][1]; $this->forecast[$i]['date'] = $tmp_forecast['date'][$i][1]; $this->forecast[$i]['image'] = $tmp_forecast['image'][$i][1]; $this->forecast[$i]['high'] = $tmp_forecast['high'][$i][1]; $this->forecast[$i]['low'] = $tmp_forecast['low'][$i][1]; $this->forecast[$i]['description'] = $tmp_forecast['description'][$i][1]; } } /** * Set the city in the URL * */ private function setCityInUrl() { $this->url = str_replace("{city}",$this->city,$this->url); } /** * Actually, create the cache file... but it's the same... * */ private function createHtmlFile() { if(!is_dir($this->cache_folder)){ mkdir($this->cache_folder); chmod($this->cache_folder, 0755); } mt_srand(); $random = mt_rand()."_".time(); $this->cache_file = $this->cache_folder . "/" . "content_".$random.".html"; } } ?>