Created
April 18, 2011 17:52
-
-
Save avdg/925792 to your computer and use it in GitHub Desktop.
Current diff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | |
+ } | |
} | |
/** |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Tests/Phergie/Plugin/WeatherTest.php b/Tests/Phergie/Plugin/WeatherTest.php | |
index 9f647f1..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,7 +89,7 @@ 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, $response1)); | |
@@ -89,6 +97,42 @@ class Phergie_Plugin_WeatherTest extends Phergie_Plugin_TestCase | |
$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