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";