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: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at                              |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Alexander Wirtz <alex@pc4p.net>                             |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Weatherdotcom.php,v 1.34 2004/03/31 12:32:58 eru Exp $
  20.  
  21. require_once "Services/Weather/Common.php";
  22.  
  23. // {{{ class Services_Weather_Weatherdotcom
  24. /**
  25. * PEAR::Services_Weather_Weatherdotcom
  26. *
  27. * This class acts as an interface to the xml service of weather.com. It searches for given
  28. * locations and retrieves current weather data as well as forecast for up to 10 days.
  29. *
  30. * For using the weather.com xml-service please visit
  31. *     http://www.weather.com/services/xmloap.html
  32. * and follow the link to sign up, it's free! You will receive an email where to download
  33. * the SDK with the needed images and guidelines how to publish live data from weather.com.
  34. * Unfortunately the guidelines are a bit harsh, that's why there's no actual data-representation
  35. * in this class, just the raw data.
  36. * Also weather.com demands active caching, so I'd strongly recommend enabling the caching
  37. * implemented in this class. It obeys to the times as written down in the guidelines.
  38. *
  39. * For a working example, please take a look at
  40. *     docs/Services_Weather/examples/weather.com-basic.php
  41. *
  42. @author       Alexander Wirtz <alex@pc4p.net>
  43. @link         http://www.weather.com/services/xmloap.html
  44. @example      docs/Services_Weather/examples/weather.com-basic.php
  45. @package      Services_Weather
  46. @license      http://www.php.net/license/2_02.txt
  47. @version      1.2
  48. */
  49.  
  50.     // {{{ properties
  51.     /**
  52.     * Partner-ID at weather.com
  53.     *
  54.     * @var      string                      $_partnerID 
  55.     * @access   private
  56.     */
  57.     var $_partnerID "";
  58.  
  59.     /**
  60.     * License key at weather.com
  61.     *
  62.     * @var      string                      $_licenseKey 
  63.     * @access   private
  64.     */
  65.     var $_licenseKey "";
  66.  
  67.     /**
  68.     * XML_Unserializer, used for processing the xml
  69.     *
  70.     * @var      object XML_Unserializer     $_unserializer 
  71.     * @access   private
  72.     */
  73.     var $_unserializer;
  74.     // }}}
  75.  
  76.     // {{{ constructor
  77.     /**
  78.     * Constructor
  79.     *
  80.     * Requires XML_Serializer to be installed
  81.     *
  82.     * @param    array                       $options 
  83.     * @param    mixed                       $error 
  84.     * @throws   PEAR_Error
  85.     * @see      Science_Weather::Science_Weather
  86.     * @access   private
  87.     */
  88.     function Services_Weather_Weatherdotcom($options&$error)
  89.     {
  90.         $perror = null;
  91.         $this->Services_Weather_Common($options$perror);
  92.         if (Services_Weather::isError($perror)) {
  93.             $error $perror;
  94.             return;
  95.         }
  96.  
  97.         // Set options accordingly
  98.         if (isset($options["partnerID"])) {
  99.             $this->setAccountData($options["partnerID"]);
  100.         }
  101.         if (isset($options["licenseKey"])) {
  102.             $this->setAccountData(""$options["licenseKey"]);
  103.         }
  104.         
  105.         include_once "XML/Unserializer.php";
  106.         $unserializer &new XML_Unserializer(array("complexType" => "object""keyAttribute" => "type"));
  107.         if (Services_Weather::isError($unserializer)) {
  108.             $error $unserializer;
  109.             return;
  110.         else {
  111.             $this->_unserializer $unserializer;
  112.         }
  113.         
  114.         // Can't acquire an object here, has to be clean on every request
  115.         include_once "HTTP/Request.php";
  116.     }
  117.     // }}}
  118.  
  119.     // {{{ setAccountData()
  120.     /**
  121.     * Sets the neccessary account-information for weather.com, you'll receive them after registering for the XML-stream
  122.     *
  123.     * @param    string                      $partnerID 
  124.     * @param    string                      $licenseKey 
  125.     * @access   public
  126.     */
  127.     function setAccountData($partnerID$licenseKey)
  128.     {
  129.         if (strlen($partnerID&& ctype_digit($partnerID)) {
  130.             $this->_partnerID  $partnerID;
  131.         }
  132.         if (strlen($licenseKey&& ctype_alnum($licenseKey)) {
  133.             $this->_licenseKey $licenseKey;
  134.         }
  135.     }
  136.     // }}}
  137.  
  138.     // {{{ _checkLocationID()
  139.     /**
  140.     * Checks the id for valid values and thus prevents silly requests to weather.com server
  141.     *
  142.     * @param    string                      $id 
  143.     * @return   PEAR_Error|bool
  144.     * @throws   PEAR_Error::SERVICES_WEATHER_ERROR_NO_LOCATION
  145.     * @throws   PEAR_Error::SERVICES_WEATHER_ERROR_INVALID_LOCATION
  146.     * @access   private
  147.     */
  148.     function _checkLocationID($id)
  149.     {
  150.         if (!strlen($id)) {
  151.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_NO_LOCATION);
  152.         elseif (!ctype_alnum($id|| (strlen($id> 8)) {
  153.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_INVALID_LOCATION);
  154.         }
  155.  
  156.         return true;
  157.     }
  158.     // }}}
  159.  
  160.     // {{{ _parseWeatherData()
  161.     /**
  162.     * Parses the data returned by the provided URL and caches it
  163.     *
  164.     * @param    string                      $id 
  165.     * @param    string                      $url 
  166.     * @return   PEAR_Error|bool
  167.     * @throws   PEAR_Error::SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA
  168.     * @throws   PEAR_Error
  169.     * @access   private
  170.     */
  171.     function _parseWeatherData($id$url)
  172.     {
  173.         // Get data from URL...
  174.         $request &new HTTP_Request($urlarray("timeout" => $this->_httpTimeout));
  175.         $status $request->sendRequest();
  176.         if (Services_Weather::isError($status)) {
  177.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA);
  178.         }
  179.         $data $request->getResponseBody();
  180.         
  181.         // ...and unserialize
  182.         $status $this->_unserializer->unserialize($data);
  183.  
  184.         if (Services_Weather::isError($status)) {
  185.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA);
  186.         else {
  187.             $root $this->_unserializer->getRootName();
  188.             $data $this->_unserializer->getUnserializedData();
  189.  
  190.             if (Services_Weather::isError($root)) {
  191.                 // Something wrong here...
  192.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA);
  193.             elseif ($root == "error"{
  194.                 // We got an error back from weather.com
  195.                 $errno  key(get_object_vars($data));
  196.                 return Services_Weather::raiseError($errno);
  197.             else {
  198.                 // Valid data, lets get started
  199.                 // Loop through the different sub-parts of the data fro processing
  200.                 foreach (get_object_vars($dataas $key => $val{
  201.                     switch ($key{
  202.                         case "head":
  203.                             continue 2;
  204.                             break;
  205.                         case "loc":
  206.                             $varname  "location";
  207.                             break;
  208.                         case "cc":
  209.                             $varname  "weather";
  210.                             break;
  211.                         case "dayf":
  212.                             $varname  "forecast";
  213.                             break;
  214.                     }
  215.                     // Save data in object
  216.                     $this->{"_".$varname$val;
  217.                     if ($this->_cacheEnabled{
  218.                         // ...and cache if possible
  219.                         $expire constant("SERVICES_WEATHER_EXPIRES_".strtoupper($varname));
  220.                         $this->_cache->extSave($id$val""$expire$varname);
  221.                     }
  222.                 }
  223.             }
  224.         }
  225.  
  226.         return true;
  227.     }
  228.     // }}}
  229.  
  230.     // {{{ searchLocation()
  231.     /**
  232.     * Searches IDs for given location, returns array of possible locations or single ID
  233.     *
  234.     * @param    string                      $location 
  235.     * @param    bool                        $useFirst       If set, first ID of result-array is returned
  236.     * @return   PEAR_Error|array|string
  237.     * @throws   PEAR_Error::SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA
  238.     * @throws   PEAR_Error::SERVICES_WEATHER_ERROR_UNKNOWN_LOCATION
  239.     * @access   public
  240.     */
  241.     function searchLocation($location$useFirst = false)
  242.     {
  243.         // Get search data from server and unserialize
  244.         $searchURL "http://xoap.weather.com/search/search?where=".urlencode(trim($location));
  245.         $status $this->_unserializer->unserialize($searchURLtruearray("overrideOptions" => true"complexType" => "array""keyAttribute" => "id"));
  246.  
  247.         if (Services_Weather::isError($status)) {
  248.             return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA);
  249.         else {
  250.             $search $this->_unserializer->getUnserializedData();
  251.  
  252.             if (Services_Weather::isError($search)) {
  253.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA);
  254.             elseif (!is_array($search|| !sizeof($search)) {
  255.                 return Services_Weather::raiseError(SERVICES_WEATHER_ERROR_UNKNOWN_LOCATION);
  256.             else {
  257.                 if (!$useFirst && (sizeof($search> 1)) {
  258.                     $searchReturn $search;
  259.                 elseif ($useFirst || (sizeof($search== 1)) {
  260.                     $searchReturn key($search);
  261.                 }
  262.             }
  263.         }
  264.  
  265.         return $searchReturn;
  266.     }
  267.     // }}}
  268.  
  269.     // {{{ searchLocationByCountry()
  270.     /**
  271.     * Returns only false, as weather.com offers no country listing via
  272.     * its XML services
  273.     *
  274.     * @param    string                      $country 
  275.     * @return   bool 
  276.     * @access   public
  277.     * @deprecated
  278.     */
  279.     function searchLocationByCountry($country "")
  280.     {
  281.         return false;
  282.     }
  283.     // }}}
  284.  
  285.     // {{{ getUnits()
  286.     /**
  287.     * Returns the units for the current query
  288.     *
  289.     * @param    string                      $id 
  290.     * @param    string                      $unitsFormat 
  291.     * @return   array 
  292.     * @deprecated
  293.     * @access   public
  294.     */
  295.     function getUnits($id = null$unitsFormat "")
  296.     {
  297.         return $this->getUnitsFormat($unitsFormat);
  298.     }
  299.     // }}}
  300.  
  301.     // {{{ getLocation()
  302.     /**
  303.     * Returns the data for the location belonging to the ID
  304.     *
  305.     * @param    string                      $id 
  306.     * @return   PEAR_Error|array
  307.     * @throws   PEAR_Error
  308.     * @access   public
  309.     */
  310.     function getLocation($id "")
  311.     {
  312.         $status $this->_checkLocationID($id);
  313.  
  314.         if (Services_Weather::isError($status)) {
  315.             return $status;
  316.         }
  317.  
  318.         $locationReturn = array();
  319.         $locationURL    "http://xoap.weather.com/weather/local/".$id."?prod=xoap&par=".$this->_partnerID."&key=".$this->_licenseKey."&unit=s";
  320.  
  321.         if ($this->_cacheEnabled && ($location $this->_cache->get($id"location"))) {
  322.             // Get data from cache
  323.             $this->_location = $location;
  324.             $locationReturn["cache""HIT";
  325.         else {
  326.             // Same as in the function above...
  327.             $status $this->_parseWeatherData($id$locationURL);
  328.  
  329.             if (Services_Weather::isError($status)) {
  330.                 return $status;
  331.             }
  332.             $locationReturn["cache""MISS";
  333.         }
  334.         $locationReturn["name"]      $this->_location->dnam;
  335.         $locationReturn["time"]      date($this->_timeFormatstrtotime($this->_location->tm));
  336.         $locationReturn["latitude"]  $this->_location->lat;
  337.         $locationReturn["longitude"$this->_location->lon;
  338.         $locationReturn["sunrise"]   date($this->_timeFormatstrtotime($this->_location->sunr));
  339.         $locationReturn["sunset"]    date($this->_timeFormatstrtotime($this->_location->suns));
  340.         $locationReturn["timezone"]  $this->_location->zone;
  341.  
  342.         return $locationReturn;
  343.     }
  344.     // }}}
  345.  
  346.     // {{{ getWeather()
  347.     /**
  348.     * Returns the weather-data for the supplied location
  349.     *
  350.     * @param    string                      $id 
  351.     * @param    string                      $unitsFormat 
  352.     * @return   PEAR_Error|array
  353.     * @throws   PEAR_Error
  354.     * @access   public
  355.     */
  356.     function getWeather($id ""$unitsFormat "")
  357.     {
  358.         $status $this->_checkLocationID($id);
  359.  
  360.         if (Services_Weather::isError($status)) {
  361.             return $status;
  362.         }
  363.  
  364.         // Get other data
  365.         $units    $this->getUnitsFormat($unitsFormat);
  366.  
  367.         $weatherReturn = array();
  368.         $weatherURL    "http://xoap.weather.com/weather/local/".$id."?cc=*&prod=xoap&par=".$this->_partnerID."&key=".$this->_licenseKey."&unit=s";
  369.  
  370.         if ($this->_cacheEnabled && ($weather $this->_cache->get($id"weather"))) {
  371.             // Same procedure...
  372.             $this->_weather = $weather;
  373.             $weatherReturn["cache""HIT";
  374.         else {
  375.             // ...as last function
  376.             $status $this->_parseWeatherData($id$weatherURL);
  377.  
  378.             if (Services_Weather::isError($status)) {
  379.                 return $status;
  380.             }
  381.             $weatherReturn["cache""MISS";
  382.         }
  383.         
  384.         $update  str_replace("Local Time"""$this->_weather->lsup);
  385.         $weatherReturn["update"]            gmdate(trim($this->_dateFormat." ".$this->_timeFormat)strtotime($update));
  386.         $weatherReturn["updateRaw"]         $this->_weather->lsup;
  387.         $weatherReturn["station"]           $this->_weather->obst;
  388.         $weatherReturn["temperature"]       $this->convertTemperature($this->_weather->tmp"f"$units["temp"]);
  389.         $weatherReturn["feltTemperature"]   $this->convertTemperature($this->_weather->flik"f"$units["temp"]);
  390.         $weatherReturn["condition"]         $this->_weather->t;
  391.         $weatherReturn["conditionIcon"]     $this->_weather->icon;
  392.         $weatherReturn["pressure"]          $this->convertPressure($this->_weather->bar->r"in"$units["pres"]);
  393.         $weatherReturn["pressureTrend"]     $this->_weather->bar->d;
  394.         $weatherReturn["wind"]              $this->convertSpeed($this->_weather->wind->s"mph"$units["wind"]);
  395.         $weatherReturn["windGust"]            $this->convertSpeed($this->_weather->wind->gust"mph"$units["wind"]);        
  396.         $weatherReturn["windDegrees"]       $this->_weather->wind->d;
  397.         $weatherReturn["windDirection"]     $this->_weather->wind->t;
  398.         $weatherReturn["humidity"]          $this->_weather->hmid;
  399.         if (is_numeric($this->_weather->vis)) {
  400.             $weatherReturn["visibility"]    $this->convertDistance($this->_weather->vis"sm"$units["vis"]);
  401.         else {
  402.             $weatherReturn["visibility"]    $this->_weather->vis;
  403.         }
  404.         $weatherReturn["uvIndex"]           $this->_weather->uv->i;
  405.         $weatherReturn["uvText"]            $this->_weather->uv->t;
  406.         $weatherReturn["dewPoint"]          $this->convertTemperature($this->_weather->dewp"f"$units["temp"]);
  407.  
  408.         return $weatherReturn;
  409.     }
  410.     // }}}
  411.  
  412.     // {{{ getForecast()
  413.     /**
  414.     * Get the forecast for the next days
  415.     *
  416.     * @param    string                      $id 
  417.     * @param    int                         $days           Values between 1 and 10
  418.     * @param    string                      $unitsFormat 
  419.     * @return   PEAR_Error|array
  420.     * @throws   PEAR_Error
  421.     * @access   public
  422.     */
  423.     function getForecast($id ""$days = 2$unitsFormat "")
  424.     {
  425.         $status $this->_checkLocationID($id);
  426.  
  427.         if (Services_Weather::isError($status)) {
  428.             return $status;
  429.         }
  430.         if (!in_array($daysrange(110))) {
  431.             $days = 2;
  432.         }
  433.         
  434.         // Get other data
  435.         $units    $this->getUnitsFormat($unitsFormat);
  436.  
  437.         $forecastReturn = array();
  438.         $forecastURL "http://xoap.weather.com/weather/local/".$id."?dayf=10&prod=xoap&par=".$this->_partnerID."&key=".$this->_licenseKey."&unit=s";
  439.  
  440.         if ($this->_cacheEnabled && ($forecast $this->_cache->get($id"forecast"))) {
  441.             // Encore...
  442.             $this->_forecast = $forecast;
  443.             $forecastReturn["cache""HIT";
  444.         else {
  445.             // ...
  446.             $status $this->_parseWeatherData($id$forecastURL$days);
  447.  
  448.             if (Services_Weather::isError($status)) {
  449.                 return $status;
  450.             }
  451.             $forecastReturn["cache""MISS";
  452.         }
  453.  
  454.         $update implode(" "array_slice(explode(" "$this->_forecast->lsup )03));
  455.  
  456.         $forecastReturn["update"date($this->_dateFormat." ".$this->_timeFormatstrtotime($update));
  457.         $forecastReturn["days"]   = array();
  458.  
  459.         for ($i = 0; $i $days$i++{
  460.             $day = array(
  461.                 "temperatureHigh" => $this->convertTemperature($this->_forecast->day[$i]->hi"f"$units["temp"]),
  462.                 "temperatureLow"  => $this->convertTemperature($this->_forecast->day[$i]->low"f"$units["temp"]),
  463.                 "sunrise"         => date($this->_timeFormatstrtotime($this->_forecast->day[$i]->sunr)),
  464.                 "sunset"          => date($this->_timeFormatstrtotime($this->_forecast->day[$i]->suns)),
  465.                 "day" => array(
  466.                     "condition"     => $this->_forecast->day[$i]->part[0]->t,
  467.                     "conditionIcon" => $this->_forecast->day[$i]->part[0]->icon,
  468.                     "wind"          => $this->convertSpeed($this->_forecast->day[$i]->part[0]->wind->s"mph"$units["wind"]),
  469.                     "windGust"      => $this->convertSpeed($this->_forecast->day[$i]->part[0]->wind->gust"mph"$units["wind"]),
  470.                     "windDegrees"   => $this->_forecast->day[$i]->part[0]->wind->d,
  471.                     "windDirection" => $this->_forecast->day[$i]->part[0]->wind->t,
  472.                     "precipitation" => $this->_forecast->day[$i]->part[0]->ppcp,
  473.                     "humidity"      => $this->_forecast->day[$i]->part[0]->hmid
  474.                 ),
  475.                 "night" => array (
  476.                     "condition"     => $this->_forecast->day[$i]->part[1]->t,
  477.                     "conditionIcon" => $this->_forecast->day[$i]->part[1]->icon,
  478.                     "wind"          => $this->convertSpeed($this->_forecast->day[$i]->part[1]->wind->s"mph"$units["wind"]),
  479.                     "windGust"      => $this->convertSpeed($this->_forecast->day[$i]->part[1]->wind->gust"mph"$units["wind"]),
  480.                     "windDegrees"   => $this->_forecast->day[$i]->part[1]->wind->d,
  481.                     "windDirection" => $this->_forecast->day[$i]->part[1]->wind->t,
  482.                     "precipitation" => $this->_forecast->day[$i]->part[1]->ppcp,
  483.                     "humidity"      => $this->_forecast->day[$i]->part[1]->hmid
  484.                 )
  485.             );
  486.  
  487.             $forecastReturn["days"][$day;
  488.         }
  489.  
  490.         return $forecastReturn;
  491.     }
  492.     // }}}
  493. }
  494. // }}}
  495. ?>

Documentation generated on Mon, 11 Mar 2019 10:14:20 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.