Skip to content

Instantly share code, notes, and snippets.

@avdg
Created April 18, 2011 17:52
Show Gist options
  • Save avdg/925792 to your computer and use it in GitHub Desktop.
Save avdg/925792 to your computer and use it in GitHub Desktop.
Current diff
diff --git a/Phergie/Plugin/Weather.php b/Phergie/Plugin/Weather.php
index c12d15e..531c8e7 100644
--- a/Phergie/Plugin/Weather.php
+++ b/Phergie/Plugin/Weather.php
@@ -32,6 +32,7 @@
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Weather
* @link http://www.weather.com/services/xmloap.html
+ * @uses Phergie_Plugin_Cache pear.phergie.org
* @uses Phergie_Plugin_Command pear.phergie.org
* @uses Phergie_Plugin_Http pear.phergie.org
* @uses Phergie_Plugin_Temperature pear.phergie.org
@@ -40,6 +41,13 @@
class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract
{
/**
+ * True if the last fetched location was reliable
+ *
+ * @var bool
+ */
+ protected $isLocationReliable = false;
+
+ /**
* Checks for dependencies.
*
* @return void
@@ -47,6 +55,7 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract
public function onLoad()
{
$plugins = $this->getPluginHandler();
+ $plugins->getPlugin('Cache');
$plugins->getPlugin('Command');
$plugins->getPlugin('Http');
$plugins->getPlugin('Temperature');
@@ -131,31 +140,25 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract
*
* @param string $location place to retrieve weather data for
*
+ * @throws Phergie_Exception When no location can be returned
+ * (unexpected error or location not found)
+ *
* @return array weather conditions
*/
public function getWeatherData($location)
{
- $response = $this->getPluginHandler()
- ->getPlugin('Http')
- ->get(
- 'http://xoap.weather.com/search/search',
- array('where' => $location)
- );
-
- if ($response->isError()) {
- throw new Phergie_Exception(
- 'ERROR: ' . $response->getMessage() . ' ' . $response->getCode()
- );
- }
+ $locId = $this->getWeatherLocation($location);
- $xml = $response->getContent();
+ // If the location was reliable, maybe also the weather data
+ if ($this->isLocationReliable) {
+ $data = $this->getPluginHandler()->getPlugin('cache')
+ ->fetch('WeatherData_' . $locId);
- if (count($xml->loc) == 0) {
- throw new Phergie_Exception('No results for that location.');
+ if (is_array($data)) {
+ return $data;
+ }
}
- $locId = (string) $xml->loc[0]['id'];
-
$response = $this->getPluginHandler()
->getPlugin('Http')
->get(
@@ -175,8 +178,37 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract
);
}
- $data = $response->getContent();
- return array(
+ $cache = $this->getPluginHandler()->getPlugin('cache');
+ $data = $response->getContent();
+
+ // Retrieve the right location data (small hack, but blame the api)
+ if (!$this->isLocationReliable) {
+ $rightLocation = str_replace(
+ array('(', ')', ',', ' '),
+ array('', '', '', '+'),
+ (string) $data->loc->dnam
+ );
+
+ try {
+ $result = $this->getWeatherLocation($rightLocation);
+
+ // Cache the location data, by default for 1 day
+ $expires = 86400;
+ if (isset($this->config['weather.cache_locations'])) {
+ $expires = $this->config['weather.cache_locations'];
+ }
+ $cache->store('WeatherLocation_' . $locId, $result, $expires);
+ $cache->store('WeatherLocation_' . $location, $result, $expires);
+ $cache->store('WeatherLocation_' . $results, $result, $expires);
+
+ // Actually fix the location
+ $locId = $result;
+ } catch (Phergie_Exception $e) {
+ // Do nothing when fail
+ }
+ }
+
+ $data = array(
'locationCode'=>"{$locId}",
'cityName'=>"{$data->loc->dnam}",
'observationDateTime'=>"{$data->cc->lsup}",
@@ -200,5 +232,63 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract
'sunset'=>"{$data->loc->suns}",
'moonPhaseDescription'=>"{$data->cc->moon->t}",
);
+
+ // Cache the weather data, by default for 30 minutes
+ $expires = 1800;
+ if (isset($this->config['weather.cache_data'])) {
+ $expires = $this->config['weather.cache_data'];
+ }
+ $cache->store('WeatherData_' . $locId, $data, $expires);
+
+ return $data;
+ }
+
+ /**
+ * Tries to find the api-readable id of the given location
+ *
+ * It also sets $this->isReliable, which is set to false
+ * when the current location isn't verfied yet
+ *
+ * @param string $location Location to search
+ *
+ * @throws Phergie_Exception When no location can be returned
+ * (unexpected error or location not found)
+ *
+ * @return string
+ */
+ public function getWeatherLocation($location)
+ {
+ // By default, we can't rely anything
+ $this->isLocationReliable = false;
+
+ // Try to get a hit from the cache
+ $cached = $this->getPluginHandler()->getPlugin('cache')
+ ->fetch('WeatherLocation_' . $location);
+
+ if ($cached) {
+ $this->isLocationReliable = true;
+ return $cached;
+ }
+
+ $response = $this->getPluginHandler()
+ ->getPlugin('Http')
+ ->get(
+ 'http://xoap.weather.com/search/search',
+ array('where' => $location)
+ );
+
+ if ($response->isError()) {
+ throw new Phergie_Exception(
+ 'ERROR: ' . $response->getMessage() . ' ' . $response->getCode()
+ );
+ }
+
+ $xml = $response->getContent();
+
+ if (count($xml->loc) == 0) {
+ throw new Phergie_Exception('No results for that location.');
+ }
+
+ return (string) $xml->loc[0]['id'];
}
}
diff --git a/Tests/Phergie/Plugin/WeatherTest.php b/Tests/Phergie/Plugin/WeatherTest.php
index 9c7a730..1014eef 100644
--- a/Tests/Phergie/Plugin/WeatherTest.php
+++ b/Tests/Phergie/Plugin/WeatherTest.php
@@ -46,6 +46,13 @@ class Phergie_Plugin_WeatherTest extends Phergie_Plugin_TestCase
private $_temperature;
/**
+ * Cache of the weather plugin
+ *
+ * @var array
+ */
+ private $_cache;
+
+ /**
* Mock a HTTP Plugin and prime it with response data
*
* @return void
@@ -64,6 +71,7 @@ class Phergie_Plugin_WeatherTest extends Phergie_Plugin_TestCase
->will($this->returnValue(false));
$contents = simplexml_load_file($dir . '/location.xml');
+ $location = $contents->loc[0]->id;
$response1->expects($this->any())
->method('getContent')
->will($this->returnValue($contents));
@@ -81,14 +89,50 @@ class Phergie_Plugin_WeatherTest extends Phergie_Plugin_TestCase
$this->_data = $this->requirePlugin('Http');
- $this->_data->expects($this->any())
+ $this->_data->expects($this->exactly(3))
->method('get')
- ->will($this->onConsecutiveCalls($response1, $response2));
+ ->will($this->onConsecutiveCalls($response1, $response2, $response1));
$this->_temperature = $this->requirePlugin('Temperature');
$this->_temperature->expects($this->any())
->method('convertFahrenheitToCelsius')
->will($this->returnValue(10.5));
+
+ $this->_cache = $this->requirePlugin('Cache');
+
+ $this->_cache->expects($this->any())
+ ->method('store')
+ ->will($this->returnValue(null));
+
+ $cacheLocation = $location;
+ $cacheWeatherData = array(
+ 'locationCode'=>"{$cacheLocation}",
+ 'cityName'=>"{$contents->loc->dnam}",
+ 'observationDateTime'=>"{$contents->cc->lsup}",
+ 'observationPoint'=>"{$contents->cc->obst}",
+ 'temp'=>"{$contents->cc->tmp}",
+ 'feelsLikeTemp'=>"{$contents->cc->flik}",
+ 'tempUnit'=>"{$contents->head->ut}",
+ 'weatherDescriptionPhrase'=>"{$contents->cc->t}",
+ 'barometricPressure'=>"{$contents->cc->bar->r}",
+ 'barometricTrend'=>"{$contents->cc->bar->d}",
+ 'windSpeed'=>"{$contents->cc->wind->s}",
+ 'windGust'=>"{$contents->cc->wind->gust}",
+ 'windDirection'=>"{$contents->cc->wind->d}",
+ 'windDirectionPhrase'=>"{$contents->cc->wind->t}",
+ 'relativeHumidity'=>"{$contents->cc->hmid}",
+ 'visibility'=>"{$contents->cc->vis}",
+ 'uvIndex'=>"{$contents->cc->uv->i}",
+ 'uvIndexDescription'=>"{$contents->cc->uv->t}",
+ 'dewPoint'=>"{$contents->cc->dewp}",
+ 'sunrise'=>"{$contents->loc->sunr}",
+ 'sunset'=>"{$contents->loc->suns}",
+ 'moonPhaseDescription'=>"{$contents->cc->moon->t}",
+ );
+ $this->_cache->expects($this->any())
+ ->method('fetch')
+ ->will($this->onConsecutiveCalls(false, false, false,
+ $cacheLocation, $cacheWeatherData));
}
/**
@@ -136,13 +180,15 @@ class Phergie_Plugin_WeatherTest extends Phergie_Plugin_TestCase
'Humidity: 96%, Conditions: Fog, Updated: 3/27/11 12:52 PM EDT [ ' .
'http://weather.com/weather/today/USGA0028 ]';
- $this->assertEmitsEvent(
- 'privmsg',
- array($this->source,
- $weatherReport)
- );
+ for ($i = 0; $i < 2; $i++) {
+ $this->assertEmitsEvent(
+ 'privmsg',
+ array($this->source,
+ $weatherReport)
+ );
- $report = $this->plugin->onCommandWeather('atlanta');
+ $report = $this->plugin->onCommandWeather('atlanta');
+ }
}
/**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment