diff --git a/htdocs/okapi/core.php b/htdocs/okapi/core.php index a7f1ef7c..d0684a23 100644 --- a/htdocs/okapi/core.php +++ b/htdocs/okapi/core.php @@ -778,7 +778,7 @@ class Okapi { public static $data_store; public static $server; - public static $revision = 590; # This gets replaced in automatically deployed packages + public static $revision = 594; # This gets replaced in automatically deployed packages private static $okapi_vars = null; /** Get a variable stored in okapi_vars. If variable not found, return $default. */ diff --git a/htdocs/okapi/cronjobs.php b/htdocs/okapi/cronjobs.php index 673cb473..ab355900 100644 --- a/htdocs/okapi/cronjobs.php +++ b/htdocs/okapi/cronjobs.php @@ -27,6 +27,7 @@ use okapi\OkapiServiceRunner; use okapi\OkapiInternalRequest; use okapi\OkapiInternalConsumer; use okapi\services\replicate\ReplicateCommon; +use okapi\services\attrs\AttrHelper; class CronJobController { @@ -50,6 +51,7 @@ class CronJobController new FulldumpGeneratorJob(), new TileTreeUpdater(), new SearchSetsCleanerJob(), + new AttrsRefresherJob(), ); foreach ($cache as $cronjob) if (!in_array($cronjob->get_type(), array('pre-request', 'cron-5'))) @@ -537,13 +539,13 @@ class TileTreeUpdater extends Cron5Job if (!$response['more']) break; } catch (BadRequest $e) { - # Invalid 'since' parameter? May happen whne crontab was + # Invalid 'since' parameter? May happen when crontab was # not working for more than 10 days. Or, just after OKAPI # is installed (and this is the first time this cronjob # if being run). $mail_admins = ($tiletree_revision > 0); - \okapi\services\caches\map\ReplicateListener::reset($mail_admins); + \okapi\services\caches\map\ReplicateListener::reset(); Okapi::set_var('clog_followup_revision', $current_clog_revision); break; } @@ -773,3 +775,17 @@ class LocaleChecker extends Cron5Job } } +/** + * Once every hour, update the official cache attributes listing. + * + * WRTODO: Make it 12 hours later. + */ +class AttrsRefresherJob extends Cron5Job +{ + public function get_period() { return 3600; } + public function execute() + { + require_once($GLOBALS['rootpath']."okapi/services/attrs/attr_helper.inc.php"); + AttrHelper::refresh_if_stale(); + } +} diff --git a/htdocs/okapi/service_runner.php b/htdocs/okapi/service_runner.php index 81e61d77..5c8bb592 100644 --- a/htdocs/okapi/service_runner.php +++ b/htdocs/okapi/service_runner.php @@ -23,6 +23,7 @@ class OkapiServiceRunner 'services/apiref/method', 'services/apiref/method_index', 'services/apiref/issue', + 'services/attrs/info', 'services/oauth/request_token', 'services/oauth/authorize', 'services/oauth/access_token', diff --git a/htdocs/okapi/services/attrs/attr_helper.inc.php b/htdocs/okapi/services/attrs/attr_helper.inc.php new file mode 100644 index 00000000..e91b0b36 --- /dev/null +++ b/htdocs/okapi/services/attrs/attr_helper.inc.php @@ -0,0 +1,157 @@ + array( + 'method' => "GET", + 'timeout' => 5.0 + ) + ); + $context = stream_context_create($opts); + $xml = file_get_contents("http://opencaching-api.googlecode.com/svn/trunk/etc/attributes.xml", + false, $context); + } + catch (ErrorException $e) + { + # Google failed on us. We won't update the cached attributes. + return; + } + + $my_site_url = "http://opencaching.pl/"; // WRTODO + $doc = simplexml_load_string($xml); + $cachedvalue = array( + 'attr_dict' => array(), + 'last_refreshed' => time(), + ); + foreach ($doc->attr as $attrnode) + { + $attr = array( + 'code' => (string)$attrnode['okapi_attr_id'], + 'gs_equiv' => null, + 'internal_id' => null, + 'names' => array(), + 'descriptions' => array() + ); + foreach ($attrnode->groundspeak as $gsnode) + { + $attr['gs_equiv'] = array( + 'id' => (int)$gsnode['id'], + 'inc' => in_array((string)$gsnode['inc'], array("true", "1")) ? 1 : 0, + 'name' => (string)$gsnode['name'] + ); + } + foreach ($attrnode->opencaching as $ocnode) + { + if ((string)$ocnode['site_url'] == $my_site_url) { + $attr['internal_id'] = (int)$ocnode['id']; + } + } + foreach ($attrnode->name as $namenode) + { + $attr['names'][(string)$namenode['lang']] = (string)$namenode; + } + foreach ($attrnode->desc as $descnode) + { + $xml = $descnode->asxml(); /* contains "" and "" */ + $innerxml = preg_replace("/(^[^>]+>)|(<[^<]+$)/us", "", $xml); + $attr['descriptions'][(string)$descnode['lang']] = self::cleanup_string($innerxml); + } + $cachedvalue['attr_dict'][$attr['code']] = $attr; + } + + # Cache it for a month (just in case, usually it will be refreshed every day). + + Cache::set(self::$CACHE_KEY, $cachedvalue, 30*86400); + self::$attr_dict = $cachedvalue['attr_dict']; + self::$last_refreshed = $cachedvalue['last_refreshed']; + } + + /** + * Initialize all the internal attributes (if not yet initialized). This + * loads attribute values from the cache. If they are not present in the cache, + * it won't download them from Google Code, it will initialize them as empty! + */ + private static function init_from_cache() + { + if (self::$attr_dict !== null) + { + /* Already initialized. */ + return; + } + $cachedvalue = Cache::get(self::$CACHE_KEY); + if ($cachedvalue === null) + { + $cachedvalue = array( + 'attr_dict' => array(), + 'last_refreshed' => 0, + ); + } + self::$attr_dict = $cachedvalue['attr_dict']; + self::$last_refreshed = $cachedvalue['last_refreshed']; + } + + /** + * Check if the cached attribute values might be stale. If they were not + * refreshed in a while, perform the refresh from Google Code. (This might + * take a couple of seconds, it should be done via a cronjob.) + */ + public static function refresh_if_stale() + { + self::init_from_cache(); + if (self::$last_refreshed < time() - 86400) + self::refresh_now(); + if (self::$last_refreshed < time() - 3 * 86400) + { + Okapi::mail_admins( + "OKAPI was unable to refresh attributes", + "OKAPI periodically refreshes all cache attributes from the list\n". + "kept in global repository. OKAPI tried to contact the repository,\n". + "but it failed. Your list of attributes might be stale.\n\n". + "You should probably update OKAPI or contact OKAPI developers." + ); + } + } + + /** + * Return a dictionary of all attributes. The format is the same as in the "attributes" + * key returned by the "services/attrs/attrlist" method. + */ + public static function get_attrdict() + { + self::init_from_cache(); + return self::$attr_dict; + } + + /** "\n\t\tBla blabla\n\t\tblabla.\n\t" => "Bla blabla blabla." */ + private static function cleanup_string($s) + { + return preg_replace('/(^\s+)|(\s+$)/us', "", preg_replace('/\s+/us', " ", $s)); + } +} diff --git a/htdocs/okapi/services/attrs/info.php b/htdocs/okapi/services/attrs/info.php new file mode 100644 index 00000000..17288c89 --- /dev/null +++ b/htdocs/okapi/services/attrs/info.php @@ -0,0 +1,40 @@ + 1 + ); + } + + public static function call(OkapiRequest $request) + { + # The list of attributes is periodically refreshed by contacting OKAPI + # repository (the refreshing is done via a cronjob). This method displays + # the cached version of the list. + + require_once 'attr_helper.inc.php'; + AttrHelper::refresh_if_stale(); + $results = array( + 'attributes' => AttrHelper::get_attrdict() + ); + return Okapi::formatted_response($request, $results); + } +} diff --git a/htdocs/okapi/services/attrs/info.xml b/htdocs/okapi/services/attrs/info.xml new file mode 100644 index 00000000..ce0f7551 --- /dev/null +++ b/htdocs/okapi/services/attrs/info.xml @@ -0,0 +1,12 @@ + + ALPHA: Get the list of all cache attributes + 194 + + This method is in its ALPHA stage. It's signature will most probably change, or + it might be removed altogether. You should not use it! + + + + Not yet documented. You should not use this method. + + \ No newline at end of file diff --git a/htdocs/okapi/services/caches/map/replicate_listener.inc.php b/htdocs/okapi/services/caches/map/replicate_listener.inc.php index 10e52f5b..e27f3bb9 100644 --- a/htdocs/okapi/services/caches/map/replicate_listener.inc.php +++ b/htdocs/okapi/services/caches/map/replicate_listener.inc.php @@ -45,24 +45,8 @@ class ReplicateListener { # This will be called when there are "too many" entries in the changelog # and the replicate module thinks it better to just reset the entire TileTree. - # For the first hours after such reset maps may work very slow! + # For the first hours after such reset maps may work a little slower. - if ($mail_admins) - { - Okapi::mail_admins("OKAPI TileMap database reset", - "Hello,\n\n". - "OKAPI's 'replicate' module detected a big database update. As result\n". - "of this, OKAPI decided to reset the TileMap cache. This may\n". - "temporarily influence TileMap performance. The map may work much\n". - "slower during the next few hours or days, while the cache is being\n". - "rebuilt.\n\n". - "If this happens frequently, please contact OKAPI developers. It may\n". - "indicate a bug in OKAPI's 'replicate' module or cronjob settings.\n\n". - "Thanks!\n\n". - "P.S. This may also happen if you didn't run OKAPI on this server\n". - "for a while (your server was down or OKAPI didn't work properly)." - ); - } Db::execute("delete from okapi_tile_status"); Db::execute("delete from okapi_tile_caches"); } diff --git a/htdocs/okapi/views/devel/attrlist.php b/htdocs/okapi/views/devel/attrlist.php index 4ba7f376..7fc55a9d 100644 --- a/htdocs/okapi/views/devel/attrlist.php +++ b/htdocs/okapi/views/devel/attrlist.php @@ -46,6 +46,19 @@ class View foreach ($langkeys as $langkey) print " $langkey: ".$langs[$langkey]."\n"; } + foreach ($dict as $internal_id => $langs) + { + print "\n"; + print "\t\n"; + print "\t\n"; + $langkeys = array_keys($langs); + usort($langkeys, function($a, $b) { + return ($a == "en") ? -1 : (($a == $b) ? 0 : (($a < $b) ? -1 : 1)); + }); + foreach ($langkeys as $langkey) + print "\t".$langs[$langkey]."\n"; + print "\n"; + } $response = new OkapiHttpResponse(); $response->content_type = "text/plain; charset=utf-8";