Services_Weather
[ class tree: Services_Weather ] [ index: Services_Weather ] [ all elements ]

Source for file Weatherdotcom.php

Documentation is available at Weatherdotcom.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
  3.  
  4. /**
  5.  * PEAR::Services_Weather_Weatherdotcom
  6.  *
  7.  * PHP versions 4 and 5
  8.  *
  9.  * <LICENSE>
  10.  * Copyright (c) 2005-2011, Alexander Wirtz
  11.  * All rights reserved.
  12.  *
  13.  * Redistribution and use in source and binary forms, with or without
  14.  * modification, are permitted provided that the following conditions
  15.  * are met:
  16.  * o Redistributions of source code must retain the above copyright notice,
  17.  *   this list of conditions and the following disclaimer.
  18.  * o Redistributions in binary form must reproduce the above copyright notice,
  19.  *   this list of conditions and the following disclaimer in the documentation
  20.  *   and/or other materials provided with the distribution.
  21.  * o Neither the name of the software nor the names of its contributors
  22.  *   may be used to endorse or promote products derived from this software
  23.  *   without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35.  * POSSIBILITY OF SUCH DAMAGE.
  36.  * </LICENSE>
  37.  *
  38.  * @category    Web Services
  39.  * @package     Services_Weather
  40.  * @author      Alexander Wirtz <alex@pc4p.net>
  41.  * @copyright   2005-2011 Alexander Wirtz
  42.  * @license     http://www.opensource.org/licenses/bsd-license.php  BSD License
  43.  * @version     CVS: $Id$
  44.  * @link        http://pear.php.net/package/Services_Weather
  45.  * @link        http://www.weather.com/services/xmloap.html
  46.  * @example     examples/weather.com-basic.php      weather.com-basic.php
  47.  * @example     examples/weather.com-extensive.php  weather.com-extensive.php
  48.  * @filesource
  49.  */
  50.  
  51. require_once "Services/Weather/Common.php";
  52.  
  53. // {{{ class Services_Weather_Weatherdotcom
  54. /**
  55.  * This class acts as an interface to the xml service of weather.com. It
  56.  * searches for given locations and retrieves current weather data as well
  57.  * as forecast for up to 5 days.
  58.  *
  59.  * For using the weather.com xml-service please visit
  60.  *     http://www.weather.com/services/xmloap.html
  61.  * and follow the link to sign up, it's free! You will receive an email
  62.  * where to download the SDK with the needed images and guidelines how to
  63.  * publish live data from weather.com. Unfortunately the guidelines are a
  64.  * bit harsh, that's why there's no actual data-representation in this
  65.  * class, just the raw data. Also weather.com demands active caching, so I'd
  66.  * strongly recommend enabling the caching implemented in this class. It
  67.  * obeys to the times as written down in the guidelines.
  68.  *
  69.  * For working examples, please take a look at
  70.  *     docs/Services_Weather/examples/weather.com-basic.php
  71.  *     docs/Services_Weather/examples/weather.com-extensive.php
  72.  *
  73.  * @category    Web Services
  74.  * @package     Services_Weather
  75.  * @author      Alexander Wirtz <alex@pc4p.net>
  76.  * @copyright   2005-2011 Alexander Wirtz
  77.  * @license     http://www.opensource.org/licenses/bsd-license.php  BSD License
  78.  * @version     Release: 1.4.7
  79.  * @link        http://pear.php.net/package/Services_Weather
  80.  * @link        http://www.weather.com/services/xmloap.html
  81.  * @example     examples/weather.com-basic.php      weather.com-basic.php
  82.  * @example     examples/weather.com-extensive.php  weather.com-extensive.php
  83.  */
  84.  
  85.     // {{{ properties
  86.     /**
  87.      * Partner-ID at weather.com
  88.      *
  89.      * @var     string                      $_partnerID 
  90.      * @access  private
  91.      */
  92.     var $_partnerID "";
  93.  
  94.     /**
  95.      * License key at weather.com
  96.      *
  97.      * @var     string                      $_licenseKey 
  98.      * @access  private
  99.      */
  100.     var $_licenseKey "";
  101.  
  102.     /**
  103.      * Switch to toggle pre-fetching of data in one single request
  104.      *
  105.      * @var     bool                        $_preFetch 
  106.      * @access  private
  107.      */
  108.      var $_preFetch = false;
  109.  
  110.     /**
  111.      * Object containing the promotional links-data
  112.      *
  113.      * @var     object stdClass             $_links 
  114.      * @access  private
  115.      */
  116.     var $_links;
  117.  
  118.     /**
  119.      * Object containing the location
  120.      *
  121.      * @var     object stdClass             $_location 
  122.      * @access  private
  123.      */
  124.     var $_location;
  125.     
  126.     /**
  127.      * Object containing the weather
  128.      *
  129.      * @var     object stdClass             $_weather 
  130.      * @access  private
  131.      */
  132.     var $_weather;
  133.     
  134.     /**
  135.      * Object containing the forecast
  136.      *
  137.      * @var     object stdClass             $_forecast 
  138.      * @access  private
  139.      */
  140.     var $_forecast;
  141.  
  142.     /**
  143.      * XML_Unserializer, used for processing the xml
  144.      *
  145.      * @var     object XML_Unserializer     $_unserializer 
  146.      * @access  private
  147.      */
  148.     var $_unserializer;
  149.     // }}}
  150.  
  151.     // {{{ constructor
  152.     /**
  153.      * Constructor
  154.      *
  155.      * Requires XML_Serializer to be installed
  156.      *
  157.      * @param   array                       $options 
  158.      * @param   mixed                       $error 
  159.      * @throws  PEAR_Error
  160.      * @access  private
  161.      */
  162.     function Services_Weather_Weatherdotcom($options&$error)
  163.     {
  164.         $perror = null;
  165.         $this->Services_Weather_Common($options$perror);
  166.         if (Services_Weather::isError($perror)) {
  167.             $error $perror;
  168.             return;
  169.         }
  170.  
  171.         // Set options accordingly
  172.         if (isset($options["partnerID"])) {
  173.             $this->setAccountData($options["partnerID"]);
  174.         }
  175.         if (isset($options["licenseKey"])) {
  176.             $this->setAccountData(""$options["licenseKey"]);
  177.         }
  178.         if (isset($options["preFetch"])) {
  179.             $this->enablePreFetch($options["preFetch"]);
  180.         }
  181.  
  182.         include_once "XML/Unserializer.php";
  183.         $unserializer &new XML_Unserializer(array("complexType" => "object""keyAttribute" => "type"));
  184.         if (Services_Weather::isError($unserializer)) {
  185.             $error $unserializer;
  186.             return;
  187.         else {
  188.             $this->_unserializer $unserializer;
  189.         }
  190.  
  191.         // Initialize the properties containing the data from the server
  192.         $this->_links    = null;
  193.         $this->_location = null;
  194.         $this->_weather  = null;
  195.         $this->_forecast = null;
  196.  
  197.         // Can't acquire an object here, has to be clean on every request
  198.         include_once "HTTP/Request.php";
  199.     }
  200.     // }}}
  201.  
  202.     // {{{ setAccountData()
  203.     /**
  204.      * Sets the neccessary account-information for weather.com, you'll
  205.      * receive them after registering for the XML-stream
  206.      *
  207.      * @param   string                      $partnerID 
  208.      * @param   string                      $licenseKey 
  209.      * @access  public
  210.      */
  211.     function setAccountData($partnerID$licenseKey)
  212.     {
  213.         if (strlen($partnerID&& ctype_digit($partnerID)) {
  214.             $this->_partnerID  $partnerID;
  215.         }
  216.         if (strlen($licenseKey&& ctype_alnum($licenseKey)) {
  217.             $this->_licenseKey $licenseKey;
  218.         }
  219.     }
  220.     // }}}
  221.  
  222.     // {{{ enablePreFetch()
  223.     /**
  224.      * Enables pre-fetching of data in one single request
  225.      *
  226.      * @param   bool                        $preFetch 
  227.      * @access  public
  228.      */
  229.     function enablePreFetch($preFetch)
  230.     {
  231.         if ($preFetch == true{
  232.             $this->_preFetch = true;
  233.         }
  234.     }
  235.     // }}}
  236.  
  237.     // {{{ _checkLocationID()
  238.     /**
  239.      * Checks the id for valid values and thus prevents silly requests to
  240.      * weather.com server
  241.      *
  242.      * @param   string                      $id 
  243.      * @return  PEAR_Error|bool
  244.      * @throws  PEAR_Error::SERVICES_WEATHER_ERROR_NO_LOCATION
  245.      * @throws  PEAR_Error::SERVICES_WEATHER_ERROR_INVALID_LOCATION
  246.      * @access  private
  247.      */
  248.     function _checkLocationID($id)
  249.     {
  250.         if (is_array($id|| is_object($id|| !strlen($id)) {
  251.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_NO_LOCATION__FILE____LINE__);
  252.         elseif (!ctype_alnum($id|| (strlen($id> 8)) {
  253.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_INVALID_LOCATION__FILE____LINE__);
  254.         }
  255.  
  256.         return true;
  257.     }
  258.     // }}}
  259.  
  260.     // {{{ _parseWeatherData()
  261.     /**
  262.      * Fetches the data based on the requested type and caches it
  263.      *
  264.      * @param   string                      $id 
  265.      * @param   string                      $reqType 
  266.      * @return  PEAR_Error|bool
  267.      * @throws  PEAR_Error::SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA
  268.      * @throws  PEAR_Error
  269.      * @access  private
  270.      */
  271.     function _parseWeatherData($id$reqType)
  272.     {
  273.         if ($this->_preFetch{
  274.             $reqType "all";
  275.         }
  276.  
  277.         $url "http://xoap.weather.com/weather/local/".$id."?link=xoap&prod=xoap&par=".$this->_partnerID."&key=".$this->_licenseKey;
  278.  
  279.         switch ($reqType{
  280.             case "links":
  281.                 $url .= "";
  282.                 break;
  283.             case "weather":
  284.                 $url .= "&cc=*&unit=s";
  285.                 break;
  286.             case "forecast":
  287.                 $url .= "&dayf=5&unit=s";
  288.                 break;
  289.             case "all":
  290.                 $url .= "&cc=*&dayf=5&unit=s";
  291.                 break;
  292.         }
  293.  
  294.         // Get data from URL...
  295.         $request &new HTTP_Request($url$this->_httpOptions);
  296.         $status $request->sendRequest();
  297.         if (Services_Weather::isError($status|| (int) $request->getResponseCode(<> 200{
  298.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA__FILE____LINE__);
  299.         }
  300.         $data $request->getResponseBody();
  301.  
  302.         // ...and unserialize
  303.         $status $this->_unserializer->unserialize($data);
  304.  
  305.         if (Services_Weather::isError($status)) {
  306.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA__FILE____LINE__);
  307.         else {
  308.             $root $this->_unserializer->getRootName();
  309.             $data $this->_unserializer->getUnserializedData();
  310.  
  311.             if (Services_Weather::isError($root|| $root == "HTML"{
  312.                 // Something wrong here, maybe not XML retrieved...
  313.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA__FILE____LINE__);
  314.             elseif ($root == "error"{
  315.                 // We got an error back from weather.com
  316.                 $errno  key(get_object_vars($data));
  317.                 return Services_Weather::raiseError($errno__FILE____LINE__);
  318.             else {
  319.                 // Valid data, lets get started
  320.                 // Loop through the different sub-parts of the data for processing
  321.                 foreach (get_object_vars($dataas $key => $val{
  322.                     switch ($key{
  323.                         case "head":
  324.                             continue 2;
  325.                         case "prmo":
  326.                             $varname  "links";
  327.                             break;
  328.                         case "loc":
  329.                             $varname  "location";
  330.                             break;
  331.                         case "cc":
  332.                             $varname  "weather";
  333.                             break;
  334.                         case "dayf":
  335.                             $varname  "forecast";
  336.                             break;
  337.                     }
  338.                     // Save data in object
  339.                     $this->{"_".$varname$val;
  340.                     if ($this->_cacheEnabled{
  341.                         // ...and cache if possible
  342.                         $this->_saveCache($id$val""$varname);
  343.                     }
  344.                 }
  345.             }
  346.         }
  347.  
  348.         return true;
  349.     }
  350.     // }}}
  351.  
  352.     // {{{ searchLocation()
  353.     /**
  354.      * Searches IDs for given location, returns array of possible locations
  355.      * or single ID
  356.      *
  357.      * @param   string                      $location 
  358.      * @param   bool                        $useFirst       If set, first ID of result-array is returned
  359.      * @return  PEAR_Error|array|string
  360.      * @throws  PEAR_Error::SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA
  361.      * @throws  PEAR_Error::SERVICES_WEATHER_ERROR_UNKNOWN_LOCATION
  362.      * @access  public
  363.      */
  364.     function searchLocation($location$useFirst = false)
  365.     {
  366.         $location trim($location);
  367.         $locLow   strtolower($location);
  368.         
  369.         // Check on cached data: MD5-hash of location has to be correct and the userdata has to be the same as the given location 
  370.         if ($this->_cacheEnabled && $locLow == $this->_getUserCache(md5($locLow)"search")) {
  371.             $search $this->_getCache(md5($locLow)"search");
  372.         else {
  373.             // Get search data from server and unserialize
  374.             $request &new HTTP_Request("http://xoap.weather.com/search/search?where=".urlencode($location)$this->_httpOptions);
  375.             $status $request->sendRequest();
  376.             if (Services_Weather::isError($status|| (int) $request->getResponseCode(<> 200{
  377.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA__FILE____LINE__);
  378.             }
  379.             $data $request->getResponseBody();
  380.     
  381.             // ...and unserialize
  382.             $status $this->_unserializer->unserialize($datafalsearray("overrideOptions" => true"complexType" => "array""keyAttribute" => "id"));
  383.     
  384.             if (Services_Weather::isError($status)) {
  385.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA__FILE____LINE__);
  386.             }
  387.     
  388.             $root $this->_unserializer->getRootName();
  389.             $search $this->_unserializer->getUnserializedData();
  390.     
  391.             if (Services_Weather::isError($search|| $root == "HTML"{
  392.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA__FILE____LINE__);
  393.             elseif (!is_array($search|| !sizeof($search)) {
  394.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_UNKNOWN_LOCATION__FILE____LINE__);
  395.             }
  396.  
  397.             if ($this->_cacheEnabled{
  398.                 // ...and cache if possible
  399.                 $this->_saveCache(md5($locLow)$search$locLow"search");
  400.             }
  401.         }
  402.  
  403.         if (!$useFirst && (sizeof($search> 1)) {
  404.             $searchReturn $search;
  405.         elseif ($useFirst || (sizeof($search== 1)) {
  406.             $searchReturn key($search);
  407.         else {
  408.             $searchReturn = array();
  409.         }
  410.  
  411.         return $searchReturn;
  412.     }
  413.     // }}}
  414.  
  415.     // {{{ searchLocationByCountry()
  416.     /**
  417.      * Returns only false, as weather.com offers no country listing via
  418.      * its XML services
  419.      *
  420.      * @param   string                      $country 
  421.      * @return  bool 
  422.      * @access  public
  423.      * @deprecated
  424.      */
  425.     function searchLocationByCountry($country "")
  426.     {
  427.         return false;
  428.     }
  429.     // }}}
  430.  
  431.     // {{{ getLinks()
  432.     /**
  433.      * Returns the data for the promotional links belonging to the ID
  434.      *
  435.      * @param   string                      $id 
  436.      * @return  PEAR_Error|array
  437.      * @throws  PEAR_Error
  438.      * @access  public
  439.      */
  440.     function getLinks($id "")
  441.     {
  442.         $status $this->_checkLocationID($id);
  443.  
  444.         if (Services_Weather::isError($status)) {
  445.             return $status;
  446.         }
  447.  
  448.         $linksReturn = array();
  449.  
  450.         if (is_object($this->_links)) {
  451.             $linksReturn["cache""MEM";
  452.         elseif ($this->_cacheEnabled && ($links $this->_getCache($id"links"))) {
  453.             // Get data from cache
  454.             $this->_links = $links;
  455.             $linksReturn["cache""HIT";
  456.         else {
  457.             // Same as in the function above...
  458.             $status $this->_parseWeatherData($id"links");
  459.  
  460.             if (Services_Weather::isError($status)) {
  461.                 return $status;
  462.             }
  463.             $linksReturn["cache""MISS";
  464.         }
  465.  
  466.         $linksReturn["promo"= array();
  467.         for ($i = 0; $i sizeof($this->_links->link)$i++{
  468.             $linksReturn["promo"][$i= array();
  469.             $linksReturn["promo"][$i]["title"$this->_links->link[$i]->t;
  470.             // B0rked response (returned is &par=xoap, should be &prod=xoap), fix it
  471.             $linksReturn["promo"][$i]["link"]  str_replace("par=""prod="$this->_links->link[$i]->l);
  472.             $linksReturn["promo"][$i]["link".= "&par=".$this->_partnerID;
  473.         }
  474.  
  475.         return $linksReturn;
  476.     }
  477.     // }}}
  478.  
  479.     // {{{ getLocation()
  480.     /**
  481.      * Returns the data for the location belonging to the ID
  482.      *
  483.      * @param   string                      $id 
  484.      * @return  PEAR_Error|array
  485.      * @throws  PEAR_Error
  486.      * @access  public
  487.      */
  488.     function getLocation($id "")
  489.     {
  490.         $status $this->_checkLocationID($id);
  491.  
  492.         if (Services_Weather::isError($status)) {
  493.             return $status;
  494.         }
  495.  
  496.         $locationReturn = array();
  497.  
  498.         if (is_object($this->_location)) {
  499.             $locationReturn["cache""MEM";
  500.         elseif ($this->_cacheEnabled && ($location $this->_getCache($id"location"))) {
  501.             // Get data from cache
  502.             $this->_location = $location;
  503.             $locationReturn["cache""HIT";
  504.         else {
  505.             // Same as in the function above...
  506.             $status $this->_parseWeatherData($id"location");
  507.  
  508.             if (Services_Weather::isError($status)) {
  509.                 return $status;
  510.             }
  511.             $locationReturn["cache""MISS";
  512.         }
  513.  
  514.         $locationReturn["name"]      $this->_location->dnam;
  515.         $locationReturn["time"]      date($this->_timeFormatstrtotime($this->_location->tm));
  516.         $locationReturn["latitude"]  $this->_location->lat;
  517.         $locationReturn["longitude"$this->_location->lon;
  518.         $locationReturn["sunrise"]   date($this->_timeFormatstrtotime($this->_location->sunr));
  519.         $locationReturn["sunset"]    date($this->_timeFormatstrtotime($this->_location->suns));
  520.         $locationReturn["timezone"]  $this->_location->zone;
  521.  
  522.         return $locationReturn;
  523.     }
  524.     // }}}
  525.  
  526.     // {{{ getWeather()
  527.     /**
  528.      * Returns the weather-data for the supplied location
  529.      *
  530.      * @param   string                      $id 
  531.      * @param   string                      $unitsFormat 
  532.      * @return  PEAR_Error|array
  533.      * @throws  PEAR_Error
  534.      * @access  public
  535.      */
  536.     function getWeather($id ""$unitsFormat "")
  537.     {
  538.         $status $this->_checkLocationID($id);
  539.  
  540.         if (Services_Weather::isError($status)) {
  541.             return $status;
  542.         }
  543.  
  544.         // Get other data
  545.         $units    $this->getUnitsFormat($unitsFormat);
  546.  
  547.         $weatherReturn = array();
  548.  
  549.         if (is_object($this->_weather)) {
  550.             $weatherReturn["cache""MEM";
  551.         elseif ($this->_cacheEnabled && ($weather $this->_getCache($id"weather"))) {
  552.             // Same procedure...
  553.             $this->_weather = $weather;
  554.             $weatherReturn["cache""HIT";
  555.         else {
  556.             // ...as last function
  557.             $status $this->_parseWeatherData($id"weather");
  558.  
  559.             if (Services_Weather::isError($status)) {
  560.                 return $status;
  561.             }
  562.             $weatherReturn["cache""MISS";
  563.         }
  564.  
  565.         // Make sure the location object has been loaded
  566.         if (!is_object($this->_location)) {
  567.             $this->getLocation($id);
  568.         }
  569.  
  570.         // Some explanation for the next two lines:
  571.         // weather.com isn't always supplying the timezone in the update string, but
  572.         // uses "Local Time" as reference, which is imho utterly stupid, because it's
  573.         // inconsistent. Well, what I do here is check for this string and if I can
  574.         // find it, I calculate the difference between the timezone at the location
  575.         // and this computers timezone. This amount of seconds is then subtracted from
  576.         // the time the update-string has delivered.
  577.         $update   str_replace("Local Time"""$this->_weather->lsup);
  578.         $adjustTZ ($update == $this->_weather->lsup? 0 : $this->_location->zone * 3600 - date("Z");
  579.         $weatherReturn["update"]            gmdate(trim($this->_dateFormat." ".$this->_timeFormat)strtotime($update$adjustTZ);
  580.         $weatherReturn["updateRaw"]         $this->_weather->lsup;
  581.         $weatherReturn["station"]           $this->_weather->obst;
  582.         $weatherReturn["temperature"]       round($this->convertTemperature($this->_weather->tmp"f"$units["temp"])2);
  583.         $weatherReturn["feltTemperature"]   round($this->convertTemperature($this->_weather->flik"f"$units["temp"]2));
  584.         $weatherReturn["condition"]         $this->_weather->t;
  585.         $weatherReturn["conditionIcon"]     $this->_weather->icon;
  586.         $weatherReturn["pressure"]          round($this->convertPressure($this->_weather->bar->r"in"$units["pres"])2);
  587.         $weatherReturn["pressureTrend"]     $this->_weather->bar->d;
  588.         $weatherReturn["wind"]              round($this->convertSpeed($this->_weather->wind->s"mph"$units["wind"])2);
  589.         $weatherReturn["windGust"]          round($this->convertSpeed($this->_weather->wind->gust"mph"$units["wind"])2);
  590.         $weatherReturn["windDegrees"]       $this->_weather->wind->d;
  591.         $weatherReturn["windDirection"]     $this->_weather->wind->t;
  592.         $weatherReturn["humidity"]          round($this->_weather->hmid1);
  593.         if (is_numeric($this->_weather->vis)) {
  594.             $weatherReturn["visibility"]    round($this->convertDistance($this->_weather->vis"sm"$units["vis"])2);
  595.         else {
  596.             $weatherReturn["visibility"]    $this->_weather->vis;
  597.         }
  598.         $weatherReturn["uvIndex"]           $this->_weather->uv->i;
  599.         $weatherReturn["uvText"]            $this->_weather->uv->t;
  600.         $weatherReturn["dewPoint"]          round($this->convertTemperature($this->_weather->dewp"f"$units["temp"])2);
  601.         $weatherReturn["moon"]              $this->_weather->moon->t;
  602.         $weatherReturn["moonIcon"]          $this->_weather->moon->icon;
  603.  
  604.         return $weatherReturn;
  605.     }
  606.     // }}}
  607.  
  608.     // {{{ getForecast()
  609.     /**
  610.      * Get the forecast for the next days
  611.      *
  612.      * @param   string                      $id 
  613.      * @param   int                         $days           Values between 1 and 5
  614.      * @param   string                      $unitsFormat 
  615.      * @return  PEAR_Error|array
  616.      * @throws  PEAR_Error
  617.      * @access  public
  618.      */
  619.     function getForecast($id ""$days = 5$unitsFormat "")
  620.     {
  621.         $status $this->_checkLocationID($id);
  622.  
  623.         if (Services_Weather::isError($status)) {
  624.             return $status;
  625.         }
  626.         if (!is_int($days|| ($days < 1|| ($days > 5)) {
  627.             $days = 5;
  628.         }
  629.  
  630.         // Get other data
  631.         $units    $this->getUnitsFormat($unitsFormat);
  632.  
  633.         $forecastReturn = array();
  634.  
  635.         if (is_object($this->_forecast)) {
  636.             $forecastReturn["cache""MEM";
  637.         elseif ($this->_cacheEnabled && ($forecast $this->_getCache($id"forecast"))) {
  638.             // Encore...
  639.             $this->_forecast = $forecast;
  640.             $forecastReturn["cache""HIT";
  641.         else {
  642.             // ...
  643.             $status $this->_parseWeatherData($id"forecast");
  644.  
  645.             if (Services_Weather::isError($status)) {
  646.                 return $status;
  647.             }
  648.             $forecastReturn["cache""MISS";
  649.         }
  650.  
  651.         // Make sure the location object has been loaded
  652.         if (!is_object($this->_location)) {
  653.             $this->getLocation($id);
  654.         }
  655.  
  656.         // Some explanation for the next two lines: (same as above)
  657.         // weather.com isn't always supplying the timezone in the update string, but
  658.         // uses "Local Time" as reference, which is imho utterly stupid, because it's
  659.         // inconsistent. Well, what I do here is check for this string and if I can
  660.         // find it, I calculate the difference between the timezone at the location
  661.         // and this computers timezone. This amount of seconds is then subtracted from
  662.         // the time the update-string has delivered.
  663.         $update   str_replace("Local Time"""$this->_forecast->lsup);
  664.         $adjustTZ ($update == $this->_forecast->lsup? 0 : $this->_location->zone * 3600 - date("Z");
  665.         $forecastReturn["update"]    gmdate($this->_dateFormat." ".$this->_timeFormatstrtotime($update$adjustTZ);
  666.         $forecastReturn["updateRaw"$this->_forecast->lsup;
  667.         $forecastReturn["days"]      = array();
  668.  
  669.         for ($i = 0; $i $days$i++{
  670.             $day = array(
  671.                 "temperatureHigh" => round($this->convertTemperature($this->_forecast->day[$i]->hi"f"$units["temp"])2),
  672.                 "temperatureLow"  => round($this->convertTemperature($this->_forecast->day[$i]->low"f"$units["temp"])2),
  673.                 "sunrise"         => date($this->_timeFormatstrtotime($this->_forecast->day[$i]->sunr)),
  674.                 "sunset"          => date($this->_timeFormatstrtotime($this->_forecast->day[$i]->suns)),
  675.                 "day" => array(
  676.                     "condition"     => $this->_forecast->day[$i]->part[0]->t,
  677.                     "conditionIcon" => $this->_forecast->day[$i]->part[0]->icon,
  678.                     "wind"          => round($this->convertSpeed($this->_forecast->day[$i]->part[0]->wind->s"mph"$units["wind"])2),
  679.                     "windGust"      => round($this->convertSpeed($this->_forecast->day[$i]->part[0]->wind->gust"mph"$units["wind"])2),
  680.                     "windDegrees"   => $this->_forecast->day[$i]->part[0]->wind->d,
  681.                     "windDirection" => $this->_forecast->day[$i]->part[0]->wind->t,
  682.                     "precipitation" => $this->_forecast->day[$i]->part[0]->ppcp,
  683.                     "humidity"      => round($this->_forecast->day[$i]->part[0]->hmid1)
  684.                 ),
  685.                 "night" => array (
  686.                     "condition"     => $this->_forecast->day[$i]->part[1]->t,
  687.                     "conditionIcon" => $this->_forecast->day[$i]->part[1]->icon,
  688.                     "wind"          => round($this->convertSpeed($this->_forecast->day[$i]->part[1]->wind->s"mph"$units["wind"])2),
  689.                     "windGust"      => round($this->convertSpeed($this->_forecast->day[$i]->part[1]->wind->gust"mph"$units["wind"])2),
  690.                     "windDegrees"   => $this->_forecast->day[$i]->part[1]->wind->d,
  691.                     "windDirection" => $this->_forecast->day[$i]->part[1]->wind->t,
  692.                     "precipitation" => $this->_forecast->day[$i]->part[1]->ppcp,
  693.                     "humidity"      => round($this->_forecast->day[$i]->part[1]->hmid1)
  694.                 )
  695.             );
  696.  
  697.             $forecastReturn["days"][$day;
  698.         }
  699.  
  700.         return $forecastReturn;
  701.     }
  702.     // }}}
  703. }
  704. // }}}
  705. ?>

Documentation generated on Mon, 11 Mar 2019 15:51:00 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.