Source for file WeatherForecast.php

Documentation is available at WeatherForecast.php

  1. <?php
  2. /* SVN FILE: $Id: WeatherForecast.php 13 2009-10-13 13:36:59Z Chris $ */
  3. /**
  4.  * Weather Forecast widget
  5.  *
  6.  * Parses data from a weather forecast provider and creates a view.
  7.  *
  8.  * Three weather forecast providers are supported by default:
  9.  * BBC (Note: the API is not published so the symbolMap is almost certainly incomplete)
  10.  * Google (Note: the API is not published so the symbolMap is almost certainly incomplete)
  11.  * Yahoo (Note: Yahoo data is provided by the Weather Channel)
  12.  *
  13.  * Adding a new provider by writing the {provider}Weather class and
  14.  * placing the {provider}Weather.php file in the providers directory.
  15.  *
  16.  * Cacheing is supported to reduce bandwidth requirements.
  17.  * Cacheing is for provider::location; this means that if you have multiple forecasts
  18.  * for different locations and/or from different providers each is cached.
  19.  *
  20.  * @filesource
  21.  * @copyright    Copyright 2009 PBM Web Development - All Rights Reserved
  22.  * @package      weatherForecast
  23.  * @since        V1.0.0
  24.  * @version      $Revision: 13 $
  25.  * @modifiedby   $LastChangedBy: Chris $
  26.  * @lastmodified $Date: 2009-10-13 14:36:59 +0100 (Tue, 13 Oct 2009) $
  27.  * @license      http://www.opensource.org/licenses/bsd-license.php The BSD License
  28.  */
  29.  
  30. /**
  31.  * Weather Forecast widget class
  32.  *
  33.  * <p><b>Options:</b></p>
  34.  * <p><b>provider (string):</b><br>
  35.  * Name of the weather forecast provider.
  36.  * Can be specified with or without "Weather" at the end:
  37.  * e.g. BBC and BBWeather will both use the BBCWeather provider</p>
  38.  *
  39.  * <p><b>params (array):</b><br>
  40.  * Contains provider dependant parameters;
  41.  * see the documentation for the provider classes.<br>
  42.  * While the exact requiremets are provider dependant,
  43.  * there are three common parameters:<br>
  44.  * dateFormat (string) => Date format for days;
  45.  * Used by {@link http://www.yiiframework.com/doc/api/CDateFormatter#format-detail CDateFormatter::format()},
  46.  * see {@link http://www.unicode.org/reports/tr35/#Date_Format_Patterns Date Format Patterns}
  47.  * for a description of formats. Default: "EEE d'&nbsp;'MMM yyyy"<br>
  48.  * location (string) => location of the forecast in the providers format.
  49.  * Default location is London, UK<br>
  50.  * units (string) => Units to provide the forecast in.
  51.  * "C"|"F" C=metric (default), F=imperial</p>
  52.  *
  53.  * <p><b>cache (mixed):</b><br>
  54.  * integer: number of seconds before the forecast expires</br>
  55.  * array:<br>
  56.  * 0 (integer) => number of seconds before the forecast expires<br>
  57.  * 1 (CCacheDependency) => Cache dependency object<br>
  58.  * boolean false: Disable cacheing. i.e. every access creates a request
  59.  * to the provider.<br>
  60.  * null (default): Cache the forecast for one hour</p>
  61.  *
  62.  * <p><b>cssFile (mixed):</b><br>
  63.  * string: Path to the CSS file to use<br>
  64.  * boolean false: No CSS file<br>
  65.  * null (default): Use the default CSS file</p>
  66.  *
  67.  * <p><b>symbolsDir (mixed):</b><br>
  68.  * string: Path to the directory containing symbols to use<br>
  69.  * boolen false: Use the providers symbols specified in the data (Google only)<br>
  70.  * null (default): Use the default symbols</p>
  71.  *
  72.  * <p><b>symbolMap (mixed):</b><br>
  73.  * array: Associative array that maps a forecast parameter
  74.  * (e.g., description, code, etc.) to the symbol to use
  75.  * for a given value of the parameter. e.g.
  76.  * 'symbolMap' => array(
  77.  *   'Partly Cloudy' => partly_cloudy.gif,
  78.  *   'Sunny' => 'sunn.gif',
  79.  *   etc.
  80.  * );<br>
  81.  * null (default): Use the provider's default symbol map</p>
  82.  *
  83.  * <p><b>Example Useage</b></p>
  84.  * <p><code>
  85.  * $this->widget('application.extensions.widgets.weatherForecast.WeatherForecast', array(
  86.  *  'provider'=>'BBC',
  87.  *  'params' => array(
  88.  *  'location'=>'40', // BBCWeather::Paris
  89.  *    'units' => 'C'
  90.  *  ),
  91.  *  'cache'=>array(
  92.  *    3600, // Cache up to one hour
  93.  *    new CExpressionDependency("date('H)") // Expire the cache at the top of the hour
  94.  *  )
  95.  * ));</code></p>
  96.  *
  97.  * @package weatherForecast
  98.  */
  99. class WeatherForecast extends CWidget {
  100.   /**
  101.    * @var string Forecast provider
  102.    */
  103.   public $provider;
  104.   /**
  105.    * @var array Parameters for the forecast provider
  106.    */
  107.   public $params;
  108.   /**
  109.    * @var mixed integer: the number of seconds in which the cached forecast will expire; array: (the number of seconds in which the cached forecast will expire, cache dependency object); boolean false: no cacheing
  110.    * @link http://www.yiiframework.com/doc/api/CCache
  111.    * @link http://www.yiiframework.com/doc/api/CCacheDependency
  112.    */
  113.   public $cache 3600;
  114.   /**
  115.    * @var string Path of CSS file to use
  116.    */
  117.   public $cssFile;
  118.   /**
  119.    * @var string Path of directory containing symbols to use.
  120.    * Set to false if the provider provides symbols to be used
  121.    */
  122.   public $symbolsDir;
  123.   /**
  124.    * @var array Map of a forecast parameter to symbols.
  125.    * Leave empty if there is a 1:1 correlation between the parameter and symbol name
  126.    */
  127.   public $symbolMap;
  128.   /**
  129.    * @var object The active forecast provider
  130.    */
  131.   private $forecastProvider;
  132.   /**
  133.    * @var array Loaded forecast providers
  134.    */
  135.   private $forecastProviders;
  136.  
  137.   /**
  138.    * Initialises the widget
  139.    *
  140.    * Registers the CSS file and sets the required forecast provider,
  141.    * loading it if required
  142.    */
  143.   public function init({
  144.     if ($this->cssFile !== false{
  145.       if ($this->cssFile === null{
  146.         $file dirname(__FILE__DS 'assets' DS 'weather_forecast.css';
  147.         $this->cssFile Yii::app()->getAssetManager()->publish($file);
  148.       }
  149.  
  150.       Yii::app()->getClientScript()->registerCssFile($this->cssFile);
  151.     }
  152.  
  153.     if ($this->symbolsDir === null{
  154.       $this->symbolsDir Yii::app()->getAssetManager()->publish(dirname(__FILE__.DS.'assets'.DS.'symbols''/';
  155.     }
  156.  
  157.     $this->provider .= (substr($this->provider-7!= 'Weather' 'Weather' '');
  158.     $this->forecastProvider $this->getProvider($this->provider);
  159.   }
  160.  
  161.   /**
  162.    * Display the forecast
  163.    *
  164.    * The cached forecast is used if enabled and not expired
  165.    */
  166.   public function run({
  167.     if ($this->cache !== false{
  168.       $location = isset($this->params['location']$this->params['location''';
  169.       $forecast Yii::app()->cache->get("weatherForecast.{$this->provider}.{$location}");
  170.       if ($forecast === false) {
  171.         $forecast = $this->forecastProvider->getForecast($this->paramsarray($this->symbolsDir$this->symbolMap));
  172.         if (is_integer($this->cache)) {
  173.           $this->cache array($this->cachenull);
  174.         }
  175.         Yii::app()->cache->set("weatherForecast.{$this->provider}.{$location}", $forecast, $this->cache[0]$this->cache[1]);
  176.       }
  177.     }
  178.     else {
  179.       $forecast = $this->forecastProvider->getForecast($this->paramsarray($this->symbolsDir$this->symbolMap));
  180.     }
  181.  
  182.     $this->render('weatherForecast'compact('forecast'));
  183.   }
  184.  
  185.   /**
  186.    * Factory method to load the forecast provider
  187.    *
  188.    * @param  string $provider Forecast provider
  189.    * @return WFBaseProvider Forecast provider class
  190.    * @throws CDbException if provider not suppored
  191.    */
  192.   private function getProvider($provider) {
  193.     if (isset($this->forecastProviders[$provider])) {
  194.       return $this->forecastProviders[$provider];
  195.     }
  196.  
  197.     if (file_exists(dirname(__FILE__).DS.'providers' . DS . "$provider.php")) {
  198.       include_once "providers/$provider.php";
  199.       $this->forecastProviders[$providernew $provider;
  200.       return $this->forecastProviders[$provider];
  201.     }
  202.     else {
  203.       throw new CDbException(Yii::t('app', __CLASS__ . ' does not support {driver} as a provider.', array('{driver}'=>$provider)));
  204.     }
  205.   }
  206.  
  207.   /**
  208.    * Renders the forecast table
  209.    *
  210.    * @param array $sections sections of the table
  211.    * @param array $htmlOptions HTML options for the table
  212.    * @return string The rendered table
  213.    */
  214.   public function renderTable($sections, $htmlOptions = array()) {
  215.     $table = '';
  216.     $sectionOrder = array('caption', 'thead', 'tfoot', 'tbody');
  217.  
  218.     foreach ($sectionOrder as $tag) {
  219.       if (isset($sections[$tag])) {
  220.         $table .= $this->renderTableSection($tag$sections[$tag]);
  221.       }
  222.     } // foreach
  223.     return Chtml::tag('table', $htmlOptions, $table);
  224.   }
  225.  
  226.   private function renderTableSection($tag, $content) {
  227.     if ($tag == 'caption') {
  228.       $out = $this->renderTableElement($tag$content);
  229.     }
  230.     else {
  231.       $htmlOptions = isset($content['htmlOptions']) ? $content['htmlOptions'] : array();
  232.       unset($content['htmlOptions']);
  233.  
  234.       $rows = '';
  235.       foreach ($content as $key => $row) {
  236.         $rows .= $this->renderTableRow($key$row);
  237.         $out CHtml::tag($tag$htmlOptions$rows);
  238.       } // foreach
  239.     }
  240.     return $out;
  241.   }
  242.  
  243.   private function renderTableRow($key, $content) {
  244.     $htmlOptions = isset($content['htmlOptions']) ? $content['htmlOptions'] : array();
  245.     unset($content['htmlOptions']);
  246.  
  247.     if ($key%2) {
  248.       if (isset($htmlOptions['class'])) $htmlOptions['class'] .= ' even';
  249.       else $htmlOptions['class'] = 'even';
  250.     }
  251.  
  252.     $cells = '';
  253.     foreach ($content as $column => $cell) {
  254.       if (is_string($cell)) {
  255.         $cell = array($cell);
  256.       }
  257.  
  258.       if (isset($cell['htmlOptions']['class'])) $cell['htmlOptions']['class'] .= ' column-' . ($column + 1);
  259.       else $cell['htmlOptions']['class'] = 'column-' . ($column + 1);
  260.  
  261.       $cells .= $this->renderTableElement(isset($cell['htmlOptions']['scope']'th' 'td'$cell);
  262.       $out CHtml::tag('tr'$htmlOptions$cells);
  263.     } // foreach
  264.     return $out;
  265.   }
  266.  
  267. private function renderTableElement($tag, $content) {
  268.     if (is_array($content)) {
  269.       $htmlOptions = isset($content['htmlOptions']) ? $content['htmlOptions'] : array();
  270.       unset($content['htmlOptions']);
  271.       $content = $content[0];
  272.     }
  273.     else {
  274.       $htmlOptions = array();
  275.     }
  276.  
  277.     return CHtml::tag($tag, $htmlOptions, $content);
  278.   }
  279. }

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