Source for file BBCWeather.php

Documentation is available at BBCWeather.php

  1. <?php
  2. /* SVN FILE: $Id: BBCWeather.php 13 2009-10-13 13:36:59Z Chris $ */
  3. /**
  4.  * BBC Weather data provider
  5.  *
  6.  * @link http://news.bbc.co.uk/weather/ BBC Weather site
  7.  * @filesource
  8.  * @copyright    Copyright 2009 PBM Web Development - All Rights Reserved
  9.  * @package      weatherForecast
  10.  * @subpackage   weatherForecast.providers
  11.  * @version      $Revision: 13 $
  12.  * @modifiedby   $LastChangedBy: Chris $
  13.  * @lastmodified $Date: 2009-10-13 14:36:59 +0100 (Tue, 13 Oct 2009) $
  14.  * @license      http://www.opensource.org/licenses/bsd-license.php The BSD License
  15.  */
  16.  
  17. include 'WeatherForecastProvider.php';
  18.  
  19. /**
  20.  * BBC Weather data provider
  21.  *
  22.  * <p>Values in params:<br>
  23.  * dateFormat (string) => Date format for days;
  24.  * Used by {@link http://www.yiiframework.com/doc/api/CDateFormatter#format-detail CDateFormatter::format()},
  25.  * see {@link http://www.unicode.org/reports/tr35/#Date_Format_Patterns Date Format Patterns}
  26.  * for a description of formats. Default: "EEE d'&nbsp;'MMM yyyy"<br>
  27.  * location (string) => Location.<br>
  28.  * To find the location id use the search on the above page.
  29.  * The id is the number immediately after "http://news.bbc.co.uk/weather/"<br>
  30.  * units (string) => Units to provide the forecast in.
  31.  * "C"|"F" C=metric (default), F=imperial</p>
  32.  *
  33.  * @package    weatherForecast
  34.  * @subpackage weatherForecast.providers
  35.  */
  36. class BBCWeather extends WFXMLProvider {
  37.   /**
  38.    * @var string Driver description
  39.    */
  40.   private $provider "BBC Weather";
  41.   /**#@+
  42.    * BBC Weather URLs
  43.    */
  44.   /**
  45.    * @var string BBC Weather url
  46.    */
  47.   private $url 'http://news.bbc.co.uk/weather/';
  48.   /**
  49.    * @var string Observations - current conditions
  50.    */
  51.   private $observationsUrl 'http://newsrss.bbc.co.uk/weather/forecast/%s/ObservationsRSS.xml';
  52.   /**
  53.    * @var string 3 Day forecast
  54.    */
  55.   private $next3DayUrl 'http://newsrss.bbc.co.uk/weather/forecast/%s/Next3DaysRSS.xml';
  56.   /**#@-*/
  57.   /**
  58.    * @var string Default values
  59.    */
  60.   protected $defaults array(
  61.     'location' => '2574'//London
  62.     'units' => 'C',
  63.     'dateFormat' => "EEE d'&nbsp;'MMM yyyy"
  64.   );
  65.   /**
  66.    * @var array Maps weather conditions to symbols
  67.    * Note: Probably not complete as the API is not documented
  68.    */
  69.   protected $symbolMap array(
  70.     'Clear Sky' => 'clear_night.png',
  71.     'Drizzle' => 'drizzle.png',
  72.     'Grey Cloud' => 'overcast.png',
  73.     'Heavy Rain Shower' => 'showers_heavy.png',
  74.     'Heavy Rain' => 'rain_heavy.png',
  75.     'Light Rain' => 'rain.png',
  76.     'Light Rain Shower' => 'showers.png',
  77.     'Partly Cloudy' => 'partly_cloudy_day.png',
  78.     'Sunny Intervals' => 'partly_cloudy_day.png',
  79.     'Sunny' => 'sunny.png',
  80.     'White Cloud' => 'cloudy.png'
  81.   );
  82.  
  83.   /**
  84.    * Fetches the forecast from the provider's datasource
  85.    *
  86.    * Required by IWeatherForecastProvider interface
  87.    *
  88.    * @return WFWeatherForecast Forecast object
  89.    */
  90.   public function getForecast($params$symbols{
  91.     $this->init($params$symbols);
  92.  
  93.     $forecast new WFWeatherForecast();
  94.     $dateFormatter Yii::app()->dateFormatter;
  95.  
  96.     $this->read(vsprintf($this->observationsUrl,  $this->location));
  97.  
  98.     $issued $this->xpath->evaluate('string(channel/lastBuildDate)');
  99.     if (substr($issued-5== '+0100'{
  100.       $tz 'BST';
  101.     }
  102.     else {
  103.       $tz 'GMT';
  104.     }
  105.     $issued substr($issued022$tz;
  106.  
  107.     $forecast->provider CHtml::link($this->provider$this->urlarray('rel'=>'external'));
  108.     $forecast->issued $issued;
  109.  
  110.     $location $this->xpath->evaluate('string(channel/title)');
  111.     preg_match('/for\s([- A-Za-z]+), ([ \w])+$/i'$location$matches);
  112.     $forecast->location->name $matches[1];
  113.  
  114.     $contextNode $this->xpath->evaluate('channel/item')->item(0);
  115.     $forecast->location->lat  =
  116.       $this->xpath->evaluate('string(geo:lat)'$contextNode);
  117.     $forecast->location->long =
  118.       $this->xpath->evaluate('string(geo:long)'$contextNode);
  119.  
  120.     $details $this->getDetails($contextNode);
  121.  
  122.     $day new WFDay();
  123.     $day->date 'Current Conditions';
  124.     $day->description $details['Description'];
  125.     $day->symbol $this->symbolsDir $this->symbolMap[$day->description];
  126.     $day->temperature->value   $details['Temperature'][0];
  127.     $day->temperature->units   $details['Temperature'][1];
  128.     $day->windSpeed->value     $details['Wind Speed'][0];
  129.     $day->windSpeed->units     $details['Wind Speed'][1];
  130.     $day->windDirection->value $details['Wind Direction'];
  131.     $day->humidity->value      $details['Humidity'][0];
  132.     $day->humidity->units      $details['Humidity'][1];
  133.     $day->visibility->value    $details['Visibility'];
  134.     $day->pressure->value      $details['Pressure'][0];
  135.     $day->pressure->units      $details['Pressure'][1];
  136.     $day->pressureTrend        $details['Pressure Trend'];
  137.     $forecast->days->add(0$day);
  138.  
  139.     $this->read(vsprintf($this->next3DayUrl,  $this->location));
  140.  
  141.     $items $this->xpath->evaluate('channel/item');
  142.     for ($i 0$l $items->length$i $l;{
  143.       $day new WFDay();
  144.       $details $this->getDetails($items->item($i++));
  145.       $day->date $dateFormatter->format($this->dateFormat"+$i days");
  146.       $day->description           $details['Description'];
  147.       $day->symbol $this->symbolsDir $this->symbolMap[$day->description];
  148.       $day->maxTemperature->value $details['Max Temp'][0];
  149.       $day->maxTemperature->units $details['Max Temp'][1];
  150.       $day->minTemperature->value $details['Min Temp'][0];
  151.       $day->minTemperature->units $details['Min Temp'][1];
  152.       $day->windSpeed->value      $details['Wind Speed'][0];
  153.       $day->windSpeed->units      $details['Wind Speed'][1];
  154.       $day->windDirection->value  $details['Wind Direction'];
  155.       $day->humidity->value       $details['Humidity'][0];
  156.       $day->humidity->units       $details['Humidity'][1];
  157.       $day->visibility->value     $details['Visibility'];
  158.       $day->pressure->value       $details['Pressure'][0];
  159.       $day->pressure->units       $details['Pressure'][1];
  160.       $forecast->days->add($i$day);
  161.     }
  162.  
  163.     return $forecast;
  164.   }
  165.  
  166.   /**
  167.    * Extracts the details from the title and description nodes of the context node
  168.    *
  169.    * @param DOMNode $contextNode The node from with to start XPath evaluation
  170.    * @return array The forecast details
  171.    */
  172.   private function getDetails($contextNode{
  173.     $_details explode(','$this->xpath->evaluate('string(title)'$contextNode));
  174.     foreach ($_details as $_detail{
  175.       $detail explode(':'$_detail);
  176.  
  177.       if (strpos($detail[0]' '!== false{
  178.         $detail[0substr($detail[0]0strpos($detail[0]' '));
  179.         $detail[1substr($detail[2]0strpos($detail[2]'.'));
  180.       }
  181.  
  182.       if (in_array($detail[0]array('Sunday''Monday''Tuesday''Wednesday''Thursday''Friday''Saturday'))) {
  183.         $details['Description'ucwords(trim($detail[1]));
  184.       }
  185.     // foreach
  186.  
  187.     $_details explode(','$this->xpath->evaluate('string(description)'$contextNode));
  188.     foreach ($_details as $_detail{
  189.       $detail explode(':'$_detail);
  190.  
  191.       if (empty($detail[1])) {
  192.         $details['Pressure Trend'trim($detail[0]);
  193.       }
  194.       else {
  195.         $detail[0trim($detail[0]);
  196.         $detail[1trim($detail[1]);
  197.         switch ($detail[0]{
  198.           case 'Max Temp':
  199.           case 'Min Temp':
  200.           case 'Temperature':
  201.             // The length value in substr MAY depend on the system encoding
  202.             $detail[1explode(' '$detail[1]);
  203.             if ($this->units == 'C'{
  204.               $value substr($detail[1][0]0-3);
  205.             }
  206.             else {
  207.               $value substr($detail[1][1]1-4);
  208.             }
  209.             $details[$detail[0]] array($value$this->units);
  210.             break;
  211.           case 'Wind Speed':
  212.             $value $this->units=='F' substr($detail[1]0-3$this->mph2kph(substr($detail[1]0-3));
  213.             $units $this->units=='F'?'mph':'kph';
  214.             $details[$detail[0]] array($value$units);
  215.             break;
  216.           case 'Pressure':
  217.             $value substr($detail[1]0-2);
  218.             $units substr($detail[1]-2);
  219.             $details[$detail[0]] array($value$units);
  220.             break;
  221.           case 'Relative Humidity':
  222.           case 'Humidity':
  223.             $value substr($detail[1]0-1);
  224.             $units substr($detail[1]-1);
  225.             $details[substr($detail[0]-8)array($value$units);
  226.             break;
  227.           default:
  228.             $details[$detail[0]] $detail[1];
  229.             break;
  230.         // switch
  231.       }
  232.     // foreach
  233.     return $details;
  234.   }
  235. }
  236. ?>

Documentation generated on Tue, 13 Oct 2009 14:44:43 +0100 by phpDocumentor 1.4.2