Skip to content

Commit b685264

Browse files
committed
Method infotags - visual cues for OCPL/OCDE-specific features
#463
1 parent 1639233 commit b685264

File tree

17 files changed

+279
-57
lines changed

17 files changed

+279
-57
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ way, that the same change will also work on all other OC sites:
112112
you have OKAPI installed, we will make every effort for future versions of
113113
OKAPIs to be compatible with your site.
114114

115+
You should know that there are two primary branches of Opencaching - we call
116+
them OCPL and OCDE - and all OKAPI methods MUST support both these branches
117+
(unless the particular functionality is available on only one of them). You can
118+
read more about OCPL and OCDE branching
119+
[here](https://github.com/opencaching/opencaching-pl/wiki#brief-introduction-in-english).
120+
You can also read about how OKAPI tries to deal with branch differences
121+
[here](https://opencaching.pl/okapi/introduction.html#oc-branch-differences).
122+
115123

116124
## Requirements ##
117125

okapi/core.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,23 @@ public static function update_user_activity($request) {
22422242
}
22432243
}
22442244

2245+
/**
2246+
* Take a list of "infotags" (as defined in services/apiref/method), and format
2247+
* them for being displayed in OKAPI public documentation pages.
2248+
*/
2249+
public static function format_infotags($infotags) {
2250+
$chunks = [];
2251+
$url = Settings::get('SITE_URL')."okapi/introduction.html#oc-branch-differences";
2252+
foreach ($infotags as $infotag) {
2253+
if ($infotag == "ocpl-specific") {
2254+
$chunks[] = "<a href='$url' class='infotag infotag-ocpl-specific'>OCPL</a> ";
2255+
} elseif ($infotag == "ocde-specific") {
2256+
$chunks[] = "<a href='$url' class='infotag infotag-ocde-specific'>OCDE</a> ";
2257+
}
2258+
}
2259+
return implode("", $chunks);
2260+
}
2261+
22452262
# object types in table okapi_submitted_objects
22462263
const OBJECT_TYPE_CACHE = 1;
22472264
const OBJECT_TYPE_CACHE_DESCRIPTION = 2;

okapi/services/apiref/method.php

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,29 @@ public static function options()
2424
private static function arg_desc($arg_node)
2525
{
2626
$attrs = $arg_node->attributes();
27-
return array(
27+
$result = array(
2828
'name' => (string)$attrs['name'],
2929
'is_required' => $arg_node->getName() == 'req',
3030
'is_deprecated' => (isset($attrs['class']) && (strpos($attrs['class'], 'deprecated') !== false)),
3131
'class' => 'public',
32+
'infotags' => [],
3233
'description' =>
3334
(isset($attrs['default']) ? ("<p>Default value: <b>".$attrs['default']."</b></p>") : "").
3435
self::get_inner_xml($arg_node),
35-
3636
);
37+
if (isset($attrs['infotags'])) {
38+
foreach (explode(" ", (string)$attrs['infotags']) as $infotag) {
39+
switch ($infotag) {
40+
case 'ocpl-specific':
41+
case 'ocde-specific':
42+
$result['infotags'][] = $infotag;
43+
break;
44+
default:
45+
throw new Exception("Invalid infotag '".$infotag." in $methodname.xml");
46+
}
47+
}
48+
}
49+
return $result;
3750
}
3851

3952
private static function get_inner_xml($node)
@@ -47,7 +60,7 @@ private static function get_inner_xml($node)
4760

4861
/* Find and replace %okapi:plugins%. */
4962

50-
$s = preg_replace_callback('~%OKAPI:([a-z:/_#]+)%~', array("self", "plugin_callback"), $s);
63+
$s = preg_replace_callback('~%OKAPI:([a-z:/_#-]+)%~', array("self", "plugin_callback"), $s);
5164

5265
return $s;
5366
}
@@ -78,6 +91,9 @@ private static function get_inner_xml($node)
7891
* <a href="%OKAPI:methodretref:#returned_key%">any text</a> - to reference
7992
* returned value within current method
8093
*
94+
* %OKAPI:infotag:TAGNAME% - to output a HTML with a proper infotag "badge".
95+
* TAGNAME must match one of the infotags defined in services/apiref/method.
96+
*
8197
* NOTE!
8298
*
8399
* Since returned JSON dictionaries are not standardized (they are simply plain
@@ -120,6 +136,8 @@ public static function plugin_callback($matches)
120136
$result .= $elements[1];
121137
}
122138
return $result;
139+
case 'infotag':
140+
return Okapi::format_infotags([$arr[1]]);
123141
default:
124142
throw new Exception("Unknown plugin: ".$input);
125143
}
@@ -147,7 +165,8 @@ public static function call(OkapiRequest $request)
147165
'min_auth_level' => $options['min_auth_level'],
148166
'oauth_consumer' => $options['min_auth_level'] >= 2,
149167
'oauth_token' => $options['min_auth_level'] >= 3,
150-
)
168+
),
169+
"infotags" => [],
151170
);
152171
if (!$docs->brief)
153172
throw new Exception("Missing <brief> element in the $methodname.xml file.");
@@ -167,6 +186,18 @@ public static function call(OkapiRequest $request)
167186
if (!$docs->desc)
168187
throw new Exception("Missing <desc> element in the $methodname.xml file.");
169188
$result['description'] = self::get_inner_xml($docs->desc);
189+
if ($docs->infotags) {
190+
foreach (explode(" ", (string)$docs->infotags) as $infotag) {
191+
switch ($infotag) {
192+
case 'ocpl-specific':
193+
case 'ocde-specific':
194+
$result['infotags'][] = $infotag;
195+
break;
196+
default:
197+
throw new Exception("Invalid infotag '".$infotag." in $methodname.xml");
198+
}
199+
}
200+
}
170201
$result['arguments'] = array();
171202
foreach ($docs->req as $arg) { $result['arguments'][] = self::arg_desc($arg); }
172203
foreach ($docs->opt as $arg) { $result['arguments'][] = self::arg_desc($arg); }
@@ -207,13 +238,15 @@ public static function call(OkapiRequest $request)
207238
'is_required' => false,
208239
'is_deprecated' => false,
209240
'class' => 'common-formatting',
241+
'infotags' => [],
210242
'description' => "<i>Standard <a href='".Settings::get('SITE_URL')."okapi/introduction.html#common-formatting'>common formatting</a> argument.</i>"
211243
);
212244
$result['arguments'][] = array(
213245
'name' => 'callback',
214246
'is_required' => false,
215247
'is_deprecated' => false,
216248
'class' => 'common-formatting',
249+
'infotags' => [],
217250
'description' => "<i>Standard <a href='".Settings::get('SITE_URL')."okapi/introduction.html#common-formatting'>common formatting</a> argument.</i>"
218251
);
219252
}

okapi/services/apiref/method.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@
2525
description of what the method does,
2626
</li>
2727
<li><b>ref_url</b> - URL of the documentation page with method description,</li>
28+
<li>
29+
<p><b>infotags</b> - list of tags. Each tag is represented by its unique code
30+
(string). Existence (or absence) of each tag has its meaning. Currently, the
31+
following tags are allowed:</p>
32+
33+
<ul>
34+
<li>
35+
<p><b>ocpl-specific</b> - if present, then this method is (currently)
36+
specific to OCPL-branch (as described
37+
<a href='%OKAPI:docurl:oc-branch-differences%'>here</a>).</p>
38+
39+
<p>Please note, that such method may still become a "regular" method in the
40+
future (as support for certain feature gets implemented in other OC
41+
branches).</p>
42+
</li>
43+
<li>
44+
<p><b>ocde-specific</b> - as above, but for OCDE-branch.</p>
45+
</li>
46+
</ul>
47+
</li>
2848
<li>
2949
<p><b>auth_options</b> - a dictionary which describes authentication
3050
requirements for this method, it has a following structure:</p>
@@ -61,6 +81,12 @@
6181
<p>Currently these values do not mean anything specific. They are used
6282
for different coloring/styling in the documentation pages.</p>
6383
</li>
84+
<li>
85+
<p><b>infotags</b> - list of tags. Currently they may have exactly the
86+
same values as the "method-level" infotags defined above. They indicate
87+
that a particular argument is designed to "work best" on one of the OC
88+
branches only.</p>
89+
</li>
6490
</ul>
6591
</li>
6692
<li><b>returns</b> - HTML-formatted description method's return value.</li>

okapi/services/apiref/method_index.php

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
use okapi\OkapiInternalRequest;
99
use okapi\OkapiRequest;
1010
use okapi\OkapiServiceRunner;
11+
use okapi\Settings;
12+
use RecursiveIteratorIterator;
13+
use RecursiveDirectoryIterator;
1114

1215

1316
class WebService
@@ -21,24 +24,76 @@ public static function options()
2124

2225
public static function call(OkapiRequest $request)
2326
{
24-
$methodnames = OkapiServiceRunner::$all_names;
25-
sort($methodnames);
26-
$cache_key = "api_ref/method_index#".md5(implode("#", $methodnames));
27+
$cache_key = self::generateCacheKey();
2728
$results = Cache::get($cache_key);
2829
if ($results == null)
2930
{
3031
$results = array();
31-
foreach ($methodnames as $methodname)
32+
foreach (OkapiServiceRunner::$all_names as $methodname)
3233
{
3334
$info = OkapiServiceRunner::call('services/apiref/method', new OkapiInternalRequest(
3435
new OkapiInternalConsumer(), null, array('name' => $methodname)));
3536
$results[] = array(
3637
'name' => $info['name'],
38+
'short_name' => $info['short_name'],
3739
'brief_description' => $info['brief_description'],
40+
'infotags' => $info['infotags'],
41+
'auth_options' => $info['auth_options'],
3842
);
3943
}
40-
Cache::set($cache_key, $results, 3600);
44+
Cache::set($cache_key, $results, 86400);
4145
}
4246
return Okapi::formatted_response($request, $results);
4347
}
48+
49+
/**
50+
* This method will generate a best cache key to be used, depending on the environment.
51+
*
52+
* We want the method index to return fast, but we also don't want developers to see cached
53+
* results when they are adding (or changing) methods (in dev-environments).
54+
*/
55+
private static function generateCacheKey() {
56+
57+
if (!Settings::get('DEBUG')) {
58+
59+
/* Production. */
60+
61+
if (Okapi::$version_number !== null) {
62+
return "api_ref/method_index#prod#".Okapi::$version_number;
63+
} else {
64+
$methodnames = OkapiServiceRunner::$all_names;
65+
sort($methodnames);
66+
return "api_ref/method_index#".md5(implode("#", $methodnames));
67+
}
68+
69+
} else {
70+
71+
/* Development. */
72+
73+
return (
74+
"api_ref/method_index#dev#".
75+
self::getDirModDateRecursive($GLOBALS['rootpath']."okapi/services")
76+
);
77+
}
78+
}
79+
80+
private static function getDirModDateRecursive($absoluteDir) {
81+
$iterator = new \RecursiveIteratorIterator(
82+
new \RecursiveDirectoryIterator($absoluteDir, RecursiveDirectoryIterator::SKIP_DOTS),
83+
\RecursiveIteratorIterator::SELF_FIRST
84+
);
85+
$max_timestamp = 0;
86+
foreach ($iterator as $item) {
87+
if($item->isDir()) {
88+
$pth = $item->getPath()."/.";
89+
} else {
90+
$pth = $item->getPathname();
91+
}
92+
$timestamp = filemtime($pth);
93+
if ($timestamp > $max_timestamp) {
94+
$max_timestamp = $timestamp;
95+
}
96+
}
97+
return $max_timestamp;
98+
}
4499
}

okapi/services/apiref/method_index.xml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22
<brief>Get a list of OKAPI methods with brief descriptions</brief>
33
<issue-id>12</issue-id>
44
<desc>
5-
<p>Get a list of OKAPI methods with brief descriptions.</p>
5+
<p>Get a list of OKAPI methods with brief descriptions and a bunch
6+
of other basic properties.</p>
67
</desc>
78
<common-format-params/>
89
<returns>
9-
A list of dictionaries, each of which contains one API
10-
method description in the following format:
11-
<ul>
12-
<li><b>name</b> - name of a method,</li>
13-
<li><b>brief_description</b> - brief (max 80 characters), single-line,
14-
plain-text description of what the method does.</li>
15-
</ul>
10+
<p>A list of dictionaries. Each dictionary describes one API method,
11+
and contains the following <i>subset</i> of the fields described in the
12+
<a href="%OKAPI:methodref:services/apiref/method%">method</a> method:
13+
<b>name</b>, <b>short_name</b>, <b>brief_description</b>,
14+
<b>ref_url</b>, <b>infotags</b>, <b>auth_options</b>.</p>
1615
</returns>
1716
</xml>

okapi/services/caches/formatters/gpx.xml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@
9191
Such attributes cannot be included as gc:attrs and will be ignored.</p>
9292
</li>
9393
<li>
94-
<p><b>gc_ocde:attrs</b> - attributes will be listed as Groundspeak's
95-
<i>groundspeak:attribute</i> elements (<b>ns_ground</b> has to be <b>true</b>).
96-
Opencaching attributes which have no Geocaching.com counterparts will be
97-
included according to an Opencaching.DE convention, using "makeshift IDs"
98-
which may change in the future.</p>
99-
<p>Note that this option is supported only by some OC sites. Other sites will
100-
handle <b>gc_ocde:attrs</b> in the same way as <b>gc:attrs</b>.</p>
94+
<p>%OKAPI:infotag:ocde-specific% <b>gc_ocde:attrs</b> - attributes will be
95+
listed as Groundspeak's <i>groundspeak:attribute</i> elements (<b>ns_ground</b>
96+
has to be <b>true</b>). Opencaching attributes which have no Geocaching.com
97+
counterparts will be included according to an Opencaching.DE convention, using
98+
"makeshift IDs" which may change in the future.</p>
99+
100+
<p>This alternative is supported only by some OC sites (the ones originating
101+
from the OCDE branch). Other sites will handle <b>gc_ocde:attrs</b> in the same
102+
way as <b>gc:attrs</b>.</p>
101103
</li>
102104
</ul>
103105

okapi/services/caches/geocache.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,13 @@
267267
<b>null</b> if unknown,</p>
268268
</li>
269269
<li>
270-
<p><b>rating</b> - float (between 1 and 5), an overall rating of the cache,
271-
or <b>null</b> when the geocache does not have a sufficient amount of votes
272-
to have a rating.</p>
270+
<p>%OKAPI:infotag:ocpl-specific% <b>rating</b> - float (between 1 and 5), an
271+
overall rating of the cache, or <b>null</b> when the geocache does not have a
272+
sufficient amount of votes to have a rating.</p>
273273

274-
<p>Please note: some OC installations do not use the
275-
rating/voting system. The <b>rating</b> will always be
276-
<b>null</b> on such installations.</p>
274+
<p><b>Notice:</b> Only OCPL-based Opencaching installations provide ratings for
275+
their geocaches. On OCDE-based installations, this field will always contain
276+
<b>null</b>.</p>
277277
</li>
278278
<li>
279279
<p><b>rating_votes</b> - number of votes submitted for the

okapi/services/caches/map/tilerenderer.inc.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ private static function get_image($name, $opacity=1, $brightness=0,
110110
$key = "$name/$opacity/$brightness/$contrast/$r/$g/$b";
111111
if (!isset($locmem_cache[$key]))
112112
{
113-
# Miss. Check default cache. WRTODO: upgrade to normal Cache?
113+
# Miss. Check default cache.
114114

115115
try
116116
{

okapi/services/caches/search/all.xml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
<p><b>Note:</b> Not all OC servers use all of these. I.e. OCPL does not
9292
have 'nano' nor 'other' caches (but it might have them in the future).</p>
9393
</opt>
94-
<opt name='rating'>
94+
<opt name='rating' infotags="ocpl-specific">
9595
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X &lt;= Y.
9696
Only caches with an overall rating between these numbers (inclusive) will be returned
9797
(1 - poor, 5 - excellent).</p>
@@ -100,8 +100,8 @@
100100
excluded from results. If you still want unrated caches included, append "|X" suffix
101101
to the value of this parameter (e.g. "3-5|X").</p>
102102

103-
<p><b>Notice:</b> Some OC installations do not provide ratings for their geocaches.
104-
On such installation, this parameter will be ignored.</p>
103+
<p><b>Notice:</b> Only OCPL-based Opencaching installations provide ratings for their
104+
geocaches. On OCDE-based installations, this parameter will be ignored.</p>
105105
</opt>
106106
<opt name='min_rcmds'>
107107
<p>There are two possible value-types for this argument:</p>
@@ -205,14 +205,14 @@
205205
Boolean. If set to <b>true</b>, only caches which have not yet been
206206
found <b>by anyone</b> will be included.
207207
</opt>
208-
<opt name='powertrail_only' default='false'>
208+
<opt name='powertrail_only' default='false' infotags="ocpl-specific">
209209
<p>Boolean. If set to <b>true</b>, only caches which belong to at
210210
least one <b>active</b> Power Trail will be included.</p>
211211

212212
<p>Power Trails are sets of geocaches. Only some Opencaching sites
213-
implement this feature. If this site does not implement it, and you
214-
will set this parameter to <b>true</b>, then you will <b>always</b>
215-
receive an empty result.</p>
213+
implement this feature (OCPL-branch). If this site does not implement
214+
it, and you will set this parameter to <b>true</b>, then you will
215+
<b>always</b> receive an empty result.</p>
216216
</opt>
217217
<opt name='powertrail_ids'>
218218
<p>Pipe-separated list of Power Trail IDs. If given, then only

0 commit comments

Comments
 (0)