Skip to content

Commit b21cc2d

Browse files
committed
added log and geocache options to select user fields; updates #569
1 parent a2cfb31 commit b21cc2d

File tree

10 files changed

+216
-45
lines changed

10 files changed

+216
-45
lines changed

okapi/services/caches/geocache/WebService.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@ public static function call(OkapiRequest $request)
2828
if (!$langpref) $langpref = "en";
2929
$fields = $request->get_parameter('fields');
3030
if (!$fields) $fields = "code|name|location|type|status";
31+
$owner_fields = $request->get_parameter('owner_fields');
32+
if (!$owner_fields) $owner_fields = "uuid|username|profile_url";
3133
$log_fields = $request->get_parameter('log_fields');
3234
if (!$log_fields) $log_fields = "uuid|date|user|type|comment";
35+
$log_user_fields = $request->get_parameter('log_user_fields');
36+
if (!$log_user_fields) $log_user_fields = "uuid|username|profile_url";
3337
$lpc = $request->get_parameter('lpc');
3438
if (!$lpc) $lpc = 10;
3539
$user_logs_only = $request->get_parameter('user_logs_only');
@@ -42,10 +46,12 @@ public static function call(OkapiRequest $request)
4246
'cache_codes' => $cache_code,
4347
'langpref' => $langpref,
4448
'fields' => $fields,
49+
'owner_fields' => $owner_fields,
4550
'attribution_append' => $attribution_append,
4651
'oc_team_annotation' => $oc_team_annotation,
4752
'lpc' => $lpc,
4853
'log_fields' => $log_fields,
54+
'log_user_fields' => $log_user_fields,
4955
'user_logs_only' => $user_logs_only,
5056
);
5157
$my_location = $request->get_parameter('my_location');

okapi/services/caches/geocache/docs.xml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,25 @@
6969
<p>Note that some OC installations do not implement team annotations. They will
7070
ignore this parameter.</p>
7171
</opt>
72+
<opt name='owner_fields' default='uuid|username|profile_url'>
73+
Pipe-separated list of user fields to include in the <b>owner</b> field.
74+
For valid field names, see
75+
<a href='%OKAPI:methodargref:services/users/user%'>services/users/user</a> method.
76+
</opt>
7277
<opt name='lpc' default='10'>
7378
Log-entries per cache - the number of logs returned in the <b>latest_logs</b> field.
7479
This should be an integer or a special "all" value. Please note, that you must include
7580
the <b>latest_logs</b> field in <b>fields</b> in order to see the log entries.
7681
</opt>
7782
<opt name='log_fields' default='uuid|date|user|type|comment'>
7883
Pipe-separated list of log fields to include in the <b>latest_logs</b> field.
79-
For valid field names, see <b>logs/entry</b> method.
84+
For valid field names, see the
85+
<a href='%OKAPI:methodargref:services/logs/entry%'>logs/entry</a> method.
86+
</opt>
87+
<opt name='log_user_fields' default='uuid|username|profile_url'>
88+
Pipe-separated list of user fields to include in the <b>user</b> subfield
89+
of the <b>latest_logs</b> field. For valid field names, see the
90+
<a href='%OKAPI:methodargref:services/users/user%'>services/users/user</a> method.
8091
</opt>
8192
<opt name='user_logs_only' default='false'>
8293
<p>Boolean. If <b>true</b> with Level 3 Authentication, only logs
@@ -97,7 +108,7 @@
97108
western hemispheres accordingly). These are full degrees with a dot
98109
as a decimal point (ex. "54.3|22.3").</p>
99110
</opt>
100-
<opt name="user_uuid">
111+
<opt name='user_uuid'>
101112
<p>User'd ID. Required to access fields like <b>is_found</b> using <b>Level 1</b> Authentication.</p>
102113

103114
<p>Please note that if you want to access private fields (like <b>my_notes</b>), then
@@ -181,12 +192,8 @@
181192
</li>
182193
<li><b>url</b> - URL of the cache's web page,</li>
183194
<li>
184-
<p><b>owner</b> - dictionary of:</p>
185-
<ul>
186-
<li><b>uuid</b> - geocache owner's user ID,</li>
187-
<li><b>username</b> - name of the user,</li>
188-
<li><b>profile_url</b> - URL of the user profile page,</li>
189-
</ul>
195+
<p><b>owner</b> - dictionary of user fields that are selected by the
196+
<b>owner_fields</b> option.</p>
190197
</li>
191198
<li>
192199
<p><b>gc_code</b> - Geocaching.com code (GC code) of the geocache
@@ -463,7 +470,8 @@
463470
<p><b>latest_logs</b> - a couple of latest log entries in the cache.
464471
The format is the same as the one returned by the services/logs/logs method.</p>
465472

466-
<p>Note: The number of logs returned can be set with the <b>lpc</b> option.</p>
473+
<p>Note: The number of logs returned can be set with the <b>lpc</b> option,
474+
and the fields to return can be selected by the <b>log_fields</b> option.</p>
467475
</li>
468476
<li>
469477
<p><b>my_notes</b> - user's notes on the cache, in plain-text, or <b>null</b>

okapi/services/caches/geocaches/WebService.php

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ public static function call(OkapiRequest $request)
121121

122122
$log_fields = $request->get_parameter('log_fields');
123123
if (!$log_fields) $log_fields = "uuid|date|user|type|comment"; // validation is done on call
124+
$log_user_fields = $request->get_parameter('log_user_fields');
125+
if (!$log_user_fields) $log_user_fields = "uuid|username|profile_url"; // validation is done on call
126+
$owner_fields = $request->get_parameter('owner_fields');
127+
if (!$owner_fields) $owner_fields = "uuid|username|profile_url"; // validation is done on call
124128

125129
$lpc = $request->get_parameter('lpc');
126130
if ($lpc === null) $lpc = 10;
@@ -395,25 +399,77 @@ public static function call(OkapiRequest $request)
395399

396400
# owner
397401

398-
if (in_array('owner', $fields) && (count($results) > 0))
402+
if (in_array('owner', $fields) && count($results) > 0)
399403
{
400-
$rs = Db::query("
401-
select user_id, uuid, username
402-
from user
403-
where user_id in ('".implode("','", array_map('\okapi\core\Db::escape_string', array_values($owner_ids)))."')
404-
");
405-
$tmp = array();
406-
while ($row = Db::fetch_assoc($rs))
407-
$tmp[$row['user_id']] = $row;
408-
foreach ($results as $cache_code => &$result_ref)
404+
# If the user only requests default fields or other "basic fields"
405+
# which can easily be handled, we will directly serve the request.
406+
# Otherwise we call the more expensive users/by_internal_ids method.
407+
408+
$basic_owner_fields = ['uuid', 'username', 'profile_url', 'internal_id'];
409+
$owner_fields_exploded = explode('|', $owner_fields);
410+
411+
if (count(array_diff($owner_fields_exploded, $basic_owner_fields)) == 0)
409412
{
410-
$row = $tmp[$owner_ids[$cache_code]];
411-
$result_ref['owner'] = array(
412-
'uuid' => $row['uuid'],
413-
'username' => $row['username'],
414-
'profile_url' => Settings::get('SITE_URL')."viewprofile.php?userid=".$row['user_id']
413+
$rs = Db::query("
414+
select user_id, uuid, username
415+
from user
416+
where user_id in ('".implode("','", array_map('\okapi\core\Db::escape_string', array_values($owner_ids)))."')
417+
");
418+
$tmp = array();
419+
while ($row = Db::fetch_assoc($rs))
420+
$tmp[$row['user_id']] = $row;
421+
Db::free_result($rs);
422+
423+
foreach ($results as $cache_code => &$result_ref)
424+
{
425+
$row = $tmp[$owner_ids[$cache_code]];
426+
$tmp = [];
427+
foreach ($owner_fields_exploded as $field)
428+
{
429+
if ($field == 'uuid')
430+
$tmp['uuid'] = $row['uuid'];
431+
elseif ($field == 'username')
432+
$tmp['username'] = $row['username'];
433+
elseif ($field == 'profile_url')
434+
$tmp['profile_url'] = Settings::get('SITE_URL')."viewprofile.php?userid=".$row['user_id'];
435+
elseif ($field == 'internal_id')
436+
$tmp['internal_id'] = $row['user_id'];
437+
}
438+
$result_ref['owner'] = $tmp;
439+
}
440+
}
441+
else
442+
{
443+
$ownersRequest = new OkapiInternalRequest(
444+
$request->consumer,
445+
$request->token,
446+
array(
447+
'internal_ids' => implode('|', $owner_ids),
448+
'fields' => $owner_fields
449+
)
415450
);
451+
$ownersRequest->skip_limits = true;
452+
try
453+
{
454+
$tmp = OkapiServiceRunner::call("services/users/by_internal_ids", $ownersRequest);
455+
}
456+
catch (Exception $e)
457+
{
458+
if (($e instanceof InvalidParam) && ($e->paramName == 'fields')) {
459+
throw new InvalidParam('owner_fields', $e->whats_wrong_about_it);
460+
}
461+
else {
462+
/* Something is wrong with OUR code. */
463+
throw new Exception($e);
464+
}
465+
}
466+
foreach ($results as $cache_code => &$result_ref) {
467+
$result_ref['owner'] = $tmp[$owner_ids[$cache_code]];
468+
}
469+
unset($ownersRequest);
416470
}
471+
unset($owner_fields_exploded);
472+
unset($basic_owner_fields);
417473
}
418474

419475
# is_found
@@ -969,7 +1025,8 @@ public static function call(OkapiRequest $request)
9691025
new OkapiInternalRequest(
9701026
$request->consumer, $request->token, array(
9711027
'log_uuids' => implode("|", $subset),
972-
'fields' => $log_fields
1028+
'fields' => $log_fields,
1029+
'user_fields' => $log_user_fields,
9731030
)
9741031
)
9751032
);
@@ -986,6 +1043,10 @@ public static function call(OkapiRequest $request)
9861043
{
9871044
throw new InvalidParam('log_fields', $e->whats_wrong_about_it);
9881045
}
1046+
elseif (($e instanceof InvalidParam) && ($e->paramName == 'user_fields'))
1047+
{
1048+
throw new InvalidParam('log_user_fields', $e->whats_wrong_about_it);
1049+
}
9891050
else
9901051
{
9911052
/* Something is wrong with OUR code. */

okapi/services/caches/geocaches/docs.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,21 @@
2929
<opt name='attribution_append' default='full'>
3030
<p>Same as in the services/caches/geocache method.</p>
3131
</opt>
32+
<opt name='oc_team_annotation' default='description'>
33+
Same as in the services/caches/geocache method.
34+
</opt>
35+
<opt name='owner_fields' default='uuid|username|profile_url'>
36+
Same as in the services/caches/geocache method.
37+
</opt>
3238
<opt name='lpc' default='10'>
3339
Same as in the services/caches/geocache method.
3440
</opt>
3541
<opt name='log_fields' default='uuid|date|user|type|comment'>
3642
Same as in the services/caches/geocache method.
3743
</opt>
44+
<opt name='log_user_fields' default='uuid|username|profile_url'>
45+
Same as in the services/caches/geocache method.
46+
</opt>
3847
<opt name='user_logs_only' default='false'>
3948
Same as in the services/caches/geocache method.
4049
</opt>

okapi/services/logs/entries/WebService.php

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
namespace okapi\services\logs\entries;
44

5+
use Exception;
56
use okapi\core\Db;
67
use okapi\core\Exception\InvalidParam;
78
use okapi\core\Exception\ParamMissing;
89
use okapi\core\Okapi;
10+
use okapi\core\OkapiServiceRunner;
11+
use okapi\core\Request\OkapiInternalRequest;
912
use okapi\core\Request\OkapiRequest;
1013
use okapi\Settings;
1114

@@ -47,6 +50,22 @@ public static function call(OkapiRequest $request)
4750
if (!in_array($field, self::$valid_field_names))
4851
throw new InvalidParam('fields', "'$field' is not a valid field code.");
4952

53+
if (!in_array('user', $fields))
54+
$user_fields = false;
55+
else
56+
{
57+
$user_fields = $request->get_parameter('user_fields'); // validation is done on call
58+
if (!$user_fields) {
59+
$user_fields = ['uuid', 'username', 'profile_url'];
60+
$only_basic_user_fields = true;
61+
} else {
62+
$user_fields = explode('|', $user_fields);
63+
$only_basic_user_fields = count(array_diff(
64+
$user_fields, ['uuid', 'username', 'profile_url', 'internal_id']
65+
)) == 0;
66+
}
67+
}
68+
5069
if (Settings::get('OC_BRANCH') == 'oc.de')
5170
{
5271
$teamentry_field = 'cl.oc_team_comment';
@@ -102,18 +121,14 @@ public static function call(OkapiRequest $request)
102121
");
103122
$results = array();
104123
$log_id2uuid = array(); /* Maps logs' internal_ids to uuids */
124+
$log_user_ids = array();
105125
$flag_options = array('null', 'false', 'true');
106126
while ($row = Db::fetch_assoc($rs))
107127
{
108128
$results[$row['uuid']] = array(
109129
'uuid' => $row['uuid'],
110130
'cache_code' => $row['cache_code'],
111131
'date' => date('c', $row['date']),
112-
'user' => array(
113-
'uuid' => $row['user_uuid'],
114-
'username' => $row['username'],
115-
'profile_url' => Settings::get('SITE_URL')."viewprofile.php?userid=".$row['user_id'],
116-
),
117132
'type' => Okapi::logtypeid2name($row['type']),
118133
'was_recommended' => $row['was_recommended'] ? true : false,
119134
'needs_maintenance2' => $flag_options[$row['needs_maintenance2']],
@@ -126,7 +141,23 @@ public static function call(OkapiRequest $request)
126141
'last_modified' => date("Y-m-d", strtotime($row['last_modified'])),
127142
'internal_id' => $row['id'],
128143
);
144+
if ($user_fields && $only_basic_user_fields) {
145+
$tmp = [];
146+
foreach ($user_fields as $field)
147+
{
148+
if ($field == 'uuid')
149+
$tmp['uuid'] = $row['user_uuid'];
150+
elseif ($field == 'username')
151+
$tmp['username'] = $row['username'];
152+
elseif ($field == 'profile_url')
153+
$tmp['profile_url'] = Settings::get('SITE_URL')."viewprofile.php?userid=".$row['user_id'];
154+
elseif ($field == 'internal_id')
155+
$tmp['internal_id'] = $row['user_id'];
156+
}
157+
$results[$row['uuid']]['user'] = $tmp;
158+
}
129159
$log_id2uuid[$row['id']] = $row['uuid'];
160+
$log_uuid2user_uuid[$row['uuid']] = $row['user_uuid'];
130161
}
131162
Db::free_result($rs);
132163

@@ -166,6 +197,39 @@ public static function call(OkapiRequest $request)
166197
Db::free_result($rs);
167198
}
168199

200+
# fetch users, if non-default user fields are selected
201+
202+
if ($user_fields && !$only_basic_user_fields)
203+
{
204+
$usersRequest = new OkapiInternalRequest(
205+
$request->consumer,
206+
$request->token,
207+
array(
208+
'user_uuids' => implode('|', array_values($log_uuid2user_uuid)),
209+
'fields' => implode('|', $user_fields)
210+
)
211+
);
212+
$usersRequest->skip_limits = true;
213+
try
214+
{
215+
$tmp = OkapiServiceRunner::call("services/users/users", $usersRequest);
216+
}
217+
catch (Exception $e)
218+
{
219+
if (($e instanceof InvalidParam) && ($e->paramName == 'fields')) {
220+
throw new InvalidParam('user_fields', $e->whats_wrong_about_it);
221+
}
222+
else {
223+
/* Something is wrong with OUR code. */
224+
throw new Exception($e);
225+
}
226+
}
227+
foreach ($results as $uuid => &$result_ref) {
228+
$result_ref['user'] = $tmp[$log_uuid2user_uuid[$uuid]];
229+
}
230+
unset($usersRequest);
231+
}
232+
169233
# Check which UUIDs were not found and mark them with null.
170234

171235
foreach ($log_uuids as $log_uuid)

okapi/services/logs/entries/docs.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313
</req>
1414
<opt name='fields' default='date|user|type|comment'>
1515
<p>Same as in the services/logs/entry method. Pipe-separated list
16-
of field names which you are interested with.
16+
of field names which you are interested in.
1717
See services/logs/entry method for a list of available values.</p>
1818
</opt>
19+
<opt name='user_fields' default='uuid|username|profile_url'>
20+
Same as in the services/logs/entry method. Pipe-separated list
21+
of user fields to include in the <b>user</b> field. For valid
22+
field names, see the
23+
<a href='%OKAPI:methodargref:services/users/user%'>services/users/user</a> method.
24+
</opt>
1925
<common-format-params/>
2026
<returns>
2127
<p>A dictionary. UUIDs you provide will be mapped to dictionary keys,

okapi/services/logs/entry/WebService.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,16 @@ public static function call(OkapiRequest $request)
2424
if (!$log_uuid) throw new ParamMissing('log_uuid');
2525
$fields = $request->get_parameter('fields');
2626
if (!$fields) $fields = "date|user|type|comment";
27+
$user_fields = $request->get_parameter('user_fields');
28+
if (!$user_fields) $user_fields = "uuid|username|profile_url";
2729

2830
$results = OkapiServiceRunner::call('services/logs/entries', new OkapiInternalRequest(
29-
$request->consumer, $request->token, array('log_uuids' => $log_uuid,
30-
'fields' => $fields)));
31+
$request->consumer, $request->token, array(
32+
'log_uuids' => $log_uuid,
33+
'fields' => $fields,
34+
'user_fields' => $user_fields,
35+
)
36+
));
3137
$result = $results[$log_uuid];
3238
if ($result == null)
3339
throw new InvalidParam('log_uuid', "This log entry does not exist.");

0 commit comments

Comments
 (0)