Merge remote-tracking branch 'upstream/stable' into stable
@@ -315,8 +315,11 @@
|
||||
*/
|
||||
$opt['logic']['pictures']['dir'] = $opt['rootpath'] . 'images/uploads'; // Ocprop
|
||||
$opt['logic']['pictures']['url'] = 'http://devel.opencaching.de/images/uploads';
|
||||
$opt['logic']['pictures']['maxsize'] = 256000;
|
||||
$opt['logic']['pictures']['extensions'] = 'jpg;jpeg;gif;png;bmp';
|
||||
$opt['logic']['pictures']['maxsize'] = 6000*1024;
|
||||
if (extension_loaded('imagick'))
|
||||
$opt['logic']['pictures']['extensions'] = 'jpg;jpeg;gif;png;bmp;tif;psd;pcx;svg;xpm';
|
||||
else
|
||||
$opt['logic']['pictures']['extensions'] = 'jpg;jpeg;gif;png';
|
||||
|
||||
/* Thumbnail sizes
|
||||
*/
|
||||
|
||||
@@ -902,6 +902,7 @@ INSERT INTO `sys_menu` (`id`, `id_string`, `title`, `title_trans_id`, `menustrin
|
||||
INSERT INTO `sys_menu` (`id`, `id_string`, `title`, `title_trans_id`, `menustring`, `menustring_trans_id`, `access`, `href`, `visible`, `parent`, `position`, `color`, `sitemap`, `only_if_parent`) VALUES ('102', 'MNU_START_NEWFEATURES', 'New features', '2115', 'New features', '2115', '0', 'articles.php?page=changelog', '1', '1', '5', '', '0', NULL);
|
||||
INSERT INTO `sys_menu` (`id`, `id_string`, `title`, `title_trans_id`, `menustring`, `menustring_trans_id`, `access`, `href`, `visible`, `parent`, `position`, `color`, `sitemap`, `only_if_parent`) VALUES ('103', 'MNU_MYPROFILE_OWNERLOGS', 'Log history', '2126', 'Log history', '2126', '0', 'ownerlogs.php', '0', '9', '10', '', '1', NULL);
|
||||
INSERT INTO `sys_menu` (`id`, `id_string`, `title`, `title_trans_id`, `menustring`, `menustring_trans_id`, `access`, `href`, `visible`, `parent`, `position`, `color`, `sitemap`, `only_if_parent`) VALUES ('104', 'MNU_MYPROFILE_OWNLOGS', 'Log history', '2126', 'Log history', '2126', '0', 'ownlogs.php', '0', '9', '11', '', '1', NULL);
|
||||
INSERT INTO `sys_menu` (`id`, `id_string`, `title`, `title_trans_id`, `menustring`, `menustring_trans_id`, `access`, `href`, `visible`, `parent`, `position`, `color`, `sitemap`, `only_if_parent`) VALUES ('105', 'MNU_CACHES_OCONLY81', 'OConly-81', '2139', 'OConly-81', '2139', '0', 'oconly81.php', '1', '10', '5', '', '1', NULL);
|
||||
|
||||
-- Table sys_trans
|
||||
SET NAMES 'utf8';
|
||||
@@ -978,7 +979,7 @@ INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('80', 'Start', '
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('81', 'What do i find on this website?', '2010-08-28 11:48:03');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('82', 'You can find everything you need to go Geocaching ...', '2010-08-28 11:48:03');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('83', 'The file was not uploaded correctly.', '2010-08-28 11:48:03');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('84', 'The file was too big. The maximum file size is 250 KB.', '2010-08-28 11:48:03');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('84', 'The file was too big. The maximum file size is %1 KB.', '2010-08-28 11:48:03');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('85', 'No picture file given.', '2010-08-28 11:48:03');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('86', 'same type', '2010-08-28 11:48:03');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('87', 'Opencaching.de', '2010-08-28 11:48:03');
|
||||
@@ -1634,8 +1635,8 @@ INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('758', 'Give the
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('759', 'After click to upload, it can take a while, until the next page is been shown.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('760', 'This picture is a spoiler - dont show a thumbnail.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('761', 'Upload', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('762', 'Only the following picture formats are allowed: BMP, GIF, PNG and JPEG. We recommend JPEG for photos.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('763', 'The file size of the pictures must not exeed 250 KB. We recommend 640x480 pixel of picture size.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('762', 'Only the following picture formats are allowed: %1. We recommend JPEG for photos.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('763', 'The file size of the pictures must not exeed %1 KB. We recommend 640x480 pixel of picture size.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('764', 'Report for %1 submitted', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('765', 'Reason:', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('766', 'Comment:', '2010-08-28 11:48:04');
|
||||
@@ -1802,7 +1803,7 @@ INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1275', 'Main me
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1278', 'Editor', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1279', '\<html\>', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1292', 'Setting smilies is not supported', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1296', 'Only the following picture formats are allowed: BMP, GIF, PNG and JPEG.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1296', 'Only the following picture formats are allowed: %1.', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1297', 'at (time)', '2010-08-28 11:48:04');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1298', 'The following list is generated automatically by the given recommendations of the users. You can find more informations on regional classification in the <a href=\"http://wiki.opencaching.de/index.php/Empfehlungen\">Wiki</a>.<br /> <br /> The numbers in the list below means:<br /> <img src=\"images/rating-star.gif\" border=\"0\" alt=\"Recommendations\" /> Number of users that recommend this cache<br /> <img src=\"resource2/%1/images/log/16x16-found.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"Found\" /> Checks = Number of time the cache was found<br /> Index tries to take the number of recommendations and founds in an order to show \'the best\' geocache first.<br /> <img src=\"images/tops-formula.png\" border=\"0\" alt=\"Formula\" />', '2010-08-28 12:03:52');
|
||||
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('1299', 'File upload failed!', '2010-08-29 17:44:48');
|
||||
@@ -2659,8 +2660,8 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('18',
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('18', 'table:sys_menu;field=menustring', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('18', 'table:sys_menu;field=title', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('19', './templates2/ocstyle/register.tpl', '10');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('20', './templates2/ocstyle/picture.tpl', '99');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('20', './templates2/ocstyle/picture.tpl', '121');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('20', './templates2/ocstyle/picture.tpl', '107');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('20', './templates2/ocstyle/picture.tpl', '129');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('20', './templates2/ocstyle/register.tpl', '14');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('20', './templates2/ocstyle/register.tpl', '62');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('20', './templates2/ocstyle/register.tpl', '174');
|
||||
@@ -2729,7 +2730,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51',
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51', './templates2/ocstyle/mywatches.tpl', '96');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51', './templates2/ocstyle/newemail.tpl', '108');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51', './templates2/ocstyle/newpw.tpl', '118');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51', './templates2/ocstyle/picture.tpl', '141');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51', './templates2/ocstyle/picture.tpl', '149');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51', './templates2/ocstyle/register.tpl', '196');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('51', './templates2/ocstyle/reportcache.tpl', '90');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('52', './lang/de/ocstyle/lib/menu.php', '190');
|
||||
@@ -2802,9 +2803,10 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('79',
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('80', './lang/de/ocstyle/lib/menu.php', '43');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('80', 'table:sys_menu;field=menustring', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('82', './index.php', '30');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('83', './templates2/ocstyle/picture.tpl', '81');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('84', './templates2/ocstyle/picture.tpl', '79');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('85', './templates2/ocstyle/picture.tpl', '77');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('83', './templates2/ocstyle/picture.tpl', '89');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('84', './templates2/ocstyle/picture.tpl', '87');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('84', './templates2/ocstyle/picture.tpl', '22');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('85', './templates2/ocstyle/picture.tpl', '85');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('86', './templates2/ocstyle/viewcache.tpl', '472');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('90', './templates2/ocstyle/start.tpl', '150');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('91', 'table:languages;field=name', '0');
|
||||
@@ -3276,7 +3278,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455',
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455', './templates2/ocstyle/mydetails.tpl', '91');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455', './templates2/ocstyle/myprofile.tpl', '200');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455', './templates2/ocstyle/newstopic.tpl', '99');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455', './templates2/ocstyle/picture.tpl', '142');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455', './templates2/ocstyle/picture.tpl', '150');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455', './templates2/ocstyle/remindemail.tpl', '45');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('455', './templates2/ocstyle/restorecaches.tpl', '22');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('456', './templates2/ocstyle/newstopic.tpl', '92');
|
||||
@@ -3754,7 +3756,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('739',
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('740', './templates2/mail/usercontactmail.tpl', '6');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('741', './lang/de/ocstyle/lib/menu.php', '227');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('741', './lang/de/ocstyle/lib/menu.php', '230');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('741', './templates2/ocstyle/picture.tpl', '37');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('741', './templates2/ocstyle/picture.tpl', '45');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('741', 'table:sys_menu;field=menustring', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('741', 'table:sys_menu;field=title', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('742', './templates2/ocstyle/error.tpl', '64');
|
||||
@@ -3768,22 +3770,22 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('749',
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('750', './templates2/ocstyle/adminreports.tpl', '15');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('750', 'table:sys_menu;field=menustring', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('750', 'table:sys_menu;field=title', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('751', './templates2/ocstyle/picture.tpl', '70');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('751', './templates2/ocstyle/picture.tpl', '78');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('752', './templates2/ocstyle/picture.tpl', '14');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('753', './templates2/ocstyle/picture.tpl', '44');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('754', './templates2/ocstyle/picture.tpl', '46');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('755', './templates2/ocstyle/picture.tpl', '50');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('756', './templates2/ocstyle/picture.tpl', '52');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('753', './templates2/ocstyle/picture.tpl', '52');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('754', './templates2/ocstyle/picture.tpl', '54');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('755', './templates2/ocstyle/picture.tpl', '58');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('756', './templates2/ocstyle/picture.tpl', '60');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('757', './lang/de/ocstyle/editcache.tpl.php', '120');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('757', './lang/de/ocstyle/newcache.tpl.php', '139');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('757', './templates2/ocstyle/map2.tpl', '2337');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('757', './templates2/ocstyle/picture.tpl', '60');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('758', './templates2/ocstyle/picture.tpl', '64');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('759', './templates2/ocstyle/picture.tpl', '124');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('760', './templates2/ocstyle/picture.tpl', '92');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('761', './templates2/ocstyle/picture.tpl', '142');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('762', './templates2/ocstyle/picture.tpl', '122');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('763', './templates2/ocstyle/picture.tpl', '123');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('757', './templates2/ocstyle/picture.tpl', '68');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('758', './templates2/ocstyle/picture.tpl', '72');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('759', './templates2/ocstyle/picture.tpl', '132');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('760', './templates2/ocstyle/picture.tpl', '100');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('761', './templates2/ocstyle/picture.tpl', '150');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('762', './templates2/ocstyle/picture.tpl', '130');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('763', './templates2/ocstyle/picture.tpl', '131');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('764', './templates2/ocstyle/reportcache.tpl', '14');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('765', './templates2/ocstyle/adminreports.tpl', '70');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('765', './templates2/ocstyle/reportcache.tpl', '20');
|
||||
@@ -3819,7 +3821,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('789',
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('792', './templates2/ocstyle/adminreports.tpl', '84');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('793', './templates2/ocstyle/adminreports.tpl', '76');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('794', './templates2/ocstyle/reportcache.tpl', '44');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('795', './templates2/ocstyle/picture.tpl', '109');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('795', './templates2/ocstyle/picture.tpl', '117');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('796', './templates2/ocstyle/mydetails.tpl', '81');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('797', './templates2/ocstyle/restorecaches.tpl', '81');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('797', './templates2/ocstyle/viewcache.tpl', '187');
|
||||
@@ -4046,7 +4048,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1279'
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1279', './templates2/ocstyle/log_cache.tpl', '144');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1279', './templates2/ocstyle/mydescription.tpl', '23');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1292', './templates2/ocstyle/log_cache.tpl', '33');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1296', './templates2/ocstyle/picture.tpl', '83');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1296', './templates2/ocstyle/picture.tpl', '91');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1297', './templates2/ocstyle/event_attendance.tpl', '10');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1298', './templates2/ocstyle/tops.tpl', '15');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1299', './translate.php', '568');
|
||||
@@ -4618,7 +4620,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1807'
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1807', './lang/de/ocstyle/editlog.tpl.php', '153');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1807', './templates2/ocstyle/log_cache.tpl', '191');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1807', './templates2/ocstyle/mydescription.tpl', '42');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1807', './templates2/ocstyle/picture.tpl', '132');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1807', './templates2/ocstyle/picture.tpl', '140');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1808', './templates2/ocstyle/register.tpl', '185');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1809', './templates2/ocstyle/register.tpl', '187');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1810', './templates2/ocstyle/viewcache.tpl', '488');
|
||||
@@ -4739,7 +4741,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1926'
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1927', 'table:coordinates_type;field=name', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1928', './templates2/ocstyle/map2.tpl', '2242');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1928', 'table:profile_options;field=name', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1929', './templates2/ocstyle/picture.tpl', '114');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1929', './templates2/ocstyle/picture.tpl', '122');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1930', './templates2/ocstyle/map2.tpl', '2238');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1940', 'table:sys_menu;field=menustring', '0');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1940', 'table:sys_menu;field=title', '0');
|
||||
@@ -4777,7 +4779,7 @@ INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1970'
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1970', './templates2/ocstyle/log_cache.tpl', '102');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1971', './lang/de/ocstyle/editlog.inc.php', '22');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1971', './templates2/ocstyle/log_cache.tpl', '110');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1973', './templates2/ocstyle/picture.tpl', '100');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1973', './templates2/ocstyle/picture.tpl', '108');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1974', './templates2/ocstyle/newemail.tpl', '49');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1974', './templates2/ocstyle/newpw.tpl', '45');
|
||||
INSERT INTO `sys_trans_ref` (`trans_id`, `resource_name`, `line`) VALUES ('1974', './templates2/ocstyle/register.tpl', '17');
|
||||
@@ -5065,7 +5067,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('81', 'DE', 'Was finde ich auf dieser Website?', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('82', 'DE', 'Auf dieser Website findest du Geocaches aus der ganzen Welt, mit Schwerpunkt Deutschland, \Österreich, Schweiz, Italien und Spanien. Au\ßerdem gibt es das <a href=\"http://wiki.opencaching.de\">Opencaching-Wiki</a> mit Anleitungen und Informationen rund um Opencaching und Geocaching, und ein Diskussionsforum.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('83', 'DE', 'Bei der Dateiübertragung ist ein Fehler aufgetreten.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'DE', 'Die Datei war zu groß. Es sind maximal 250 KB erlaubt.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'DE', 'Die Datei war zu groß. Es sind maximal %1 KB erlaubt.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('85', 'DE', 'Kein Bild angegeben.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('86', 'DE', 'gleiche Cacheart', '2010-09-04 21:39:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('87', 'DE', 'Opencaching.de', '2010-08-29 17:36:59');
|
||||
@@ -5722,8 +5724,8 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('759', 'DE', 'Nach dem Bestätigen kann der nächste Seitenaufbau je nach Bildgröße eine Weile dauern.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('760', 'DE', 'Dieses Bild ist ein Spoiler - keine Vorschau anzeigen.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('761', 'DE', 'Hinzufügen', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'DE', 'Es sind nur die Bildformate JPEG, GIF, PNG und BMP erlaubt; für Fotos wird JPEG empfohlen.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'DE', 'Außerdem ist eine maximale Dateigröße von 250 KB zu beachten. Als Bildgröße sind 640 Pixel Breite und 480 Pixel Höhe empfohlen.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'DE', 'Es sind nur die Bildformate %1 erlaubt; für Fotos wird JPEG empfohlen.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'DE', 'Außerdem ist eine maximale Dateigröße von %1 KB zu beachten. Als Bildgröße sind 640 Pixel Breite und 480 Pixel Höhe empfohlen.', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('764', 'DE', 'Meldebericht für %1 eingetragen', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('765', 'DE', 'Ursache:', '2010-08-28 11:48:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('766', 'DE', 'Kommentar:', '2010-08-28 11:48:06');
|
||||
@@ -5890,7 +5892,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1278', 'DE', 'Editor', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1279', 'DE', '\<html\>', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1292', 'DE', 'Smilies werden nicht unterstützt', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'DE', 'Nur die folgenden Dateiformate sind für Bilder erlaubt: BMP, GIF, PNG and JPEG.', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'DE', 'Nur die folgenden Dateiformate sind für Bilder erlaubt: %1.', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1297', 'DE', 'am', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1298', 'DE', 'Die Liste wird automatisch anhand der Empfehlungen unserer Benutzer aktualisiert. Mehr Informationen zur regionalen Einteilung kannst du im <a href=\"http://wiki.opencaching.de/index.php/Empfehlungen\" target=\"_blank\">Wiki</a> finden.<br />\r\n<br />\r\nDie Zahlen bedeuten Folgendes:<br />\r\n<img src=\"images/rating-star.gif\" border=\"0\" alt=\"Empfehlungen\" /> Anzahl der Benutzer die diesen Geocache empfohlen haben<br />\r\n<img src=\"resource2/%1/images/log/16x16-found.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"Gefunden\" /> Anzahl der Funde des Geocaches<br />\r\nDer Index setzt die beiden Zahlen in Relation, um den besten Geocache zu ermitteln:<br />\r\n<img src=\"images/tops-formula.png\" border=\"0\" alt=\"Formel\" />', '2010-08-28 12:10:29');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1299', 'DE', 'Dateiupload fehlerhaft!', '2010-08-29 17:46:28');
|
||||
@@ -6194,7 +6196,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1625', 'DE', 'Der Cache f\ührt in eine (ehemalige) Bergbauregion. M\öglicherweise bestehen Gefahren durch verst\ürzte Stollenmundl\öcher oder es m\üssen Stollen betreten werden. Entsprechende Ausr\üstung und Vorsicht, besonders bei Dunkelheit, wird empfohlen. Historische Bergwerke stehen m\öglicherweise unter Denkmalschutz.', '2010-09-12 23:43:40');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1626', 'DE', 'In der N\ähe des Caches gibt es giftige Pflanzen. Achtet also insbesondere darauf, dass Kinder und Hunde diese nicht anfassen oder essen.', '2010-09-12 23:43:45');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1627', 'DE', 'In dem Gebiet sind Wildtiere angesiedelt, die f\ür Menschen eine Gefahr darstellen k\önnen, z.B. Tollwutgebiete, giftige Schlangen, Skorpione oder B\ären.', '2010-09-12 23:43:35');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1628', 'DE', 'Es gibt in der Nähe einen Parklplatz, der sich als Startpunkt für die Cachesuche eignet. Falls alle Parkplätze gebührenpflichtig sind, bitte auch das Attribut Zugangs- bzw. Parkentgelt angeben.', '2010-09-12 23:47:42');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1628', 'DE', 'Es gibt in der Nähe einen Parkplatz, der sich als Startpunkt für die Cachesuche eignet. Falls alle Parkplätze gebührenpflichtig sind, bitte auch das Attribut Zugangs- bzw. Parkentgelt angeben.', '2010-09-12 23:47:42');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1629', 'DE', 'Dieser Cache lässt sich mit Hilfe von öffentlichen Verkehrsmitteln erreichen und liegt außerhalb von Städten. Besonders bei Geocaches die an abgelegenen Aussichtspunkten, Wanderparkplätzen oder Ausflugszielen liegen ist dieses Attribut hilfreich. Für Geocaches in Städten soll dieses Attribut hingegen nicht angegeben werden, da diese in der Regel immer per ÖVM erreichbar sind.', '2010-09-12 23:47:12');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1630', 'DE', 'W\ährend der Cachetour oder in der N\ähe des Geocaches ist Trinkwasser verf\ügbar. Besonders bei Event-Caches, l\ängeren Multicaches und bei Geocaches, wo man vermutlich schmutzig wird (z.B. manche H\öhlencaches), hilft dieses Attribut bei der Planung der Cachetour.', '2010-09-12 23:43:10');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1631', 'DE', 'W\ährend der Cachetour oder in der N\ähe des Geocaches ist eine \öffentliche Toilette verf\ügbar. Besonders bei Event-Caches und bei l\ängeren Multicaches hilft dieses Attribut bei der Planung der Cachetour.', '2010-09-12 23:43:04');
|
||||
@@ -6757,7 +6759,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('81', 'EN', 'Welcome to opencaching.de', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('82', 'EN', 'On this page you will find Geocaches from all over the world, with focus on Germany, Austria, Switzerland, Italy and Spain. We also offer information on miscellaneous geocaching topics, and a forum (message board) and chat for communicating with other cachers.</p><p class=\"startmessage\">If you would like to propagate geocaching in your own country, you may run your own Opencaching site in your own language, using our <a href=\"https://github.com/OpencachingDeutschland/oc-server3\" target=\"_blank\">software</a> and known-how. The long-term plan is to form a global geocaching network out of all Opencaching sites. Please contact us in our <a href=\"http://forum.opencaching-network.org/index.php?board=24.0\" target=\"_blank\">international forum</a> for more information.', '2013-02-11 14:25:06');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('83', 'EN', 'The file was not uploaded correctly.', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'EN', 'The file was too big. The maximum file size is 250 KB.', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'EN', 'The file was too big. The maximum file size is %1 KB.', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('85', 'EN', 'No picture file given.', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('86', 'EN', 'same type', '2010-08-28 11:48:07');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('87', 'EN', 'Opencaching.de', '2010-08-29 17:36:59');
|
||||
@@ -7413,8 +7415,8 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('759', 'EN', 'After clicking <i>upload</i>, it may take a while until the next page appears.', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('760', 'EN', 'This picture is a spoiler - don\'t show a thumbnail.', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('761', 'EN', 'Upload', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'EN', 'Only the following picture formats are allowed: BMP, GIF, PNG and JPEG. We recommend JPEG for photos.', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'EN', 'The file size of the picture must not exeed 250 KB. We recommend 640x480 pixels picture size.', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'EN', 'Only the following picture formats are allowed: %1. We recommend JPEG for photos.', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'EN', 'The file size of the picture must not exeed %1 KB. We recommend 640x480 pixels picture size.', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('764', 'EN', 'Report for %1 has been submitted.', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('765', 'EN', 'Reason:', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('766', 'EN', 'Comment:', '2010-08-28 11:48:08');
|
||||
@@ -7581,7 +7583,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1278', 'EN', 'Editor', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1279', 'EN', '\<html\>', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1292', 'EN', 'Setting smilies is not supported', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'EN', 'Only the following picture formats are allowed: BMP, GIF, PNG and JPEG.', '2010-08-28 11:50:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'EN', 'Only the following picture formats are allowed: %1.', '2010-08-28 11:50:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1297', 'EN', 'am', '2010-08-28 11:48:08');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1298', 'EN', 'The following list is generated automatically by the given recommendations of the users. You can find more informations on regional classification in the <a href=\"http://wiki.opencaching.de/index.php/Empfehlungen\" target=\"_blank\">Wiki</a>.<br /> <br /> The numbers in the list below means:<br /> <img src=\"images/rating-star.gif\" border=\"0\" alt=\"Recommendations\" /> Number of users that recommend this cache<br /> <img src=\"resource2/%1/images/log/16x16-found.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"Found\" /> Checks = Number of time the cache was found<br /> Index tries to take the number of recommendations and founds in an order to show \'the best\' geocache first.<br /> <img src=\"images/tops-formula.png\" border=\"0\" alt=\"Formula\" />', '2010-08-29 22:49:51');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1299', 'EN', 'File upload failed!', '2010-08-29 22:50:32');
|
||||
@@ -8415,7 +8417,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('81', 'ES', '¿Que me parece en este sitio?', '2010-12-09 00:17:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('82', 'ES', 'En esta página podrás encontrar geocaches en todo el mundo, con especial atención a Alemania, Austria, Suiza, Italia y España. También ofrecemos información sobre temas diversos geocaching, y un foro (tablón de anuncios) y chat para comunicarse con otros cachers.', '2010-12-09 00:17:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('83', 'ES', 'El archivo no se ha subido correctamente.', '2010-12-09 00:17:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'ES', 'El archivo era demasiado grande. Se permite un máximo de 250 KB.', '2010-12-09 00:17:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'ES', 'El archivo era demasiado grande. Se permite un máximo de %1 KB.', '2010-12-09 00:17:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('85', 'ES', 'No hay imagen de archivo determinado.', '2010-12-09 00:17:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('86', 'ES', 'mismo tipo', '2010-12-09 00:17:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('87', 'ES', 'Opencaching.de', '2010-12-09 00:17:56');
|
||||
@@ -9071,8 +9073,8 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('759', 'ES', 'Cuando pulse <i>carica</i> puede que tarde algo de tiempo antes de que se muestre la página siguiente.', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('760', 'ES', 'Esta imagen es un spoiler - No hay vista previa.', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('761', 'ES', 'Cargar', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'ES', 'Los siguientes formatos se permite sólo para imágenes: BMP, GIF, PNG y JPEG. Recomendamos JPEG para las fotos.', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'ES', 'El tamaño de la imagen no debe superar los 250KB. Se recomienda imágenes de 640 píxeles de ancho por 480 de alto.', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'ES', 'Los siguientes formatos se permite sólo para imágenes: %1. Recomendamos JPEG para las fotos.', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'ES', 'El tamaño de la imagen no debe superar los %1KB. Se recomienda imágenes de 640 píxeles de ancho por 480 de alto.', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('764', 'ES', 'El informe sobre %1 ha sido presentado', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('765', 'ES', 'Motivo:', '2010-12-09 00:17:58');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('766', 'ES', 'Comentario:', '2010-12-09 00:17:58');
|
||||
@@ -9239,7 +9241,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1278', 'ES', 'Editor', '2010-12-09 00:17:59');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1279', 'ES', '\<html\>', '2010-12-09 00:17:59');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1292', 'ES', 'Smilies no son compatibles', '2010-12-09 00:17:59');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'ES', 'Sólo los siguientes formatos de archivo se permite para las imágenes: BMP, GIF, PNG y JPEG.', '2010-12-09 00:17:59');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'ES', 'Sólo los siguientes formatos de archivo se permite para las imágenes: %1.', '2010-12-09 00:17:59');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1297', 'ES', 'a la (hora)', '2010-12-09 00:17:59');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1298', 'ES', 'La lista se actualizará automáticamente basado en las recomendaciones de nuestros usuarios. Más información sobre la división regional se puede en el <a href=\"http://wiki.opencaching.de/index.php/Empfehlungen\" target=\"_blank\">Wiki</a>.<br />\r\n<br />\r\nLos números indican lo siguiente:<br />\r\n<img src=\"images/rating-star.gif\" border=\"0\" alt=\"Empfehlungen\" />Número de hallazgos del Geocache<br />\r\n<img src=\"resource2/%1/images/log/16x16-found.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"\" /> Número de hallazgos del Geocache<br />\r\nEl índice es el número dos en relación a determinar el mejor Geocache<br />\r\n<img src=\"images/tops-formula.png\" border=\"0\" alt=\"Formel\" />', '2010-12-09 00:17:59');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1299', 'ES', '¡Archivo de errores de carga!', '2010-12-09 00:17:59');
|
||||
@@ -9979,7 +9981,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('81', 'IT', 'Che cosa trovo in questo sito?', '2010-10-27 18:49:19');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('82', 'IT', 'In questa pagina trovi le Geocache di tutto il mondo, con particolare riguardo a Germania, Austria, Italia e Spagna. Offriamo anche informazioni su svariati argomenti, e un forum (scambio messaggi) con chat per comunicare con altrio cachers.', '2010-12-19 00:27:25');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('83', 'IT', 'Il file non è stato caricato correttamente.', '2010-08-28 21:20:35');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'IT', 'Il file è troppo grande. La dimensione massima è 250 KB.', '2010-08-28 21:21:01');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'IT', 'Il file è troppo grande. La dimensione massima è %1 KB.', '2010-08-28 21:21:01');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('85', 'IT', 'File per l\'immagine non definito.', '2010-08-28 21:22:12');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('86', 'IT', 'stesso tipo', '2010-08-28 21:27:16');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('87', 'IT', 'Opencaching.de', '2010-08-28 21:22:19');
|
||||
@@ -10635,8 +10637,8 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('759', 'IT', 'Quando premi <i>carica</i> può essere necessario un certo tempo prima che venga visualizzata la pagina successiva.', '2010-09-01 23:49:32');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('760', 'IT', 'Questa immagine è uno spoiler - non visualizzare l\'anteprima.', '2010-09-10 23:15:35');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('761', 'IT', 'Carica', '2010-08-31 20:06:23');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'IT', 'Sono ammessi solo i seguenti formati per le immagini: BMP, GIF, PNG and JPEG. Raccomandiamo JPEG per le foto.', '2010-09-01 23:49:32');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'IT', 'La dimensione dell\'immagine non deve essere superiore a 250kB. Raccomandiamo immagini di 640 pixel di larghezza per 480 di altezza.', '2010-10-27 18:49:19');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('762', 'IT', 'Sono ammessi solo i seguenti formati per le immagini: %1. Raccomandiamo JPEG per le foto.', '2010-09-01 23:49:32');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('763', 'IT', 'La dimensione dell\'immagine non deve essere superiore a %1kB. Raccomandiamo immagini di 640 pixel di larghezza per 480 di altezza.', '2010-10-27 18:49:19');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('764', 'IT', 'Segnalazione per %1 inviata.', '2010-09-01 23:49:32');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('765', 'IT', 'Motivo:', '2010-08-31 20:06:24');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('766', 'IT', 'Commento:', '2010-09-01 23:49:32');
|
||||
@@ -10803,7 +10805,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1278', 'IT', 'Editor', '2010-09-10 23:15:37');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1279', 'IT', '\<html\>', '2010-09-10 23:15:37');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1292', 'IT', 'L\'utilizzo degli smilies non è supportato', '2010-09-10 23:15:37');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'IT', 'Sono ammesse solo le immagini nei seguenti formati: BMP, GIF, PNG e JPEG.', '2010-10-27 18:49:19');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1296', 'IT', 'Sono ammesse solo le immagini nei seguenti formati: %1.', '2010-10-27 18:49:19');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1297', 'IT', 'alle (ora)', '2010-08-28 22:26:55');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1298', 'IT', 'Questa lista è generata automaticamente sulla base delle raccomandazioni degli utenti. Puoi trovare maggiori informazioni sulla classificazione regionale nell <a href=\"http://wiki.opencaching.de/index.php/Empfehlungen\" target=\"_blank\">Wiki</a>.<br /> <br /> I numeri nella lista qui sotto significano:<br /> <img src=\"images/rating-star.gif\" border=\"0\" alt=\"Recommendations\" /> Numbero di utenti che raccomandano questa cache<br /> <img src=\"resource2/%1/images/log/16x16-found.png\" width=\"16\" height=\"16\" border=\"0\" alt=\"Found\" /> Checks = Numero di volte in cui la cache è stata trovata<br /> L\' indice cerca di ordinare il numero di raccomandazioni e i ritrovamenti in modo da visualizzare per prime \'le migliori\' geocache.<br /> <img src=\"images/tops-formula.png\" border=\"0\" alt=\"Formula\" />', '2010-08-28 22:26:30');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1299', 'IT', 'Errore caricamento file!', '2010-09-10 23:15:37');
|
||||
@@ -11665,7 +11667,7 @@ INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUE
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('81', 'NL', 'Welkom op opencaching.nl', '2011-02-04 19:49:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('82', 'NL', 'Hier kan alles gevonden worden wat met Geocaching te maken heeft, als beginner of iemand die veel ervaring heeft. van een eenvoudige wiki tot forum waar met andere cachers gediscussieerd kan worden.', '2011-02-04 19:49:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('83', 'NL', 'Bij de dataoverdracht is een fout opgetreden.', '2011-02-04 19:49:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'NL', 'Het bestand is te groot, de maximale grootte is 250 KB.', '2011-02-04 19:49:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('84', 'NL', 'Het bestand is te groot, de maximale grootte is %1 KB.', '2011-02-04 19:49:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('85', 'NL', 'Geen afbeelding opgegeven.', '2011-02-04 19:49:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('86', 'NL', 'zelfde cache soort', '2011-02-04 19:49:56');
|
||||
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('87', 'NL', 'Opencaching.nl', '2011-02-04 19:49:56');
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
<title><?php echo $tpl_subtitle; ?>{title}</title>
|
||||
<meta name="keywords" content="Geocaching, Geocache, Cache, Geocashing, Schnitzeljagd, Schatzsuche, GPS, Openstreetmap, kostenlos, GPX, GPX download, Koordinaten, Hobby, Natur" />
|
||||
<meta name="description" content="Opencaching.de ist das freie Portal für Geocaching, ein GPS-Schatzsuche-Spiel: Es werden kleine Behälter versteckt, die anhand von GPS-Koordinaten zu finden sind." />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="Content-Style-Type" content="text/css" />
|
||||
<meta http-equiv="Content-Language" content="{lang}" />
|
||||
@@ -68,7 +67,8 @@
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="resource2/{style}/images/oclogo/apple-touch-icon-iphone-retina.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="resource2/{style}/images/oclogo/apple-touch-icon-ipad-retina.png" />
|
||||
<link rel="stylesheet" type="text/css" media="screen,projection" href="resource2/{style}/css/style_screen.css?ft={screen_css_time}" />
|
||||
<!--[if IE]>
|
||||
<!--[if lte IE 9]>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
|
||||
<link rel="stylesheet" type="text/css" media="screen,projection" href="resource2/{style}/css/style_screen_msie.css?ft={screen_msie_css_time}" />
|
||||
<![endif]-->
|
||||
<script type="text/javascript">
|
||||
@@ -312,6 +312,7 @@
|
||||
<div class="content2">
|
||||
<div class="tplhelp">
|
||||
<?php mnu_EchoHelpLink($tplname); ?>
|
||||
<!--[if IE]><div></div><![endif]-->
|
||||
</div>
|
||||
|
||||
<div id="ocmain">
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
|
||||
****************************************************************************/
|
||||
?>
|
||||
<div class="content2-pagetitle"><img src="lang/de/ocstyle/images/description/22x22-logs.png" style="align: left; margin-right: 10px;" width="22" height="22"/>{t}remove log entry for <a href="viewcache.php?cacheid={cacheid}">{cachename}</a>{/t}</div>
|
||||
<form action="removelog.php" method="post" enctype="application/x-www-form-urlencoded" name="removelog_form" dir="ltr">
|
||||
<input type="hidden" name="commit" value="1" />
|
||||
<input type="hidden" name="logid" value="{logid}" />
|
||||
<table class="table">
|
||||
<tr><td class="header" colspan="2"><img src="lang/de/ocstyle/images/description/22x22-logs.png" border="0" width="22" height="22" alt="" title="" align="middle" /> <b>{t}remove log entry for <a href="viewcache.php?cacheid={cacheid}">{cachename}</a>{/t}</b></td></tr>
|
||||
|
||||
<tr><td colspan="2">{t}are you sure that this log entry shall be removed?{/t}</td></tr>
|
||||
<tr><td class="spacer"></td></tr>
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
****************************************************************************/
|
||||
?>
|
||||
<div class="content2-pagetitle"><img src="lang/de/ocstyle/images/description/22x22-logs.png" style="align: left; margin-right: 10px;" width="22" height="22"/>{t}remove log entry for <a href="viewcache.php?cacheid={cacheid}">{cachename}</a>{/t}</div>
|
||||
<form action="removelog.php" method="post" enctype="application/x-www-form-urlencoded" name="removelog_form" dir="ltr">
|
||||
<input type="hidden" name="commit" value="1"/>
|
||||
<input type="hidden" name="logid" value="{logid}"/>
|
||||
<table class="table">
|
||||
<tr><td class="header" colspan="2"><img src="lang/de/ocstyle/images/description/22x22-logs.png" border="0" width="22" height="22" alt="" title="" align="middle" /> <b>{t}remove log entry for <a href="viewcache.php?cacheid={cacheid}">{cachename}</a>{/t}</b></td></tr>
|
||||
<tr><td class="spacer"></td></tr>
|
||||
|
||||
<tr><td colspan="2">{t}Are you sure to remove your log entry?{/t}</td></tr>
|
||||
|
||||
@@ -83,4 +83,8 @@
|
||||
define('NEW_DATA_LICENSE_PASSIVELY_ACCEPTED',3); // did not decline license until deadline
|
||||
define('NEW_DATA_LICENSE_PASSIVELY_DECLINED',4); // could not accept/decline because disabled
|
||||
|
||||
//picture upload/resize parameters
|
||||
define('PICTURE_QUALITY',85);
|
||||
define('PICTURE_RESOLUTION',72);
|
||||
define('PICTURE_MAX_LONG_SIDE',1024);
|
||||
?>
|
||||
@@ -109,7 +109,7 @@ class picture
|
||||
if (strpos($sFilename, '.') === false)
|
||||
return;
|
||||
|
||||
$sExtension = mb_strtolower(substr($sFilename, strrpos($sFilename, '.') + 1));
|
||||
$sExtension = 'jpg';//mb_strtolower(substr($sFilename, strrpos($sFilename, '.') + 1));
|
||||
$this->sFileExtension = $sExtension;
|
||||
|
||||
$sUUID = $this->getUUID();
|
||||
@@ -453,6 +453,71 @@ class picture
|
||||
}
|
||||
return $pl;
|
||||
}
|
||||
/*
|
||||
Shrink picture to a specified maximum size. If present Imagemagick extension will be used, if not gd.
|
||||
Imagick is sharper, faster, need less memory and supports more types.
|
||||
For gd size is limited to 5000px (memory consumption).
|
||||
i prefer FILTER_CATROM because its faster but similiar to lanczos see http://de1.php.net/manual/de/imagick.resizeimage.php
|
||||
parameter:
|
||||
$tmpfile: full name of uploaded file
|
||||
$longSideSize: if longer side of picture > $longSideSize, then it will be prop. shrinked to
|
||||
returns: true if no error occur, otherwise false
|
||||
*/
|
||||
public function shrink($tmpFile,$longSideSize)
|
||||
{
|
||||
global $opt;
|
||||
if (extension_loaded('imagick')) {
|
||||
try {
|
||||
|
||||
$image = new Imagick();
|
||||
$image->readImage($tmpFile);
|
||||
$w=$image->getImageWidth();
|
||||
$h=$image->getImageHeight();
|
||||
$image->setImageResolution(PICTURE_RESOLUTION,PICTURE_RESOLUTION);
|
||||
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
|
||||
$image->setImageCompressionQuality(PICTURE_QUALITY);
|
||||
$image->stripImage(); //clears exif, private data
|
||||
//$newSize=$w<$h?array($w*$longSideSize/$h,$longSideSize):array($longSideSize,$h*$longSideSize/$w);
|
||||
if (max($w,$h)>$longSideSize)
|
||||
$image->resizeImage($longSideSize,$longSideSize,imagick::FILTER_CATROM,1,true);
|
||||
$result=$image->writeImage($this->getFilename());
|
||||
$image->clear();
|
||||
}
|
||||
catch (Exception $e){
|
||||
if ($image)$image->clear();
|
||||
if($opt['debug'] & DEBUG_DEVELOPER)die($e);
|
||||
$result=false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
else if (extension_loaded('gd')) {
|
||||
$imageNew=null;
|
||||
try{
|
||||
$image = imagecreatefromstring(file_get_contents($tmpFile)); ;
|
||||
$w=imagesx($image);
|
||||
$h=imagesy($image);
|
||||
if (max($w,$h)>5000)throw new Exception("Image too large >5000px");
|
||||
if (max($w,$h)<=$longSideSize)
|
||||
$result=imagejpeg($image,$this->getFilename(),PICTURE_QUALITY);
|
||||
else {
|
||||
$newSize=$w<$h?array($w*$longSideSize/$h,$longSideSize):array($longSideSize,$h*$longSideSize/$w);
|
||||
$imageNew = imagecreatetruecolor($newSize[0], $newSize[1]);
|
||||
imagecopyresampled($imageNew, $image, 0, 0, 0, 0,$newSize[0], $newSize[1], $w, $h);
|
||||
$result=imagejpeg($imageNew,$this->getFilename(),PICTURE_QUALITY);
|
||||
imagedestroy($imageNew);
|
||||
}
|
||||
imagedestroy($image);
|
||||
}
|
||||
catch (Exception $e){
|
||||
if ($image)imagedestroy($image);
|
||||
if ($imageNew)imagedestroy($imageNew);
|
||||
if($opt['debug'] & DEBUG_DEVELOPER)die($e);
|
||||
$result=false;
|
||||
}
|
||||
return $result;
|
||||
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/***************************************************************************
|
||||
* For license information see doc/license.txt
|
||||
*
|
||||
* Unicode Reminder メモ
|
||||
*
|
||||
* Display some status information about the server and Opencaching
|
||||
***************************************************************************/
|
||||
|
||||
require 'lib2/web.inc.php';
|
||||
require 'lib2/logic/oconly81.inc.php';
|
||||
|
||||
$showall = (@$_REQUEST['showall'] == 1);
|
||||
|
||||
$tpl->name = 'oconly81';
|
||||
$tpl->menuitem = MNU_CACHES_OCONLY81;
|
||||
$tpl->caching = true;
|
||||
$tpl->cache_lifetime = 900;
|
||||
$tpl->cache_id = $showall ? 1 : 0;
|
||||
|
||||
$login->verify();
|
||||
|
||||
sql_temp_table('oconly81');
|
||||
sql("
|
||||
CREATE TEMPORARY TABLE &oconly81 ENGINE=MEMORY
|
||||
SELECT DISTINCT `user`.`user_id`, `caches`.`terrain`, `caches`.`difficulty`
|
||||
FROM `user`
|
||||
INNER JOIN `cache_logs` ON `cache_logs`.`user_id`=`user`.`user_id` AND `cache_logs`.`type` IN (1,7)
|
||||
INNER JOIN `caches` ON `caches`.`cache_id`=`cache_logs`.`cache_id`
|
||||
INNER JOIN `caches_attributes` ON `caches_attributes`.`cache_id`=`cache_logs`.`cache_id` AND `caches_attributes`.`attrib_id`=6
|
||||
INNER JOIN `user_options` ON `user_options`.`user_id`=`user`.`user_id`
|
||||
WHERE `user_options`.`option_id`=13 AND `user_options`.`option_value`='1'");
|
||||
// users with 0 OConly founds are filtered out here
|
||||
|
||||
$rs = sql("
|
||||
SELECT `user`.`username`, `user`.`user_id`, COUNT(*) AS `count`
|
||||
FROM `user`
|
||||
INNER JOIN &oconly81 ON &oconly81.`user_id`=`user`.`user_id`
|
||||
GROUP BY `user`.`user_id`
|
||||
ORDER BY `count` DESC, `username` ASC " .
|
||||
($showall ? "" : "LIMIT " . sql_escape($opt['logic']['oconly81']['default_maxusers']+1)) );
|
||||
|
||||
$tpl->assign_rs('users', $rs);
|
||||
sql_free_result($rs);
|
||||
sql_drop_temp_table('oconly81');
|
||||
|
||||
set_oconly81_tpldata(0);
|
||||
$tpl->assign('default_maxusers', $opt['logic']['oconly81']['default_maxusers']);
|
||||
$tpl->assign('showall', $showall);
|
||||
|
||||
$tpl->display();
|
||||
?>
|
||||
@@ -23,75 +23,75 @@ require_once($GLOBALS['rootpath'].'okapi/urls.php');
|
||||
|
||||
if (ob_list_handlers() == array('default output handler'))
|
||||
{
|
||||
# We will assume that this one comes from "output_buffering" being turned on
|
||||
# in PHP config. This is very common and probably is good for most other OC
|
||||
# pages. But we don't need it in OKAPI. We will just turn this off.
|
||||
# We will assume that this one comes from "output_buffering" being turned on
|
||||
# in PHP config. This is very common and probably is good for most other OC
|
||||
# pages. But we don't need it in OKAPI. We will just turn this off.
|
||||
|
||||
ob_end_clean();
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
|
||||
class OkapiScriptEntryPointController
|
||||
{
|
||||
public static function dispatch_request($uri)
|
||||
{
|
||||
# Chop off the ?args=... part.
|
||||
public static function dispatch_request($uri)
|
||||
{
|
||||
# Chop off the ?args=... part.
|
||||
|
||||
if (strpos($uri, '?') !== false)
|
||||
$uri = substr($uri, 0, strpos($uri, '?'));
|
||||
if (strpos($uri, '?') !== false)
|
||||
$uri = substr($uri, 0, strpos($uri, '?'));
|
||||
|
||||
# Chop off everything before "/okapi/". This should work for okay for most "weird"
|
||||
# server configurations. It will also address a more subtle issue described here:
|
||||
# http://stackoverflow.com/questions/8040461/request-uri-unexpectedly-contains-fqdn
|
||||
# Chop off everything before "/okapi/". This should work for okay for most "weird"
|
||||
# server configurations. It will also address a more subtle issue described here:
|
||||
# http://stackoverflow.com/questions/8040461/request-uri-unexpectedly-contains-fqdn
|
||||
|
||||
if (strpos($uri, "/okapi/") !== false)
|
||||
$uri = substr($uri, strpos($uri, "/okapi/"));
|
||||
if (strpos($uri, "/okapi/") !== false)
|
||||
$uri = substr($uri, strpos($uri, "/okapi/"));
|
||||
|
||||
# Make sure we're in the right directory (.htaccess should make sure of that).
|
||||
# Make sure we're in the right directory (.htaccess should make sure of that).
|
||||
|
||||
if (strpos($uri, "/okapi/") !== 0)
|
||||
throw new Exception("'$uri' is outside of the /okapi/ path.");
|
||||
$uri = substr($uri, 7);
|
||||
if (strpos($uri, "/okapi/") !== 0)
|
||||
throw new Exception("'$uri' is outside of the /okapi/ path.");
|
||||
$uri = substr($uri, 7);
|
||||
|
||||
# Initializing internals and running pre-request cronjobs (we don't want
|
||||
# cronjobs to be run before "okapi/update", for example before database
|
||||
# was installed).
|
||||
# Initializing internals and running pre-request cronjobs (we don't want
|
||||
# cronjobs to be run before "okapi/update", for example before database
|
||||
# was installed).
|
||||
|
||||
$allow_cronjobs = ($uri != "update");
|
||||
Okapi::init_internals($allow_cronjobs);
|
||||
$allow_cronjobs = ($uri != "update");
|
||||
Okapi::init_internals($allow_cronjobs);
|
||||
|
||||
# Checking for allowed patterns...
|
||||
# Checking for allowed patterns...
|
||||
|
||||
try
|
||||
{
|
||||
foreach (OkapiUrls::$mapping as $pattern => $namespace)
|
||||
{
|
||||
$matches = null;
|
||||
if (preg_match("#$pattern#", $uri, $matches))
|
||||
{
|
||||
# Pattern matched! Moving on to the proper View...
|
||||
try
|
||||
{
|
||||
foreach (OkapiUrls::$mapping as $pattern => $namespace)
|
||||
{
|
||||
$matches = null;
|
||||
if (preg_match("#$pattern#", $uri, $matches))
|
||||
{
|
||||
# Pattern matched! Moving on to the proper View...
|
||||
|
||||
array_shift($matches);
|
||||
require_once($GLOBALS['rootpath']."okapi/views/$namespace.php");
|
||||
$response = call_user_func_array(array('\\okapi\\views\\'.
|
||||
str_replace('/', '\\', $namespace).'\\View', 'call'), $matches);
|
||||
if ($response)
|
||||
$response->display();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Http404 $e)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
array_shift($matches);
|
||||
require_once($GLOBALS['rootpath']."okapi/views/$namespace.php");
|
||||
$response = call_user_func_array(array('\\okapi\\views\\'.
|
||||
str_replace('/', '\\', $namespace).'\\View', 'call'), $matches);
|
||||
if ($response)
|
||||
$response->display();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Http404 $e)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
|
||||
# None of the patterns matched OR method threw the Http404 exception.
|
||||
# None of the patterns matched OR method threw the Http404 exception.
|
||||
|
||||
require_once($GLOBALS['rootpath']."okapi/views/http404.php");
|
||||
$response = \okapi\views\http404\View::call();
|
||||
$response->display();
|
||||
}
|
||||
require_once($GLOBALS['rootpath']."okapi/views/http404.php");
|
||||
$response = \okapi\views\http404\View::call();
|
||||
$response->display();
|
||||
}
|
||||
}
|
||||
|
||||
Okapi::gettext_domain_init();
|
||||
|
||||
@@ -6,180 +6,180 @@ use OAuthDataStore;
|
||||
|
||||
class OkapiDataStore extends OAuthDataStore
|
||||
{
|
||||
public function lookup_consumer($consumer_key)
|
||||
{
|
||||
$row = Db::select_row("
|
||||
select `key`, secret, name, url, email
|
||||
from okapi_consumers
|
||||
where `key` = '".mysql_real_escape_string($consumer_key)."'
|
||||
");
|
||||
if (!$row)
|
||||
return null;
|
||||
return new OkapiConsumer($row['key'], $row['secret'], $row['name'],
|
||||
$row['url'], $row['email']);
|
||||
}
|
||||
public function lookup_consumer($consumer_key)
|
||||
{
|
||||
$row = Db::select_row("
|
||||
select `key`, secret, name, url, email, admin
|
||||
from okapi_consumers
|
||||
where `key` = '".mysql_real_escape_string($consumer_key)."'
|
||||
");
|
||||
if (!$row)
|
||||
return null;
|
||||
return new OkapiConsumer($row['key'], $row['secret'], $row['name'],
|
||||
$row['url'], $row['email'], $row['admin'] ? true : false);
|
||||
}
|
||||
|
||||
public function lookup_token($consumer, $token_type, $token)
|
||||
{
|
||||
$row = Db::select_row("
|
||||
select `key`, consumer_key, secret, token_type, user_id, verifier, callback
|
||||
from okapi_tokens
|
||||
where
|
||||
consumer_key = '".mysql_real_escape_string($consumer->key)."'
|
||||
and token_type = '".mysql_real_escape_string($token_type)."'
|
||||
and `key` = '".mysql_real_escape_string($token)."'
|
||||
");
|
||||
if (!$row)
|
||||
return null;
|
||||
switch ($row['token_type'])
|
||||
{
|
||||
case 'request':
|
||||
return new OkapiRequestToken($row['key'], $row['secret'],
|
||||
$row['consumer_key'], $row['callback'], $row['user_id'],
|
||||
$row['verifier']);
|
||||
case 'access':
|
||||
return new OkapiAccessToken($row['key'], $row['secret'],
|
||||
$row['consumer_key'], $row['user_id']);
|
||||
default:
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
public function lookup_token($consumer, $token_type, $token)
|
||||
{
|
||||
$row = Db::select_row("
|
||||
select `key`, consumer_key, secret, token_type, user_id, verifier, callback
|
||||
from okapi_tokens
|
||||
where
|
||||
consumer_key = '".mysql_real_escape_string($consumer->key)."'
|
||||
and token_type = '".mysql_real_escape_string($token_type)."'
|
||||
and `key` = '".mysql_real_escape_string($token)."'
|
||||
");
|
||||
if (!$row)
|
||||
return null;
|
||||
switch ($row['token_type'])
|
||||
{
|
||||
case 'request':
|
||||
return new OkapiRequestToken($row['key'], $row['secret'],
|
||||
$row['consumer_key'], $row['callback'], $row['user_id'],
|
||||
$row['verifier']);
|
||||
case 'access':
|
||||
return new OkapiAccessToken($row['key'], $row['secret'],
|
||||
$row['consumer_key'], $row['user_id']);
|
||||
default:
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
public function lookup_nonce($consumer, $token, $nonce, $timestamp)
|
||||
{
|
||||
# Since it's not important for us to save the actual token and nonce
|
||||
# value, we will save a hash only. We could also include the consumer
|
||||
# key in this hash and drop the column, but we will leave it be for
|
||||
# now (for a couple of less important reasons).
|
||||
public function lookup_nonce($consumer, $token, $nonce, $timestamp)
|
||||
{
|
||||
# Since it's not important for us to save the actual token and nonce
|
||||
# value, we will save a hash only. We could also include the consumer
|
||||
# key in this hash and drop the column, but we will leave it be for
|
||||
# now (for a couple of less important reasons).
|
||||
|
||||
$nonce_hash = md5(serialize(array(
|
||||
$token ? $token->key : null,
|
||||
$timestamp,
|
||||
$nonce
|
||||
)));
|
||||
try
|
||||
{
|
||||
# Time timestamp is saved separately, because we are periodically
|
||||
# removing older nonces from the database (see cronjobs).
|
||||
$nonce_hash = md5(serialize(array(
|
||||
$token ? $token->key : null,
|
||||
$timestamp,
|
||||
$nonce
|
||||
)));
|
||||
try
|
||||
{
|
||||
# Time timestamp is saved separately, because we are periodically
|
||||
# removing older nonces from the database (see cronjobs).
|
||||
|
||||
Db::execute("
|
||||
insert into okapi_nonces (consumer_key, nonce_hash, timestamp)
|
||||
values (
|
||||
'".mysql_real_escape_string($consumer->key)."',
|
||||
'".mysql_real_escape_string($nonce_hash)."',
|
||||
'".mysql_real_escape_string($timestamp)."'
|
||||
);
|
||||
");
|
||||
return null;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
# INSERT failed. This nonce was already used.
|
||||
Db::execute("
|
||||
insert into okapi_nonces (consumer_key, nonce_hash, timestamp)
|
||||
values (
|
||||
'".mysql_real_escape_string($consumer->key)."',
|
||||
'".mysql_real_escape_string($nonce_hash)."',
|
||||
'".mysql_real_escape_string($timestamp)."'
|
||||
);
|
||||
");
|
||||
return null;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
# INSERT failed. This nonce was already used.
|
||||
|
||||
return $nonce;
|
||||
}
|
||||
}
|
||||
return $nonce;
|
||||
}
|
||||
}
|
||||
|
||||
public function new_request_token($consumer, $callback = null)
|
||||
{
|
||||
if ((preg_match("#^[a-z][a-z0-9_.-]*://#", $callback) > 0) ||
|
||||
$callback == "oob")
|
||||
{ /* ok */ }
|
||||
else { throw new BadRequest("oauth_callback should begin with <scheme>://, or should equal 'oob'."); }
|
||||
$token = new OkapiRequestToken(Okapi::generate_key(20), Okapi::generate_key(40),
|
||||
$consumer->key, $callback, null, Okapi::generate_key(8, true));
|
||||
Db::execute("
|
||||
insert into okapi_tokens
|
||||
(`key`, secret, token_type, timestamp,
|
||||
user_id, consumer_key, verifier, callback)
|
||||
values (
|
||||
'".mysql_real_escape_string($token->key)."',
|
||||
'".mysql_real_escape_string($token->secret)."',
|
||||
'request',
|
||||
unix_timestamp(),
|
||||
null,
|
||||
'".mysql_real_escape_string($consumer->key)."',
|
||||
'".mysql_real_escape_string($token->verifier)."',
|
||||
".(($token->callback_url == 'oob')
|
||||
? "null"
|
||||
: "'".mysql_real_escape_string($token->callback_url)."'"
|
||||
)."
|
||||
);
|
||||
");
|
||||
return $token;
|
||||
}
|
||||
public function new_request_token($consumer, $callback = null)
|
||||
{
|
||||
if ((preg_match("#^[a-z][a-z0-9_.-]*://#", $callback) > 0) ||
|
||||
$callback == "oob")
|
||||
{ /* ok */ }
|
||||
else { throw new BadRequest("oauth_callback should begin with lower case <scheme>://, or should equal 'oob'."); }
|
||||
$token = new OkapiRequestToken(Okapi::generate_key(20), Okapi::generate_key(40),
|
||||
$consumer->key, $callback, null, Okapi::generate_key(8, true));
|
||||
Db::execute("
|
||||
insert into okapi_tokens
|
||||
(`key`, secret, token_type, timestamp,
|
||||
user_id, consumer_key, verifier, callback)
|
||||
values (
|
||||
'".mysql_real_escape_string($token->key)."',
|
||||
'".mysql_real_escape_string($token->secret)."',
|
||||
'request',
|
||||
unix_timestamp(),
|
||||
null,
|
||||
'".mysql_real_escape_string($consumer->key)."',
|
||||
'".mysql_real_escape_string($token->verifier)."',
|
||||
".(($token->callback_url == 'oob')
|
||||
? "null"
|
||||
: "'".mysql_real_escape_string($token->callback_url)."'"
|
||||
)."
|
||||
);
|
||||
");
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function new_access_token($token, $consumer, $verifier = null)
|
||||
{
|
||||
if ($token->consumer_key != $consumer->key)
|
||||
throw new BadRequest("Request Token given is not associated with the Consumer who signed the request.");
|
||||
if (!$token->authorized_by_user_id)
|
||||
throw new BadRequest("Request Token given has not been authorized.");
|
||||
if ($token->verifier != $verifier)
|
||||
throw new BadRequest("Invalid verifier.");
|
||||
public function new_access_token($token, $consumer, $verifier = null)
|
||||
{
|
||||
if ($token->consumer_key != $consumer->key)
|
||||
throw new BadRequest("Request Token given is not associated with the Consumer who signed the request.");
|
||||
if (!$token->authorized_by_user_id)
|
||||
throw new BadRequest("Request Token given has not been authorized.");
|
||||
if ($token->verifier != $verifier)
|
||||
throw new BadRequest("Invalid verifier.");
|
||||
|
||||
# Invalidate the Request Token.
|
||||
# Invalidate the Request Token.
|
||||
|
||||
Db::execute("
|
||||
delete from okapi_tokens
|
||||
where `key` = '".mysql_real_escape_string($token->key)."'
|
||||
");
|
||||
Db::execute("
|
||||
delete from okapi_tokens
|
||||
where `key` = '".mysql_real_escape_string($token->key)."'
|
||||
");
|
||||
|
||||
# In OKAPI, all Access Tokens are long lived. Therefore, we don't want
|
||||
# to generate a new one every time a Consumer wants it. We will check
|
||||
# if there is already an Access Token generated for this (Consumer, User)
|
||||
# pair and return it if there is.
|
||||
# In OKAPI, all Access Tokens are long lived. Therefore, we don't want
|
||||
# to generate a new one every time a Consumer wants it. We will check
|
||||
# if there is already an Access Token generated for this (Consumer, User)
|
||||
# pair and return it if there is.
|
||||
|
||||
$row = Db::select_row("
|
||||
select `key`, secret
|
||||
from okapi_tokens
|
||||
where
|
||||
token_type = 'access'
|
||||
and user_id = '".mysql_real_escape_string($token->authorized_by_user_id)."'
|
||||
and consumer_key = '".mysql_real_escape_string($consumer->key)."'
|
||||
");
|
||||
if ($row)
|
||||
{
|
||||
# Use existing Access Token
|
||||
$row = Db::select_row("
|
||||
select `key`, secret
|
||||
from okapi_tokens
|
||||
where
|
||||
token_type = 'access'
|
||||
and user_id = '".mysql_real_escape_string($token->authorized_by_user_id)."'
|
||||
and consumer_key = '".mysql_real_escape_string($consumer->key)."'
|
||||
");
|
||||
if ($row)
|
||||
{
|
||||
# Use existing Access Token
|
||||
|
||||
$access_token = new OkapiAccessToken($row['key'], $row['secret'],
|
||||
$consumer->key, $token->authorized_by_user_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
# Generate a new Access Token.
|
||||
$access_token = new OkapiAccessToken($row['key'], $row['secret'],
|
||||
$consumer->key, $token->authorized_by_user_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
# Generate a new Access Token.
|
||||
|
||||
$access_token = new OkapiAccessToken(Okapi::generate_key(20), Okapi::generate_key(40),
|
||||
$consumer->key, $token->authorized_by_user_id);
|
||||
Db::execute("
|
||||
insert into okapi_tokens
|
||||
(`key`, secret, token_type, timestamp, user_id, consumer_key)
|
||||
values (
|
||||
'".mysql_real_escape_string($access_token->key)."',
|
||||
'".mysql_real_escape_string($access_token->secret)."',
|
||||
'access',
|
||||
unix_timestamp(),
|
||||
'".mysql_real_escape_string($access_token->user_id)."',
|
||||
'".mysql_real_escape_string($consumer->key)."'
|
||||
);
|
||||
");
|
||||
}
|
||||
return $access_token;
|
||||
}
|
||||
$access_token = new OkapiAccessToken(Okapi::generate_key(20), Okapi::generate_key(40),
|
||||
$consumer->key, $token->authorized_by_user_id);
|
||||
Db::execute("
|
||||
insert into okapi_tokens
|
||||
(`key`, secret, token_type, timestamp, user_id, consumer_key)
|
||||
values (
|
||||
'".mysql_real_escape_string($access_token->key)."',
|
||||
'".mysql_real_escape_string($access_token->secret)."',
|
||||
'access',
|
||||
unix_timestamp(),
|
||||
'".mysql_real_escape_string($access_token->user_id)."',
|
||||
'".mysql_real_escape_string($consumer->key)."'
|
||||
);
|
||||
");
|
||||
}
|
||||
return $access_token;
|
||||
}
|
||||
|
||||
public function cleanup()
|
||||
{
|
||||
Db::execute("
|
||||
delete from okapi_nonces
|
||||
where
|
||||
timestamp < unix_timestamp(date_add(now(), interval -6 minute))
|
||||
or timestamp > unix_timestamp(date_add(now(), interval 6 minute))
|
||||
");
|
||||
Db::execute("
|
||||
delete from okapi_tokens
|
||||
where
|
||||
token_type = 'request'
|
||||
and timestamp < unix_timestamp(date_add(now(), interval -2 hour))
|
||||
");
|
||||
}
|
||||
public function cleanup()
|
||||
{
|
||||
Db::execute("
|
||||
delete from okapi_nonces
|
||||
where
|
||||
timestamp < unix_timestamp(date_add(now(), interval -6 minute))
|
||||
or timestamp > unix_timestamp(date_add(now(), interval 6 minute))
|
||||
");
|
||||
Db::execute("
|
||||
delete from okapi_tokens
|
||||
where
|
||||
token_type = 'request'
|
||||
and timestamp < unix_timestamp(date_add(now(), interval -2 hour))
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ use okapi\OkapiServiceRunner;
|
||||
use okapi\OkapiInternalRequest;
|
||||
use okapi\OkapiFacadeConsumer;
|
||||
use okapi\OkapiFacadeAccessToken;
|
||||
use okapi\Cache;
|
||||
|
||||
require_once($GLOBALS['rootpath']."okapi/core.php");
|
||||
OkapiErrorHandler::$treat_notices_as_errors = true;
|
||||
@@ -45,131 +46,214 @@ Okapi::init_internals();
|
||||
*/
|
||||
class Facade
|
||||
{
|
||||
/**
|
||||
* Perform OKAPI service call, signed by internal 'facade' consumer key, and return the result
|
||||
* (this will be PHP object or OkapiHttpResponse, depending on the method). Use this method
|
||||
* whenever you need to access OKAPI services from within OC code. If you want to simulate
|
||||
* Level 3 Authentication, you should supply user's internal ID (the second parameter).
|
||||
*/
|
||||
public static function service_call($service_name, $user_id_or_null, $parameters)
|
||||
{
|
||||
$request = new OkapiInternalRequest(
|
||||
new OkapiFacadeConsumer(),
|
||||
($user_id_or_null !== null) ? new OkapiFacadeAccessToken($user_id_or_null) : null,
|
||||
$parameters
|
||||
);
|
||||
$request->perceive_as_http_request = true;
|
||||
return OkapiServiceRunner::call($service_name, $request);
|
||||
}
|
||||
/**
|
||||
* Perform OKAPI service call, signed by internal 'facade' consumer key, and return the result
|
||||
* (this will be PHP object or OkapiHttpResponse, depending on the method). Use this method
|
||||
* whenever you need to access OKAPI services from within OC code. If you want to simulate
|
||||
* Level 3 Authentication, you should supply user's internal ID (the second parameter).
|
||||
*/
|
||||
public static function service_call($service_name, $user_id_or_null, $parameters)
|
||||
{
|
||||
$request = new OkapiInternalRequest(
|
||||
new OkapiFacadeConsumer(),
|
||||
($user_id_or_null !== null) ? new OkapiFacadeAccessToken($user_id_or_null) : null,
|
||||
$parameters
|
||||
);
|
||||
$request->perceive_as_http_request = true;
|
||||
return OkapiServiceRunner::call($service_name, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* This works like service_call with two exceptions: 1. It passes all your
|
||||
* current HTTP request headers to OKAPI (which can make use of them in
|
||||
* terms of caching), 2. It outputs the service response directly, instead
|
||||
* of returning it.
|
||||
*/
|
||||
public static function service_display($service_name, $user_id_or_null, $parameters)
|
||||
{
|
||||
$request = new OkapiInternalRequest(
|
||||
new OkapiFacadeConsumer(),
|
||||
($user_id_or_null !== null) ? new OkapiFacadeAccessToken($user_id_or_null) : null,
|
||||
$parameters
|
||||
);
|
||||
$request->perceive_as_http_request = true;
|
||||
if (isset($_SERVER['HTTP_IF_NONE_MATCH']))
|
||||
$request->etag = $_SERVER['HTTP_IF_NONE_MATCH'];
|
||||
$response = OkapiServiceRunner::call($service_name, $request);
|
||||
$response->display();
|
||||
}
|
||||
/**
|
||||
* This works like service_call with two exceptions: 1. It passes all your
|
||||
* current HTTP request headers to OKAPI (which can make use of them in
|
||||
* terms of caching), 2. It outputs the service response directly, instead
|
||||
* of returning it.
|
||||
*/
|
||||
public static function service_display($service_name, $user_id_or_null, $parameters)
|
||||
{
|
||||
$request = new OkapiInternalRequest(
|
||||
new OkapiFacadeConsumer(),
|
||||
($user_id_or_null !== null) ? new OkapiFacadeAccessToken($user_id_or_null) : null,
|
||||
$parameters
|
||||
);
|
||||
$request->perceive_as_http_request = true;
|
||||
if (isset($_SERVER['HTTP_IF_NONE_MATCH']))
|
||||
$request->etag = $_SERVER['HTTP_IF_NONE_MATCH'];
|
||||
$response = OkapiServiceRunner::call($service_name, $request);
|
||||
$response->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a search set from a temporary table. This is very similar to
|
||||
* the "services/caches/search/save" method, but allows OC server to
|
||||
* include its own result instead of using OKAPI's search options. The
|
||||
* $temp_table should be a valid name of a temporary table with the
|
||||
* following (or similar) structure:
|
||||
*
|
||||
* create temporary table temp_12345 (
|
||||
* cache_id integer primary key
|
||||
* ) engine=memory;
|
||||
*/
|
||||
public static function import_search_set($temp_table, $min_store, $max_ref_age)
|
||||
{
|
||||
require_once 'services/caches/search/save.php';
|
||||
$tables = array('caches', $temp_table);
|
||||
$where_conds = array(
|
||||
$temp_table.".cache_id = caches.cache_id",
|
||||
'caches.status in (1,2,3)',
|
||||
);
|
||||
return \okapi\services\caches\search\save\WebService::get_set(
|
||||
$tables, $where_conds, $min_store, $max_ref_age
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Create a search set from a temporary table. This is very similar to
|
||||
* the "services/caches/search/save" method, but allows OC server to
|
||||
* include its own result instead of using OKAPI's search options. The
|
||||
* $temp_table should be a valid name of a temporary table with the
|
||||
* following (or similar) structure:
|
||||
*
|
||||
* create temporary table temp_12345 (
|
||||
* cache_id integer primary key
|
||||
* ) engine=memory;
|
||||
*/
|
||||
public static function import_search_set($temp_table, $min_store, $max_ref_age)
|
||||
{
|
||||
require_once($GLOBALS['rootpath'].'okapi/services/caches/search/save.php');
|
||||
$tables = array('caches', $temp_table);
|
||||
$where_conds = array(
|
||||
$temp_table.".cache_id = caches.cache_id",
|
||||
'caches.status in (1,2,3)',
|
||||
);
|
||||
return \okapi\services\caches\search\save\WebService::get_set(
|
||||
$tables, $where_conds, $min_store, $max_ref_age
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the specified caches as *possibly* modified. The replicate module
|
||||
* will scan for changes within these caches on the next changelog update.
|
||||
* This is useful in some cases, when OKAPI cannot detect the modification
|
||||
* for itself (grep OCPL code for examples). See issue #179.
|
||||
*
|
||||
* $cache_codes - a single cache code OR an array of cache codes.
|
||||
*/
|
||||
public static function schedule_geocache_check($cache_codes)
|
||||
{
|
||||
if (!is_array($cache_codes))
|
||||
$cache_codes = array($cache_codes);
|
||||
Db::execute("
|
||||
update caches
|
||||
set okapi_syncbase = now()
|
||||
where wp_oc in ('".implode("','", array_map('mysql_real_escape_string', $cache_codes))."')
|
||||
");
|
||||
}
|
||||
/**
|
||||
* Mark the specified caches as *possibly* modified. The replicate module
|
||||
* will scan for changes within these caches on the next changelog update.
|
||||
* This is useful in some cases, when OKAPI cannot detect the modification
|
||||
* for itself (grep OCPL code for examples). See issue #179.
|
||||
*
|
||||
* $cache_codes - a single cache code OR an array of cache codes.
|
||||
*/
|
||||
public static function schedule_geocache_check($cache_codes)
|
||||
{
|
||||
if (!is_array($cache_codes))
|
||||
$cache_codes = array($cache_codes);
|
||||
Db::execute("
|
||||
update caches
|
||||
set okapi_syncbase = now()
|
||||
where wp_oc in ('".implode("','", array_map('mysql_real_escape_string', $cache_codes))."')
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all log entries of the specified user for the specified cache and
|
||||
* mark them as *possibly* modified. See issue #265.
|
||||
*
|
||||
* $cache_id - internal ID of the geocache,
|
||||
* $user_id - internal ID of the user.
|
||||
*/
|
||||
public static function schedule_user_entries_check($cache_id, $user_id)
|
||||
{
|
||||
Db::execute("
|
||||
update cache_logs
|
||||
set okapi_syncbase = now()
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($cache_id)."'
|
||||
and user_id = '".mysql_real_escape_string($user_id)."'
|
||||
");
|
||||
}
|
||||
/**
|
||||
* Find all log entries of the specified user for the specified cache and
|
||||
* mark them as *possibly* modified. See issue #265.
|
||||
*
|
||||
* $cache_id - internal ID of the geocache,
|
||||
* $user_id - internal ID of the user.
|
||||
*/
|
||||
public static function schedule_user_entries_check($cache_id, $user_id)
|
||||
{
|
||||
Db::execute("
|
||||
update cache_logs
|
||||
set okapi_syncbase = now()
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($cache_id)."'
|
||||
and user_id = '".mysql_real_escape_string($user_id)."'
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run OKAPI database update.
|
||||
* Will output messages to stdout.
|
||||
*/
|
||||
public static function database_update()
|
||||
{
|
||||
require_once($GLOBALS['rootpath']."okapi/views/update.php");
|
||||
$update = new views\update\View;
|
||||
$update->call();
|
||||
}
|
||||
/**
|
||||
* Run OKAPI database update.
|
||||
* Will output messages to stdout.
|
||||
*/
|
||||
public static function database_update()
|
||||
{
|
||||
require_once($GLOBALS['rootpath']."okapi/views/update.php");
|
||||
$update = new views\update\View;
|
||||
$update->call();
|
||||
}
|
||||
|
||||
/**
|
||||
* You will probably want to call that with FALSE when using Facade
|
||||
* in buggy, legacy OC code. This will disable OKAPI's default behavior
|
||||
* of treating NOTICEs as errors.
|
||||
*/
|
||||
public static function disable_error_handling()
|
||||
{
|
||||
OkapiErrorHandler::disable();
|
||||
}
|
||||
/**
|
||||
* You will probably want to call that with FALSE when using Facade
|
||||
* in buggy, legacy OC code. This will disable OKAPI's default behavior
|
||||
* of treating NOTICEs as errors.
|
||||
*/
|
||||
public static function disable_error_handling()
|
||||
{
|
||||
OkapiErrorHandler::disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* If you disabled OKAPI's error handling with disable_error_handling,
|
||||
* you may reenable it with this method.
|
||||
*/
|
||||
public static function reenable_error_handling()
|
||||
{
|
||||
OkapiErrorHandler::reenable();
|
||||
}
|
||||
/**
|
||||
* If you disabled OKAPI's error handling with disable_error_handling,
|
||||
* you may reenable it with this method.
|
||||
*/
|
||||
public static function reenable_error_handling()
|
||||
{
|
||||
OkapiErrorHandler::reenable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the object $value in OKAPI's cache, under the name of $key.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* $key -- must be a string of max 57 characters in length (you can use
|
||||
* md5(...) to shorten your keys). Use the same $key to retrieve your
|
||||
* value later.
|
||||
*
|
||||
* $value -- can be any serializable PHP object. Currently there's no
|
||||
* strict size limit, but try to keep it below 1 MB (for future
|
||||
* compatibility with memcached).
|
||||
*
|
||||
* $timeout -- *maximum* time allowed to store the value, given in seconds
|
||||
* (however, the value *can* be removed sooner than that, see the note
|
||||
* below). Timeout can be also set to null, but you should avoid this,
|
||||
* because such objects may clutter the cache unnecessarilly. (You must
|
||||
* remember to remove them yourself!)
|
||||
*
|
||||
* Please note, that this cache is not guaranteed to be persistent.
|
||||
* Usually it is, but it can be emptied in case of emergency (low disk
|
||||
* space), or if we decide to switch the underlying cache engine in the
|
||||
* future (e.g. to memcached). Most of your values should be safe though.
|
||||
*/
|
||||
public static function cache_set($key, $value, $timeout)
|
||||
{
|
||||
Cache::set("facade#".$key, $value, $timeout);
|
||||
}
|
||||
|
||||
/** Same as `cache_set`, but works on many key->value pair at once. */
|
||||
public static function cache_set_many($dict, $timeout)
|
||||
{
|
||||
$prefixed_dict = array();
|
||||
foreach ($dict as $key => &$value_ref) {
|
||||
$prefixed_dict["facade#".$key] = &$value_ref;
|
||||
}
|
||||
Cache::set_many($prefixed_dict, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve object stored in cache under the name of $key. If object does
|
||||
* not exist or its timeout has expired, return null.
|
||||
*/
|
||||
public static function cache_get($key)
|
||||
{
|
||||
return Cache::get("facade#".$key);
|
||||
}
|
||||
|
||||
/** Same as `cache_get`, but it works on multiple keys at once. */
|
||||
public static function get_many($keys)
|
||||
{
|
||||
$prefixed_keys = array();
|
||||
foreach ($keys as $key) {
|
||||
$prefixed_keys[] = "facade#".$key;
|
||||
}
|
||||
$prefixed_result = Cache::get_many($prefixed_keys);
|
||||
$result = array();
|
||||
foreach ($prefixed_result as $prefixed_key => &$value_ref) {
|
||||
$result[substr($prefixed_key, 7)] = &$value_ref;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the entry named $key from the cache.
|
||||
*/
|
||||
public static function cache_delete($key)
|
||||
{
|
||||
Cache::delete("facade#".$key);
|
||||
}
|
||||
|
||||
/** Same as `cache_delete`, but works on many keys at once. */
|
||||
public static function cache_delete_many($keys)
|
||||
{
|
||||
$prefixed_keys = array();
|
||||
foreach ($keys as $key) {
|
||||
$prefixed_keys[] = "facade#".$key;
|
||||
}
|
||||
Cache::delete_many($prefixed_keys);
|
||||
}
|
||||
}
|
||||
|
||||
# (This comment is added here simply to debug OKAPI deployment.....)
|
||||
|
||||
@@ -8,23 +8,23 @@ namespace okapi;
|
||||
*/
|
||||
class OCSession
|
||||
{
|
||||
/** Return ID of currently logged in user or NULL if no user is logged in. */
|
||||
public static function get_user_id()
|
||||
{
|
||||
static $cached_result = false;
|
||||
if ($cached_result !== false)
|
||||
return $cached_result;
|
||||
/** Return ID of currently logged in user or NULL if no user is logged in. */
|
||||
public static function get_user_id()
|
||||
{
|
||||
static $cached_result = false;
|
||||
if ($cached_result !== false)
|
||||
return $cached_result;
|
||||
|
||||
$cookie_name = Settings::get('OC_COOKIE_NAME');
|
||||
if (!isset($_COOKIE[$cookie_name]))
|
||||
return null;
|
||||
$OC_data = unserialize(base64_decode($_COOKIE[$cookie_name]));
|
||||
if (!isset($OC_data['sessionid']))
|
||||
return null;
|
||||
$OC_sessionid = $OC_data['sessionid'];
|
||||
if (!$OC_sessionid)
|
||||
return null;
|
||||
$cookie_name = Settings::get('OC_COOKIE_NAME');
|
||||
if (!isset($_COOKIE[$cookie_name]))
|
||||
return null;
|
||||
$OC_data = unserialize(base64_decode($_COOKIE[$cookie_name]));
|
||||
if (!isset($OC_data['sessionid']))
|
||||
return null;
|
||||
$OC_sessionid = $OC_data['sessionid'];
|
||||
if (!$OC_sessionid)
|
||||
return null;
|
||||
|
||||
return Db::select_value("select user_id from sys_sessions where uuid='".mysql_real_escape_string($OC_sessionid)."'");
|
||||
}
|
||||
return Db::select_value("select user_id from sys_sessions where uuid='".mysql_real_escape_string($OC_sessionid)."'");
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OKAPI\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-10 12:30+0100\n"
|
||||
"PO-Revision-Date: 2013-07-10 12:31+0100\n"
|
||||
"Last-Translator: following <following@online.de>\n"
|
||||
"POT-Creation-Date: 2014-01-23 15:51+0100\n"
|
||||
"PO-Revision-Date: 2014-01-23 15:52+0100\n"
|
||||
"Last-Translator: Wojciech Rygielski <rygielski@mimuw.edu.pl>\n"
|
||||
"Language-Team: following <following@online.de>\n"
|
||||
"Language: German\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -14,20 +14,29 @@ msgstr ""
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Generator: Poedit 1.5.5\n"
|
||||
"X-Generator: Poedit 1.6.3\n"
|
||||
"X-Poedit-SearchPath-0: c:\\source\\oc\\server-3.0\\htdocs\\okapi\n"
|
||||
"X-Poedit-SearchPath-1: D:\\PRIV\\Projekty\\EclipseWorkspace\\opencaching-api"
|
||||
"\\okapi\n"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/geocaches.php:956
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:957
|
||||
msgid "Stage"
|
||||
msgstr "Station"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/geocaches.php:1108
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:986
|
||||
msgid "User location"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:989
|
||||
#, php-format
|
||||
msgid "Your own custom coordinates for the %s geocache"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1148
|
||||
msgid "National Park / Landscape"
|
||||
msgstr "Nationalpark / Landschaft"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/geocaches.php:1260
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1300
|
||||
#, php-format
|
||||
msgid ""
|
||||
"This <a href='%s'>geocache</a> description comes from the <a href='%s'>%s</"
|
||||
@@ -35,7 +44,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Diese <a href='%s'>Cache</a>-Beschreibung stammt von <a href='%s'>%s</a>."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/geocaches.php:1272
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1312
|
||||
#, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
@@ -46,7 +55,7 @@ msgstr ""
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/de/'>CC-BY-NC-ND</a>, Stand: %s; "
|
||||
"alle Logeinträge © jeweiliger Autor"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/geocaches.php:1283
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1323
|
||||
#, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
@@ -57,63 +66,84 @@ msgstr ""
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/de/'>CC-BY-NC-ND</a>; alle "
|
||||
"Logeinträge © jeweiliger Autor"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:31
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:60
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:360
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> They have been replaced with "
|
||||
"your own custom coordinates which you have provided for this geocache."
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:366
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> Currently they point to one "
|
||||
"of the alternate waypoints originally described as:"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:379
|
||||
msgid "Original geocache location"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:381
|
||||
#, php-format
|
||||
msgid "Original (owner-supplied) location of the %s geocache"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:30
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:62
|
||||
msgid "hidden by"
|
||||
msgstr "versteckt von"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:62
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:64
|
||||
#, php-format
|
||||
msgid "%d recommendation"
|
||||
msgid_plural "%d recommendations"
|
||||
msgstr[0] "%d Empfehlung"
|
||||
msgstr[1] "%d Empfehlungen"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:63
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:65
|
||||
#, php-format
|
||||
msgid "found %d time"
|
||||
msgid_plural "found %d times"
|
||||
msgstr[0] "%d mal gefunden"
|
||||
msgstr[1] "%d mal gefunden"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:66
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:68
|
||||
#, php-format
|
||||
msgid "%d trackable"
|
||||
msgid_plural "%d trackables"
|
||||
msgstr[0] "%d Geokret"
|
||||
msgstr[1] "%d Geokrets"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:70
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:72
|
||||
msgid "Personal notes"
|
||||
msgstr "Persönliche Notizen"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:74
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:76
|
||||
msgid "Attributes"
|
||||
msgstr "Attribute"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:78
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:80
|
||||
msgid "Trackables"
|
||||
msgstr "Geokrets"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:88
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:104
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:90
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:106
|
||||
msgid "Images"
|
||||
msgstr "Bilder"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:111
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:113
|
||||
msgid "Spoilers"
|
||||
msgstr "Spoiler"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:120
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:122
|
||||
msgid "Image descriptions"
|
||||
msgstr "Bildbeschreibungen"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/caches/formatters/gpxfile.tpl.php:128
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:130
|
||||
msgid "The cache probably is located in the following protection areas:"
|
||||
msgstr ""
|
||||
"Der Geocache befindet sich wahrscheinlich in den folgenden Schutzgebieten:"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:70
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:70
|
||||
msgid ""
|
||||
"You are trying to publish a log entry with a date in future. Cache log "
|
||||
"entries are allowed to be published in the past, but NOT in the future."
|
||||
@@ -121,7 +151,7 @@ msgstr ""
|
||||
"Das Datum deines Logeintrags liegt in der Zukunft. Cache-Logs können nur für "
|
||||
"die Vergangenheit oder für heute eingetragen werden."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:92
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:92
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your cache rating was ignored, because %s does not have a rating "
|
||||
@@ -129,7 +159,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Deine Cachewertung wurde jedoch ignoriert, weil %s kein Bewertungssystem hat."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:111
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:111
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your cache recommendation was ignored, because %s does not allow "
|
||||
@@ -138,7 +168,7 @@ msgstr ""
|
||||
"Deine Empfehlung wurde jedoch ignoriert, weil auf %s keine Event-Caches "
|
||||
"empfohlen werden können."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:125
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:125
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your \"needs maintenance\" flag was ignored, because %s does not "
|
||||
@@ -147,7 +177,7 @@ msgstr ""
|
||||
"Deine Angabe \"benötigt Wartung\" wurde jedoch ignoriert, weil es diese "
|
||||
"Funktion bei %s nicht gibt."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:145
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:145
|
||||
msgid ""
|
||||
"This cache is an Event cache. You cannot \"Find\" it (but you can attend it, "
|
||||
"or comment on it)!"
|
||||
@@ -155,7 +185,7 @@ msgstr ""
|
||||
"Dies ist ein Event-Cache. Du kannst ihn nicht \"finden\" (aber du kannst am "
|
||||
"Event teilnehmen oder einen Hinweis loggen)."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:150
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:150
|
||||
msgid ""
|
||||
"This cache is NOT an Event cache. You cannot \"Attend\" it (but you can find "
|
||||
"it, or comment on it)!"
|
||||
@@ -163,26 +193,26 @@ msgstr ""
|
||||
"Dies ist KEIN Event-Cache. Du kannst an ihm nicht \"teilnehmen\" (aber du "
|
||||
"kannst ihn finden oder kommentieren)."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:155
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:155
|
||||
msgid "Your have to supply some text for your comment."
|
||||
msgstr "Du musst einen Text für dein Hinweislog eingeben!"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:168
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:168
|
||||
msgid "This cache requires a password. You didn't provide one!"
|
||||
msgstr ""
|
||||
"Dieser Cache kann nur mit Kennwort geloggt werden, aber du hast keines "
|
||||
"angegeben."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:170
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:170
|
||||
msgid "Invalid password!"
|
||||
msgstr "Ungültiges Kennwort!"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:282
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:285
|
||||
msgid "You have already submitted a log entry with exactly the same contents."
|
||||
msgstr ""
|
||||
"Du hast bereits einen Logeintrag mit genau dem gleichen Inhalt gemacht."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:305
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:308
|
||||
msgid ""
|
||||
"You have already submitted a \"Found it\" log entry once. Now you may submit "
|
||||
"\"Comments\" only!"
|
||||
@@ -190,53 +220,53 @@ msgstr ""
|
||||
"Du hast diesen Cache bereits als gefunden geloggt. Ein zweites Fundlog ist "
|
||||
"nicht möglich, aber du kannst stattdessen einen Hinweis loggen."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:307
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:310
|
||||
msgid "You are the owner of this cache. You may submit \"Comments\" only!"
|
||||
msgstr ""
|
||||
"Als Besitzer des Caches kannst du nur Hinweise loggen, keine Funde oder "
|
||||
"Nichtfunde."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:325
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:328
|
||||
msgid "You have already rated this cache once. Your rating cannot be changed."
|
||||
msgstr ""
|
||||
"Du hast diesen Cache bereits bewertet. Deine Bewertung ist nicht änderbar."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:342
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:345
|
||||
msgid "You have already recommended this cache once."
|
||||
msgstr "Du hast diesen Cache bereits empfohlen."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:352
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:355
|
||||
msgid "You don't have any recommendations to give. Find more caches first!"
|
||||
msgstr ""
|
||||
"Du musst mehr Caches finden, um eine weitere Bewertung abgeben zu können!"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:395
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:398
|
||||
msgid "Event caches cannot \"need maintenance\"."
|
||||
msgstr "Event-Caches können keine \"Wartung benötigen\"."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/services/logs/submit.php:525
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:528
|
||||
msgid "Your cache log entry was posted successfully."
|
||||
msgstr "Dein Log wurde veröffentlicht."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:5
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:5
|
||||
msgid "Authorization Form"
|
||||
msgstr "Authorisierungs-Formular"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:46
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:46
|
||||
msgid "Expired request"
|
||||
msgstr "Anfrage abgelaufen"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:47
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:47
|
||||
msgid "Unfortunately, the request has expired. Please try again."
|
||||
msgstr ""
|
||||
"Die Anfrage ist wegen Zeitüberschreitung abgelaufen. Bitte versuche es noch "
|
||||
"einmal."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:49
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:49
|
||||
msgid "External application is requesting access..."
|
||||
msgstr "Eine externe Anwendung wünscht Zugriff ..."
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:50
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:50
|
||||
#, php-format
|
||||
msgid ""
|
||||
"<b>%s</b> wants to access your <b>%s</b> account. Do you agree to grant "
|
||||
@@ -245,28 +275,29 @@ msgstr ""
|
||||
"<b>%s</b> möchte auf dein <b>%s</b>-Benutzerkonto zugreifen. Möchtest du "
|
||||
"dieser Anwendung Zugriff gewähren?"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:53
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:53
|
||||
msgid "I agree"
|
||||
msgstr "Ja"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:54
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:54
|
||||
msgid "Decline"
|
||||
msgstr "Nein"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorize.tpl.php:56
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:56
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Once permission is granted it is valid until its withdrawal on\n"
|
||||
"\t\t\t\t\tthe <a href='%s'>applications management</a> page.</p>\n"
|
||||
"\t\t\t\t\t<p>The application will access your acount via <a href='%s'>the "
|
||||
"OKAPI Framework</a>.\n"
|
||||
"\t\t\t\t\tIf you allow this request application will be able to access all "
|
||||
"methods delivered\n"
|
||||
"\t\t\t\t\tby the OKAPI Framework, i.e. post log entries on geocaches in your "
|
||||
"name.\n"
|
||||
"\t\t\t\t\tYou can revoke this permission at any moment.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Once permission is granted it is valid until its "
|
||||
"withdrawal on\n"
|
||||
" the <a href='%s'>applications management</a> page.</p>\n"
|
||||
" <p>The application will access your acount via <a "
|
||||
"href='%s'>the OKAPI Framework</a>.\n"
|
||||
" If you allow this request application will be able to "
|
||||
"access all methods delivered\n"
|
||||
" by the OKAPI Framework, i.e. post log entries on "
|
||||
"geocaches in your name.\n"
|
||||
" You can revoke this permission at any moment.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Wenn die Erlaubnis erteilt wurde, ist sie so lange gültig, bis "
|
||||
@@ -281,23 +312,23 @@ msgstr ""
|
||||
"\t\t\t\t\tDu kannst diese Erlaubnis jederzeit widerrufen.</p>\n"
|
||||
"\t\t\t\t"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorized.tpl.php:5
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorized.tpl.php:5
|
||||
msgid "Authorization Succeeded"
|
||||
msgstr "Authorisierung erfolgreich"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorized.tpl.php:28
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorized.tpl.php:28
|
||||
msgid "Access successfully granted"
|
||||
msgstr "Zugang wurde gewährt"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/authorized.tpl.php:29
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorized.tpl.php:29
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t<p><b>You've just granted %s application access to your %s account.</"
|
||||
"b>\n"
|
||||
"\t\t\t\tTo complete the operation, go back to %s and enter the following PIN "
|
||||
"code:</p>\n"
|
||||
"\t\t\t"
|
||||
" <p><b>You've just granted %s application access to your %s "
|
||||
"account.</b>\n"
|
||||
" To complete the operation, go back to %s and enter the "
|
||||
"following PIN code:</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t<p><b>Du hast der Anwendung \"%s\" Zugriff auf dein %s-Benutzerkonto "
|
||||
@@ -306,26 +337,26 @@ msgstr ""
|
||||
"PIN-Code ein:</p>\n"
|
||||
"\t\t\t"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/index.tpl.php:5
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:5
|
||||
msgid "My Apps"
|
||||
msgstr "Meine Apps"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/index.tpl.php:29
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:29
|
||||
msgid "Your external applications"
|
||||
msgstr "Deine externen Anwendungen"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/index.tpl.php:31
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:31
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>This is the list of applications which you granted access to "
|
||||
"your <b>%s</b> account.\n"
|
||||
"\t\t\t\t\tThis page gives you the abbility to revoke all previously granted "
|
||||
"privileges.\n"
|
||||
"\t\t\t\t\tOnce you click \"remove\" the application will no longer be able "
|
||||
"to perform any\n"
|
||||
"\t\t\t\t\tactions on your behalf.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>This is the list of applications which you granted "
|
||||
"access to your <b>%s</b> account.\n"
|
||||
" This page gives you the abbility to revoke all "
|
||||
"previously granted privileges.\n"
|
||||
" Once you click \"remove\" the application will no longer "
|
||||
"be able to perform any\n"
|
||||
" actions on your behalf.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Dies ist eine Liste der Anwendungen, denen du Zugriff auf dein "
|
||||
@@ -336,21 +367,21 @@ msgstr ""
|
||||
"Aktionen mehr unter deinem \t\t\t\t\tBenutzername ausführen können.</p>\n"
|
||||
"\t\t\t\t"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/index.tpl.php:45
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:45
|
||||
msgid "remove"
|
||||
msgstr "entfernen"
|
||||
|
||||
#: c:\source\oc\server-3.0\htdocs\okapi/views/apps/index.tpl.php:50
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:50
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Thanks to the <a href='%s'>OKAPI Framework</a> you can grant "
|
||||
"external applications\n"
|
||||
"\t\t\t\t\taccess to your <b>%s</b> account. Currently no applications are "
|
||||
"authorized to act\n"
|
||||
"\t\t\t\t\ton your behalf. Once you start using external Opencaching "
|
||||
"applications, they will appear here.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Thanks to the <a href='%s'>OKAPI Framework</a> you "
|
||||
"can grant external applications\n"
|
||||
" access to your <b>%s</b> account. Currently no "
|
||||
"applications are authorized to act\n"
|
||||
" on your behalf. Once you start using external "
|
||||
"Opencaching applications, they will appear here.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Die <a href='%s'>OKAPI-Schnittstelle</a> ermöglichst es dir, "
|
||||
|
||||
@@ -2,11 +2,11 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OKAPI\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-19 08:41+0100\n"
|
||||
"PO-Revision-Date: 2013-07-19 08:46+0100\n"
|
||||
"Last-Translator: faina09 <stefanocotterli@gmail.com>\n"
|
||||
"POT-Creation-Date: 2014-01-23 15:53+0100\n"
|
||||
"PO-Revision-Date: 2014-01-23 16:04+0100\n"
|
||||
"Last-Translator: Wojciech Rygielski <rygielski@mimuw.edu.pl>\n"
|
||||
"Language-Team: following <following@online.de>\n"
|
||||
"Language: Italian\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -14,22 +14,31 @@ msgstr ""
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Generator: Poedit 1.5.7\n"
|
||||
"X-Generator: Poedit 1.6.3\n"
|
||||
"X-Poedit-SearchPath-0: c:\\source\\okapi\\following2\n"
|
||||
"X-Poedit-SearchPath-1: D:\\PRIV\\Projekty\\EclipseWorkspace\\opencaching-api"
|
||||
"\\okapi\n"
|
||||
"X-Poedit-SearchPath-2: C:\\Users\\stefano.cotterli\\Desktop\\opencaching-"
|
||||
"api\n"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/geocaches.php:956
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:957
|
||||
msgid "Stage"
|
||||
msgstr "Passo"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/geocaches.php:1111
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:986
|
||||
msgid "User location"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:989
|
||||
#, php-format
|
||||
msgid "Your own custom coordinates for the %s geocache"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1148
|
||||
msgid "National Park / Landscape"
|
||||
msgstr "Parco Nazionale / Paesaggio"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/geocaches.php:1263
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1300
|
||||
#, php-format
|
||||
msgid ""
|
||||
"This <a href='%s'>geocache</a> description comes from the <a href='%s'>%s</"
|
||||
@@ -38,7 +47,7 @@ msgstr ""
|
||||
"La deescrizione di questa <a href='%s'>geocache</a>proviene dal sito <a "
|
||||
"href='%s'>%s</a>."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/geocaches.php:1275
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1312
|
||||
#, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
@@ -46,7 +55,7 @@ msgid ""
|
||||
"%s; all log entries © their authors"
|
||||
msgstr ""
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/geocaches.php:1286
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/geocaches.php:1323
|
||||
#, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
@@ -54,62 +63,83 @@ msgid ""
|
||||
"log entries © their authors"
|
||||
msgstr ""
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:31
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:60
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:360
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> They have been replaced with "
|
||||
"your own custom coordinates which you have provided for this geocache."
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:366
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> Currently they point to one "
|
||||
"of the alternate waypoints originally described as:"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:379
|
||||
msgid "Original geocache location"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpx.php:381
|
||||
#, php-format
|
||||
msgid "Original (owner-supplied) location of the %s geocache"
|
||||
msgstr ""
|
||||
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:30
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:62
|
||||
msgid "hidden by"
|
||||
msgstr "nascosta da"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:62
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:64
|
||||
#, php-format
|
||||
msgid "%d recommendation"
|
||||
msgid_plural "%d recommendations"
|
||||
msgstr[0] "%d raccomandazione"
|
||||
msgstr[1] "%d raccomandazioni"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:63
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:65
|
||||
#, php-format
|
||||
msgid "found %d time"
|
||||
msgid_plural "found %d times"
|
||||
msgstr[0] "trovata %d volta"
|
||||
msgstr[1] "trovata %d volte"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:66
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:68
|
||||
#, php-format
|
||||
msgid "%d trackable"
|
||||
msgid_plural "%d trackables"
|
||||
msgstr[0] "%d travel bug"
|
||||
msgstr[1] "%d travel bugs"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:70
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:72
|
||||
msgid "Personal notes"
|
||||
msgstr "Note personali"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:74
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:76
|
||||
msgid "Attributes"
|
||||
msgstr "Attributi"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:78
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:80
|
||||
msgid "Trackables"
|
||||
msgstr "Travel bugs"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:88
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:104
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:90
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:106
|
||||
msgid "Images"
|
||||
msgstr "Immagini"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:111
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:113
|
||||
msgid "Spoilers"
|
||||
msgstr "Spoiler"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:120
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:122
|
||||
msgid "Image descriptions"
|
||||
msgstr "Descrizione immagine"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/caches/formatters/gpxfile.tpl.php:128
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/caches/formatters/gpxfile.tpl.php:130
|
||||
msgid "The cache probably is located in the following protection areas:"
|
||||
msgstr "La cache probabilmente è situata nelle seguenti aree protette:"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:70
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:70
|
||||
msgid ""
|
||||
"You are trying to publish a log entry with a date in future. Cache log "
|
||||
"entries are allowed to be published in the past, but NOT in the future."
|
||||
@@ -117,7 +147,7 @@ msgstr ""
|
||||
"Hai cercato di pubblicare un log con una data nel futuro. E' permsso loggare "
|
||||
"una cache con una data passata, ma NON futura."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:92
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:92
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your cache rating was ignored, because %s does not have a rating "
|
||||
@@ -126,7 +156,7 @@ msgstr ""
|
||||
"Tuttavia, la tua valutazione della cache sarà ignorata, perché %s non ha un "
|
||||
"sistema di valutazione."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:111
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:111
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your cache recommendation was ignored, because %s does not allow "
|
||||
@@ -135,7 +165,7 @@ msgstr ""
|
||||
"Tuttavia, la tua valutazione della cache sarà ignorata, perché %s non ha "
|
||||
"permette la valutazione di cache evento."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:125
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:125
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your \"needs maintenance\" flag was ignored, because %s does not "
|
||||
@@ -144,7 +174,7 @@ msgstr ""
|
||||
"Tuttavia, la tua segnalazione di \"manutenzione necessaria\" sarà ignorata, "
|
||||
"perché %s non supporta questa opzione."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:145
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:145
|
||||
msgid ""
|
||||
"This cache is an Event cache. You cannot \"Find\" it (but you can attend it, "
|
||||
"or comment on it)!"
|
||||
@@ -152,7 +182,7 @@ msgstr ""
|
||||
"Questa cache è una cache Evento. Non puoi \"Trovarla\" (ma puoi partecipare, "
|
||||
"o commentare l'evento)!"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:150
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:150
|
||||
msgid ""
|
||||
"This cache is NOT an Event cache. You cannot \"Attend\" it (but you can find "
|
||||
"it, or comment on it)!"
|
||||
@@ -160,23 +190,23 @@ msgstr ""
|
||||
"Questa cache NON è una cache Evento. Non puoi \"Partecipare\" (ma puoi "
|
||||
"trovarla, o inserirci un commento)!"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:155
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:155
|
||||
msgid "Your have to supply some text for your comment."
|
||||
msgstr "Devi inserire del testo per il tuo commento."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:168
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:168
|
||||
msgid "This cache requires a password. You didn't provide one!"
|
||||
msgstr "Questa cache richiede una password, ma non ne hai fornita nessuuna."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:170
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:170
|
||||
msgid "Invalid password!"
|
||||
msgstr "Password non valida!"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:282
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:285
|
||||
msgid "You have already submitted a log entry with exactly the same contents."
|
||||
msgstr "Hai già inserito un log esattamente con lo stesso contenuto."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:305
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:308
|
||||
msgid ""
|
||||
"You have already submitted a \"Found it\" log entry once. Now you may submit "
|
||||
"\"Comments\" only!"
|
||||
@@ -184,49 +214,49 @@ msgstr ""
|
||||
"Hai già inserito un log \"Trovata\". Adesso puoi inserire solamente "
|
||||
"\"Commenti\"!"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:307
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:310
|
||||
msgid "You are the owner of this cache. You may submit \"Comments\" only!"
|
||||
msgstr "Sei il proprietario della cache. Puoi inserire solamente \"Commenti\"!"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:325
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:328
|
||||
msgid "You have already rated this cache once. Your rating cannot be changed."
|
||||
msgstr ""
|
||||
"Hai giàvalutato questa cache. La tua valutazione non può essere cambiata."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:342
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:345
|
||||
msgid "You have already recommended this cache once."
|
||||
msgstr "Hai già raccmandato questa cache."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:352
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:355
|
||||
msgid "You don't have any recommendations to give. Find more caches first!"
|
||||
msgstr ""
|
||||
"Non hai possibilità di dare raccomandazioni. Prima devio trovare altre cache!"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:395
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:398
|
||||
msgid "Event caches cannot \"need maintenance\"."
|
||||
msgstr "Le cache evento non necessitano di manutenzione!"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/services/logs/submit.php:525
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/services/logs/submit.php:528
|
||||
msgid "Your cache log entry was posted successfully."
|
||||
msgstr "Il tuo log sulla cache è stato correttamente inserito."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:5
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:5
|
||||
msgid "Authorization Form"
|
||||
msgstr "Modulo di autorizzazione"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:46
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:46
|
||||
msgid "Expired request"
|
||||
msgstr "Richiesta scaduta"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:47
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:47
|
||||
msgid "Unfortunately, the request has expired. Please try again."
|
||||
msgstr "Sfortunatamente, la richiesta è scaduta. Per favore riprova."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:49
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:49
|
||||
msgid "External application is requesting access..."
|
||||
msgstr "Una applicazione esterna sta richiedendo l'accesso."
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:50
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:50
|
||||
#, php-format
|
||||
msgid ""
|
||||
"<b>%s</b> wants to access your <b>%s</b> account. Do you agree to grant "
|
||||
@@ -235,122 +265,118 @@ msgstr ""
|
||||
"<b>%s</b> vuole accedere al tuo account <b>%s</b>. Sei d'accordo nel "
|
||||
"concedere l'accesso a questa applicazione?"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:53
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:53
|
||||
msgid "I agree"
|
||||
msgstr "Sono d'accordo"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:54
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:54
|
||||
msgid "Decline"
|
||||
msgstr "No"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorize.tpl.php:56
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorize.tpl.php:56
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Once permission is granted it is valid until its withdrawal on\n"
|
||||
"\t\t\t\t\tthe <a href='%s'>applications management</a> page.</p>\n"
|
||||
"\t\t\t\t\t<p>The application will access your acount via <a href='%s'>the "
|
||||
"OKAPI Framework</a>.\n"
|
||||
"\t\t\t\t\tIf you allow this request application will be able to access all "
|
||||
"methods delivered\n"
|
||||
"\t\t\t\t\tby the OKAPI Framework, i.e. post log entries on geocaches in your "
|
||||
"name.\n"
|
||||
"\t\t\t\t\tYou can revoke this permission at any moment.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Once permission is granted it is valid until its "
|
||||
"withdrawal on\n"
|
||||
" the <a href='%s'>applications management</a> page.</p>\n"
|
||||
" <p>The application will access your acount via <a "
|
||||
"href='%s'>the OKAPI Framework</a>.\n"
|
||||
" If you allow this request application will be able to "
|
||||
"access all methods delivered\n"
|
||||
" by the OKAPI Framework, i.e. post log entries on "
|
||||
"geocaches in your name.\n"
|
||||
" You can revoke this permission at any moment.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Una volta concessa, l'autorizzazoine è valida finché non venga\n"
|
||||
"\t\t\t\t\trevocata nella pagina di <a href='%s'>gestione applicazioni</a>.</"
|
||||
"p>\n"
|
||||
"\t\t\t\t\t<p>L'applicazione accederà al tuo account tramite il <a "
|
||||
"href='%s'>frameword OKAPI</a>.\n"
|
||||
"\t\t\t\t\tSe permetti questa richiesta, l'applicazione potrà accedere a "
|
||||
"tutti i metodi forniti\n"
|
||||
"\t\t\t\t\tdal framework OKAPI, per es. postare i log delle geocache a tuo "
|
||||
"nome..\n"
|
||||
"\t\t\t\t\tPuoi revocare questo permesso in qualsiasi momento.</p>\n"
|
||||
"\t\t\t\t"
|
||||
"<p>Una volta concessa, l'autorizzazoine è valida finché non venga\n"
|
||||
"revocata nella pagina di <a href='%s'>gestione applicazioni</a>.</p>\n"
|
||||
"<p>L'applicazione accederà al tuo account tramite il <a href='%s'>frameword "
|
||||
"OKAPI</a>.\n"
|
||||
"Se permetti questa richiesta, l'applicazione potrà accedere a tutti i metodi "
|
||||
"forniti\n"
|
||||
"dal framework OKAPI, per es. postare i log delle geocache a tuo nome..\n"
|
||||
"Puoi revocare questo permesso in qualsiasi momento.</p>"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorized.tpl.php:5
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorized.tpl.php:5
|
||||
msgid "Authorization Succeeded"
|
||||
msgstr "Autorizzazione concessa"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorized.tpl.php:28
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorized.tpl.php:28
|
||||
msgid "Access successfully granted"
|
||||
msgstr "Accesso correttamente consentito"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/authorized.tpl.php:29
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/authorized.tpl.php:29
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t<p><b>You've just granted %s application access to your %s account.</"
|
||||
"b>\n"
|
||||
"\t\t\t\tTo complete the operation, go back to %s and enter the following PIN "
|
||||
"code:</p>\n"
|
||||
"\t\t\t"
|
||||
" <p><b>You've just granted %s application access to your %s "
|
||||
"account.</b>\n"
|
||||
" To complete the operation, go back to %s and enter the "
|
||||
"following PIN code:</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t<p><b>Hai appena concesso all'applicazione \"%s\" l'accesso al tuo "
|
||||
"account %s.</b>\n"
|
||||
"\t\t\t\tPer completare l'operazione, riorna a %s e inserisci il seguente "
|
||||
"codice PIN:</p>\n"
|
||||
"\t\t\t"
|
||||
"<p><b>Hai appena concesso all'applicazione \"%s\" l'accesso al tuo account "
|
||||
"%s.</b>\n"
|
||||
"Per completare l'operazione, riorna a %s e inserisci il seguente codice PIN:"
|
||||
"</p>"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/index.tpl.php:5
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:5
|
||||
msgid "My Apps"
|
||||
msgstr "Mie App"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/index.tpl.php:29
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:29
|
||||
msgid "Your external applications"
|
||||
msgstr "Le tue applicazioni esterne"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/index.tpl.php:31
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:31
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>This is the list of applications which you granted access to "
|
||||
"your <b>%s</b> account.\n"
|
||||
"\t\t\t\t\tThis page gives you the abbility to revoke all previously granted "
|
||||
"privileges.\n"
|
||||
"\t\t\t\t\tOnce you click \"remove\" the application will no longer be able "
|
||||
"to perform any\n"
|
||||
"\t\t\t\t\tactions on your behalf.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>This is the list of applications which you granted "
|
||||
"access to your <b>%s</b> account.\n"
|
||||
" This page gives you the abbility to revoke all "
|
||||
"previously granted privileges.\n"
|
||||
" Once you click \"remove\" the application will no longer "
|
||||
"be able to perform any\n"
|
||||
" actions on your behalf.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Questa è la lista delle applicazioni a cui hai concesso "
|
||||
"l'accesso al tuo account <b>%s</b.\n"
|
||||
"\t\t\t\t\tQuesta pagina ti da la possibilità di revocare tutti privilegi "
|
||||
"<p>Questa è la lista delle applicazioni a cui hai concesso l'accesso al tuo "
|
||||
"account <b>%s</b.\n"
|
||||
"Questa pagina ti da la possibilità di revocare tutti privilegi "
|
||||
"precedentemente concessi.\n"
|
||||
"\t\t\t\t\tQundo clicchi su \"rimuovi\" all'applicazione non sarà più "
|
||||
"concesso eseguire nessuna\n"
|
||||
" \t\t\t\t\tazione per tuo conto.</p>\n"
|
||||
"\t\t\t\t"
|
||||
"Qundo clicchi su \"rimuovi\" all'applicazione non sarà più concesso eseguire "
|
||||
"nessuna\n"
|
||||
"azione per tuo conto.</p>"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/index.tpl.php:45
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:45
|
||||
msgid "remove"
|
||||
msgstr "entfernen"
|
||||
|
||||
#: C:\Users\stefano.cotterli\Desktop\opencaching-api/okapi/views/apps/index.tpl.php:50
|
||||
#: D:\PRIV\Projekty\EclipseWorkspace\opencaching-api\okapi/views/apps/index.tpl.php:50
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Thanks to the <a href='%s'>OKAPI Framework</a> you can grant "
|
||||
"external applications\n"
|
||||
"\t\t\t\t\taccess to your <b>%s</b> account. Currently no applications are "
|
||||
"authorized to act\n"
|
||||
"\t\t\t\t\ton your behalf. Once you start using external Opencaching "
|
||||
"applications, they will appear here.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Thanks to the <a href='%s'>OKAPI Framework</a> you "
|
||||
"can grant external applications\n"
|
||||
" access to your <b>%s</b> account. Currently no "
|
||||
"applications are authorized to act\n"
|
||||
" on your behalf. Once you start using external "
|
||||
"Opencaching applications, they will appear here.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Grazie al <a href='%s'>framework OKAPI</a>puoi concedere ad "
|
||||
"applicazioni esterne\n"
|
||||
"\t\t\t\t\t l'accesso al tuo account <b>%s</b>. Attualmente non ci son "
|
||||
"applicazioni autorizzate\n"
|
||||
"\t\t\t\t\tad agire per tuo conto. Quando userai applicazioni esterne a "
|
||||
"Opencaching, queste appariranno qui</p>\n"
|
||||
"\t\t\t\t"
|
||||
"<p>Grazie al <a href='%s'>framework OKAPI</a>puoi concedere ad applicazioni "
|
||||
"esterne\n"
|
||||
"l'accesso al tuo account <b>%s</b>. Attualmente non ci son applicazioni "
|
||||
"autorizzate\n"
|
||||
"ad agire per tuo conto. Quando userai applicazioni esterne a Opencaching, "
|
||||
"queste appariranno qui</p>\n"
|
||||
" "
|
||||
|
||||
#~ msgid "Recommending is allowed only for 'Found it' logtypes."
|
||||
#~ msgstr "Le raccomandazioni sono ammesse solo per i log di tipo 'Trovata'"
|
||||
|
||||
@@ -4,53 +4,53 @@ namespace okapi;
|
||||
|
||||
class Locales
|
||||
{
|
||||
public static $languages = array(
|
||||
'pl' => array('lang' => 'pl', 'locale' => 'pl_PL.utf8', 'name' => 'Polish'),
|
||||
'en' => array('lang' => 'en', 'locale' => 'en_US.utf8', 'name' => 'English'),
|
||||
'nl' => array('lang' => 'nl', 'locale' => 'nl_NL.utf8', 'name' => 'Dutch'),
|
||||
'de' => array('lang' => 'de', 'locale' => 'de_DE.utf8', 'name' => 'German'),
|
||||
'it' => array('lang' => 'it', 'locale' => 'it_IT.utf8', 'name' => 'Italian'),
|
||||
);
|
||||
public static $languages = array(
|
||||
'pl' => array('lang' => 'pl', 'locale' => 'pl_PL.utf8', 'name' => 'Polish'),
|
||||
'en' => array('lang' => 'en', 'locale' => 'en_US.utf8', 'name' => 'English'),
|
||||
'nl' => array('lang' => 'nl', 'locale' => 'nl_NL.utf8', 'name' => 'Dutch'),
|
||||
'de' => array('lang' => 'de', 'locale' => 'de_DE.utf8', 'name' => 'German'),
|
||||
'it' => array('lang' => 'it', 'locale' => 'it_IT.utf8', 'name' => 'Italian'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the list of locales that should be installed on the system in order
|
||||
* for all translations to work properly.
|
||||
*/
|
||||
public static function get_required_locales()
|
||||
{
|
||||
$arr = array('POSIX');
|
||||
foreach (self::$languages as $key => $value)
|
||||
$arr[] = $value['locale'];
|
||||
return $arr;
|
||||
}
|
||||
/**
|
||||
* Get the list of locales that should be installed on the system in order
|
||||
* for all translations to work properly.
|
||||
*/
|
||||
public static function get_required_locales()
|
||||
{
|
||||
$arr = array('POSIX');
|
||||
foreach (self::$languages as $key => $value)
|
||||
$arr[] = $value['locale'];
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of locales installed on the current system.
|
||||
*/
|
||||
public static function get_installed_locales()
|
||||
{
|
||||
$arr = array();
|
||||
foreach (explode("\n", shell_exec("locale -a")) as $item)
|
||||
if ($item)
|
||||
$arr[] = $item;
|
||||
return $arr;
|
||||
}
|
||||
/**
|
||||
* Get the list of locales installed on the current system.
|
||||
*/
|
||||
public static function get_installed_locales()
|
||||
{
|
||||
$arr = array();
|
||||
foreach (explode("\n", shell_exec("locale -a")) as $item)
|
||||
if ($item)
|
||||
$arr[] = $item;
|
||||
return $arr;
|
||||
}
|
||||
|
||||
private static function get_locale_for_language($lang)
|
||||
{
|
||||
if (isset(self::$languages[$lang]))
|
||||
return self::$languages[$lang]['locale'];
|
||||
return null;
|
||||
}
|
||||
private static function get_locale_for_language($lang)
|
||||
{
|
||||
if (isset(self::$languages[$lang]))
|
||||
return self::$languages[$lang]['locale'];
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function get_best_locale($langprefs)
|
||||
{
|
||||
foreach ($langprefs as $lang)
|
||||
{
|
||||
$locale = self::get_locale_for_language($lang);
|
||||
if ($locale != null)
|
||||
return $locale;
|
||||
}
|
||||
return self::$languages['en']['locale'];
|
||||
}
|
||||
public static function get_best_locale($langprefs)
|
||||
{
|
||||
foreach ($langprefs as $lang)
|
||||
{
|
||||
$locale = self::get_locale_for_language($lang);
|
||||
if ($locale != null)
|
||||
return $locale;
|
||||
}
|
||||
return self::$languages['en']['locale'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OKAPI\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-04-10 01:08+0100\n"
|
||||
"PO-Revision-Date: 2013-04-10 01:12+0100\n"
|
||||
"Last-Translator: Wojciech Rygielski <rygielski@mimuw.edu.pl>\n"
|
||||
"POT-Creation-Date: 2014-01-23 16:05+0100\n"
|
||||
"PO-Revision-Date: 2014-08-09 03:47+0100\n"
|
||||
"Last-Translator: Harrie Klomp <harrie@harrieklomp.be>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: nl_NL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -13,50 +13,96 @@ msgstr ""
|
||||
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
|
||||
"X-Poedit-Basepath: D:\\PRIV\\Projekty\\EclipseWorkspace\\opencaching-api\\\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 1.5.5\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
# For additional waypoints. As in "Stage 1: Parking".
|
||||
#: okapi/services/caches/geocaches.php:846
|
||||
#: okapi/services/caches/geocaches.php:957
|
||||
msgid "Stage"
|
||||
msgstr "Etappe"
|
||||
|
||||
#: okapi/services/caches/geocaches.php:1009
|
||||
#: okapi/services/caches/geocaches.php:986
|
||||
msgid "User location"
|
||||
msgstr "Gebruikers locatie"
|
||||
|
||||
#: okapi/services/caches/geocaches.php:989
|
||||
#, php-format
|
||||
msgid "Your own custom coordinates for the %s geocache"
|
||||
msgstr "Eigen gecorrigeerde coördinaten voor %s geocache"
|
||||
|
||||
#: okapi/services/caches/geocaches.php:1148
|
||||
msgid "National Park / Landscape"
|
||||
msgstr "Nationaal park / Landschap"
|
||||
|
||||
#: okapi/services/caches/geocaches.php:1300
|
||||
#, php-format
|
||||
msgid ""
|
||||
"This <a href='%s'>geocache</a> description comes from the <a href='%s'>%s</"
|
||||
"a> site."
|
||||
msgstr ""
|
||||
"Deze <a href='%s'>geocache</a> beschrijving komt van de <a href='%s'>%s</a> "
|
||||
"\"\"site."
|
||||
|
||||
#: okapi/services/caches/geocaches.php:1021
|
||||
#, php-format
|
||||
#: okapi/services/caches/geocaches.php:1312
|
||||
#, fuzzy, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/de/deed.en'>CC-BY-NC-ND</a>, as of "
|
||||
"%s; all log entries © their authors"
|
||||
msgstr ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/nl/deed.en'>CC-BY-NC-ND</a>, as of "
|
||||
"%s; all log entries © their authors"
|
||||
|
||||
#: okapi/services/caches/geocaches.php:1032
|
||||
#, php-format
|
||||
#: okapi/services/caches/geocaches.php:1323
|
||||
#, fuzzy, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/de/deed.en'>CC-BY-NC-ND</a>; all "
|
||||
"log entries © their authors"
|
||||
msgstr ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/nl/deed.en'>CC-BY-NC-ND</a>; all "
|
||||
"log entries © their authors"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:31
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:48
|
||||
#: okapi/services/caches/formatters/gpx.php:360
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> They have been replaced with "
|
||||
"your own custom coordinates which you have provided for this geocache."
|
||||
msgstr ""
|
||||
"Geocache coördinaten zijn veranderd.</b> Deze zijn aangepast door "
|
||||
"coördinaten die je zelf hebt gewijzigd voor deze geocache."
|
||||
|
||||
#: okapi/services/caches/formatters/gpx.php:366
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> Currently they point to one "
|
||||
"of the alternate waypoints originally described as:"
|
||||
msgstr ""
|
||||
"Geocache coördinaten zijn veranderd.</b> Momenteel wijzen zij een van de "
|
||||
"alternatieve waypoints oorspronkelijk beschreven als:"
|
||||
|
||||
#: okapi/services/caches/formatters/gpx.php:379
|
||||
msgid "Original geocache location"
|
||||
msgstr "Orginele geocache locatie"
|
||||
|
||||
#: okapi/services/caches/formatters/gpx.php:381
|
||||
#, php-format
|
||||
msgid "Original (owner-supplied) location of the %s geocache"
|
||||
msgstr "Originele (opgegeven door plaatser) locatie van de %s geocache"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:30
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:62
|
||||
msgid "hidden by"
|
||||
msgstr "geplaatst door"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:50
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:64
|
||||
#, php-format
|
||||
msgid "%d recommendation"
|
||||
msgid_plural "%d recommendations"
|
||||
msgstr[0] "%d aanbeveling"
|
||||
msgstr[1] "%d aanbevelingen"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:51
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:65
|
||||
#, php-format
|
||||
msgid "found %d time"
|
||||
msgid_plural "found %d times"
|
||||
@@ -64,37 +110,42 @@ msgstr[0] "%d keer gevonden"
|
||||
msgstr[1] "%d keren gevonden"
|
||||
|
||||
# Generic term for trackable items (like geocoins and travelbugs).
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:54
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:68
|
||||
#, php-format
|
||||
msgid "%d trackable"
|
||||
msgid_plural "%d trackables"
|
||||
msgstr[0] "%d trackable"
|
||||
msgstr[1] "%d trackables"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:58
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:72
|
||||
msgid "Personal notes"
|
||||
msgstr "Persoonlijke notities"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:62
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:76
|
||||
msgid "Attributes"
|
||||
msgstr "Attributen"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:66
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:80
|
||||
msgid "Trackables"
|
||||
msgstr "Trackables"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:84
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:90
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:106
|
||||
msgid "Images"
|
||||
msgstr "Afbeeldingen"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:91
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:113
|
||||
msgid "Spoilers"
|
||||
msgstr "Spoilers"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:99
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:122
|
||||
msgid "Image descriptions"
|
||||
msgstr "Afbeelding omschrijving"
|
||||
|
||||
#: okapi/services/caches/formatters/gpxfile.tpl.php:130
|
||||
msgid "The cache probably is located in the following protection areas:"
|
||||
msgstr "De cache is waarschijnlijk in een volgend beschermd gebied geplaatst:"
|
||||
|
||||
#: okapi/services/logs/submit.php:70
|
||||
msgid ""
|
||||
"You are trying to publish a log entry with a date in future. Cache log "
|
||||
@@ -112,40 +163,59 @@ msgstr ""
|
||||
"De cachewaardering is genegeerd, omdat %s geen waarderingen in het systeem "
|
||||
"heeft."
|
||||
|
||||
#: okapi/services/logs/submit.php:113
|
||||
#: okapi/services/logs/submit.php:111
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your cache recommendation was ignored, because %s does not allow "
|
||||
"recommending event caches."
|
||||
msgstr ""
|
||||
"De cachewaardering is genegeerd, omdat %s geen waarderingen op evenementen "
|
||||
"ondersteund."
|
||||
|
||||
#: okapi/services/logs/submit.php:125
|
||||
#, php-format
|
||||
msgid ""
|
||||
"However, your \"needs maintenance\" flag was ignored, because %s does not "
|
||||
"support this feature."
|
||||
msgstr ""
|
||||
"Maar jouw \"Heeft onderhoud nodig\" log is genegeerd omdat %s dit niet "
|
||||
"ondersteunt."
|
||||
|
||||
# The user will see this error when he is trying to submit a "Fount it" entry on an event cache. "Attended" or "Will attend" log entries are not the same as "Found it". Currently OKAPI does not allow to submit "Attended" nor "Will attend" log entries, that's why user can only "Comment" on it.
|
||||
#: okapi/services/logs/submit.php:131
|
||||
# Missing "you can attend it"
|
||||
#: okapi/services/logs/submit.php:145
|
||||
msgid ""
|
||||
"This cache is an Event cache. You cannot \"Find it\"! (But - you may "
|
||||
"\"Comment\" on it.)"
|
||||
"This cache is an Event cache. You cannot \"Find\" it (but you can attend it, "
|
||||
"or comment on it)!"
|
||||
msgstr ""
|
||||
"Dit is een eventcache. Deze kan niet als \"Gevonden\" gelogd worden. Maar "
|
||||
"wel als \"Notitie\"."
|
||||
"Dit is een evenement. Deze kan niet als \"Gevonden\" gelogd worden. (maar "
|
||||
"wel deelgenomen of een notitie plaatsen)."
|
||||
|
||||
#: okapi/services/logs/submit.php:133
|
||||
#: okapi/services/logs/submit.php:150
|
||||
msgid ""
|
||||
"This cache is NOT an Event cache. You cannot \"Attend\" it (but you can find "
|
||||
"it, or comment on it)!"
|
||||
msgstr ""
|
||||
"Deze cache is GEEN evenement. Je kunt niet \"Deelnemen\" (maar wel als "
|
||||
"gevonden loggen of een notitie plaatsen)"
|
||||
|
||||
#: okapi/services/logs/submit.php:155
|
||||
msgid "Your have to supply some text for your comment."
|
||||
msgstr "Er dient enige tekst ingevuld te worden."
|
||||
|
||||
#: okapi/services/logs/submit.php:146
|
||||
#: okapi/services/logs/submit.php:168
|
||||
msgid "This cache requires a password. You didn't provide one!"
|
||||
msgstr "Deze cache vraagt om een wachtwoord. Deze is niet opgegeven!"
|
||||
|
||||
#: okapi/services/logs/submit.php:148
|
||||
#: okapi/services/logs/submit.php:170
|
||||
msgid "Invalid password!"
|
||||
msgstr "Verkeerd wachtwoord!"
|
||||
|
||||
# This error will be shown to the user when he tries to submit a log entry which is EXACTLY the same as one he had submitted before.
|
||||
#: okapi/services/logs/submit.php:260
|
||||
#: okapi/services/logs/submit.php:285
|
||||
msgid "You have already submitted a log entry with exactly the same contents."
|
||||
msgstr "Deze log is reeds met dezelfde tekst verzonden."
|
||||
|
||||
#: okapi/services/logs/submit.php:279
|
||||
#: okapi/services/logs/submit.php:308
|
||||
msgid ""
|
||||
"You have already submitted a \"Found it\" log entry once. Now you may submit "
|
||||
"\"Comments\" only!"
|
||||
@@ -153,25 +223,29 @@ msgstr ""
|
||||
"Je hebt deze cache al als \"Gevonden\" gelogd. Je kunt nu wel een \"Notitie"
|
||||
"\" plaatsen."
|
||||
|
||||
# The English text was changed from "you cannot rate it" to "you cannot find it". The translation remained.
|
||||
#: okapi/services/logs/submit.php:281
|
||||
#: okapi/services/logs/submit.php:310
|
||||
msgid "You are the owner of this cache. You may submit \"Comments\" only!"
|
||||
msgstr ""
|
||||
"Je bent eigenaar van deze cache. Je kunt alleen een \"Notitie\" plaatsen."
|
||||
|
||||
#: okapi/services/logs/submit.php:299
|
||||
#: okapi/services/logs/submit.php:328
|
||||
msgid "You have already rated this cache once. Your rating cannot be changed."
|
||||
msgstr ""
|
||||
"Je hebt deze cache al gewaardeerd. De waardering kan niet veranderd worden."
|
||||
|
||||
#: okapi/services/logs/submit.php:316
|
||||
#: okapi/services/logs/submit.php:345
|
||||
msgid "You have already recommended this cache once."
|
||||
msgstr ""
|
||||
msgstr "Je hebt al een aanbeveling op deze cache gegeven."
|
||||
|
||||
#: okapi/services/logs/submit.php:323
|
||||
#: okapi/services/logs/submit.php:355
|
||||
msgid "You don't have any recommendations to give. Find more caches first!"
|
||||
msgstr ""
|
||||
msgstr "Je kunt geen aanbeveling meer geven. Vind eerst meer caches."
|
||||
|
||||
#: okapi/services/logs/submit.php:491
|
||||
#: okapi/services/logs/submit.php:398
|
||||
msgid "Event caches cannot \"need maintenance\"."
|
||||
msgstr "Evenementen hebben geen \"onderhoud nodig"
|
||||
|
||||
#: okapi/services/logs/submit.php:528
|
||||
msgid "Your cache log entry was posted successfully."
|
||||
msgstr "De log is succesvol verzonden."
|
||||
|
||||
@@ -208,35 +282,33 @@ msgstr "Toestemmen"
|
||||
msgid "Decline"
|
||||
msgstr "Afwijzen"
|
||||
|
||||
# This should begin with "\n", but you may ignore the rest of \n and \r characters.
|
||||
# This should begin with "\n", but you may ignore the rest of \n characters.
|
||||
# This message is shown to the user when external application is trying to get user's permission to access his account.
|
||||
# Sample: http://i.imgur.com/ZCJNT.png
|
||||
#: okapi/views/apps/authorize.tpl.php:56
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Once permission is granted it is valid until its withdrawal on\n"
|
||||
"\t\t\t\t\tthe <a href='%s'>applications management</a> page.</p>\n"
|
||||
"\t\t\t\t\t<p>The application will access your acount via <a href='%s'>the "
|
||||
"OKAPI Framework</a>.\n"
|
||||
"\t\t\t\t\tIf you allow this request application will be able to access all "
|
||||
"methods delivered\n"
|
||||
"\t\t\t\t\tby the OKAPI Framework, i.e. post log entries on geocaches in your "
|
||||
"name.\n"
|
||||
"\t\t\t\t\tYou can revoke this permission at any moment.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Once permission is granted it is valid until its "
|
||||
"withdrawal on\n"
|
||||
" the <a href='%s'>applications management</a> page.</p>\n"
|
||||
" <p>The application will access your acount via <a "
|
||||
"href='%s'>the OKAPI Framework</a>.\n"
|
||||
" If you allow this request application will be able to "
|
||||
"access all methods delivered\n"
|
||||
" by the OKAPI Framework, i.e. post log entries on "
|
||||
"geocaches in your name.\n"
|
||||
" You can revoke this permission at any moment.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Wanneer toegestemd is blijft deze geldig tot intrekking op\n"
|
||||
"\t\t\t\t\tde <a href='%s'>toepassingsbeheer</a> pagina.</p>\n"
|
||||
"\t\t\t\t\t<p>De toepassing zal toegang krijgen via jouw account op <a "
|
||||
"href='%s'>the OKAPI Framework</a>.\n"
|
||||
"\t\t\t\t\tWanneer je toestemming geeft voor deze toepassing zullen de "
|
||||
"mogelijkheden\n"
|
||||
"\t\t\t\t\tvan OKAPI Framework toegepast worden, b.v. het loggen van een "
|
||||
"cache.\n"
|
||||
"\t\t\t\t\tDe toestemming kan elk moment ingetrokken worden.</p>\n"
|
||||
"\t\t\t\t"
|
||||
"<p>Wanneer toegestemd is blijft deze geldig tot intrekking op\n"
|
||||
"de <a href='%s'>toepassingsbeheer</a> pagina.</p>\n"
|
||||
"<p>De toepassing zal toegang krijgen via jouw account op <a href='%s'>the "
|
||||
"OKAPI Framework</a>.\n"
|
||||
"Wanneer je toestemming geeft voor deze toepassing zullen de mogelijkheden\n"
|
||||
"van OKAPI Framework toegepast worden, b.v. het loggen van een cache.\n"
|
||||
"De toestemming kan elk moment ingetrokken worden.</p>"
|
||||
|
||||
#: okapi/views/apps/authorized.tpl.php:5
|
||||
msgid "Authorization Succeeded"
|
||||
@@ -251,18 +323,16 @@ msgstr "Met succes toegang verleend"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t<p><b>You've just granted %s application access to your %s account.</"
|
||||
"b>\n"
|
||||
"\t\t\t\tTo complete the operation, go back to %s and enter the following PIN "
|
||||
"code:</p>\n"
|
||||
"\t\t\t"
|
||||
" <p><b>You've just granted %s application access to your %s "
|
||||
"account.</b>\n"
|
||||
" To complete the operation, go back to %s and enter the "
|
||||
"following PIN code:</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t<p><b>Je hebt toegang verleent voor %s toepassing op jouw %s account."
|
||||
"</b>\n"
|
||||
"\t\t\t\tOm de aktie te voltooien, ga terug naar %s en gebruik de volgende "
|
||||
"PIN code:</p>\n"
|
||||
"\t\t\t"
|
||||
"<p><b>Je hebt toegang verleent voor %s toepassing op jouw %s account.</b>\n"
|
||||
"Om de actie te voltooien, ga terug naar %s en gebruik de volgende PIN code:</"
|
||||
"p>"
|
||||
|
||||
#: okapi/views/apps/index.tpl.php:5
|
||||
msgid "My Apps"
|
||||
@@ -273,29 +343,25 @@ msgid "Your external applications"
|
||||
msgstr "Jouw externe toepassingen"
|
||||
|
||||
# This will be shown when user visits /okapi/apps page.
|
||||
# Sample: http://i.imgur.com/ZCJNT.png
|
||||
#: okapi/views/apps/index.tpl.php:31
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>This is the list of applications which you granted access to "
|
||||
"your <b>%s</b> account.\n"
|
||||
"\t\t\t\t\tThis page gives you the abbility to revoke all previously granted "
|
||||
"privileges.\n"
|
||||
"\t\t\t\t\tOnce you click \"remove\" the application will no longer be able "
|
||||
"to perform any\n"
|
||||
"\t\t\t\t\tactions on your behalf.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>This is the list of applications which you granted "
|
||||
"access to your <b>%s</b> account.\n"
|
||||
" This page gives you the abbility to revoke all "
|
||||
"previously granted privileges.\n"
|
||||
" Once you click \"remove\" the application will no longer "
|
||||
"be able to perform any\n"
|
||||
" actions on your behalf.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Dit is een lijst met toegestane toepassingen op jouw <b>%s</b> "
|
||||
"account.\n"
|
||||
"\t\t\t\t\tOp deze pagina kun je alle toestemmingen intrekken die gegeven "
|
||||
"zijn.\n"
|
||||
"\t\t\t\t\tMet een klik op \"verwijderen\" zal de toepassing verwijderen en "
|
||||
"is dan ook niet meer beschikbaar\n"
|
||||
"\t\t\t\t\voor anderen.</p>\n"
|
||||
"\t\t\t\t"
|
||||
"<p>Dit is een lijst met toegestane toepassingen op jouw <b>%s</b> account.\n"
|
||||
"Op deze pagina kun je alle toestemmingen intrekken die gegeven zijn.\n"
|
||||
"Met een klik op \"verwijderen\" zal de toepassing verwijderen en is dan ook "
|
||||
"niet meer beschikbaar\n"
|
||||
"oor anderen.</p>"
|
||||
|
||||
#: okapi/views/apps/index.tpl.php:45
|
||||
msgid "remove"
|
||||
@@ -305,22 +371,21 @@ msgstr "verwijderen"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Thanks to the <a href='%s'>OKAPI Framework</a> you can grant "
|
||||
"external applications\n"
|
||||
"\t\t\t\t\taccess to your <b>%s</b> account. Currently no applications are "
|
||||
"authorized to act\n"
|
||||
"\t\t\t\t\ton your behalf. Once you start using external Opencaching "
|
||||
"applications, they will appear here.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Thanks to the <a href='%s'>OKAPI Framework</a> you "
|
||||
"can grant external applications\n"
|
||||
" access to your <b>%s</b> account. Currently no "
|
||||
"applications are authorized to act\n"
|
||||
" on your behalf. Once you start using external "
|
||||
"Opencaching applications, they will appear here.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Dankzij het <a href='%s'>OKAPI Framework</a> kun je toegang "
|
||||
"verlenen via externe\n"
|
||||
"\t\t\t\t\ttoepassingen op een <b>%s</b> account. Momenteel zijn op dit "
|
||||
"account nog geen externe\n"
|
||||
"\t\t\t\t\ttoepassingen actief. Geactiveerde Opencaching toepassingen "
|
||||
"zullen hier getoond worden.</p>\n"
|
||||
"\t\t\t\t"
|
||||
"<p>Dankzij het <a href='%s'>OKAPI Framework</a> kun je toegang verlenen via "
|
||||
"externe\n"
|
||||
"toepassingen op een <b>%s</b> account. Momenteel zijn op dit account nog "
|
||||
"geen externe\n"
|
||||
"toepassingen actief. Geactiveerde Opencaching toepassingen zullen hier "
|
||||
"getoond worden.</p>"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "This cache is archived. Only admins and the owner are allowed to add a "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OKAPI\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-11 08:28+0100\n"
|
||||
"PO-Revision-Date: 2013-07-11 08:35+0100\n"
|
||||
"POT-Creation-Date: 2014-01-23 15:48+0100\n"
|
||||
"PO-Revision-Date: 2014-01-23 15:49+0100\n"
|
||||
"Last-Translator: Wojciech Rygielski <rygielski@mimuw.edu.pl>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: pl_PL\n"
|
||||
@@ -15,26 +15,35 @@ msgstr ""
|
||||
"\\okapi\n"
|
||||
"Plural-Forms: nplurals=3; plural= n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2;\n"
|
||||
"X-Poedit-SourceCharset: utf-8\n"
|
||||
"X-Generator: Poedit 1.5.5\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Generator: Poedit 1.6.3\n"
|
||||
"X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
#: services/caches/geocaches.php:956
|
||||
#: services/caches/geocaches.php:957
|
||||
msgid "Stage"
|
||||
msgstr "Etap"
|
||||
|
||||
#: services/caches/geocaches.php:1111
|
||||
#: services/caches/geocaches.php:986
|
||||
msgid "User location"
|
||||
msgstr "Współrzędne użytkownika"
|
||||
|
||||
#: services/caches/geocaches.php:989
|
||||
#, php-format
|
||||
msgid "Your own custom coordinates for the %s geocache"
|
||||
msgstr "Twoje osobiste współrzędne skrzynki %s"
|
||||
|
||||
#: services/caches/geocaches.php:1148
|
||||
msgid "National Park / Landscape"
|
||||
msgstr "Park narodowy lub krajobrazowy"
|
||||
|
||||
#: services/caches/geocaches.php:1263
|
||||
#: services/caches/geocaches.php:1300
|
||||
#, php-format
|
||||
msgid ""
|
||||
"This <a href='%s'>geocache</a> description comes from the <a href='%s'>%s</"
|
||||
"a> site."
|
||||
msgstr "Opis <a href='%s'>skrzynki</a> pochodzi z serwisu <a href='%s'>%s</a>."
|
||||
|
||||
#: services/caches/geocaches.php:1275
|
||||
#: services/caches/geocaches.php:1312
|
||||
#, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
@@ -45,7 +54,7 @@ msgstr ""
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/de/deed.pl'>CC-BY-NC-ND</a>, w "
|
||||
"dniu %s. Prawa autorskie wpisów do logów należą do ich autorów."
|
||||
|
||||
#: services/caches/geocaches.php:1286
|
||||
#: services/caches/geocaches.php:1323
|
||||
#, php-format
|
||||
msgid ""
|
||||
"© <a href='%s'>%s</a>, <a href='%s'>%s</a>, <a href='http://"
|
||||
@@ -56,12 +65,37 @@ msgstr ""
|
||||
"creativecommons.org/licenses/by-nc-nd/3.0/de/deed.pl'>CC-BY-NC-ND</a>. Prawa "
|
||||
"autorskie wpisów do logów należą do ich autorów."
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:31
|
||||
#: services/caches/formatters/gpxfile.tpl.php:60
|
||||
#: services/caches/formatters/gpx.php:360
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> They have been replaced with "
|
||||
"your own custom coordinates which you have provided for this geocache."
|
||||
msgstr ""
|
||||
"<b>Współrzędne skrzynki zostały zmienione.</b> Zostały zastąpione Twoimi "
|
||||
"osobistymi współrzędnymi, które wprowadziłeś na stronie tej skrzynki."
|
||||
|
||||
#: services/caches/formatters/gpx.php:366
|
||||
msgid ""
|
||||
"<b>Geocache coordinates have been changed.</b> Currently they point to one "
|
||||
"of the alternate waypoints originally described as:"
|
||||
msgstr ""
|
||||
"<b>Współrzędne skrzynki zostały zmienione.</b> Aktualnie wskazują one na "
|
||||
"jeden z dodatkowych waypointów, oryginalnie opisanego jako:"
|
||||
|
||||
#: services/caches/formatters/gpx.php:379
|
||||
msgid "Original geocache location"
|
||||
msgstr "Oryginalne współrzędne skrzynki"
|
||||
|
||||
#: services/caches/formatters/gpx.php:381
|
||||
#, php-format
|
||||
msgid "Original (owner-supplied) location of the %s geocache"
|
||||
msgstr "Oryginalne współrzędne skrzynki %s (podane przez autora)"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:30
|
||||
#: services/caches/formatters/gpxfile.tpl.php:62
|
||||
msgid "hidden by"
|
||||
msgstr "ukryta przez"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:62
|
||||
#: services/caches/formatters/gpxfile.tpl.php:64
|
||||
#, php-format
|
||||
msgid "%d recommendation"
|
||||
msgid_plural "%d recommendations"
|
||||
@@ -69,7 +103,7 @@ msgstr[0] "%d rekomendacja"
|
||||
msgstr[1] "%d rekomendacje"
|
||||
msgstr[2] "%d rekomendacji"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:63
|
||||
#: services/caches/formatters/gpxfile.tpl.php:65
|
||||
#, php-format
|
||||
msgid "found %d time"
|
||||
msgid_plural "found %d times"
|
||||
@@ -77,7 +111,7 @@ msgstr[0] "znaleziona %d raz"
|
||||
msgstr[1] "znaleziona %d razy"
|
||||
msgstr[2] "znaleziona %d razy"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:66
|
||||
#: services/caches/formatters/gpxfile.tpl.php:68
|
||||
#, php-format
|
||||
msgid "%d trackable"
|
||||
msgid_plural "%d trackables"
|
||||
@@ -85,32 +119,32 @@ msgstr[0] "%d GeoKret (lub TravelBug)"
|
||||
msgstr[1] "%d GeoKrety (lub TravelBugi)"
|
||||
msgstr[2] "%d GeoKretów (lub TravelBugów)"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:70
|
||||
#: services/caches/formatters/gpxfile.tpl.php:72
|
||||
msgid "Personal notes"
|
||||
msgstr "Osobiste notatki"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:74
|
||||
#: services/caches/formatters/gpxfile.tpl.php:76
|
||||
msgid "Attributes"
|
||||
msgstr "Atrybuty"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:78
|
||||
#: services/caches/formatters/gpxfile.tpl.php:80
|
||||
msgid "Trackables"
|
||||
msgstr "Geokrety, Travelbugi itp."
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:88
|
||||
#: services/caches/formatters/gpxfile.tpl.php:104
|
||||
#: services/caches/formatters/gpxfile.tpl.php:90
|
||||
#: services/caches/formatters/gpxfile.tpl.php:106
|
||||
msgid "Images"
|
||||
msgstr "Obrazki"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:111
|
||||
#: services/caches/formatters/gpxfile.tpl.php:113
|
||||
msgid "Spoilers"
|
||||
msgstr "Spoilery"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:120
|
||||
#: services/caches/formatters/gpxfile.tpl.php:122
|
||||
msgid "Image descriptions"
|
||||
msgstr "Opisy obrazków"
|
||||
|
||||
#: services/caches/formatters/gpxfile.tpl.php:128
|
||||
#: services/caches/formatters/gpxfile.tpl.php:130
|
||||
msgid "The cache probably is located in the following protection areas:"
|
||||
msgstr "Prawdopodobnie skrzynka znajduje się na terenie obszarów chronionych:"
|
||||
|
||||
@@ -177,11 +211,11 @@ msgstr "Ta skrzynka wymaga podania hasła. Nie wpisałeś go."
|
||||
msgid "Invalid password!"
|
||||
msgstr "Niepoprawne hasło!"
|
||||
|
||||
#: services/logs/submit.php:282
|
||||
#: services/logs/submit.php:285
|
||||
msgid "You have already submitted a log entry with exactly the same contents."
|
||||
msgstr "Już opublikowałeś wcześniej wpis z dokładnie taką samą treścią."
|
||||
|
||||
#: services/logs/submit.php:305
|
||||
#: services/logs/submit.php:308
|
||||
msgid ""
|
||||
"You have already submitted a \"Found it\" log entry once. Now you may submit "
|
||||
"\"Comments\" only!"
|
||||
@@ -189,30 +223,30 @@ msgstr ""
|
||||
"Już opublikowałeś jeden wpis typu \"Znaleziona\" dla tej skrzynki. Teraz "
|
||||
"możesz dodawać jedynie \"Komentarze\"!"
|
||||
|
||||
#: services/logs/submit.php:307
|
||||
#: services/logs/submit.php:310
|
||||
msgid "You are the owner of this cache. You may submit \"Comments\" only!"
|
||||
msgstr ""
|
||||
"Jesteś właścicielem tej skrzynki. Możesz przesyłać jedynie \"Komentarze\"."
|
||||
|
||||
#: services/logs/submit.php:325
|
||||
#: services/logs/submit.php:328
|
||||
msgid "You have already rated this cache once. Your rating cannot be changed."
|
||||
msgstr "Już oceniłeś tę skrzynkę. Ocena nie może być zmieniona."
|
||||
|
||||
#: services/logs/submit.php:342
|
||||
#: services/logs/submit.php:345
|
||||
msgid "You have already recommended this cache once."
|
||||
msgstr "Już raz zarekomendowałeś tę skrzynkę."
|
||||
|
||||
#: services/logs/submit.php:352
|
||||
#: services/logs/submit.php:355
|
||||
msgid "You don't have any recommendations to give. Find more caches first!"
|
||||
msgstr ""
|
||||
"Aktualnie nie możesz wystawić kolejnej rekomendacji. Znajdź najpierw więcej "
|
||||
"skrzynek!"
|
||||
|
||||
#: services/logs/submit.php:395
|
||||
#: services/logs/submit.php:398
|
||||
msgid "Event caches cannot \"need maintenance\"."
|
||||
msgstr "Skrzynki typu Wydarzenie nie mogą \"potrzebować serwisu\"."
|
||||
|
||||
#: services/logs/submit.php:525
|
||||
#: services/logs/submit.php:528
|
||||
msgid "Your cache log entry was posted successfully."
|
||||
msgstr "Twój wpis do logbooka został opublikowany pomyślnie."
|
||||
|
||||
@@ -253,16 +287,17 @@ msgstr "Odmawiam"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Once permission is granted it is valid until its withdrawal on\n"
|
||||
"\t\t\t\t\tthe <a href='%s'>applications management</a> page.</p>\n"
|
||||
"\t\t\t\t\t<p>The application will access your acount via <a href='%s'>the "
|
||||
"OKAPI Framework</a>.\n"
|
||||
"\t\t\t\t\tIf you allow this request application will be able to access all "
|
||||
"methods delivered\n"
|
||||
"\t\t\t\t\tby the OKAPI Framework, i.e. post log entries on geocaches in your "
|
||||
"name.\n"
|
||||
"\t\t\t\t\tYou can revoke this permission at any moment.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Once permission is granted it is valid until its "
|
||||
"withdrawal on\n"
|
||||
" the <a href='%s'>applications management</a> page.</p>\n"
|
||||
" <p>The application will access your acount via <a "
|
||||
"href='%s'>the OKAPI Framework</a>.\n"
|
||||
" If you allow this request application will be able to "
|
||||
"access all methods delivered\n"
|
||||
" by the OKAPI Framework, i.e. post log entries on "
|
||||
"geocaches in your name.\n"
|
||||
" You can revoke this permission at any moment.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p>Raz udzielona zgoda jest ważna aż do momentu jej wycofania na stronie <a "
|
||||
@@ -285,11 +320,11 @@ msgstr "Pomyślnie dałeś dostęp"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t<p><b>You've just granted %s application access to your %s account.</"
|
||||
"b>\n"
|
||||
"\t\t\t\tTo complete the operation, go back to %s and enter the following PIN "
|
||||
"code:</p>\n"
|
||||
"\t\t\t"
|
||||
" <p><b>You've just granted %s application access to your %s "
|
||||
"account.</b>\n"
|
||||
" To complete the operation, go back to %s and enter the "
|
||||
"following PIN code:</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p><b>Właśnie dałeś dostęp aplikacji %s do Twojego konta %s.</b>\n"
|
||||
@@ -308,14 +343,14 @@ msgstr "Twoje zewnętrzne aplikacje"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>This is the list of applications which you granted access to "
|
||||
"your <b>%s</b> account.\n"
|
||||
"\t\t\t\t\tThis page gives you the abbility to revoke all previously granted "
|
||||
"privileges.\n"
|
||||
"\t\t\t\t\tOnce you click \"remove\" the application will no longer be able "
|
||||
"to perform any\n"
|
||||
"\t\t\t\t\tactions on your behalf.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>This is the list of applications which you granted "
|
||||
"access to your <b>%s</b> account.\n"
|
||||
" This page gives you the abbility to revoke all "
|
||||
"previously granted privileges.\n"
|
||||
" Once you click \"remove\" the application will no longer "
|
||||
"be able to perform any\n"
|
||||
" actions on your behalf.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p>Następującym aplikacjom zezwoliłeś na dostęp do swojego konta <b>%s</b>.\n"
|
||||
@@ -332,13 +367,13 @@ msgstr "usuń"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"\t\t\t\t\t<p>Thanks to the <a href='%s'>OKAPI Framework</a> you can grant "
|
||||
"external applications\n"
|
||||
"\t\t\t\t\taccess to your <b>%s</b> account. Currently no applications are "
|
||||
"authorized to act\n"
|
||||
"\t\t\t\t\ton your behalf. Once you start using external Opencaching "
|
||||
"applications, they will appear here.</p>\n"
|
||||
"\t\t\t\t"
|
||||
" <p>Thanks to the <a href='%s'>OKAPI Framework</a> you "
|
||||
"can grant external applications\n"
|
||||
" access to your <b>%s</b> account. Currently no "
|
||||
"applications are authorized to act\n"
|
||||
" on your behalf. Once you start using external "
|
||||
"Opencaching applications, they will appear here.</p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p>Dzięki platformie <a href='%s'>OKAPI</a> możesz dawać zewnętrznym "
|
||||
@@ -348,6 +383,30 @@ msgstr ""
|
||||
"w Twoim imieniu. Gdy zaczniesz korzystać z zewnętrznych aplikacji, ich lista "
|
||||
"pojawi się tutaj.</p>"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "\n"
|
||||
#~ "\t\t\t\t\t\t\t\t<b>Warning: Changed coordinates.</b> These are not the "
|
||||
#~ "original\n"
|
||||
#~ "\t\t\t\t\t\t\t\tcoordinates of this geocache (as supplied by the owner). "
|
||||
#~ "They\n"
|
||||
#~ "\t\t\t\t\t\t\t\thave been replaced with other coordinates:\n"
|
||||
#~ "\t\t\t\t\t\t\t"
|
||||
#~ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "<b>Uwaga: Zmienione współrzędne.</b> To nie są oryginalne współrzędne tej "
|
||||
#~ "skrzynki (takie, jakie podał jej autor). Współrzędne zostały nadpisane "
|
||||
#~ "innymi współrzędnymi:"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "<b>Geocache's coordinates has been changed</b> to point to the user "
|
||||
#~ "supplied value."
|
||||
#~ msgstr ""
|
||||
#~ "<b>Współrzędne skrzynki zostały zmienione</b> na własną wartość "
|
||||
#~ "wprowadzoną przez użytkownika."
|
||||
|
||||
#~ msgid "User-supplied location of the %s geocache"
|
||||
#~ msgstr "Współrzędne skrzynki %s wprowadzone przez użytkownika"
|
||||
|
||||
#~ msgid "Recommending is allowed only for 'Found it' logtypes."
|
||||
#~ msgstr "Rekomendacje są dozwolone jedynie z wpisem \"Znaleziona\"."
|
||||
|
||||
|
||||
@@ -839,6 +839,9 @@ class OAuthServer {
|
||||
if( ! $timestamp )
|
||||
throw new OAuthMissingParameterException('oauth_timestamp');
|
||||
|
||||
// Cast to integer. See issue #314.
|
||||
$timestamp = $timestamp + 0;
|
||||
|
||||
// verify that timestamp is recentish
|
||||
$now = time();
|
||||
if (abs($now - $timestamp) > $this->timestamp_threshold) {
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -6,186 +6,187 @@ use Exception;
|
||||
|
||||
class OkapiServiceRunner
|
||||
{
|
||||
#
|
||||
# This the list of all available OKAPI methods. All methods on this list become
|
||||
# immediately public and all of them have to be documented. It is not possible
|
||||
# to create an invisible or undocumented OKAPI method. If you want to test your
|
||||
# methods, you should do it in your local development server. If you want to
|
||||
# create a private, "internal" method, you still have to document it properly
|
||||
# (you may describe it as "internal" and accessible to selected consumer keys only).
|
||||
#
|
||||
public static $all_names = array(
|
||||
# Valid format: ^services/[0-9a-z_/]*$ (it means you may use only alphanumeric
|
||||
# characters and the "_" sign in your method names).
|
||||
'services/apisrv/installation',
|
||||
'services/apisrv/installations',
|
||||
'services/apisrv/stats',
|
||||
'services/apiref/method',
|
||||
'services/apiref/method_index',
|
||||
'services/apiref/issue',
|
||||
'services/attrs/attribute_index',
|
||||
'services/attrs/attribute',
|
||||
'services/attrs/attributes',
|
||||
'services/oauth/request_token',
|
||||
'services/oauth/authorize',
|
||||
'services/oauth/access_token',
|
||||
'services/caches/search/all',
|
||||
'services/caches/search/bbox',
|
||||
'services/caches/search/nearest',
|
||||
'services/caches/search/by_urls',
|
||||
'services/caches/search/save',
|
||||
'services/caches/shortcuts/search_and_retrieve',
|
||||
'services/caches/geocache',
|
||||
'services/caches/geocaches',
|
||||
'services/caches/mark',
|
||||
'services/caches/formatters/gpx',
|
||||
'services/caches/formatters/garmin',
|
||||
'services/caches/map/tile',
|
||||
'services/logs/entries',
|
||||
'services/logs/entry',
|
||||
'services/logs/logs',
|
||||
'services/logs/userlogs',
|
||||
'services/logs/submit',
|
||||
'services/users/user',
|
||||
'services/users/users',
|
||||
'services/users/by_usernames',
|
||||
'services/users/by_username',
|
||||
'services/users/by_internal_id',
|
||||
'services/users/by_internal_ids',
|
||||
'services/replicate/changelog',
|
||||
'services/replicate/fulldump',
|
||||
'services/replicate/info',
|
||||
);
|
||||
#
|
||||
# This the list of all available OKAPI methods. All methods on this list become
|
||||
# immediately public and all of them have to be documented. It is not possible
|
||||
# to create an invisible or undocumented OKAPI method. If you want to test your
|
||||
# methods, you should do it in your local development server. If you want to
|
||||
# create a private, "internal" method, you still have to document it properly
|
||||
# (you may describe it as "internal" and accessible to selected consumer keys only).
|
||||
#
|
||||
public static $all_names = array(
|
||||
# Valid format: ^services/[0-9a-z_/]*$ (it means you may use only alphanumeric
|
||||
# characters and the "_" sign in your method names).
|
||||
'services/apisrv/installation',
|
||||
'services/apisrv/installations',
|
||||
'services/apisrv/stats',
|
||||
'services/apiref/method',
|
||||
'services/apiref/method_index',
|
||||
'services/apiref/issue',
|
||||
'services/attrs/attribute_index',
|
||||
'services/attrs/attribute',
|
||||
'services/attrs/attributes',
|
||||
'services/oauth/request_token',
|
||||
'services/oauth/authorize',
|
||||
'services/oauth/access_token',
|
||||
'services/caches/search/all',
|
||||
'services/caches/search/bbox',
|
||||
'services/caches/search/nearest',
|
||||
'services/caches/search/by_urls',
|
||||
'services/caches/search/save',
|
||||
'services/caches/shortcuts/search_and_retrieve',
|
||||
'services/caches/geocache',
|
||||
'services/caches/geocaches',
|
||||
'services/caches/mark',
|
||||
'services/caches/save_personal_notes',
|
||||
'services/caches/formatters/gpx',
|
||||
'services/caches/formatters/garmin',
|
||||
'services/caches/map/tile',
|
||||
'services/logs/entries',
|
||||
'services/logs/entry',
|
||||
'services/logs/logs',
|
||||
'services/logs/userlogs',
|
||||
'services/logs/submit',
|
||||
'services/users/user',
|
||||
'services/users/users',
|
||||
'services/users/by_usernames',
|
||||
'services/users/by_username',
|
||||
'services/users/by_internal_id',
|
||||
'services/users/by_internal_ids',
|
||||
'services/replicate/changelog',
|
||||
'services/replicate/fulldump',
|
||||
'services/replicate/info',
|
||||
);
|
||||
|
||||
/** Check if method exists. */
|
||||
public static function exists($service_name)
|
||||
{
|
||||
return in_array($service_name, self::$all_names);
|
||||
}
|
||||
/** Check if method exists. */
|
||||
public static function exists($service_name)
|
||||
{
|
||||
return in_array($service_name, self::$all_names);
|
||||
}
|
||||
|
||||
/** Get method options (is consumer required etc.). */
|
||||
public static function options($service_name)
|
||||
{
|
||||
if (!self::exists($service_name))
|
||||
throw new Exception();
|
||||
require_once($GLOBALS['rootpath']."okapi/$service_name.php");
|
||||
try
|
||||
{
|
||||
return call_user_func(array('\\okapi\\'.
|
||||
str_replace('/', '\\', $service_name).'\\WebService', 'options'));
|
||||
} catch (Exception $e)
|
||||
{
|
||||
throw new Exception("Make sure you've declared your WebService class ".
|
||||
"in an valid namespace (".'okapi\\'.str_replace('/', '\\', $service_name)."); ".
|
||||
$e->getMessage());
|
||||
}
|
||||
}
|
||||
/** Get method options (is consumer required etc.). */
|
||||
public static function options($service_name)
|
||||
{
|
||||
if (!self::exists($service_name))
|
||||
throw new Exception();
|
||||
require_once($GLOBALS['rootpath']."okapi/$service_name.php");
|
||||
try
|
||||
{
|
||||
return call_user_func(array('\\okapi\\'.
|
||||
str_replace('/', '\\', $service_name).'\\WebService', 'options'));
|
||||
} catch (Exception $e)
|
||||
{
|
||||
throw new Exception("Make sure you've declared your WebService class ".
|
||||
"in an valid namespace (".'okapi\\'.str_replace('/', '\\', $service_name)."); ".
|
||||
$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get method documentation file contents (stuff within the XML file).
|
||||
* If you're looking for a parsed representation, use services/apiref/method.
|
||||
*/
|
||||
public static function docs($service_name)
|
||||
{
|
||||
if (!self::exists($service_name))
|
||||
throw new Exception();
|
||||
try {
|
||||
return file_get_contents("$service_name.xml", true);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Missing documentation file: $service_name.xml");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get method documentation file contents (stuff within the XML file).
|
||||
* If you're looking for a parsed representation, use services/apiref/method.
|
||||
*/
|
||||
public static function docs($service_name)
|
||||
{
|
||||
if (!self::exists($service_name))
|
||||
throw new Exception();
|
||||
try {
|
||||
return file_get_contents("$service_name.xml", true);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Missing documentation file: $service_name.xml");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the method and return the result.
|
||||
*
|
||||
* OKAPI methods return OkapiHttpResponses, but some MAY also return
|
||||
* PHP objects (see OkapiRequest::construct_inside_request for details).
|
||||
*
|
||||
* If $request must be consistent with given method's options (must
|
||||
* include Consumer and Token, if they are required).
|
||||
*/
|
||||
public static function call($service_name, OkapiRequest $request)
|
||||
{
|
||||
Okapi::init_internals();
|
||||
/**
|
||||
* Execute the method and return the result.
|
||||
*
|
||||
* OKAPI methods return OkapiHttpResponses, but some MAY also return
|
||||
* PHP objects (see OkapiRequest::construct_inside_request for details).
|
||||
*
|
||||
* If $request must be consistent with given method's options (must
|
||||
* include Consumer and Token, if they are required).
|
||||
*/
|
||||
public static function call($service_name, OkapiRequest $request)
|
||||
{
|
||||
Okapi::init_internals();
|
||||
|
||||
if (!self::exists($service_name))
|
||||
throw new Exception("Method does not exist: '$service_name'");
|
||||
if (!self::exists($service_name))
|
||||
throw new Exception("Method does not exist: '$service_name'");
|
||||
|
||||
$options = self::options($service_name);
|
||||
if ($options['min_auth_level'] >= 2 && $request->consumer == null)
|
||||
{
|
||||
throw new Exception("Method '$service_name' called with mismatched OkapiRequest: ".
|
||||
"\$request->consumer MAY NOT be empty for Level 2 and Level 3 methods. Provide ".
|
||||
"a dummy Consumer if you have to.");
|
||||
}
|
||||
if ($options['min_auth_level'] >= 3 && $request->token == null)
|
||||
{
|
||||
throw new Exception("Method '$service_name' called with mismatched OkapiRequest: ".
|
||||
"\$request->token MAY NOT be empty for Level 3 methods.");
|
||||
}
|
||||
$options = self::options($service_name);
|
||||
if ($options['min_auth_level'] >= 2 && $request->consumer == null)
|
||||
{
|
||||
throw new Exception("Method '$service_name' called with mismatched OkapiRequest: ".
|
||||
"\$request->consumer MAY NOT be empty for Level 2 and Level 3 methods. Provide ".
|
||||
"a dummy Consumer if you have to.");
|
||||
}
|
||||
if ($options['min_auth_level'] >= 3 && $request->token == null)
|
||||
{
|
||||
throw new Exception("Method '$service_name' called with mismatched OkapiRequest: ".
|
||||
"\$request->token MAY NOT be empty for Level 3 methods.");
|
||||
}
|
||||
|
||||
$time_started = microtime(true);
|
||||
Okapi::gettext_domain_init();
|
||||
try
|
||||
{
|
||||
require_once($GLOBALS['rootpath']."okapi/$service_name.php");
|
||||
$response = call_user_func(array('\\okapi\\'.
|
||||
str_replace('/', '\\', $service_name).'\\WebService', 'call'), $request);
|
||||
Okapi::gettext_domain_restore();
|
||||
} catch (Exception $e) {
|
||||
Okapi::gettext_domain_restore();
|
||||
throw $e;
|
||||
}
|
||||
$runtime = microtime(true) - $time_started;
|
||||
$time_started = microtime(true);
|
||||
Okapi::gettext_domain_init();
|
||||
try
|
||||
{
|
||||
require_once($GLOBALS['rootpath']."okapi/$service_name.php");
|
||||
$response = call_user_func(array('\\okapi\\'.
|
||||
str_replace('/', '\\', $service_name).'\\WebService', 'call'), $request);
|
||||
Okapi::gettext_domain_restore();
|
||||
} catch (Exception $e) {
|
||||
Okapi::gettext_domain_restore();
|
||||
throw $e;
|
||||
}
|
||||
$runtime = microtime(true) - $time_started;
|
||||
|
||||
# Log the request to the stats table. Only valid requests (these which didn't end up
|
||||
# with an exception) are logged.
|
||||
self::save_stats($service_name, $request, $runtime);
|
||||
# Log the request to the stats table. Only valid requests (these which didn't end up
|
||||
# with an exception) are logged.
|
||||
self::save_stats($service_name, $request, $runtime);
|
||||
|
||||
return $response;
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use only. The stats table can be used to store any kind of
|
||||
* runtime-stats data, i.e. not only regarding services. This is a special
|
||||
* version of save_stats which saves runtime stats under the name of $extra_name.
|
||||
* Note, that $request can be null.
|
||||
*/
|
||||
public static function save_stats_extra($extra_name, $request, $runtime)
|
||||
{
|
||||
self::save_stats("extra/".$extra_name, $request, $runtime);
|
||||
}
|
||||
/**
|
||||
* For internal use only. The stats table can be used to store any kind of
|
||||
* runtime-stats data, i.e. not only regarding services. This is a special
|
||||
* version of save_stats which saves runtime stats under the name of $extra_name.
|
||||
* Note, that $request can be null.
|
||||
*/
|
||||
public static function save_stats_extra($extra_name, $request, $runtime)
|
||||
{
|
||||
self::save_stats("extra/".$extra_name, $request, $runtime);
|
||||
}
|
||||
|
||||
private static function save_stats($service_name, $request, $runtime)
|
||||
{
|
||||
# Getting rid of nulls. MySQL PRIMARY keys cannot contain nullable columns.
|
||||
# Temp table doesn't have primary key, but other stats tables (which are
|
||||
# dependant on stats table) - do.
|
||||
private static function save_stats($service_name, $request, $runtime)
|
||||
{
|
||||
# Getting rid of nulls. MySQL PRIMARY keys cannot contain nullable columns.
|
||||
# Temp table doesn't have primary key, but other stats tables (which are
|
||||
# dependant on stats table) - do.
|
||||
|
||||
if ($request !== null) {
|
||||
$consumer_key = ($request->consumer != null) ? $request->consumer->key : 'anonymous';
|
||||
$user_id = (($request->token != null) && ($request->token instanceof OkapiAccessToken)) ? $request->token->user_id : -1;
|
||||
if ($request->is_http_request() && ($service_name[0] == 's')) # 's' for "services/", we don't want "extra/" included
|
||||
$calltype = 'http';
|
||||
else
|
||||
$calltype = 'internal';
|
||||
} else {
|
||||
$consumer_key = 'internal';
|
||||
$user_id = -1;
|
||||
$calltype = 'internal';
|
||||
}
|
||||
if ($request !== null) {
|
||||
$consumer_key = ($request->consumer != null) ? $request->consumer->key : 'anonymous';
|
||||
$user_id = (($request->token != null) && ($request->token instanceof OkapiAccessToken)) ? $request->token->user_id : -1;
|
||||
if ($request->is_http_request() && ($service_name[0] == 's')) # 's' for "services/", we don't want "extra/" included
|
||||
$calltype = 'http';
|
||||
else
|
||||
$calltype = 'internal';
|
||||
} else {
|
||||
$consumer_key = 'internal';
|
||||
$user_id = -1;
|
||||
$calltype = 'internal';
|
||||
}
|
||||
|
||||
Db::execute("
|
||||
insert into okapi_stats_temp (`datetime`, consumer_key, user_id, service_name, calltype, runtime)
|
||||
values (
|
||||
now(),
|
||||
'".mysql_real_escape_string($consumer_key)."',
|
||||
'".mysql_real_escape_string($user_id)."',
|
||||
'".mysql_real_escape_string($service_name)."',
|
||||
'".mysql_real_escape_string($calltype)."',
|
||||
'".mysql_real_escape_string($runtime)."'
|
||||
);
|
||||
");
|
||||
}
|
||||
Db::execute("
|
||||
insert into okapi_stats_temp (`datetime`, consumer_key, user_id, service_name, calltype, runtime)
|
||||
values (
|
||||
now(),
|
||||
'".mysql_real_escape_string($consumer_key)."',
|
||||
'".mysql_real_escape_string($user_id)."',
|
||||
'".mysql_real_escape_string($service_name)."',
|
||||
'".mysql_real_escape_string($calltype)."',
|
||||
'".mysql_real_escape_string($runtime)."'
|
||||
);
|
||||
");
|
||||
}
|
||||
}
|
||||
@@ -15,32 +15,32 @@ use okapi\Cache;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$issue_id = $request->get_parameter('issue_id');
|
||||
if (!$issue_id)
|
||||
throw new ParamMissing('issue_id');
|
||||
if ((!preg_match("/^[0-9]+$/", $issue_id)) || (strlen($issue_id) > 6))
|
||||
throw new InvalidParam('issue_id');
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$issue_id = $request->get_parameter('issue_id');
|
||||
if (!$issue_id)
|
||||
throw new ParamMissing('issue_id');
|
||||
if ((!preg_match("/^[0-9]+$/", $issue_id)) || (strlen($issue_id) > 6))
|
||||
throw new InvalidParam('issue_id');
|
||||
|
||||
# In October 2013, Google Code feed at:
|
||||
# http://code.google.com/feeds/issues/p/opencaching-api/issues/$issue_id/comments/full
|
||||
# stopped working. We are forced to respond with a simple placeholder.
|
||||
|
||||
$result = array(
|
||||
'id' => $issue_id + 0,
|
||||
'last_updated' => null,
|
||||
'title' => null,
|
||||
'url' => "https://code.google.com/p/opencaching-api/issues/detail?id=".$issue_id,
|
||||
'comment_count' => null
|
||||
);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
# In October 2013, Google Code feed at:
|
||||
# http://code.google.com/feeds/issues/p/opencaching-api/issues/$issue_id/comments/full
|
||||
# stopped working. We are forced to respond with a simple placeholder.
|
||||
|
||||
$result = array(
|
||||
'id' => $issue_id + 0,
|
||||
'last_updated' => null,
|
||||
'title' => null,
|
||||
'url' => "https://code.google.com/p/opencaching-api/issues/detail?id=".$issue_id,
|
||||
'comment_count' => null
|
||||
);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<xml>
|
||||
<brief>Retrieve information on given issue</brief>
|
||||
<issue-id>11</issue-id>
|
||||
<desc>
|
||||
<p><b>Important:</b> This method stopped working properly in October 2013.
|
||||
Now, it returns a simple placeholder.
|
||||
<a href='https://code.google.com/p/opencaching-api/issues/detail?id=288'>Read more</a>.</p>
|
||||
|
||||
<p>OKAPI is trying to be as <b>integrated</b> with its
|
||||
<a href='http://code.google.com/p/opencaching-api/'>Main Project Page</a> as it can.
|
||||
This method retrieves basic information on a given issue from our project
|
||||
<a href='http://code.google.com/p/opencaching-api/issues/list'>Issue Tracker</a>.
|
||||
In future, it <b>might</b> also return some of the latest comments (we're not yet
|
||||
sure if we want them displayed on our documentation pages).</p>
|
||||
</desc>
|
||||
<req name='issue_id'>
|
||||
ID of an Issue.
|
||||
</req>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>id</b> - number of the issue created for this method,</li>
|
||||
<li><b>last_updated</b> - date and time (ISO 8601) when the issue was last updated
|
||||
<b>or null</b> if unknown,</li>
|
||||
<li><b>title</b> - issue title <b>or null</b> if unknown,</li>
|
||||
<li><b>url</b> - URL of the issue page,</li>
|
||||
<li><b>comment_count</b> - total number of submitted comments <b>or null</b> if unknown.</li>
|
||||
</ul>
|
||||
<p>Note, that this will respond with HTTP 400 if we fail to retrieve data from
|
||||
the Google Code site.</p>
|
||||
</returns>
|
||||
<brief>Retrieve information on given issue</brief>
|
||||
<issue-id>11</issue-id>
|
||||
<desc>
|
||||
<p><b>Important:</b> This method stopped working properly in October 2013.
|
||||
Now, it returns a simple placeholder.
|
||||
<a href='https://code.google.com/p/opencaching-api/issues/detail?id=288'>Read more</a>.</p>
|
||||
|
||||
<p>OKAPI is trying to be as <b>integrated</b> with its
|
||||
<a href='http://code.google.com/p/opencaching-api/'>Main Project Page</a> as it can.
|
||||
This method retrieves basic information on a given issue from our project
|
||||
<a href='http://code.google.com/p/opencaching-api/issues/list'>Issue Tracker</a>.
|
||||
In future, it <b>might</b> also return some of the latest comments (we're not yet
|
||||
sure if we want them displayed on our documentation pages).</p>
|
||||
</desc>
|
||||
<req name='issue_id'>
|
||||
ID of an Issue.
|
||||
</req>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>id</b> - number of the issue created for this method,</li>
|
||||
<li><b>last_updated</b> - date and time (ISO 8601) when the issue was last updated
|
||||
<b>or null</b> if unknown,</li>
|
||||
<li><b>title</b> - issue title <b>or null</b> if unknown,</li>
|
||||
<li><b>url</b> - URL of the issue page,</li>
|
||||
<li><b>comment_count</b> - total number of submitted comments <b>or null</b> if unknown.</li>
|
||||
</ul>
|
||||
<p>Note, that this will respond with HTTP 400 if we fail to retrieve data from
|
||||
the Google Code site.</p>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -14,135 +14,216 @@ use okapi\OkapiInternalConsumer;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
|
||||
private static function arg_desc($arg_node)
|
||||
{
|
||||
$attrs = $arg_node->attributes();
|
||||
return array(
|
||||
'name' => (string)$attrs['name'],
|
||||
'is_required' => $arg_node->getName() == 'req',
|
||||
'is_deprecated' => (isset($attrs['class']) && (strpos($attrs['class'], 'deprecated') !== false)),
|
||||
'class' => 'public',
|
||||
'description' =>
|
||||
(isset($attrs['default']) ? ("<p>Default value: <b>".$attrs['default']."</b></p>") : "").
|
||||
self::get_inner_xml($arg_node),
|
||||
private static function arg_desc($arg_node)
|
||||
{
|
||||
$attrs = $arg_node->attributes();
|
||||
return array(
|
||||
'name' => (string)$attrs['name'],
|
||||
'is_required' => $arg_node->getName() == 'req',
|
||||
'is_deprecated' => (isset($attrs['class']) && (strpos($attrs['class'], 'deprecated') !== false)),
|
||||
'class' => 'public',
|
||||
'description' =>
|
||||
(isset($attrs['default']) ? ("<p>Default value: <b>".$attrs['default']."</b></p>") : "").
|
||||
self::get_inner_xml($arg_node),
|
||||
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static function get_inner_xml($node)
|
||||
{
|
||||
$s = $node->asXML();
|
||||
$start = strpos($s, ">") + 1;
|
||||
$length = strlen($s) - $start - (3 + strlen($node->getName()));
|
||||
return substr($s, $start, $length);
|
||||
}
|
||||
private static function get_inner_xml($node)
|
||||
{
|
||||
/* Fetch as <some-node>content</some-node>, extract content. */
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$methodname = $request->get_parameter('name');
|
||||
if (!$methodname)
|
||||
throw new ParamMissing('name');
|
||||
if (!preg_match("#^services/[0-9a-z_/]*$#", $methodname))
|
||||
throw new InvalidParam('name');
|
||||
if (!OkapiServiceRunner::exists($methodname))
|
||||
throw new InvalidParam('name', "Method does not exist: '$methodname'.");
|
||||
$options = OkapiServiceRunner::options($methodname);
|
||||
if (!isset($options['min_auth_level']))
|
||||
throw new Exception("Method $methodname is missing a required 'min_auth_level' option!");
|
||||
$docs = simplexml_load_string(OkapiServiceRunner::docs($methodname));
|
||||
$exploded = explode("/", $methodname);
|
||||
$result = array(
|
||||
'name' => $methodname,
|
||||
'short_name' => end($exploded),
|
||||
'ref_url' => Settings::get('SITE_URL')."okapi/$methodname.html",
|
||||
'auth_options' => array(
|
||||
'min_auth_level' => $options['min_auth_level'],
|
||||
'oauth_consumer' => $options['min_auth_level'] >= 2,
|
||||
'oauth_token' => $options['min_auth_level'] >= 3,
|
||||
)
|
||||
);
|
||||
if (!$docs->brief)
|
||||
throw new Exception("Missing <brief> element in the $methodname.xml file.");
|
||||
if ($docs->brief != self::get_inner_xml($docs->brief))
|
||||
throw new Exception("The <brief> element may not contain HTML markup ($methodname.xml).");
|
||||
if (strlen($docs->brief) > 80)
|
||||
throw new Exception("The <brief> description may not be longer than 80 characters ($methodname.xml).");
|
||||
if (strpos($docs->brief, "\n") !== false)
|
||||
throw new Exception("The <brief> element may not contain new-lines ($methodname.xml).");
|
||||
if (substr(trim($docs->brief), -1) == '.')
|
||||
throw new Exception("The <brief> element should not end with a dot ($methodname.xml).");
|
||||
$result['brief_description'] = self::get_inner_xml($docs->brief);
|
||||
if ($docs->{'issue-id'})
|
||||
$result['issue_id'] = (string)$docs->{'issue-id'};
|
||||
else
|
||||
$result['issue_id'] = null;
|
||||
if (!$docs->desc)
|
||||
throw new Exception("Missing <desc> element in the $methodname.xml file.");
|
||||
$result['description'] = self::get_inner_xml($docs->desc);
|
||||
$result['arguments'] = array();
|
||||
foreach ($docs->req as $arg) { $result['arguments'][] = self::arg_desc($arg); }
|
||||
foreach ($docs->opt as $arg) { $result['arguments'][] = self::arg_desc($arg); }
|
||||
foreach ($docs->{'import-params'} as $import_desc)
|
||||
{
|
||||
$attrs = $import_desc->attributes();
|
||||
$referenced_methodname = $attrs['method'];
|
||||
$referenced_method_info = OkapiServiceRunner::call('services/apiref/method',
|
||||
new OkapiInternalRequest(new OkapiInternalConsumer(), null, array('name' => $referenced_methodname)));
|
||||
$include_list = isset($attrs['params']) ? explode("|", $attrs['params']) : null;
|
||||
$exclude_list = isset($attrs['except']) ? explode("|", $attrs['except']) : array();
|
||||
foreach ($referenced_method_info['arguments'] as $arg)
|
||||
{
|
||||
if ($arg['class'] == 'common-formatting')
|
||||
continue;
|
||||
if (($include_list === null) && (count($exclude_list) == 0))
|
||||
{
|
||||
$arg['description'] = "<i>Inherited from <a href='".$referenced_method_info['ref_url'].
|
||||
"'>".$referenced_method_info['name']."</a> method.</i>";
|
||||
}
|
||||
elseif (
|
||||
(($include_list === null) || in_array($arg['name'], $include_list))
|
||||
&& (!in_array($arg['name'], $exclude_list))
|
||||
) {
|
||||
$arg['description'] = "<i>Same as in the <a href='".$referenced_method_info['ref_url'].
|
||||
"'>".$referenced_method_info['name']."</a> method.</i>";
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$arg['class'] = 'inherited';
|
||||
$result['arguments'][] = $arg;
|
||||
}
|
||||
}
|
||||
if ($docs->{'common-format-params'})
|
||||
{
|
||||
$result['arguments'][] = array(
|
||||
'name' => 'format',
|
||||
'is_required' => false,
|
||||
'is_deprecated' => false,
|
||||
'class' => 'common-formatting',
|
||||
'description' => "<i>Standard <a href='".Settings::get('SITE_URL')."okapi/introduction.html#common-formatting'>common formatting</a> argument.</i>"
|
||||
);
|
||||
$result['arguments'][] = array(
|
||||
'name' => 'callback',
|
||||
'is_required' => false,
|
||||
'is_deprecated' => false,
|
||||
'class' => 'common-formatting',
|
||||
'description' => "<i>Standard <a href='".Settings::get('SITE_URL')."okapi/introduction.html#common-formatting'>common formatting</a> argument.</i>"
|
||||
);
|
||||
}
|
||||
foreach ($result['arguments'] as &$arg_ref)
|
||||
if ($arg_ref['is_deprecated'])
|
||||
$arg_ref['class'] .= " deprecated";
|
||||
if (!$docs->returns)
|
||||
throw new Exception("Missing <returns> element in the $methodname.xml file. ".
|
||||
"If your method does not return anything, you should document in nonetheless.");
|
||||
$result['returns'] = self::get_inner_xml($docs->returns);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
$s = $node->asXML();
|
||||
$start = strpos($s, ">") + 1;
|
||||
$length = strlen($s) - $start - (3 + strlen($node->getName()));
|
||||
$s = substr($s, $start, $length);
|
||||
|
||||
/* Find and replace %okapi:plugins%. */
|
||||
|
||||
$s = preg_replace_callback('~%OKAPI:([a-z:/_#]+)%~', array("self", "plugin_callback"), $s);
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* You can use the following syntax:
|
||||
*
|
||||
* <a href="%OKAPI:docurl:fragment%">any text</a> - to reference fragment of introducing
|
||||
* documentation
|
||||
*
|
||||
* <a href="%OKAPI:methodref:methodname%">any text</a> - to reference any other method
|
||||
*
|
||||
* <a href="%OKAPI:methodref:methodname#html_anchor%">any text</a> - to reference
|
||||
* any HTML anchor in other method
|
||||
*
|
||||
* <a href="%OKAPI:methodref:#html_anchor%">any text</a> - to reference any HTML
|
||||
* anchor within current document
|
||||
*
|
||||
* <a href="%OKAPI:methodargref:methodname#argument_name%">any text</a> - to
|
||||
* reference argument of another method
|
||||
*
|
||||
* <a href="%OKAPI:methodargref:#argument_name%">any text</a> - to reference
|
||||
* argument within current method
|
||||
*
|
||||
* <a href="%OKAPI:methodretref:methodname#returned_key%">any text</a> - to
|
||||
* reference returned value of another method
|
||||
*
|
||||
* <a href="%OKAPI:methodretref:#returned_key%">any text</a> - to reference
|
||||
* returned value within current method
|
||||
*
|
||||
* NOTE!
|
||||
*
|
||||
* Since returned JSON dictionaries are not standardized (they are simply plain
|
||||
* HTML in the docs), to reference returned values you must manually create an
|
||||
* anchor prefixed with ret_, i.e. (HTML snippet): <li
|
||||
* id="ret_alt_wpts"><p><b>alt_wpts</b> - list of alternate/additional
|
||||
* waypoints</...> and access it with (HTML snippet): <a
|
||||
* href="%OKAPI:methodretref:#alt_wpts%">any text</a>.
|
||||
*/
|
||||
public static function plugin_callback($matches)
|
||||
{
|
||||
$input = $matches[1];
|
||||
$arr = explode(":", $input);
|
||||
$plugin_name = $arr[0];
|
||||
|
||||
switch ($plugin_name) {
|
||||
case 'docurl':
|
||||
$fragment = $arr[1];
|
||||
return Settings::get('SITE_URL')."okapi/introduction.html#".$fragment;
|
||||
case 'methodref':
|
||||
case 'methodargref':
|
||||
case 'methodretref':
|
||||
$elements = explode('#', $arr[1]);
|
||||
$result = '';
|
||||
if ($elements[0] != '')
|
||||
{
|
||||
$result .= Settings::get('SITE_URL')."okapi/".$elements[0].'.html';
|
||||
}
|
||||
if (count($elements) > 1)
|
||||
{
|
||||
$result .= '#';
|
||||
switch ($plugin_name) {
|
||||
case 'methodargref':
|
||||
$result .= 'arg_';
|
||||
break;
|
||||
case 'methodretref':
|
||||
$result .= 'ret_';
|
||||
break;
|
||||
}
|
||||
$result .= $elements[1];
|
||||
}
|
||||
return $result;
|
||||
default:
|
||||
throw new Exception("Unknown plugin: ".$input);
|
||||
}
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$methodname = $request->get_parameter('name');
|
||||
if (!$methodname)
|
||||
throw new ParamMissing('name');
|
||||
if (!preg_match("#^services/[0-9a-z_/]*$#", $methodname))
|
||||
throw new InvalidParam('name');
|
||||
if (!OkapiServiceRunner::exists($methodname))
|
||||
throw new InvalidParam('name', "Method does not exist: '$methodname'.");
|
||||
$options = OkapiServiceRunner::options($methodname);
|
||||
if (!isset($options['min_auth_level']))
|
||||
throw new Exception("Method $methodname is missing a required 'min_auth_level' option!");
|
||||
$docs = simplexml_load_string(OkapiServiceRunner::docs($methodname));
|
||||
$exploded = explode("/", $methodname);
|
||||
$result = array(
|
||||
'name' => $methodname,
|
||||
'short_name' => end($exploded),
|
||||
'ref_url' => Settings::get('SITE_URL')."okapi/$methodname.html",
|
||||
'auth_options' => array(
|
||||
'min_auth_level' => $options['min_auth_level'],
|
||||
'oauth_consumer' => $options['min_auth_level'] >= 2,
|
||||
'oauth_token' => $options['min_auth_level'] >= 3,
|
||||
)
|
||||
);
|
||||
if (!$docs->brief)
|
||||
throw new Exception("Missing <brief> element in the $methodname.xml file.");
|
||||
if ($docs->brief != self::get_inner_xml($docs->brief))
|
||||
throw new Exception("The <brief> element may not contain HTML markup ($methodname.xml).");
|
||||
if (strlen($docs->brief) > 80)
|
||||
throw new Exception("The <brief> description may not be longer than 80 characters ($methodname.xml).");
|
||||
if (strpos($docs->brief, "\n") !== false)
|
||||
throw new Exception("The <brief> element may not contain new-lines ($methodname.xml).");
|
||||
if (substr(trim($docs->brief), -1) == '.')
|
||||
throw new Exception("The <brief> element should not end with a dot ($methodname.xml).");
|
||||
$result['brief_description'] = self::get_inner_xml($docs->brief);
|
||||
if ($docs->{'issue-id'})
|
||||
$result['issue_id'] = (string)$docs->{'issue-id'};
|
||||
else
|
||||
$result['issue_id'] = null;
|
||||
if (!$docs->desc)
|
||||
throw new Exception("Missing <desc> element in the $methodname.xml file.");
|
||||
$result['description'] = self::get_inner_xml($docs->desc);
|
||||
$result['arguments'] = array();
|
||||
foreach ($docs->req as $arg) { $result['arguments'][] = self::arg_desc($arg); }
|
||||
foreach ($docs->opt as $arg) { $result['arguments'][] = self::arg_desc($arg); }
|
||||
foreach ($docs->{'import-params'} as $import_desc)
|
||||
{
|
||||
$attrs = $import_desc->attributes();
|
||||
$referenced_methodname = $attrs['method'];
|
||||
$referenced_method_info = OkapiServiceRunner::call('services/apiref/method',
|
||||
new OkapiInternalRequest(new OkapiInternalConsumer(), null, array('name' => $referenced_methodname)));
|
||||
$include_list = isset($attrs['params']) ? explode("|", $attrs['params']) : null;
|
||||
$exclude_list = isset($attrs['except']) ? explode("|", $attrs['except']) : array();
|
||||
foreach ($referenced_method_info['arguments'] as $arg)
|
||||
{
|
||||
if ($arg['class'] == 'common-formatting')
|
||||
continue;
|
||||
if (($include_list === null) && (count($exclude_list) == 0))
|
||||
{
|
||||
$arg['description'] = "<i>Inherited from <a href='".$referenced_method_info['ref_url'].
|
||||
"'>".$referenced_method_info['name']."</a> method.</i>";
|
||||
}
|
||||
elseif (
|
||||
(($include_list === null) || in_array($arg['name'], $include_list))
|
||||
&& (!in_array($arg['name'], $exclude_list))
|
||||
) {
|
||||
$arg['description'] = "<i>Same as in the <a href='".$referenced_method_info['ref_url'].
|
||||
"'>".$referenced_method_info['name']."</a> method.</i>";
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$arg['class'] = 'inherited';
|
||||
$result['arguments'][] = $arg;
|
||||
}
|
||||
}
|
||||
if ($docs->{'common-format-params'})
|
||||
{
|
||||
$result['arguments'][] = array(
|
||||
'name' => 'format',
|
||||
'is_required' => false,
|
||||
'is_deprecated' => false,
|
||||
'class' => 'common-formatting',
|
||||
'description' => "<i>Standard <a href='".Settings::get('SITE_URL')."okapi/introduction.html#common-formatting'>common formatting</a> argument.</i>"
|
||||
);
|
||||
$result['arguments'][] = array(
|
||||
'name' => 'callback',
|
||||
'is_required' => false,
|
||||
'is_deprecated' => false,
|
||||
'class' => 'common-formatting',
|
||||
'description' => "<i>Standard <a href='".Settings::get('SITE_URL')."okapi/introduction.html#common-formatting'>common formatting</a> argument.</i>"
|
||||
);
|
||||
}
|
||||
foreach ($result['arguments'] as &$arg_ref)
|
||||
if ($arg_ref['is_deprecated'])
|
||||
$arg_ref['class'] .= " deprecated";
|
||||
if (!$docs->returns)
|
||||
throw new Exception("Missing <returns> element in the $methodname.xml file. ".
|
||||
"If your method does not return anything, you should document in nonetheless.");
|
||||
$result['returns'] = self::get_inner_xml($docs->returns);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
<xml>
|
||||
<brief>Get information on a given OKAPI service method</brief>
|
||||
<issue-id>13</issue-id>
|
||||
<desc>
|
||||
<p>This method allows you to <b>access API documentation</b> (the same which you
|
||||
are reading just now). Given a method name, it returns a complete method description.</p>
|
||||
</desc>
|
||||
<req name='name'>
|
||||
Name of a method (begins with "services/").
|
||||
</req>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>name</b> - name of the method,</li>
|
||||
<li><b>short_name</b> - name without a path,</li>
|
||||
<li><b>issue_id</b> - ID of the "general discussion" issue (in our project's
|
||||
homepage Issue Tracker) associated with this method <b>or null</b> if this
|
||||
method has associated issue,</li>
|
||||
<li><b>description</b> - HTML-formatted description of what the method does,</li>
|
||||
<li><b>brief_description</b> - brief (max 80 characters), single-line,
|
||||
plain-text description of what the method does,</li>
|
||||
<li><b>ref_url</b> - URL of the documentation page with method description,</li>
|
||||
<li>
|
||||
<b>auth_options</b> - a dictionary which describes authentication
|
||||
requirements for this method, it has a following structure:
|
||||
<ul>
|
||||
<li><b>min_auth_level</b> - integer, in range from 0 to 3,
|
||||
see Introduction page.</li>
|
||||
<li><b>oauth_consumer</b> - true, if requests are required to be signed
|
||||
with OAuth Consumer Key (min_auth_level >= 2),</li>
|
||||
<li><b>oauth_token</b> - true, if requests are required to include an
|
||||
OAuth Token (min_auth_level == 3).</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>arguments</b> - list of dictionaries, describes method
|
||||
arguments. Each dictionary has a following structure:
|
||||
<ul>
|
||||
<li><b>name</b> - name of an argument,</li>
|
||||
<li><b>is_required</b> - boolean, true if the argument is required,</li>
|
||||
<li><b>is_deprecated</b> - boolean, true if the argument is deprecated,</li>
|
||||
<li><b>description</b> - HTML-formatted description of an argument.</li>
|
||||
<li>
|
||||
<p><b>class</b> - space separated list of the following values: <i>public</i>,
|
||||
<i>inherited</i>, <i>common-formatting</i> and <i>deprecated</i>
|
||||
(other values might be introduced in future).</p>
|
||||
<p>Currently these values do not mean anything specific. They are
|
||||
used for different coloring/styling in the documentation pages.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>returns</b> - HTML-formatted description method's return value.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Get information on a given OKAPI service method</brief>
|
||||
<issue-id>13</issue-id>
|
||||
<desc>
|
||||
<p>This method allows you to <b>access API documentation</b> (the same which you
|
||||
are reading just now). Given a method name, it returns a complete method description.</p>
|
||||
</desc>
|
||||
<req name='name'>
|
||||
Name of a method (begins with "services/").
|
||||
</req>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>name</b> - name of the method,</li>
|
||||
<li><b>short_name</b> - name without a path,</li>
|
||||
<li><b>issue_id</b> - ID of the "general discussion" issue (in our project's
|
||||
homepage Issue Tracker) associated with this method <b>or null</b> if this
|
||||
method has associated issue,</li>
|
||||
<li><b>description</b> - HTML-formatted description of what the method does,</li>
|
||||
<li><b>brief_description</b> - brief (max 80 characters), single-line,
|
||||
plain-text description of what the method does,</li>
|
||||
<li><b>ref_url</b> - URL of the documentation page with method description,</li>
|
||||
<li>
|
||||
<b>auth_options</b> - a dictionary which describes authentication
|
||||
requirements for this method, it has a following structure:
|
||||
<ul>
|
||||
<li><b>min_auth_level</b> - integer, in range from 0 to 3,
|
||||
see Introduction page.</li>
|
||||
<li><b>oauth_consumer</b> - true, if requests are required to be signed
|
||||
with OAuth Consumer Key (min_auth_level >= 2),</li>
|
||||
<li><b>oauth_token</b> - true, if requests are required to include an
|
||||
OAuth Token (min_auth_level == 3).</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>arguments</b> - list of dictionaries, describes method
|
||||
arguments. Each dictionary has a following structure:
|
||||
<ul>
|
||||
<li><b>name</b> - name of an argument,</li>
|
||||
<li><b>is_required</b> - boolean, true if the argument is required,</li>
|
||||
<li><b>is_deprecated</b> - boolean, true if the argument is deprecated,</li>
|
||||
<li><b>description</b> - HTML-formatted description of an argument.</li>
|
||||
<li>
|
||||
<p><b>class</b> - space separated list of the following values: <i>public</i>,
|
||||
<i>inherited</i>, <i>common-formatting</i> and <i>deprecated</i>
|
||||
(other values might be introduced in future).</p>
|
||||
<p>Currently these values do not mean anything specific. They are
|
||||
used for different coloring/styling in the documentation pages.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>returns</b> - HTML-formatted description method's return value.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -15,33 +15,33 @@ use okapi\OkapiInternalRequest;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$methodnames = OkapiServiceRunner::$all_names;
|
||||
sort($methodnames);
|
||||
$cache_key = "api_ref/method_index#".md5(implode("#", $methodnames));
|
||||
$results = Cache::get($cache_key);
|
||||
if ($results == null)
|
||||
{
|
||||
$results = array();
|
||||
foreach ($methodnames as $methodname)
|
||||
{
|
||||
$info = OkapiServiceRunner::call('services/apiref/method', new OkapiInternalRequest(
|
||||
new OkapiInternalConsumer(), null, array('name' => $methodname)));
|
||||
$results[] = array(
|
||||
'name' => $info['name'],
|
||||
'brief_description' => $info['brief_description'],
|
||||
);
|
||||
}
|
||||
Cache::set($cache_key, $results, 3600);
|
||||
}
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$methodnames = OkapiServiceRunner::$all_names;
|
||||
sort($methodnames);
|
||||
$cache_key = "api_ref/method_index#".md5(implode("#", $methodnames));
|
||||
$results = Cache::get($cache_key);
|
||||
if ($results == null)
|
||||
{
|
||||
$results = array();
|
||||
foreach ($methodnames as $methodname)
|
||||
{
|
||||
$info = OkapiServiceRunner::call('services/apiref/method', new OkapiInternalRequest(
|
||||
new OkapiInternalConsumer(), null, array('name' => $methodname)));
|
||||
$results[] = array(
|
||||
'name' => $info['name'],
|
||||
'brief_description' => $info['brief_description'],
|
||||
);
|
||||
}
|
||||
Cache::set($cache_key, $results, 3600);
|
||||
}
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<xml>
|
||||
<brief>Get a list of OKAPI methods with brief descriptions</brief>
|
||||
<issue-id>12</issue-id>
|
||||
<desc>
|
||||
<p>Get a list of OKAPI methods with brief descriptions.</p>
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
A list of dictionaries, each of which contains one API
|
||||
method description in the following format:
|
||||
<ul>
|
||||
<li><b>name</b> - name of a method,</li>
|
||||
<li><b>brief_description</b> - brief (max 80 characters), single-line,
|
||||
plain-text description of what the method does.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Get a list of OKAPI methods with brief descriptions</brief>
|
||||
<issue-id>12</issue-id>
|
||||
<desc>
|
||||
<p>Get a list of OKAPI methods with brief descriptions.</p>
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
A list of dictionaries, each of which contains one API
|
||||
method description in the following format:
|
||||
<ul>
|
||||
<li><b>name</b> - name of a method,</li>
|
||||
<li><b>brief_description</b> - brief (max 80 characters), single-line,
|
||||
plain-text description of what the method does.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -13,20 +13,20 @@ use okapi\OkapiInternalRequest;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$result = array();
|
||||
$result['site_url'] = Settings::get('SITE_URL');
|
||||
$result['okapi_base_url'] = $result['site_url']."okapi/";
|
||||
$result['site_name'] = Okapi::get_normalized_site_name();
|
||||
$result['okapi_revision'] = Okapi::$revision;
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$result = array();
|
||||
$result['site_url'] = Settings::get('SITE_URL');
|
||||
$result['okapi_base_url'] = $result['site_url']."okapi/";
|
||||
$result['site_name'] = Okapi::get_normalized_site_name();
|
||||
$result['okapi_revision'] = Okapi::$revision;
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
<xml>
|
||||
<brief>Get information on this OKAPI installation</brief>
|
||||
<issue-id>14</issue-id>
|
||||
<desc>
|
||||
Retrieve some basic information about this OKAPI installation.
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>site_url</b> - URL of the Opencaching site which is running
|
||||
the OKAPI installation (usually this looks like
|
||||
"http://www.opencaching.<i>xx</i>/", where <b>xx</b> is a top
|
||||
level domain of a country).
|
||||
</li>
|
||||
<li>
|
||||
<b>okapi_base_url</b> - URL of the OKAPI installation (usually this is
|
||||
<b>site_url</b> with "okapi/" appended, but you should not assume
|
||||
that); this value is to be used as a prefix when constructing service
|
||||
method URLs,
|
||||
</li>
|
||||
<li>
|
||||
<b>site_name</b> - international name of the Opencaching site,
|
||||
</li>
|
||||
<li><b>okapi_revision</b> - integer, an SVN revision of the OKAPI project
|
||||
installed on this Opencaching site, <b>or null</b>, when could not
|
||||
determine revision number.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Get information on this OKAPI installation</brief>
|
||||
<issue-id>14</issue-id>
|
||||
<desc>
|
||||
Retrieve some basic information about this OKAPI installation.
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>site_url</b> - URL of the Opencaching site which is running
|
||||
the OKAPI installation (usually this looks like
|
||||
"http://www.opencaching.<i>xx</i>/", where <b>xx</b> is a top
|
||||
level domain of a country).
|
||||
</li>
|
||||
<li>
|
||||
<b>okapi_base_url</b> - URL of the OKAPI installation (usually this is
|
||||
<b>site_url</b> with "okapi/" appended, but you should not assume
|
||||
that); this value is to be used as a prefix when constructing service
|
||||
method URLs,
|
||||
</li>
|
||||
<li>
|
||||
<b>site_name</b> - international name of the Opencaching site,
|
||||
</li>
|
||||
<li><b>okapi_revision</b> - integer, an SVN revision of the OKAPI project
|
||||
installed on this Opencaching site, <b>or null</b>, when could not
|
||||
determine revision number.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -15,104 +15,104 @@ use okapi\OkapiInternalRequest;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# The list of installations is periodically refreshed by contacting OKAPI
|
||||
# repository. This method usually displays the cached version of it.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# The list of installations is periodically refreshed by contacting OKAPI
|
||||
# repository. This method usually displays the cached version of it.
|
||||
|
||||
$cachekey = 'apisrv/installations';
|
||||
$backupkey = 'apisrv/installations-backup';
|
||||
$results = Cache::get($cachekey);
|
||||
if (!$results)
|
||||
{
|
||||
# Download the current list of OKAPI servers.
|
||||
$cachekey = 'apisrv/installations';
|
||||
$backupkey = 'apisrv/installations-backup';
|
||||
$results = Cache::get($cachekey);
|
||||
if (!$results)
|
||||
{
|
||||
# Download the current list of OKAPI servers.
|
||||
|
||||
try
|
||||
{
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 5.0
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$xml = file_get_contents("http://opencaching-api.googlecode.com/svn/trunk/etc/installations.xml",
|
||||
false, $context);
|
||||
}
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
# Google failed on us. Try to respond with a backup list.
|
||||
try
|
||||
{
|
||||
$opts = array(
|
||||
'http' => array(
|
||||
'method' => "GET",
|
||||
'timeout' => 5.0
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$xml = file_get_contents("http://opencaching-api.googlecode.com/svn/trunk/etc/installations.xml",
|
||||
false, $context);
|
||||
}
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
# Google failed on us. Try to respond with a backup list.
|
||||
|
||||
$results = Cache::get($backupkey);
|
||||
if ($results)
|
||||
{
|
||||
Cache::set($cachekey, $results, 12 * 3600); # so to retry no earlier than after 12 hours
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
$results = Cache::get($backupkey);
|
||||
if ($results)
|
||||
{
|
||||
Cache::set($cachekey, $results, 12 * 3600); # so to retry no earlier than after 12 hours
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
|
||||
# Backup has expired (or have never been cached). If we're on a development
|
||||
# server then probably it's okay. In production this SHOULD NOT happen.
|
||||
# Backup has expired (or have never been cached). If we're on a development
|
||||
# server then probably it's okay. In production this SHOULD NOT happen.
|
||||
|
||||
$results = array(
|
||||
array(
|
||||
'site_url' => Settings::get('SITE_URL'),
|
||||
'site_name' => "Unable to retrieve!",
|
||||
'okapi_base_url' => Settings::get('SITE_URL')."okapi/",
|
||||
)
|
||||
);
|
||||
Cache::set($cachekey, $results, 12 * 3600); # so to retry no earlier than after 12 hours
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
$results = array(
|
||||
array(
|
||||
'site_url' => Settings::get('SITE_URL'),
|
||||
'site_name' => "Unable to retrieve!",
|
||||
'okapi_base_url' => Settings::get('SITE_URL')."okapi/",
|
||||
)
|
||||
);
|
||||
Cache::set($cachekey, $results, 12 * 3600); # so to retry no earlier than after 12 hours
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
|
||||
$doc = simplexml_load_string($xml);
|
||||
$results = array();
|
||||
$i_was_included = false;
|
||||
foreach ($doc->installation as $inst)
|
||||
{
|
||||
$site_url = (string)$inst[0]['site_url'];
|
||||
if ($inst[0]['okapi_base_url'])
|
||||
$okapi_base_url = (string)$inst[0]['okapi_base_url'];
|
||||
else
|
||||
$okapi_base_url = $site_url."okapi/";
|
||||
if ($inst[0]['site_name'])
|
||||
$site_name = (string)$inst[0]['site_name'];
|
||||
else
|
||||
$site_name = Okapi::get_normalized_site_name($site_url);
|
||||
$results[] = array(
|
||||
'site_url' => $site_url,
|
||||
'site_name' => $site_name,
|
||||
'okapi_base_url' => $okapi_base_url,
|
||||
);
|
||||
if ($site_url == Settings::get('SITE_URL'))
|
||||
$i_was_included = true;
|
||||
}
|
||||
$doc = simplexml_load_string($xml);
|
||||
$results = array();
|
||||
$i_was_included = false;
|
||||
foreach ($doc->installation as $inst)
|
||||
{
|
||||
$site_url = (string)$inst[0]['site_url'];
|
||||
if ($inst[0]['okapi_base_url'])
|
||||
$okapi_base_url = (string)$inst[0]['okapi_base_url'];
|
||||
else
|
||||
$okapi_base_url = $site_url."okapi/";
|
||||
if ($inst[0]['site_name'])
|
||||
$site_name = (string)$inst[0]['site_name'];
|
||||
else
|
||||
$site_name = Okapi::get_normalized_site_name($site_url);
|
||||
$results[] = array(
|
||||
'site_url' => $site_url,
|
||||
'site_name' => $site_name,
|
||||
'okapi_base_url' => $okapi_base_url,
|
||||
);
|
||||
if ($site_url == Settings::get('SITE_URL'))
|
||||
$i_was_included = true;
|
||||
}
|
||||
|
||||
# If running on a local development installation, then include the local
|
||||
# installation URL.
|
||||
# If running on a local development installation, then include the local
|
||||
# installation URL.
|
||||
|
||||
if (!$i_was_included)
|
||||
{
|
||||
$results[] = array(
|
||||
'site_url' => Settings::get('SITE_URL'),
|
||||
'site_name' => "DEVELSITE",
|
||||
'okapi_base_url' => Settings::get('SITE_URL')."okapi/",
|
||||
);
|
||||
# Contact OKAPI developers in order to get added to the official sites list!
|
||||
}
|
||||
if (!$i_was_included)
|
||||
{
|
||||
$results[] = array(
|
||||
'site_url' => Settings::get('SITE_URL'),
|
||||
'site_name' => "DEVELSITE",
|
||||
'okapi_base_url' => Settings::get('SITE_URL')."okapi/",
|
||||
);
|
||||
# Contact OKAPI developers in order to get added to the official sites list!
|
||||
}
|
||||
|
||||
# Cache it for one day. Also, save a backup (valid for 30 days).
|
||||
# Cache it for one day. Also, save a backup (valid for 30 days).
|
||||
|
||||
Cache::set($cachekey, $results, 86400);
|
||||
Cache::set($backupkey, $results, 86400*30);
|
||||
}
|
||||
Cache::set($cachekey, $results, 86400);
|
||||
Cache::set($backupkey, $results, 86400*30);
|
||||
}
|
||||
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<xml>
|
||||
<brief>Get the list of all public OKAPI installations</brief>
|
||||
<issue-id>39</issue-id>
|
||||
<desc>
|
||||
Get the list of all public OKAPI installations. Keep in mind that
|
||||
OKAPI installations might differ slightly. If you plan on using
|
||||
multiple OKAPI installations in your application (which is a very
|
||||
good thing!) you should test it against the one with the <b>lowest</b>
|
||||
OKAPI revision number.
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>site_url</b> - URL of the Opencaching site which is running
|
||||
the OKAPI installation (usually this looks like
|
||||
"http://www.opencaching.<i>xx</i>/", where <b>xx</b> is a top
|
||||
level domain of a country).
|
||||
</li>
|
||||
<li>
|
||||
<b>site_name</b> - universal name for this site (should be fine
|
||||
for all languages),
|
||||
</li>
|
||||
<li>
|
||||
<b>okapi_base_url</b> - URL of the OKAPI installation (usually this is
|
||||
<b>site_url</b> with "okapi/" appended, but you should not assume
|
||||
that); this value is to be used as a prefix when constructing service
|
||||
method URLs.
|
||||
</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Get the list of all public OKAPI installations</brief>
|
||||
<issue-id>39</issue-id>
|
||||
<desc>
|
||||
Get the list of all public OKAPI installations. Keep in mind that
|
||||
OKAPI installations might differ slightly. If you plan on using
|
||||
multiple OKAPI installations in your application (which is a very
|
||||
good thing!) you should test it against the one with the <b>lowest</b>
|
||||
OKAPI revision number.
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>site_url</b> - URL of the Opencaching site which is running
|
||||
the OKAPI installation (usually this looks like
|
||||
"http://www.opencaching.<i>xx</i>/", where <b>xx</b> is a top
|
||||
level domain of a country).
|
||||
</li>
|
||||
<li>
|
||||
<b>site_name</b> - universal name for this site (should be fine
|
||||
for all languages),
|
||||
</li>
|
||||
<li>
|
||||
<b>okapi_base_url</b> - URL of the OKAPI installation (usually this is
|
||||
<b>site_url</b> with "okapi/" appended, but you should not assume
|
||||
that); this value is to be used as a prefix when constructing service
|
||||
method URLs.
|
||||
</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -15,48 +15,48 @@ use okapi\Settings;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 0
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$cachekey = "apisrv/stats";
|
||||
$result = Cache::get($cachekey);
|
||||
if (!$result)
|
||||
{
|
||||
$result = array(
|
||||
'cache_count' => 0 + Db::select_value("
|
||||
select count(*) from caches where status in (1,2,3)
|
||||
"),
|
||||
'user_count' => 0 + Db::select_value("
|
||||
select count(*) from (
|
||||
select distinct user_id
|
||||
from cache_logs
|
||||
where
|
||||
type in (1,2)
|
||||
and ".((Settings::get('OC_BRANCH') == 'oc.pl') ? "deleted = 0" : "true")."
|
||||
UNION DISTINCT
|
||||
select distinct user_id
|
||||
from caches
|
||||
) as t;
|
||||
"),
|
||||
'apps_count' => 0 + Db::select_value("select count(*) from okapi_consumers;"),
|
||||
'apps_active' => 0 + Db::select_value("
|
||||
select count(distinct s.consumer_key)
|
||||
from
|
||||
okapi_stats_hourly s,
|
||||
okapi_consumers c
|
||||
where
|
||||
s.consumer_key = c.`key`
|
||||
and s.period_start > date_add(now(), interval -30 day)
|
||||
"),
|
||||
);
|
||||
Cache::set($cachekey, $result, 86400); # cache it for one day
|
||||
}
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$cachekey = "apisrv/stats";
|
||||
$result = Cache::get($cachekey);
|
||||
if (!$result)
|
||||
{
|
||||
$result = array(
|
||||
'cache_count' => 0 + Db::select_value("
|
||||
select count(*) from caches where status in (1,2,3)
|
||||
"),
|
||||
'user_count' => 0 + Db::select_value("
|
||||
select count(*) from (
|
||||
select distinct user_id
|
||||
from cache_logs
|
||||
where
|
||||
type in (1,2)
|
||||
and ".((Settings::get('OC_BRANCH') == 'oc.pl') ? "deleted = 0" : "true")."
|
||||
UNION DISTINCT
|
||||
select distinct user_id
|
||||
from caches
|
||||
) as t;
|
||||
"),
|
||||
'apps_count' => 0 + Db::select_value("select count(*) from okapi_consumers;"),
|
||||
'apps_active' => 0 + Db::select_value("
|
||||
select count(distinct s.consumer_key)
|
||||
from
|
||||
okapi_stats_hourly s,
|
||||
okapi_consumers c
|
||||
where
|
||||
s.consumer_key = c.`key`
|
||||
and s.period_start > date_add(now(), interval -30 day)
|
||||
"),
|
||||
);
|
||||
Cache::set($cachekey, $result, 86400); # cache it for one day
|
||||
}
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<xml>
|
||||
<brief>Get some basic stats about the site</brief>
|
||||
<issue-id>43</issue-id>
|
||||
<desc>
|
||||
Retrieve some basic statistics about this OKAPI installation.
|
||||
If you want some more stats, post a comment!
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>cache_count</b> - approximate total number of geocaches stored at this site,</li>
|
||||
<li><b>user_count</b> - approximate total number of active users of this site,</li>
|
||||
<li><b>apps_count</b> - approximate total number of all OKAPI applications (number of
|
||||
registered API Keys).</li>
|
||||
<li><b>apps_active</b> - approximate number of active OKAPI applications (the ones which issued
|
||||
at least one, non-anonymous OKAPI request during the last month).</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Get some basic stats about the site</brief>
|
||||
<issue-id>43</issue-id>
|
||||
<desc>
|
||||
Retrieve some basic statistics about this OKAPI installation.
|
||||
If you want some more stats, post a comment!
|
||||
</desc>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>cache_count</b> - approximate total number of geocaches stored at this site,</li>
|
||||
<li><b>user_count</b> - approximate total number of active users of this site,</li>
|
||||
<li><b>apps_count</b> - approximate total number of all OKAPI applications (number of
|
||||
registered API Keys).</li>
|
||||
<li><b>apps_active</b> - approximate number of active OKAPI applications (the ones which issued
|
||||
at least one, non-anonymous OKAPI request during the last month).</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -18,272 +18,272 @@ use SimpleXMLElement;
|
||||
|
||||
class AttrHelper
|
||||
{
|
||||
/**
|
||||
* By default, when DEBUG mode is enabled, the attributes.xml file is
|
||||
* reloaded practically on every request. If you don't want that, you can
|
||||
* temporarilly disable this behavior by settings this to false.
|
||||
*/
|
||||
private static $RELOAD_ON_DEBUG = true;
|
||||
/**
|
||||
* By default, when DEBUG mode is enabled, the attributes.xml file is
|
||||
* reloaded practically on every request. If you don't want that, you can
|
||||
* temporarilly disable this behavior by settings this to false.
|
||||
*/
|
||||
private static $RELOAD_ON_DEBUG = true;
|
||||
|
||||
private static $attr_dict = null;
|
||||
private static $attr_dict = null;
|
||||
|
||||
/**
|
||||
* Return the cache key suffix to be used for caching. This should be used
|
||||
* In order for the $RELOAD_ON_DEBUG to work properly when switching to/from
|
||||
* DEBUG mode.
|
||||
*/
|
||||
private static function cache_key_suffix()
|
||||
{
|
||||
return (self::$RELOAD_ON_DEBUG) ? "#DBG" : "";
|
||||
}
|
||||
/**
|
||||
* Return the cache key suffix to be used for caching. This should be used
|
||||
* In order for the $RELOAD_ON_DEBUG to work properly when switching to/from
|
||||
* DEBUG mode.
|
||||
*/
|
||||
private static function cache_key_suffix()
|
||||
{
|
||||
return (self::$RELOAD_ON_DEBUG) ? "#DBG" : "";
|
||||
}
|
||||
|
||||
/** Return the timeout to be used for attribute caching. */
|
||||
private static function ttl()
|
||||
{
|
||||
return (Settings::get('DEBUG') && self::$RELOAD_ON_DEBUG) ? 2 : 86400;
|
||||
}
|
||||
/** Return the timeout to be used for attribute caching. */
|
||||
private static function ttl()
|
||||
{
|
||||
return (Settings::get('DEBUG') && self::$RELOAD_ON_DEBUG) ? 2 : 86400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces an immediate refresh of the current attributes from the
|
||||
* attribute-definitions.xml file.
|
||||
*/
|
||||
public static function refresh_now()
|
||||
{
|
||||
try
|
||||
{
|
||||
$path = $GLOBALS['rootpath']."okapi/services/attrs/attribute-definitions.xml";
|
||||
$xml = file_get_contents($path);
|
||||
self::refresh_from_string($xml);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
# Failed to read or parse the file (i.e. after a syntax error was
|
||||
# commited). Let's check when the last successful parse occured.
|
||||
/**
|
||||
* Forces an immediate refresh of the current attributes from the
|
||||
* attribute-definitions.xml file.
|
||||
*/
|
||||
public static function refresh_now()
|
||||
{
|
||||
try
|
||||
{
|
||||
$path = $GLOBALS['rootpath']."okapi/services/attrs/attribute-definitions.xml";
|
||||
$xml = file_get_contents($path);
|
||||
self::refresh_from_string($xml);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
# Failed to read or parse the file (i.e. after a syntax error was
|
||||
# commited). Let's check when the last successful parse occured.
|
||||
|
||||
self::init_from_cache(false);
|
||||
self::init_from_cache(false);
|
||||
|
||||
if (self::$attr_dict === null)
|
||||
{
|
||||
# That's bad! We don't have ANY copy of the data AND we failed
|
||||
# to parse it. We will use a fake, empty data.
|
||||
if (self::$attr_dict === null)
|
||||
{
|
||||
# That's bad! We don't have ANY copy of the data AND we failed
|
||||
# to parse it. We will use a fake, empty data.
|
||||
|
||||
$cache_key = "attrhelper/dict#".Okapi::$revision.self::cache_key_suffix();
|
||||
$cachedvalue = array(
|
||||
'attr_dict' => array(),
|
||||
);
|
||||
Cache::set($cache_key, $cachedvalue, self::ttl());
|
||||
}
|
||||
$cache_key = "attrhelper/dict#".Okapi::$revision.self::cache_key_suffix();
|
||||
$cachedvalue = array(
|
||||
'attr_dict' => array(),
|
||||
);
|
||||
Cache::set($cache_key, $cachedvalue, self::ttl());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh all attributes from the given XML. Usually, this file is
|
||||
* downloaded from Google Code (using refresh_now).
|
||||
*/
|
||||
public static function refresh_from_string($xml)
|
||||
{
|
||||
/* The attribute-definitions.xml file defines relationships between
|
||||
* attributes originating from various OC installations. Each
|
||||
* installation uses internal IDs of its own. Which "attribute schema"
|
||||
* is being used in THIS installation? */
|
||||
/**
|
||||
* Refresh all attributes from the given XML. Usually, this file is
|
||||
* downloaded from Google Code (using refresh_now).
|
||||
*/
|
||||
public static function refresh_from_string($xml)
|
||||
{
|
||||
/* The attribute-definitions.xml file defines relationships between
|
||||
* attributes originating from various OC installations. Each
|
||||
* installation uses internal IDs of its own. Which "attribute schema"
|
||||
* is being used in THIS installation? */
|
||||
|
||||
$my_schema = Settings::get('ORIGIN_URL');
|
||||
$my_schema = Settings::get('ORIGIN_URL');
|
||||
|
||||
$doc = simplexml_load_string($xml);
|
||||
$cachedvalue = array(
|
||||
'attr_dict' => array(),
|
||||
);
|
||||
$doc = simplexml_load_string($xml);
|
||||
$cachedvalue = array(
|
||||
'attr_dict' => array(),
|
||||
);
|
||||
|
||||
# Build cache attributes dictionary
|
||||
# Build cache attributes dictionary
|
||||
|
||||
$all_internal_ids = array();
|
||||
foreach ($doc->attr as $attrnode)
|
||||
{
|
||||
$attr = array(
|
||||
'acode' => (string)$attrnode['acode'],
|
||||
'gc_equivs' => array(),
|
||||
'internal_id' => null,
|
||||
'names' => array(),
|
||||
'descriptions' => array(),
|
||||
'is_discontinued' => true
|
||||
);
|
||||
foreach ($attrnode->groundspeak as $gsnode)
|
||||
{
|
||||
$attr['gc_equivs'][] = 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 it is used by at least one OC node, then it's NOT discontinued. */
|
||||
$attr['is_discontinued'] = false;
|
||||
$all_internal_ids = array();
|
||||
foreach ($doc->attr as $attrnode)
|
||||
{
|
||||
$attr = array(
|
||||
'acode' => (string)$attrnode['acode'],
|
||||
'gc_equivs' => array(),
|
||||
'internal_id' => null,
|
||||
'names' => array(),
|
||||
'descriptions' => array(),
|
||||
'is_discontinued' => true
|
||||
);
|
||||
foreach ($attrnode->groundspeak as $gsnode)
|
||||
{
|
||||
$attr['gc_equivs'][] = 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 it is used by at least one OC node, then it's NOT discontinued. */
|
||||
$attr['is_discontinued'] = false;
|
||||
|
||||
if ((string)$ocnode['schema'] == $my_schema)
|
||||
{
|
||||
/* It is used by THIS OC node. */
|
||||
if ((string)$ocnode['schema'] == $my_schema)
|
||||
{
|
||||
/* It is used by THIS OC node. */
|
||||
|
||||
$internal_id = (int)$ocnode['id'];
|
||||
if (isset($all_internal_ids[$internal_id]))
|
||||
throw new Exception("The internal attribute ".$internal_id.
|
||||
" has multiple assigments to OKAPI attributes.");
|
||||
$all_internal_ids[$internal_id] = true;
|
||||
if (!is_null($attr['internal_id']))
|
||||
throw new Exception("There are multiple internal IDs for the ".
|
||||
$attr['acode']." attribute.");
|
||||
$attr['internal_id'] = $internal_id;
|
||||
}
|
||||
}
|
||||
foreach ($attrnode->lang as $langnode)
|
||||
{
|
||||
$lang = (string)$langnode['id'];
|
||||
foreach ($langnode->name as $namenode)
|
||||
{
|
||||
if (isset($attr['names'][$lang]))
|
||||
throw new Exception("Duplicate ".$lang." name of attribute ".$attr['acode']);
|
||||
$attr['names'][$lang] = (string)$namenode;
|
||||
}
|
||||
foreach ($langnode->desc as $descnode)
|
||||
{
|
||||
if (isset($attr['descriptions'][$lang]))
|
||||
throw new Exception("Duplicate ".$lang." description of attribute ".$attr['acode']);
|
||||
$xml = $descnode->asxml(); /* contains "<desc>" and "</desc>" */
|
||||
$innerxml = preg_replace("/(^[^>]+>)|(<[^<]+$)/us", "", $xml);
|
||||
$attr['descriptions'][$lang] = self::cleanup_string($innerxml);
|
||||
}
|
||||
}
|
||||
$cachedvalue['attr_dict'][$attr['acode']] = $attr;
|
||||
}
|
||||
$internal_id = (int)$ocnode['id'];
|
||||
if (isset($all_internal_ids[$internal_id]))
|
||||
throw new Exception("The internal attribute ".$internal_id.
|
||||
" has multiple assigments to OKAPI attributes.");
|
||||
$all_internal_ids[$internal_id] = true;
|
||||
if (!is_null($attr['internal_id']))
|
||||
throw new Exception("There are multiple internal IDs for the ".
|
||||
$attr['acode']." attribute.");
|
||||
$attr['internal_id'] = $internal_id;
|
||||
}
|
||||
}
|
||||
foreach ($attrnode->lang as $langnode)
|
||||
{
|
||||
$lang = (string)$langnode['id'];
|
||||
foreach ($langnode->name as $namenode)
|
||||
{
|
||||
if (isset($attr['names'][$lang]))
|
||||
throw new Exception("Duplicate ".$lang." name of attribute ".$attr['acode']);
|
||||
$attr['names'][$lang] = (string)$namenode;
|
||||
}
|
||||
foreach ($langnode->desc as $descnode)
|
||||
{
|
||||
if (isset($attr['descriptions'][$lang]))
|
||||
throw new Exception("Duplicate ".$lang." description of attribute ".$attr['acode']);
|
||||
$xml = $descnode->asxml(); /* contains "<desc>" and "</desc>" */
|
||||
$innerxml = preg_replace("/(^[^>]+>)|(<[^<]+$)/us", "", $xml);
|
||||
$attr['descriptions'][$lang] = self::cleanup_string($innerxml);
|
||||
}
|
||||
}
|
||||
$cachedvalue['attr_dict'][$attr['acode']] = $attr;
|
||||
}
|
||||
|
||||
$cache_key = "attrhelper/dict#".Okapi::$revision.self::cache_key_suffix();
|
||||
Cache::set($cache_key, $cachedvalue, self::ttl());
|
||||
self::$attr_dict = $cachedvalue['attr_dict'];
|
||||
}
|
||||
$cache_key = "attrhelper/dict#".Okapi::$revision.self::cache_key_suffix();
|
||||
Cache::set($cache_key, $cachedvalue, self::ttl());
|
||||
self::$attr_dict = $cachedvalue['attr_dict'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Object to be used for forward-compatibility (see the attributes method).
|
||||
*/
|
||||
public static function get_unknown_placeholder($acode)
|
||||
{
|
||||
return array(
|
||||
'acode' => $acode,
|
||||
'gc_equivs' => array(),
|
||||
'internal_id' => null,
|
||||
'names' => array(
|
||||
'en' => "Unknown attribute"
|
||||
),
|
||||
'descriptions' => array(
|
||||
'en' => (
|
||||
"This attribute ($acode) is unknown at ".Okapi::get_normalized_site_name().
|
||||
". It might not exist, or it may be a new attribute, recognized ".
|
||||
"only in newer OKAPI installations. Perhaps ".Okapi::get_normalized_site_name().
|
||||
" needs to have its OKAPI updated?"
|
||||
)
|
||||
),
|
||||
'is_discontinued' => true
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Object to be used for forward-compatibility (see the attributes method).
|
||||
*/
|
||||
public static function get_unknown_placeholder($acode)
|
||||
{
|
||||
return array(
|
||||
'acode' => $acode,
|
||||
'gc_equivs' => array(),
|
||||
'internal_id' => null,
|
||||
'names' => array(
|
||||
'en' => "Unknown attribute"
|
||||
),
|
||||
'descriptions' => array(
|
||||
'en' => (
|
||||
"This attribute ($acode) is unknown at ".Okapi::get_normalized_site_name().
|
||||
". It might not exist, or it may be a new attribute, recognized ".
|
||||
"only in newer OKAPI installations. Perhaps ".Okapi::get_normalized_site_name().
|
||||
" needs to have its OKAPI updated?"
|
||||
)
|
||||
),
|
||||
'is_discontinued' => true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 will read and parse them from attribute-definitions.xml file.
|
||||
*/
|
||||
private static function init_from_cache($allow_refreshing=true)
|
||||
{
|
||||
if (self::$attr_dict !== null)
|
||||
{
|
||||
/* Already initialized. */
|
||||
return;
|
||||
}
|
||||
$cache_key = "attrhelper/dict#".Okapi::$revision.self::cache_key_suffix();
|
||||
$cachedvalue = Cache::get($cache_key);
|
||||
if ($cachedvalue === null)
|
||||
{
|
||||
# I.e. after Okapi::$revision is changed, or cache got invalidated.
|
||||
/**
|
||||
* 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 will read and parse them from attribute-definitions.xml file.
|
||||
*/
|
||||
private static function init_from_cache($allow_refreshing=true)
|
||||
{
|
||||
if (self::$attr_dict !== null)
|
||||
{
|
||||
/* Already initialized. */
|
||||
return;
|
||||
}
|
||||
$cache_key = "attrhelper/dict#".Okapi::$revision.self::cache_key_suffix();
|
||||
$cachedvalue = Cache::get($cache_key);
|
||||
if ($cachedvalue === null)
|
||||
{
|
||||
# I.e. after Okapi::$revision is changed, or cache got invalidated.
|
||||
|
||||
if ($allow_refreshing)
|
||||
{
|
||||
self::refresh_now();
|
||||
self::init_from_cache(false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
$cachedvalue = array(
|
||||
'attr_dict' => array(),
|
||||
);
|
||||
}
|
||||
}
|
||||
self::$attr_dict = $cachedvalue['attr_dict'];
|
||||
}
|
||||
if ($allow_refreshing)
|
||||
{
|
||||
self::refresh_now();
|
||||
self::init_from_cache(false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
$cachedvalue = array(
|
||||
'attr_dict' => array(),
|
||||
);
|
||||
}
|
||||
}
|
||||
self::$attr_dict = $cachedvalue['attr_dict'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a dictionary of all attributes. The format is INTERNAL and PRIVATE,
|
||||
* it is NOT the same as in the "attributes" method (but it is quite similar).
|
||||
*/
|
||||
public static function get_attrdict()
|
||||
{
|
||||
self::init_from_cache();
|
||||
return self::$attr_dict;
|
||||
}
|
||||
/**
|
||||
* Return a dictionary of all attributes. The format is INTERNAL and PRIVATE,
|
||||
* it is NOT the same as in the "attributes" method (but it is quite similar).
|
||||
*/
|
||||
public static function get_attrdict()
|
||||
{
|
||||
self::init_from_cache();
|
||||
return self::$attr_dict;
|
||||
}
|
||||
|
||||
/** "\n\t\tBla blabla\n\t\t<b>bla</b>bla.\n\t" => "Bla blabla <b>bla</b>bla." */
|
||||
private static function cleanup_string($s)
|
||||
{
|
||||
return preg_replace('/(^\s+)|(\s+$)/us', "", preg_replace('/\s+/us', " ", $s));
|
||||
}
|
||||
/** "\n\t\tBla blabla\n\t\t<b>bla</b>bla.\n\t" => "Bla blabla <b>bla</b>bla." */
|
||||
private static function cleanup_string($s)
|
||||
{
|
||||
return preg_replace('/(^\s+)|(\s+$)/us', "", preg_replace('/\s+/us', " ", $s));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mapping table between internal attribute id => OKAPI A-code.
|
||||
* The result is cached!
|
||||
*/
|
||||
public static function get_internal_id_to_acode_mapping()
|
||||
{
|
||||
static $mapping = null;
|
||||
if ($mapping !== null)
|
||||
return $mapping;
|
||||
/**
|
||||
* Get the mapping table between internal attribute id => OKAPI A-code.
|
||||
* The result is cached!
|
||||
*/
|
||||
public static function get_internal_id_to_acode_mapping()
|
||||
{
|
||||
static $mapping = null;
|
||||
if ($mapping !== null)
|
||||
return $mapping;
|
||||
|
||||
$cache_key = "attrhelper/id2acode/".Okapi::$revision.self::cache_key_suffix();
|
||||
$mapping = Cache::get($cache_key);
|
||||
if (!$mapping)
|
||||
{
|
||||
self::init_from_cache();
|
||||
$mapping = array();
|
||||
foreach (self::$attr_dict as $acode => &$attr_ref)
|
||||
$mapping[$attr_ref['internal_id']] = $acode;
|
||||
Cache::set($cache_key, $mapping, self::ttl());
|
||||
}
|
||||
return $mapping;
|
||||
}
|
||||
$cache_key = "attrhelper/id2acode/".Okapi::$revision.self::cache_key_suffix();
|
||||
$mapping = Cache::get($cache_key);
|
||||
if (!$mapping)
|
||||
{
|
||||
self::init_from_cache();
|
||||
$mapping = array();
|
||||
foreach (self::$attr_dict as $acode => &$attr_ref)
|
||||
$mapping[$attr_ref['internal_id']] = $acode;
|
||||
Cache::set($cache_key, $mapping, self::ttl());
|
||||
}
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mapping: A-codes => attribute name. The language for the name
|
||||
* is selected based on the $langpref parameter. The result is cached!
|
||||
*/
|
||||
public static function get_acode_to_name_mapping($langpref)
|
||||
{
|
||||
static $mapping = null;
|
||||
if ($mapping !== null)
|
||||
return $mapping;
|
||||
/**
|
||||
* Get the mapping: A-codes => attribute name. The language for the name
|
||||
* is selected based on the $langpref parameter. The result is cached!
|
||||
*/
|
||||
public static function get_acode_to_name_mapping($langpref)
|
||||
{
|
||||
static $mapping = null;
|
||||
if ($mapping !== null)
|
||||
return $mapping;
|
||||
|
||||
$cache_key = md5(serialize(array("attrhelper/acode2name", $langpref,
|
||||
Okapi::$revision, self::cache_key_suffix())));
|
||||
$mapping = Cache::get($cache_key);
|
||||
if (!$mapping)
|
||||
{
|
||||
self::init_from_cache();
|
||||
$mapping = array();
|
||||
foreach (self::$attr_dict as $acode => &$attr_ref)
|
||||
{
|
||||
$mapping[$acode] = Okapi::pick_best_language(
|
||||
$attr_ref['names'], $langpref);
|
||||
}
|
||||
Cache::set($cache_key, $mapping, self::ttl());
|
||||
}
|
||||
return $mapping;
|
||||
}
|
||||
$cache_key = md5(serialize(array("attrhelper/acode2name", $langpref,
|
||||
Okapi::$revision, self::cache_key_suffix())));
|
||||
$mapping = Cache::get($cache_key);
|
||||
if (!$mapping)
|
||||
{
|
||||
self::init_from_cache();
|
||||
$mapping = array();
|
||||
foreach (self::$attr_dict as $acode => &$attr_ref)
|
||||
{
|
||||
$mapping[$acode] = Okapi::pick_best_language(
|
||||
$attr_ref['names'], $langpref);
|
||||
}
|
||||
Cache::set($cache_key, $mapping, self::ttl());
|
||||
}
|
||||
return $mapping;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,45 +17,45 @@ use okapi\services\attrs\AttrHelper;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Read the parameters.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Read the parameters.
|
||||
|
||||
$acode = $request->get_parameter('acode');
|
||||
if ($acode === null) throw new ParamMissing('acode');
|
||||
$acode = $request->get_parameter('acode');
|
||||
if ($acode === null) throw new ParamMissing('acode');
|
||||
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "name";
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "name";
|
||||
|
||||
$forward_compatible = $request->get_parameter('forward_compatible');
|
||||
if (!$forward_compatible) $forward_compatible = "true";
|
||||
$forward_compatible = $request->get_parameter('forward_compatible');
|
||||
if (!$forward_compatible) $forward_compatible = "true";
|
||||
|
||||
# Pass them all to the attributes method.
|
||||
# Pass them all to the attributes method.
|
||||
|
||||
$params = array(
|
||||
'acodes' => $acode,
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
'forward_compatible' => $forward_compatible
|
||||
);
|
||||
$results = OkapiServiceRunner::call('services/attrs/attributes',
|
||||
new OkapiInternalRequest($request->consumer, $request->token, $params));
|
||||
$result = $results[$acode];
|
||||
if ($result === null)
|
||||
{
|
||||
/* Note, this can happen only when $forward_compatible is false. */
|
||||
throw new InvalidParam('acode', "Unknown A-code.");
|
||||
}
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
$params = array(
|
||||
'acodes' => $acode,
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
'forward_compatible' => $forward_compatible
|
||||
);
|
||||
$results = OkapiServiceRunner::call('services/attrs/attributes',
|
||||
new OkapiInternalRequest($request->consumer, $request->token, $params));
|
||||
$result = $results[$acode];
|
||||
if ($result === null)
|
||||
{
|
||||
/* Note, this can happen only when $forward_compatible is false. */
|
||||
throw new InvalidParam('acode', "Unknown A-code.");
|
||||
}
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,127 +1,134 @@
|
||||
<xml>
|
||||
<brief>Retrieve data on a single attribute</brief>
|
||||
<issue-id>268</issue-id>
|
||||
<desc>
|
||||
<p>Retrieve data on a single OKAPI geocache-attribute.</p>
|
||||
|
||||
<p>OKAPI attributes are identified by an unique ID called an <b>A-code</b>.
|
||||
All OKAPI attributes are shared among all OKAPI servers. Once an attribute is
|
||||
published (e.g. via the <b>attribute_index</b> method), it won't
|
||||
disappear in any of the future OKAPI revisions, nor will its meaning change.
|
||||
Some attributes may get discontinued in the future, but they will remain accessible
|
||||
by their original A-code.</p>
|
||||
</desc>
|
||||
<req name='acode'>
|
||||
The A-code of the attribute you're interested in.
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for fields like
|
||||
<b>name</b> and <b>description</b>.</p>
|
||||
</opt>
|
||||
<opt name='fields' default='name'>
|
||||
<p>Pipe-separated list of field names which you are interested with.
|
||||
See below for the list of available fields.</p>
|
||||
</opt>
|
||||
<opt name='forward_compatible' default='true'>
|
||||
By default, OKAPI will return an empty placeholder if you ask for an
|
||||
unknown attribute. If you'd like to catch such errors and handle them
|
||||
differently, then you may change this behavior by setting this parameter
|
||||
to <b>false</b>. Then, OKAPI will return HTTP 400 error response,
|
||||
instead of the placeholder (note that it behaves differently in the
|
||||
<b>attributes</b> method).
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of fields you have selected in the <b>fields</b>
|
||||
parameter. Available fields:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p><b>acode</b> - string, the A-code. Unique identifier of the
|
||||
attribute.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>name</b> - plaintext string, name of the attribute (language is
|
||||
selected based on your <b>langpref</b> parameter),</p>
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>names</b> - a dictionary of all known names of the attribute, in
|
||||
various languages (ISO 639-1 language code is used as dictionary
|
||||
key).</p>
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<b>description</b> - HTML string, description of the attribute (language is
|
||||
selected based on your <b>langpref</b> parameter),
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>descriptions</b> - a dictionary of all known descriptions of the
|
||||
attribute, in various languages (ISO 639-1 language code is used as
|
||||
dictionary key).</p>
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>gc_equivs</b> - a list of Geocaching.com (Groundspeak)
|
||||
attributes, which have exactly the same (or a very similar) meaning. Each
|
||||
attribute is described as a dictionary of the following structure:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>id</b> - ID of the Geocaching.com attribute,</li>
|
||||
<li>
|
||||
<b>inc</b> - integer, either 1 or 0. See Geocaching.com's
|
||||
XSD for details on its meaning,
|
||||
</li>
|
||||
<li>
|
||||
<b>name</b> - the name of the attribute (as it is included
|
||||
in Geocaching.com GPX files).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Note that one gc_equivs list may have multiple items on it, and
|
||||
that one Geocaching.com ID may be present in many gc_equivs.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_locally_used</b> - boolean, indicates if the attribute is *currently*
|
||||
used by *this* Opencaching server. Or, to be more specific, <b>true</b>
|
||||
means that the attribute CAN *currently* be included in the <b>attr_acodes</b> field
|
||||
of the <b>geocache</b> method in the *current* OKAPI installation.</p>
|
||||
|
||||
<p>Since currently you cannot search with A-codes (we're implementing S-codes
|
||||
for that purpose), this field is purely informative.</p>
|
||||
|
||||
<p>Note that this flag can change in time. Some attributes may get
|
||||
introduced into other installations, whereas other attributes may
|
||||
(temporarily or permanently) stop being used. In general, we are aiming
|
||||
towards global unification of all attributes between all OC nodes,
|
||||
but this process will take time (and probably it will never
|
||||
be 100% complete).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_discontinued</b> - boolean, indicates if the attribute is discontinued.
|
||||
This means that it is no longer in use at OC servers which run current OKAPI
|
||||
versions, i.e. geocaches are no longer tagged with this attribute. However,
|
||||
it may still be in use at servers which have not been updated yet to the
|
||||
current OKAPI version.</p>
|
||||
|
||||
<p><b>Important:</b> This flag can change in time. Discontinued attributes can
|
||||
"come back to life" later. You can never be 100% sure you will not
|
||||
encounter them in OKAPI responses, so this field is purely informative.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Retrieve data on a single attribute</brief>
|
||||
<issue-id>268</issue-id>
|
||||
<desc>
|
||||
<p>Retrieve data on a single OKAPI geocache-attribute.</p>
|
||||
|
||||
<p>OKAPI attributes are identified by an unique ID called an <b>A-code</b>.
|
||||
All OKAPI attributes are shared among all OKAPI servers. Once an attribute is
|
||||
published (e.g. via the <b>attribute_index</b> method), it won't
|
||||
disappear in any of the future OKAPI revisions, nor will its meaning change.
|
||||
Some attributes may get discontinued in the future, but they will remain accessible
|
||||
by their original A-code.</p>
|
||||
</desc>
|
||||
<req name='acode'>
|
||||
The A-code of the attribute you're interested in.
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for fields like
|
||||
<b>name</b> and <b>description</b>.</p>
|
||||
</opt>
|
||||
<opt name='fields' default='name'>
|
||||
<p>Pipe-separated list of field names which you are interested with.
|
||||
See below for the list of available fields.</p>
|
||||
</opt>
|
||||
<opt name='forward_compatible' default='true'>
|
||||
By default, OKAPI will return an empty placeholder if you ask for an
|
||||
unknown attribute. If you'd like to catch such errors and handle them
|
||||
differently, then you may change this behavior by setting this parameter
|
||||
to <b>false</b>. Then, OKAPI will return HTTP 400 error response,
|
||||
instead of the placeholder (note that it behaves differently in the
|
||||
<b>attributes</b> method).
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of fields you have selected in the <b>fields</b>
|
||||
parameter. Available fields:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p><b>acode</b> - string, the A-code. Unique identifier of the
|
||||
attribute.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>name</b> - plaintext string, name of the attribute (language is
|
||||
selected based on your <b>langpref</b> parameter),</p>
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>names</b> - a dictionary of all known names of the attribute, in
|
||||
various languages (ISO 639-1 language code is used as dictionary
|
||||
key).</p>
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<b>description</b> - HTML string, description of the attribute (language is
|
||||
selected based on your <b>langpref</b> parameter),
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>descriptions</b> - a dictionary of all known descriptions of the
|
||||
attribute, in various languages (ISO 639-1 language code is used as
|
||||
dictionary key).</p>
|
||||
|
||||
<p>If you think your language is missing, then feel free to add missing
|
||||
translations directly to OKAPI repository. See
|
||||
<a href='https://code.google.com/p/opencaching-api/source/browse/trunk/okapi/services/attrs/attribute-definitions.xml'>here</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>gc_equivs</b> - a list of Geocaching.com (Groundspeak)
|
||||
attributes, which have exactly the same (or a very similar) meaning. Each
|
||||
attribute is described as a dictionary of the following structure:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>id</b> - ID of the Geocaching.com attribute,</li>
|
||||
<li>
|
||||
<b>inc</b> - integer, either 1 or 0. See Geocaching.com's
|
||||
XSD for details on its meaning,
|
||||
</li>
|
||||
<li>
|
||||
<b>name</b> - the name of the attribute (as it is included
|
||||
in Geocaching.com GPX files).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Note that one gc_equivs list may have multiple items on it, and
|
||||
that one Geocaching.com ID may be present in many gc_equivs.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_locally_used</b> - boolean, indicates if the attribute is <i>currently</i>
|
||||
used by <i>this</i> Opencaching server. Or, to be more specific, <b>true</b>
|
||||
means that the attribute can currently be included in the <b>attr_acodes</b> field
|
||||
of the <b>geocache</b> method in this OKAPI installation.</p>
|
||||
|
||||
<p>Note that this flag can change in time. Some attributes may get
|
||||
introduced into other installations, whereas other attributes may
|
||||
(temporarily or permanently) stop being used. In general, we are aiming
|
||||
towards global unification of all attributes between all OC nodes,
|
||||
but this process will take time (and probably it will never
|
||||
be 100% complete).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>local_icon_url</b> - an URL pointing to an image associated with
|
||||
this particular attribute in the local OC server, <b>or null</b> if the
|
||||
current server does not have any image for this attribute.</p>
|
||||
|
||||
<p>Please note, that each OC server uses a different image set for their
|
||||
attributes. All these images come in various sizes and can change over time.
|
||||
In other words, if you want to use this attribute, then you must always be
|
||||
prepared to receive <b>null</b>, or an image of unexpected dimensions.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_discontinued</b> - boolean, indicates if the attribute is discontinued.
|
||||
This means that it is no longer in use at OC servers which run current OKAPI
|
||||
versions, i.e. geocaches are no longer tagged with this attribute. However,
|
||||
it may still be in use at servers which have not been updated yet to the
|
||||
current OKAPI version.</p>
|
||||
|
||||
<p><b>Important:</b> This flag can change in time. Discontinued attributes can
|
||||
"come back to life" later. You can never be 100% sure you will not
|
||||
encounter them in OKAPI responses, so this field is purely informative.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -18,56 +18,56 @@ use okapi\services\attrs\AttrHelper;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Read the parameters.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Read the parameters.
|
||||
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "name";
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "name";
|
||||
|
||||
$only_locally_used = $request->get_parameter('only_locally_used');
|
||||
if (!$only_locally_used) $only_locally_used = "false";
|
||||
$only_locally_used = ($only_locally_used == "true");
|
||||
$only_locally_used = $request->get_parameter('only_locally_used');
|
||||
if (!$only_locally_used) $only_locally_used = "false";
|
||||
$only_locally_used = ($only_locally_used == "true");
|
||||
|
||||
# Get the list of attributes and filter the A-codes based on the
|
||||
# parameters.
|
||||
# Get the list of attributes and filter the A-codes based on the
|
||||
# parameters.
|
||||
|
||||
require_once 'attr_helper.inc.php';
|
||||
$attrdict = AttrHelper::get_attrdict();
|
||||
$acodes = array();
|
||||
foreach ($attrdict as $acode => &$attr_ref)
|
||||
{
|
||||
if ($only_locally_used && ($attr_ref['internal_id'] === null)) {
|
||||
/* Skip. */
|
||||
continue;
|
||||
}
|
||||
require_once 'attr_helper.inc.php';
|
||||
$attrdict = AttrHelper::get_attrdict();
|
||||
$acodes = array();
|
||||
foreach ($attrdict as $acode => &$attr_ref)
|
||||
{
|
||||
if ($only_locally_used && ($attr_ref['internal_id'] === null)) {
|
||||
/* Skip. */
|
||||
continue;
|
||||
}
|
||||
|
||||
$acodes[] = $acode;
|
||||
}
|
||||
$acodes[] = $acode;
|
||||
}
|
||||
|
||||
# Retrieve the attribute objects and return the results.
|
||||
# Retrieve the attribute objects and return the results.
|
||||
|
||||
if (count($acodes) > 0) {
|
||||
$params = array(
|
||||
'acodes' => implode("|", $acodes),
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
);
|
||||
$results = OkapiServiceRunner::call('services/attrs/attributes',
|
||||
new OkapiInternalRequest($request->consumer, $request->token, $params));
|
||||
} else {
|
||||
$results = new ArrayObject();
|
||||
}
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
if (count($acodes) > 0) {
|
||||
$params = array(
|
||||
'acodes' => implode("|", $acodes),
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
);
|
||||
$results = OkapiServiceRunner::call('services/attrs/attributes',
|
||||
new OkapiInternalRequest($request->consumer, $request->token, $params));
|
||||
} else {
|
||||
$results = new ArrayObject();
|
||||
}
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
<xml>
|
||||
<brief>Get the list of all OKAPI attributes (A-codes)</brief>
|
||||
<issue-id>270</issue-id>
|
||||
<desc>
|
||||
<p>This method returns <b>all</b> currently defined OKAPI geocache-attributes.
|
||||
It is useful when you want to cache the data on the client-side.</p>
|
||||
|
||||
<p>Keep in mind that the number of attributes will grow. Hence, <b>if your application
|
||||
uses multiple OKAPI servers, then it's best to use one of the frequently
|
||||
updated servers for pre-caching attribute data</b> (currently, Opencaching.PL
|
||||
is the most frequently updated installation). Also, you should never assume
|
||||
that you have the complete list cached: A new attribute may be created at any time!</p>
|
||||
|
||||
<p>Once an attribute is published via this method, it won't disappear, nor
|
||||
will its meaning change (names and descriptions can be slightly altered though).</p>
|
||||
</desc>
|
||||
<opt name='langpref' default='en'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='fields' default='name'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='only_locally_used' default='false'>
|
||||
<p>By default, all known attributes are returned - including those which
|
||||
were used a couple of years back, or those which are used by other OC nodes
|
||||
(and may perhaps be used by the local OC node in the future). If you're
|
||||
interested only in the attributes *currently used* within *this* Opencaching
|
||||
installation, then you may set this parameter to <b>true</b>.</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
A dictionary. All A-codes will be mapped to dictionary keys, and
|
||||
each value will be an object, as described in the <b>attribute</b> method.
|
||||
</returns>
|
||||
<brief>Get the list of all OKAPI attributes (A-codes)</brief>
|
||||
<issue-id>270</issue-id>
|
||||
<desc>
|
||||
<p>This method returns <b>all</b> currently defined OKAPI geocache-attributes.
|
||||
It is useful when you want to cache the data on the client-side.</p>
|
||||
|
||||
<p>Keep in mind that the number of attributes will grow. Hence, <b>if your application
|
||||
uses multiple OKAPI servers, then it's best to use one of the frequently
|
||||
updated servers for pre-caching attribute data</b> (currently, Opencaching.PL
|
||||
is the most frequently updated installation). Also, you should never assume
|
||||
that you have the complete list cached: A new attribute may be created at any time!</p>
|
||||
|
||||
<p>Once an attribute is published via this method, it won't disappear, nor
|
||||
will its meaning change (names and descriptions can be slightly altered though).</p>
|
||||
</desc>
|
||||
<opt name='langpref' default='en'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='fields' default='name'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='only_locally_used' default='false'>
|
||||
<p>By default, all known attributes are returned - including those which
|
||||
were used a couple of years back, or those which are used by other OC nodes
|
||||
(and may perhaps be used by the local OC node in the future). If you're
|
||||
interested only in the attributes *currently used* within *this* Opencaching
|
||||
installation, then you may set this parameter to <b>true</b>.</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
A dictionary. All A-codes will be mapped to dictionary keys, and
|
||||
each value will be an object, as described in the <b>attribute</b> method.
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -13,95 +13,125 @@ use okapi\InvalidParam;
|
||||
use okapi\OkapiServiceRunner;
|
||||
use okapi\OkapiInternalRequest;
|
||||
use okapi\services\attrs\AttrHelper;
|
||||
use okapi\Db;
|
||||
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
private static $valid_field_names = array(
|
||||
'acode', 'name', 'names', 'description', 'descriptions', 'gc_equivs',
|
||||
'is_locally_used', 'is_deprecated', 'is_discontinued'
|
||||
);
|
||||
private static $valid_field_names = array(
|
||||
'acode', 'name', 'names', 'description', 'descriptions', 'gc_equivs',
|
||||
'is_locally_used', 'is_deprecated', 'local_icon_url', 'is_discontinued'
|
||||
);
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Read the parameters.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Read the parameters.
|
||||
|
||||
$acodes = $request->get_parameter('acodes');
|
||||
if (!$acodes) throw new ParamMissing('acodes');
|
||||
$acodes = explode("|", $acodes);
|
||||
$acodes = $request->get_parameter('acodes');
|
||||
if (!$acodes) throw new ParamMissing('acodes');
|
||||
$acodes = explode("|", $acodes);
|
||||
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$langpref = explode("|", $langpref);
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$langpref = explode("|", $langpref);
|
||||
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "name";
|
||||
$fields = explode("|", $fields);
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
if (!in_array($field, self::$valid_field_names))
|
||||
throw new InvalidParam('fields', "'$field' is not a valid field code.");
|
||||
}
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "name";
|
||||
$fields = explode("|", $fields);
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
if (!in_array($field, self::$valid_field_names))
|
||||
throw new InvalidParam('fields', "'$field' is not a valid field code.");
|
||||
}
|
||||
|
||||
$forward_compatible = $request->get_parameter('forward_compatible');
|
||||
if (!$forward_compatible) $forward_compatible = "true";
|
||||
if (!in_array($forward_compatible, array("true", "false")))
|
||||
throw new InvalidParam('forward_compatible');
|
||||
$forward_compatible = ($forward_compatible == "true");
|
||||
$forward_compatible = $request->get_parameter('forward_compatible');
|
||||
if (!$forward_compatible) $forward_compatible = "true";
|
||||
if (!in_array($forward_compatible, array("true", "false")))
|
||||
throw new InvalidParam('forward_compatible');
|
||||
$forward_compatible = ($forward_compatible == "true");
|
||||
|
||||
# Load the attributes (all of them).
|
||||
# Load the attributes (all of them).
|
||||
|
||||
require_once 'attr_helper.inc.php';
|
||||
$attrdict = AttrHelper::get_attrdict();
|
||||
require_once 'attr_helper.inc.php';
|
||||
$attrdict = AttrHelper::get_attrdict();
|
||||
|
||||
# For each A-code, check if it exists, filter its fields and add it
|
||||
# to the results.
|
||||
# For each A-code, check if it exists, filter its fields and add it
|
||||
# to the results.
|
||||
|
||||
$results = array();
|
||||
foreach ($acodes as $acode)
|
||||
{
|
||||
/* Please note, that the $attr variable from the $attrdict dictionary
|
||||
* below is NOT fully compatible with the interface of the "attribute"
|
||||
* method. Some of $attr's fields are private and should not be exposed,
|
||||
* other fields don't exist and have to be added dynamically! */
|
||||
$results = array();
|
||||
foreach ($acodes as $acode)
|
||||
{
|
||||
/* Please note, that the $attr variable from the $attrdict dictionary
|
||||
* below is NOT fully compatible with the interface of the "attribute"
|
||||
* method. Some of $attr's fields are private and should not be exposed,
|
||||
* other fields don't exist and have to be added dynamically! */
|
||||
|
||||
if (isset($attrdict[$acode])) {
|
||||
$attr = $attrdict[$acode];
|
||||
} elseif ($forward_compatible) {
|
||||
$attr = AttrHelper::get_unknown_placeholder($acode);
|
||||
} else {
|
||||
$results[$acode] = null;
|
||||
continue;
|
||||
}
|
||||
if (isset($attrdict[$acode])) {
|
||||
$attr = $attrdict[$acode];
|
||||
} elseif ($forward_compatible) {
|
||||
$attr = AttrHelper::get_unknown_placeholder($acode);
|
||||
} else {
|
||||
$results[$acode] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
# Fill langpref-specific fields.
|
||||
# Fill langpref-specific fields.
|
||||
|
||||
$attr['name'] = Okapi::pick_best_language($attr['names'], $langpref);
|
||||
$attr['description'] = Okapi::pick_best_language($attr['descriptions'], $langpref);
|
||||
$attr['name'] = Okapi::pick_best_language($attr['names'], $langpref);
|
||||
$attr['description'] = Okapi::pick_best_language($attr['descriptions'], $langpref);
|
||||
|
||||
# Fill all the other fields not kept in the (private) attrdict.
|
||||
# Fill some other fields (not kept in the cached attrdict).
|
||||
|
||||
$attr['is_locally_used'] = ($attr['internal_id'] !== null);
|
||||
$attr['is_deprecated'] = $attr['is_discontinued']; // deprecated and undocumetned field, see issue 70
|
||||
$attr['is_locally_used'] = ($attr['internal_id'] !== null);
|
||||
$attr['is_deprecated'] = $attr['is_discontinued']; // deprecated and undocumetned field, see issue 70
|
||||
|
||||
# Filter the fields.
|
||||
# Add to results.
|
||||
|
||||
$clean_attr = array();
|
||||
foreach ($fields as $field)
|
||||
$clean_attr[$field] = $attr[$field];
|
||||
$results[$acode] = $attr;
|
||||
}
|
||||
|
||||
# Add to results.
|
||||
# If the user wanted local_icon_urls, fetch them now. (We cannot cache them
|
||||
# in the $attrdict because currently we have no way of knowing then they
|
||||
# change.)
|
||||
|
||||
$results[$acode] = $clean_attr;
|
||||
}
|
||||
if (in_array('local_icon_url', $fields))
|
||||
{
|
||||
$tmp = Db::select_all("
|
||||
select id, icon_large
|
||||
from cache_attrib
|
||||
");
|
||||
$map = array();
|
||||
foreach ($tmp as &$row_ref) {
|
||||
$map[$row_ref['id']] = &$row_ref;
|
||||
}
|
||||
$prefix = Settings::get('SITE_URL');
|
||||
foreach ($results as &$attr_ref) {
|
||||
$internal_id = $attr_ref['internal_id'];
|
||||
if (isset($map[$internal_id])) {
|
||||
$row = $map[$internal_id];
|
||||
$attr_ref['local_icon_url'] = $prefix.$row['icon_large'];
|
||||
} else {
|
||||
$attr_ref['local_icon_url'] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
# Filter the fields.
|
||||
|
||||
foreach ($results as &$attr_ref) {
|
||||
$clean_row = array();
|
||||
foreach ($fields as $field)
|
||||
$clean_row[$field] = $attr_ref[$field];
|
||||
$attr_ref = $clean_row;
|
||||
}
|
||||
|
||||
return Okapi::formatted_response($request, $results);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
<xml>
|
||||
<brief>Retrieve data on multiple attributes at once</brief>
|
||||
<issue-id>269</issue-id>
|
||||
<desc>
|
||||
<p>This method works like the <b>attribute</b> method, but
|
||||
with multiple A-codes instead of only one. Read the docs for
|
||||
the <b>attribute</b> method first!</p>
|
||||
</desc>
|
||||
<req name='acodes'>
|
||||
Pipe-separated list of A-codes you're interested in.
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='fields' default='name'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='forward_compatible' default='true'>
|
||||
This has a similar meaning as in the <b>attribute</b> method, but works
|
||||
differently. If set to <b>false</b>, OKAPI will return <b>null</b>s
|
||||
for unknown keys (A-codes). You will still receive an HTTP 200 response
|
||||
though!
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary. A-codes you provide will be mapped to dictionary keys,
|
||||
and each value will be an object, as described in the <b>attribute</b>
|
||||
method.</p>
|
||||
</returns>
|
||||
<brief>Retrieve data on multiple attributes at once</brief>
|
||||
<issue-id>269</issue-id>
|
||||
<desc>
|
||||
<p>This method works like the <b>attribute</b> method, but
|
||||
with multiple A-codes instead of only one. Read the docs for
|
||||
the <b>attribute</b> method first!</p>
|
||||
</desc>
|
||||
<req name='acodes'>
|
||||
Pipe-separated list of A-codes you're interested in.
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='fields' default='name'>
|
||||
Works the same as in the <b>attribute</b> method.
|
||||
</opt>
|
||||
<opt name='forward_compatible' default='true'>
|
||||
This has a similar meaning as in the <b>attribute</b> method, but works
|
||||
differently. If set to <b>false</b>, OKAPI will return <b>null</b>s
|
||||
for unknown keys (A-codes). You will still receive an HTTP 200 response
|
||||
though!
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary. A-codes you provide will be mapped to dictionary keys,
|
||||
and each value will be an object, as described in the <b>attribute</b>
|
||||
method.</p>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -20,198 +20,202 @@ use \Exception;
|
||||
|
||||
class WebService
|
||||
{
|
||||
private static $shutdown_function_registered = false;
|
||||
private static $files_to_unlink = array();
|
||||
private static $shutdown_function_registered = false;
|
||||
private static $files_to_unlink = array();
|
||||
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$cache_codes = $request->get_parameter('cache_codes');
|
||||
if ($cache_codes === null) throw new ParamMissing('cache_codes');
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$cache_codes = $request->get_parameter('cache_codes');
|
||||
if ($cache_codes === null) throw new ParamMissing('cache_codes');
|
||||
|
||||
# Issue 106 requires us to allow empty list of cache codes to be passed into this method.
|
||||
# All of the queries below have to be ready for $cache_codes to be empty!
|
||||
# Issue 106 requires us to allow empty list of cache codes to be passed into this method.
|
||||
# All of the queries below have to be ready for $cache_codes to be empty!
|
||||
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$images = $request->get_parameter('images');
|
||||
if (!$images) $images = "all";
|
||||
if (!in_array($images, array("none", "all", "spoilers", "nonspoilers")))
|
||||
throw new InvalidParam('images');
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$images = $request->get_parameter('images');
|
||||
if (!$images) $images = "all";
|
||||
if (!in_array($images, array("none", "all", "spoilers", "nonspoilers")))
|
||||
throw new InvalidParam('images');
|
||||
$location_source = $request->get_parameter('location_source');
|
||||
$location_change_prefix = $request->get_parameter('location_change_prefix');
|
||||
|
||||
# Start creating ZIP archive.
|
||||
# Start creating ZIP archive.
|
||||
|
||||
$tempfilename = Okapi::get_var_dir()."/garmin".time().rand(100000,999999).".zip";
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($tempfilename, ZIPARCHIVE::CREATE) !== true)
|
||||
throw new Exception("ZipArchive class could not create temp file $tempfilename. Check permissions!");
|
||||
$tempfilename = Okapi::get_var_dir()."/garmin".time().rand(100000,999999).".zip";
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($tempfilename, ZIPARCHIVE::CREATE) !== true)
|
||||
throw new Exception("ZipArchive class could not create temp file $tempfilename. Check permissions!");
|
||||
|
||||
# Create basic structure
|
||||
# Create basic structure
|
||||
|
||||
$zip->addEmptyDir("Garmin");
|
||||
$zip->addEmptyDir("Garmin/GPX");
|
||||
$zip->addEmptyDir("Garmin/GeocachePhotos");
|
||||
$zip->addEmptyDir("Garmin");
|
||||
$zip->addEmptyDir("Garmin/GPX");
|
||||
$zip->addEmptyDir("Garmin/GeocachePhotos");
|
||||
|
||||
# Include a GPX file compatible with Garmin devices. It should include all
|
||||
# Geocaching.com (groundspeak:) and Opencaching.com (ox:) extensions. It will
|
||||
# also include image references (actual images will be added as separate files later)
|
||||
# and personal data (if the method was invoked using Level 3 Authentication).
|
||||
# Include a GPX file compatible with Garmin devices. It should include all
|
||||
# Geocaching.com (groundspeak:) and Opencaching.com (ox:) extensions. It will
|
||||
# also include image references (actual images will be added as separate files later)
|
||||
# and personal data (if the method was invoked using Level 3 Authentication).
|
||||
|
||||
$zip->addFromString("Garmin/GPX/opencaching".time().rand(100000,999999).".gpx",
|
||||
OkapiServiceRunner::call('services/caches/formatters/gpx', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array(
|
||||
'cache_codes' => $cache_codes,
|
||||
'langpref' => $langpref,
|
||||
'ns_ground' => 'true',
|
||||
'ns_ox' => 'true',
|
||||
'images' => 'ox:all',
|
||||
'attrs' => 'ox:tags',
|
||||
'trackables' => 'desc:count',
|
||||
'alt_wpts' => 'true',
|
||||
'recommendations' => 'desc:count',
|
||||
'latest_logs' => 'true',
|
||||
'lpc' => 'all',
|
||||
'my_notes' => ($request->token != null) ? "desc:text" : "none"
|
||||
)))->get_body());
|
||||
$zip->addFromString("Garmin/GPX/opencaching".time().rand(100000,999999).".gpx",
|
||||
OkapiServiceRunner::call('services/caches/formatters/gpx', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array(
|
||||
'cache_codes' => $cache_codes,
|
||||
'langpref' => $langpref,
|
||||
'ns_ground' => 'true',
|
||||
'ns_ox' => 'true',
|
||||
'images' => 'ox:all',
|
||||
'attrs' => 'ox:tags',
|
||||
'trackables' => 'desc:count',
|
||||
'alt_wpts' => 'true',
|
||||
'recommendations' => 'desc:count',
|
||||
'latest_logs' => 'true',
|
||||
'lpc' => 'all',
|
||||
'my_notes' => ($request->token != null) ? "desc:text" : "none",
|
||||
'location_source' => $location_source,
|
||||
'location_change_prefix' => $location_change_prefix
|
||||
)))->get_body());
|
||||
|
||||
# Then, include all the images.
|
||||
# Then, include all the images.
|
||||
|
||||
$caches = OkapiServiceRunner::call('services/caches/geocaches', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array('cache_codes' => $cache_codes,
|
||||
'langpref' => $langpref, 'fields' => "images")));
|
||||
if (count($caches) > 50)
|
||||
throw new InvalidParam('cache_codes', "The maximum number of caches allowed to be downloaded with this method is 50.");
|
||||
if ($images != 'none')
|
||||
{
|
||||
$supported_extensions = array('jpg', 'jpeg', 'gif', 'png', 'bmp');
|
||||
foreach ($caches as $cache_code => $dict)
|
||||
{
|
||||
$imgs = $dict['images'];
|
||||
if (count($imgs) == 0)
|
||||
continue;
|
||||
$dir = "Garmin/GeocachePhotos/".$cache_code[strlen($cache_code) - 1];
|
||||
$zip->addEmptyDir($dir); # fails silently if it already exists
|
||||
$dir .= "/".$cache_code[strlen($cache_code) - 2];
|
||||
$zip->addEmptyDir($dir);
|
||||
$dir .= "/".$cache_code;
|
||||
$zip->addEmptyDir($dir);
|
||||
foreach ($imgs as $no => $img)
|
||||
{
|
||||
if ($images == 'spoilers' && (!$img['is_spoiler']))
|
||||
continue;
|
||||
if ($images == 'nonspoilers' && $img['is_spoiler'])
|
||||
continue;
|
||||
$tmp = false;
|
||||
foreach ($supported_extensions as $ext)
|
||||
{
|
||||
if (strtolower(substr($img['url'], strlen($img['url']) - strlen($ext) - 1)) != ".".$ext)
|
||||
{
|
||||
$tmp = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!$tmp)
|
||||
continue; # unsupported file extension
|
||||
$caches = OkapiServiceRunner::call('services/caches/geocaches', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array('cache_codes' => $cache_codes,
|
||||
'langpref' => $langpref, 'fields' => "images")));
|
||||
if (count($caches) > 50)
|
||||
throw new InvalidParam('cache_codes', "The maximum number of caches allowed to be downloaded with this method is 50.");
|
||||
if ($images != 'none')
|
||||
{
|
||||
$supported_extensions = array('jpg', 'jpeg', 'gif', 'png', 'bmp');
|
||||
foreach ($caches as $cache_code => $dict)
|
||||
{
|
||||
$imgs = $dict['images'];
|
||||
if (count($imgs) == 0)
|
||||
continue;
|
||||
$dir = "Garmin/GeocachePhotos/".$cache_code[strlen($cache_code) - 1];
|
||||
$zip->addEmptyDir($dir); # fails silently if it already exists
|
||||
$dir .= "/".$cache_code[strlen($cache_code) - 2];
|
||||
$zip->addEmptyDir($dir);
|
||||
$dir .= "/".$cache_code;
|
||||
$zip->addEmptyDir($dir);
|
||||
foreach ($imgs as $no => $img)
|
||||
{
|
||||
if ($images == 'spoilers' && (!$img['is_spoiler']))
|
||||
continue;
|
||||
if ($images == 'nonspoilers' && $img['is_spoiler'])
|
||||
continue;
|
||||
$tmp = false;
|
||||
foreach ($supported_extensions as $ext)
|
||||
{
|
||||
if (strtolower(substr($img['url'], strlen($img['url']) - strlen($ext) - 1)) != ".".$ext)
|
||||
{
|
||||
$tmp = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!$tmp)
|
||||
continue; # unsupported file extension
|
||||
|
||||
if ($img['is_spoiler']) {
|
||||
$zip->addEmptyDir($dir."/Spoilers");
|
||||
$zippath = $dir."/Spoilers/".$img['unique_caption'].".jpg";
|
||||
} else {
|
||||
$zippath = $dir."/".$img['unique_caption'].".jpg";
|
||||
}
|
||||
if ($img['is_spoiler']) {
|
||||
$zip->addEmptyDir($dir."/Spoilers");
|
||||
$zippath = $dir."/Spoilers/".$img['unique_caption'].".jpg";
|
||||
} else {
|
||||
$zippath = $dir."/".$img['unique_caption'].".jpg";
|
||||
}
|
||||
|
||||
# The safest way would be to use the URL, but that would be painfully slow!
|
||||
# That's why we're trying to access files directly (and fail silently on error).
|
||||
# This was tested on OCPL server only.
|
||||
# The safest way would be to use the URL, but that would be painfully slow!
|
||||
# That's why we're trying to access files directly (and fail silently on error).
|
||||
# This was tested on OCPL server only.
|
||||
|
||||
# Note: Oliver Dietz (oc.de) replied that images with 'local' set to 0 could not
|
||||
# be accessed locally. But all the files have 'local' set to 1 anyway.
|
||||
# Note: Oliver Dietz (oc.de) replied that images with 'local' set to 0 could not
|
||||
# be accessed locally. But all the files have 'local' set to 1 anyway.
|
||||
|
||||
$syspath = Settings::get('IMAGES_DIR')."/".$img['uuid'].".jpg";
|
||||
if (file_exists($syspath))
|
||||
{
|
||||
$file = file_get_contents($syspath);
|
||||
if ($file)
|
||||
$zip->addFromString($zippath, $file);
|
||||
}
|
||||
else
|
||||
{
|
||||
# If file exists, but does not end with ".jpg", we will create
|
||||
# JPEG version of it and store it in the cache.
|
||||
$syspath = Settings::get('IMAGES_DIR')."/".$img['uuid'].".jpg";
|
||||
if (file_exists($syspath))
|
||||
{
|
||||
$file = file_get_contents($syspath);
|
||||
if ($file)
|
||||
$zip->addFromString($zippath, $file);
|
||||
}
|
||||
else
|
||||
{
|
||||
# If file exists, but does not end with ".jpg", we will create
|
||||
# JPEG version of it and store it in the cache.
|
||||
|
||||
$cache_key = "jpg#".$img['uuid'];
|
||||
$jpeg_contents = Cache::get($cache_key);
|
||||
if ($jpeg_contents === null)
|
||||
{
|
||||
foreach ($supported_extensions as $ext)
|
||||
{
|
||||
$syspath_other = Settings::get('IMAGES_DIR')."/".$img['uuid'].".".$ext;
|
||||
if (file_exists($syspath_other))
|
||||
{
|
||||
try
|
||||
{
|
||||
$image = imagecreatefromstring(file_get_contents($syspath_other));
|
||||
ob_start();
|
||||
imagejpeg($image);
|
||||
$jpeg_contents = ob_get_clean();
|
||||
imagedestroy($image);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
# GD couldn't parse the file. We will skip it, and cache
|
||||
# the "false" value as the contents. This way, we won't
|
||||
# attempt to parse it during the next 24 hours.
|
||||
$cache_key = "jpg#".$img['uuid'];
|
||||
$jpeg_contents = Cache::get($cache_key);
|
||||
if ($jpeg_contents === null)
|
||||
{
|
||||
foreach ($supported_extensions as $ext)
|
||||
{
|
||||
$syspath_other = Settings::get('IMAGES_DIR')."/".$img['uuid'].".".$ext;
|
||||
if (file_exists($syspath_other))
|
||||
{
|
||||
try
|
||||
{
|
||||
$image = imagecreatefromstring(file_get_contents($syspath_other));
|
||||
ob_start();
|
||||
imagejpeg($image);
|
||||
$jpeg_contents = ob_get_clean();
|
||||
imagedestroy($image);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
# GD couldn't parse the file. We will skip it, and cache
|
||||
# the "false" value as the contents. This way, we won't
|
||||
# attempt to parse it during the next 24 hours.
|
||||
|
||||
$jpeg_contents = false;
|
||||
}
|
||||
Cache::set($cache_key, $jpeg_contents, 86400);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($jpeg_contents) # This can be "null" *or* "false"!
|
||||
$zip->addFromString($zippath, $jpeg_contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$jpeg_contents = false;
|
||||
}
|
||||
Cache::set($cache_key, $jpeg_contents, 86400);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($jpeg_contents) # This can be "null" *or* "false"!
|
||||
$zip->addFromString($zippath, $jpeg_contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
$zip->close();
|
||||
|
||||
# The result could be big. Bigger than our memory limit. We will
|
||||
# return an open file stream instead of a string. We also should
|
||||
# set a higher time limit, because downloading this response may
|
||||
# take some time over slow network connections (and I'm not sure
|
||||
# what is the PHP's default way of handling such scenario).
|
||||
# The result could be big. Bigger than our memory limit. We will
|
||||
# return an open file stream instead of a string. We also should
|
||||
# set a higher time limit, because downloading this response may
|
||||
# take some time over slow network connections (and I'm not sure
|
||||
# what is the PHP's default way of handling such scenario).
|
||||
|
||||
set_time_limit(600);
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = "application/zip";
|
||||
$response->content_disposition = 'attachment; filename="results.zip"';
|
||||
$response->stream_length = filesize($tempfilename);
|
||||
$response->body = fopen($tempfilename, "rb");
|
||||
$response->allow_gzip = false;
|
||||
self::add_file_to_unlink($tempfilename);
|
||||
return $response;
|
||||
}
|
||||
set_time_limit(600);
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = "application/zip";
|
||||
$response->content_disposition = 'attachment; filename="results.zip"';
|
||||
$response->stream_length = filesize($tempfilename);
|
||||
$response->body = fopen($tempfilename, "rb");
|
||||
$response->allow_gzip = false;
|
||||
self::add_file_to_unlink($tempfilename);
|
||||
return $response;
|
||||
}
|
||||
|
||||
private static function add_file_to_unlink($filename)
|
||||
{
|
||||
if (!self::$shutdown_function_registered)
|
||||
register_shutdown_function(array("okapi\\services\\caches\\formatters\\garmin\\WebService", "unlink_temporary_files"));
|
||||
self::$files_to_unlink[] = $filename;
|
||||
}
|
||||
private static function add_file_to_unlink($filename)
|
||||
{
|
||||
if (!self::$shutdown_function_registered)
|
||||
register_shutdown_function(array("okapi\\services\\caches\\formatters\\garmin\\WebService", "unlink_temporary_files"));
|
||||
self::$files_to_unlink[] = $filename;
|
||||
}
|
||||
|
||||
public static function unlink_temporary_files()
|
||||
{
|
||||
foreach (self::$files_to_unlink as $filename)
|
||||
@unlink($filename);
|
||||
self::$files_to_unlink = array();
|
||||
}
|
||||
public static function unlink_temporary_files()
|
||||
{
|
||||
foreach (self::$files_to_unlink as $filename)
|
||||
@unlink($filename);
|
||||
self::$files_to_unlink = array();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,55 @@
|
||||
<xml>
|
||||
<brief>Retrieve ZIP file for Garmin devices</brief>
|
||||
<issue-id>99</issue-id>
|
||||
<desc>
|
||||
<p>Produce a ZIP file with content compatible with Geocaching-enabled Garmin
|
||||
GPS devices. The general idea is, <b>you should <u>extract</u> the contents</b> of the ZIP
|
||||
file directly <b>into the root directory</b> of your Garmin's internal memory storage
|
||||
(currently it doesn't work if you extract the data to the external MicroSD card). The device
|
||||
will then be filled with all the data we are currently able to fill it with.</p>
|
||||
<p>Currently, the ZIP file will contain GPX file and all JPEG images associated
|
||||
with the chosen geocaches. Options for the GPX file are fixed, use the
|
||||
services/caches/formatters/gpx method if
|
||||
you want a custom-tailored GPX file.</p>
|
||||
<p><b>Important note:</b> The contents of the returned ZIP archive may change in the
|
||||
future. You should not parse the contents, nor assume that they have any specific
|
||||
structure.</p>
|
||||
<p><b>Important note:</b> We might be increasing required authentication level for
|
||||
this method to level 2 or 3. You should be prepared for that. Use the highest authentication
|
||||
level you've got. Also, if you want the GPX file to include <b>personal data (like user's notes)</b>,
|
||||
you have to use Level 3 Authentication anyway.</p>
|
||||
<p><b>Note:</b> All non-JPEG images will be skipped. Currently OKAPI does not convert
|
||||
other types of images to JPEG.</p>
|
||||
</desc>
|
||||
<req name='cache_codes'>
|
||||
<p>Pipe-separated list of cache codes which you are interested in.
|
||||
No more than 50 codes are allowed. (This limit is smaller than usual, because
|
||||
we're afraid about the sizes of ZIP files produced.)
|
||||
This CAN be an empty string (it will still result in a valid ZIP file).</p>
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for GPX entities.</p>
|
||||
</opt>
|
||||
<opt name='images' default='all'>
|
||||
<p>One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no images will be included in the result,</li>
|
||||
<li><b>all</b> - all images will be included in the result,</li>
|
||||
<li><b>spoilers</b> - only spoiler images will be included in the result,</li>
|
||||
<li><b>nonspoilers</b> - only non-spoiler images will be included in the result.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<returns>
|
||||
<p>ZIP file. You should extract it's contents directly into the root
|
||||
directory of your Garmin's internal memory storage.</p>
|
||||
</returns>
|
||||
<brief>Retrieve ZIP file for Garmin devices</brief>
|
||||
<issue-id>99</issue-id>
|
||||
<desc>
|
||||
<p>Produce a ZIP file with content compatible with Geocaching-enabled Garmin
|
||||
GPS devices. The general idea is, <b>you should <u>extract</u> the contents</b> of the ZIP
|
||||
file directly <b>into the root directory</b> of your Garmin's internal memory storage
|
||||
(currently it doesn't work if you extract the data to the external MicroSD card). The device
|
||||
will then be filled with all the data we are currently able to fill it with.</p>
|
||||
<p>Currently, the ZIP file will contain GPX file and all JPEG images associated
|
||||
with the chosen geocaches. Options for the GPX file are fixed, use the
|
||||
services/caches/formatters/gpx method if
|
||||
you want a custom-tailored GPX file.</p>
|
||||
<p><b>Important note:</b> The contents of the returned ZIP archive may change in the
|
||||
future. You should not parse the contents, nor assume that they have any specific
|
||||
structure.</p>
|
||||
<p><b>Important note:</b> We might be increasing required authentication level for
|
||||
this method to level 2 or 3. You should be prepared for that. Use the highest authentication
|
||||
level you've got. Also, if you want the GPX file to include <b>personal data (like user's notes)</b>,
|
||||
you have to use Level 3 Authentication anyway.</p>
|
||||
<p><b>Note:</b> All non-JPEG images will be skipped. Currently OKAPI does not convert
|
||||
other types of images to JPEG.</p>
|
||||
</desc>
|
||||
<req name='cache_codes'>
|
||||
<p>Pipe-separated list of cache codes which you are interested in.
|
||||
No more than 50 codes are allowed. (This limit is smaller than usual, because
|
||||
we're afraid about the sizes of ZIP files produced.)
|
||||
This CAN be an empty string (it will still result in a valid ZIP file).</p>
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for GPX entities.</p>
|
||||
</opt>
|
||||
<opt name='images' default='all'>
|
||||
<p>One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no images will be included in the result,</li>
|
||||
<li><b>all</b> - all images will be included in the result,</li>
|
||||
<li><b>spoilers</b> - only spoiler images will be included in the result,</li>
|
||||
<li><b>nonspoilers</b> - only non-spoiler images will be included in the result.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name="location_source" default='default-coords'>
|
||||
Same as in the <a href="%OKAPI:methodargref:services/caches/formatters/gpx#location_source%">
|
||||
services/caches/formatters/gpx</a> method.
|
||||
</opt>
|
||||
<opt name="location_change_prefix" default="#">
|
||||
Same as in the <a href="%OKAPI:methodargref:services/caches/formatters/gpx#location_change_prefix%">
|
||||
services/caches/formatters/gpx</a> method.
|
||||
</opt>
|
||||
<returns>
|
||||
<p>ZIP file. You should extract it's contents directly into the root
|
||||
directory of your Garmin's internal memory storage.</p>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -19,280 +19,383 @@ use okapi\services\attrs\AttrHelper;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
/** Maps OKAPI cache type codes to Geocaching.com GPX cache types. */
|
||||
public static $cache_GPX_types = array(
|
||||
'Traditional' => 'Traditional Cache',
|
||||
'Multi' => 'Multi-Cache',
|
||||
'Quiz' => 'Unknown Cache',
|
||||
'Event' => 'Event Cache',
|
||||
'Virtual' => 'Virtual Cache',
|
||||
'Webcam' => 'Webcam Cache',
|
||||
'Moving' => 'Unknown Cache',
|
||||
'Math/Physics' => 'Unknown Cache',
|
||||
'Drive-In' => 'Traditional Cache',
|
||||
'Own' => 'Unknown Cache',
|
||||
'Other' => 'Unknown Cache'
|
||||
);
|
||||
/** Maps OKAPI cache type codes to Geocaching.com GPX cache types. */
|
||||
public static $cache_GPX_types = array(
|
||||
'Traditional' => 'Traditional Cache',
|
||||
'Multi' => 'Multi-Cache',
|
||||
'Quiz' => 'Unknown Cache',
|
||||
'Event' => 'Event Cache',
|
||||
'Virtual' => 'Virtual Cache',
|
||||
'Webcam' => 'Webcam Cache',
|
||||
'Moving' => 'Unknown Cache',
|
||||
'Math/Physics' => 'Unknown Cache',
|
||||
'Drive-In' => 'Traditional Cache',
|
||||
'Podcast' => 'Unknown Cache',
|
||||
'Own' => 'Unknown Cache',
|
||||
'Other' => 'Unknown Cache'
|
||||
);
|
||||
|
||||
/** Maps OKAPI's 'size2' values to geocaching.com size codes. */
|
||||
public static $cache_GPX_sizes = array(
|
||||
'none' => 'Virtual',
|
||||
'nano' => 'Micro',
|
||||
'micro' => 'Micro',
|
||||
'small' => 'Small',
|
||||
'regular' => 'Regular',
|
||||
'large' => 'Large',
|
||||
'xlarge' => 'Large',
|
||||
'other' => 'Other',
|
||||
);
|
||||
/** Maps OKAPI's 'size2' values to geocaching.com size codes. */
|
||||
public static $cache_GPX_sizes = array(
|
||||
'none' => 'Virtual',
|
||||
'nano' => 'Micro',
|
||||
'micro' => 'Micro',
|
||||
'small' => 'Small',
|
||||
'regular' => 'Regular',
|
||||
'large' => 'Large',
|
||||
'xlarge' => 'Large',
|
||||
'other' => 'Other',
|
||||
);
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$vars = array();
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$vars = array();
|
||||
|
||||
# Validating arguments. We will also assign some of them to the
|
||||
# $vars variable which we will use later in the GPS template.
|
||||
# Validating arguments. We will also assign some of them to the
|
||||
# $vars variable which we will use later in the GPS template.
|
||||
|
||||
$cache_codes = $request->get_parameter('cache_codes');
|
||||
if ($cache_codes === null) throw new ParamMissing('cache_codes');
|
||||
$cache_codes = $request->get_parameter('cache_codes');
|
||||
if ($cache_codes === null) throw new ParamMissing('cache_codes');
|
||||
|
||||
# Issue 106 requires us to allow empty list of cache codes to be passed into this method.
|
||||
# All of the queries below have to be ready for $cache_codes to be empty!
|
||||
# Issue 106 requires us to allow empty list of cache codes to be passed into this method.
|
||||
# All of the queries below have to be ready for $cache_codes to be empty!
|
||||
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
foreach (array('ns_ground', 'ns_gsak', 'ns_ox', 'latest_logs', 'alt_wpts', 'mark_found') as $param)
|
||||
{
|
||||
$val = $request->get_parameter($param);
|
||||
if (!$val) $val = "false";
|
||||
elseif (!in_array($val, array("true", "false")))
|
||||
throw new InvalidParam($param);
|
||||
$vars[$param] = ($val == "true");
|
||||
}
|
||||
if ($vars['latest_logs'] && (!$vars['ns_ground']))
|
||||
throw new BadRequest("In order for 'latest_logs' to work you have to also include 'ns_ground' extensions.");
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
foreach (array('ns_ground', 'ns_gsak', 'ns_ox', 'latest_logs', 'alt_wpts', 'mark_found') as $param)
|
||||
{
|
||||
$val = $request->get_parameter($param);
|
||||
if (!$val) $val = "false";
|
||||
elseif (!in_array($val, array("true", "false")))
|
||||
throw new InvalidParam($param);
|
||||
$vars[$param] = ($val == "true");
|
||||
}
|
||||
if ($vars['latest_logs'] && (!$vars['ns_ground']))
|
||||
throw new BadRequest("In order for 'latest_logs' to work you have to also include 'ns_ground' extensions.");
|
||||
|
||||
$tmp = $request->get_parameter('my_notes');
|
||||
if (!$tmp) $tmp = "none";
|
||||
if (!in_array($tmp, array("none", "desc:text")))
|
||||
throw new InvalidParam("my_notes");
|
||||
if (($tmp != 'none') && ($request->token == null))
|
||||
throw new BadRequest("Level 3 Authentication is required to access my_notes data.");
|
||||
$vars['my_notes'] = $tmp;
|
||||
$tmp = $request->get_parameter('my_notes');
|
||||
$vars['my_notes'] = array();
|
||||
if ($tmp && $tmp != 'none') {
|
||||
$tmp = explode('|', $tmp);
|
||||
foreach ($tmp as $elem) {
|
||||
if ($elem == 'none') {
|
||||
/* pass */
|
||||
} elseif (in_array($elem, array('desc:text', 'gc:personal_note'))) {
|
||||
if (in_array('none', $tmp)) {
|
||||
throw new InvalidParam(
|
||||
'my_notes', "You cannot mix 'none' and '$elem'"
|
||||
);
|
||||
}
|
||||
if ($request->token == null) {
|
||||
throw new BadRequest(
|
||||
"Level 3 Authentication is required to access my_notes data."
|
||||
);
|
||||
}
|
||||
$vars['my_notes'][] = $elem;
|
||||
} else {
|
||||
throw new InvalidParam('my_notes', "Invalid list entry: '$elem'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$images = $request->get_parameter('images');
|
||||
if (!$images) $images = 'descrefs:nonspoilers';
|
||||
if (!in_array($images, array('none', 'descrefs:thumblinks', 'descrefs:nonspoilers', 'descrefs:all', 'ox:all')))
|
||||
throw new InvalidParam('images', "'$images'");
|
||||
$vars['images'] = $images;
|
||||
$images = $request->get_parameter('images');
|
||||
if (!$images) $images = 'descrefs:nonspoilers';
|
||||
if (!in_array($images, array('none', 'descrefs:thumblinks', 'descrefs:nonspoilers', 'descrefs:all', 'ox:all')))
|
||||
throw new InvalidParam('images', "'$images'");
|
||||
$vars['images'] = $images;
|
||||
|
||||
$tmp = $request->get_parameter('attrs');
|
||||
if (!$tmp) $tmp = 'desc:text';
|
||||
$tmp = explode("|", $tmp);
|
||||
$vars['attrs'] = array();
|
||||
foreach ($tmp as $elem)
|
||||
{
|
||||
if ($elem == 'none') {
|
||||
/* pass */
|
||||
} elseif (in_array($elem, array('desc:text', 'ox:tags', 'gc:attrs', 'gc_ocde:attrs'))) {
|
||||
if ($elem == 'gc_ocde:attrs' && Settings::get('OC_BRANCH') != 'oc.de')
|
||||
$vars['attrs'][] = 'gc:attrs';
|
||||
else
|
||||
$vars['attrs'][] = $elem;
|
||||
} else {
|
||||
throw new InvalidParam('attrs', "Invalid list entry: '$elem'");
|
||||
}
|
||||
}
|
||||
$tmp = $request->get_parameter('attrs');
|
||||
if (!$tmp) $tmp = 'desc:text';
|
||||
$tmp = explode("|", $tmp);
|
||||
$vars['attrs'] = array();
|
||||
foreach ($tmp as $elem)
|
||||
{
|
||||
if ($elem == 'none') {
|
||||
/* pass */
|
||||
} elseif (in_array($elem, array('desc:text', 'ox:tags', 'gc:attrs', 'gc_ocde:attrs'))) {
|
||||
if ($elem == 'gc_ocde:attrs' && Settings::get('OC_BRANCH') != 'oc.de')
|
||||
$vars['attrs'][] = 'gc:attrs';
|
||||
else
|
||||
$vars['attrs'][] = $elem;
|
||||
} else {
|
||||
throw new InvalidParam('attrs', "Invalid list entry: '$elem'");
|
||||
}
|
||||
}
|
||||
|
||||
$protection_areas = $request->get_parameter('protection_areas');
|
||||
if (!$protection_areas || $protection_areas == 'desc:auto')
|
||||
{
|
||||
if (Settings::get('OC_BRANCH') == 'oc.de') $protection_areas = 'desc:text';
|
||||
else $protection_areas = 'none';
|
||||
}
|
||||
if (!in_array($protection_areas, array('none', 'desc:text')))
|
||||
throw new InvalidParam('protection_areas',"'$protection_areas'");
|
||||
$vars['protection_areas'] = $protection_areas;
|
||||
$protection_areas = $request->get_parameter('protection_areas');
|
||||
if (!$protection_areas || $protection_areas == 'desc:auto')
|
||||
{
|
||||
if (Settings::get('OC_BRANCH') == 'oc.de') $protection_areas = 'desc:text';
|
||||
else $protection_areas = 'none';
|
||||
}
|
||||
if (!in_array($protection_areas, array('none', 'desc:text')))
|
||||
throw new InvalidParam('protection_areas',"'$protection_areas'");
|
||||
$vars['protection_areas'] = $protection_areas;
|
||||
|
||||
$tmp = $request->get_parameter('trackables');
|
||||
if (!$tmp) $tmp = 'none';
|
||||
if (!in_array($tmp, array('none', 'desc:list', 'desc:count')))
|
||||
throw new InvalidParam('trackables', "'$tmp'");
|
||||
$vars['trackables'] = $tmp;
|
||||
$tmp = $request->get_parameter('trackables');
|
||||
if (!$tmp) $tmp = 'none';
|
||||
if (!in_array($tmp, array('none', 'desc:list', 'desc:count')))
|
||||
throw new InvalidParam('trackables', "'$tmp'");
|
||||
$vars['trackables'] = $tmp;
|
||||
|
||||
$tmp = $request->get_parameter('recommendations');
|
||||
if (!$tmp) $tmp = 'none';
|
||||
if (!in_array($tmp, array('none', 'desc:count')))
|
||||
throw new InvalidParam('recommendations', "'$tmp'");
|
||||
$vars['recommendations'] = $tmp;
|
||||
$tmp = $request->get_parameter('recommendations');
|
||||
if (!$tmp) $tmp = 'none';
|
||||
if (!in_array($tmp, array('none', 'desc:count')))
|
||||
throw new InvalidParam('recommendations', "'$tmp'");
|
||||
$vars['recommendations'] = $tmp;
|
||||
|
||||
$lpc = $request->get_parameter('lpc');
|
||||
if ($lpc === null) $lpc = 10; # will be checked in services/caches/geocaches call
|
||||
$lpc = $request->get_parameter('lpc');
|
||||
if ($lpc === null) $lpc = 10; # will be checked in services/caches/geocaches call
|
||||
|
||||
$user_uuid = $request->get_parameter('user_uuid');
|
||||
$user_uuid = $request->get_parameter('user_uuid');
|
||||
|
||||
# Which fields of the services/caches/geocaches method do we need?
|
||||
# location_source (part 1 of 2)
|
||||
|
||||
$fields = 'code|name|location|date_created|url|type|status|size|size2|oxsize'.
|
||||
'|difficulty|terrain|description|hint2|rating|owner|url|internal_id'.
|
||||
'|protection_areas';
|
||||
if ($vars['images'] != 'none')
|
||||
$fields .= "|images";
|
||||
if (count($vars['attrs']) > 0)
|
||||
$fields .= "|attrnames|attr_acodes";
|
||||
if ($vars['trackables'] == 'desc:list')
|
||||
$fields .= "|trackables";
|
||||
elseif ($vars['trackables'] == 'desc:count')
|
||||
$fields .= "|trackables_count";
|
||||
if ($vars['alt_wpts'] == 'true')
|
||||
$fields .= "|alt_wpts";
|
||||
if ($vars['recommendations'] != 'none')
|
||||
$fields .= "|recommendations|founds";
|
||||
if ($vars['my_notes'] != 'none')
|
||||
$fields .= "|my_notes";
|
||||
if ($vars['latest_logs'])
|
||||
$fields .= "|latest_logs";
|
||||
if ($vars['mark_found'])
|
||||
$fields .= "|is_found";
|
||||
$location_source = $request->get_parameter('location_source');
|
||||
if (!$location_source)
|
||||
{
|
||||
$location_source = 'default-coords';
|
||||
}
|
||||
# Make sure location_source has prefix alt_wpt:
|
||||
if ($location_source != 'default-coords' && strncmp($location_source, 'alt_wpt:', 8) != 0)
|
||||
{
|
||||
throw new InvalidParam('location_source', '\''.$location_source.'\'');
|
||||
}
|
||||
|
||||
$vars['caches'] = OkapiServiceRunner::call(
|
||||
'services/caches/geocaches', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array(
|
||||
'cache_codes' => $cache_codes,
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
'lpc' => $lpc,
|
||||
'user_uuid' => $user_uuid,
|
||||
'log_fields' => 'uuid|date|user|type|comment|internal_id|was_recommended'
|
||||
)
|
||||
)
|
||||
);
|
||||
# Make sure we have sufficient authorization
|
||||
if ($location_source == 'alt_wpt:user-coords' && $request->token == null)
|
||||
{
|
||||
throw new BadRequest("Level 3 Authentication is required to access 'alt_wpt:user-coords'.");
|
||||
}
|
||||
|
||||
# Get all the other data need.
|
||||
# Which fields of the services/caches/geocaches method do we need?
|
||||
|
||||
$vars['installation'] = OkapiServiceRunner::call(
|
||||
'services/apisrv/installation', new OkapiInternalRequest(
|
||||
new OkapiInternalConsumer(), null, array()
|
||||
)
|
||||
);
|
||||
$vars['cache_GPX_types'] = self::$cache_GPX_types;
|
||||
$vars['cache_GPX_sizes'] = self::$cache_GPX_sizes;
|
||||
$fields = 'code|name|location|date_created|url|type|status|size|size2|oxsize'.
|
||||
'|difficulty|terrain|description|hint2|rating|owner|url|internal_id'.
|
||||
'|protection_areas|short_description';
|
||||
if ($vars['images'] != 'none')
|
||||
$fields .= "|images";
|
||||
if (count($vars['attrs']) > 0)
|
||||
$fields .= "|attrnames|attr_acodes";
|
||||
if ($vars['trackables'] == 'desc:list')
|
||||
$fields .= "|trackables";
|
||||
elseif ($vars['trackables'] == 'desc:count')
|
||||
$fields .= "|trackables_count";
|
||||
if ($vars['alt_wpts'] == 'true' || $location_source != 'default-coords')
|
||||
$fields .= "|alt_wpts";
|
||||
if ($vars['recommendations'] != 'none')
|
||||
$fields .= "|recommendations|founds";
|
||||
if (count($vars['my_notes']) > 0)
|
||||
$fields .= "|my_notes";
|
||||
if ($vars['latest_logs'])
|
||||
$fields .= "|latest_logs";
|
||||
if ($vars['mark_found'])
|
||||
$fields .= "|is_found";
|
||||
|
||||
if (count($vars['attrs']) > 0)
|
||||
{
|
||||
/* The user asked for some kind of attribute output. We'll fetch all
|
||||
* the data we MAY need. This is often far too much, but thanks to
|
||||
* caching, it will work fast. */
|
||||
$vars['caches'] = OkapiServiceRunner::call(
|
||||
'services/caches/geocaches', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array(
|
||||
'cache_codes' => $cache_codes,
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
'lpc' => $lpc,
|
||||
'user_uuid' => $user_uuid,
|
||||
'log_fields' => 'uuid|date|user|type|comment|internal_id|was_recommended'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$vars['attr_index'] = OkapiServiceRunner::call(
|
||||
'services/attrs/attribute_index', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array(
|
||||
'only_locally_used' => 'true',
|
||||
'langpref' => $langpref,
|
||||
'fields' => 'name|gc_equivs'
|
||||
)
|
||||
)
|
||||
);
|
||||
# Get rid of invalid cache references.
|
||||
|
||||
# prepare GS attribute data
|
||||
$valid = array();
|
||||
foreach ($vars['caches'] as $key => &$ref) {
|
||||
if ($ref !== null) {
|
||||
$valid[$key] = &$ref;
|
||||
}
|
||||
}
|
||||
$vars['caches'] = &$valid;
|
||||
unset($valid);
|
||||
|
||||
$vars['gc_attrs'] = in_array('gc:attrs', $vars['attrs']);
|
||||
$vars['gc_ocde_attrs'] = in_array('gc_ocde:attrs', $vars['attrs']);
|
||||
if ($vars['gc_attrs'] || $vars['gc_ocde_attrs'])
|
||||
{
|
||||
if ($vars['gc_ocde_attrs'])
|
||||
{
|
||||
# As this is an OCDE compatibility feature, we use the same Pseudo-GS
|
||||
# attribute names here as OCDE. Note that this code is specific to OCDE
|
||||
# database; OCPL stores attribute names in a different way and may use
|
||||
# different names for equivalent attributes.
|
||||
# Get all the other data need.
|
||||
|
||||
$ocde_attrnames = Db::select_group_by('id',"
|
||||
select id, name
|
||||
from cache_attrib
|
||||
");
|
||||
$attr_dict = AttrHelper::get_attrdict();
|
||||
}
|
||||
$vars['installation'] = OkapiServiceRunner::call(
|
||||
'services/apisrv/installation', new OkapiInternalRequest(
|
||||
new OkapiInternalConsumer(), null, array()
|
||||
)
|
||||
);
|
||||
$vars['cache_GPX_types'] = self::$cache_GPX_types;
|
||||
$vars['cache_GPX_sizes'] = self::$cache_GPX_sizes;
|
||||
|
||||
foreach ($vars['caches'] as &$cache)
|
||||
{
|
||||
$cache['gc_attrs'] = array();
|
||||
foreach ($cache['attr_acodes'] as $acode)
|
||||
{
|
||||
$has_gc_equivs = false;
|
||||
foreach ($vars['attr_index'][$acode]['gc_equivs'] as $gc)
|
||||
{
|
||||
# The assignment via GC-ID as array key will prohibit duplicate
|
||||
# GC attributes, which can result from
|
||||
# - assigning the same GC ID to multiple A-Codes,
|
||||
# - contradicting attributes in one OC listing, e.g. 24/4 + not 24/7.
|
||||
if (count($vars['attrs']) > 0)
|
||||
{
|
||||
/* The user asked for some kind of attribute output. We'll fetch all
|
||||
* the data we MAY need. This is often far too much, but thanks to
|
||||
* caching, it will work fast. */
|
||||
|
||||
$cache['gc_attrs'][$gc['id']] = $gc;
|
||||
$has_gc_equivs = true;
|
||||
}
|
||||
if (!$has_gc_equivs && $vars['gc_ocde_attrs'])
|
||||
{
|
||||
# Generate an OCDE pseudo-GS attribute;
|
||||
# see http://code.google.com/p/opencaching-api/issues/detail?id=190 and
|
||||
# http://code.google.com/p/opencaching-api/issues/detail?id=271.
|
||||
#
|
||||
# Groundspeak uses ID 1..65 (as of June, 2013), and OCDE makeshift
|
||||
# IDs start at 106, so there is space for 40 new GS attributes.
|
||||
$vars['attr_index'] = OkapiServiceRunner::call(
|
||||
'services/attrs/attribute_index', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array(
|
||||
'only_locally_used' => 'true',
|
||||
'langpref' => $langpref,
|
||||
'fields' => 'name|gc_equivs'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$internal_id = $attr_dict[$acode]['internal_id'];
|
||||
$cache['gc_attrs'][100 + $internal_id] = array(
|
||||
'inc' => 1,
|
||||
'name' => $ocde_attrnames[$internal_id][0]['name'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# prepare GS attribute data
|
||||
|
||||
/* OC sites always used internal user_ids in their generated GPX files.
|
||||
* This might be considered an error in itself (Groundspeak's XML namespace
|
||||
* doesn't allow that), but it very common (Garmin's OpenCaching.COM
|
||||
* also does that). Therefore, for backward-compatibility reasons, OKAPI
|
||||
* will do it the same way. See issue 174.
|
||||
*
|
||||
* Currently, the caches method does not expose "owner.internal_id" and
|
||||
* "latest_logs.user.internal_id" fields, we will read them manually
|
||||
* from the database here. */
|
||||
$vars['gc_attrs'] = in_array('gc:attrs', $vars['attrs']);
|
||||
$vars['gc_ocde_attrs'] = in_array('gc_ocde:attrs', $vars['attrs']);
|
||||
if ($vars['gc_attrs'] || $vars['gc_ocde_attrs'])
|
||||
{
|
||||
if ($vars['gc_ocde_attrs'])
|
||||
{
|
||||
# As this is an OCDE compatibility feature, we use the same Pseudo-GS
|
||||
# attribute names here as OCDE. Note that this code is specific to OCDE
|
||||
# database; OCPL stores attribute names in a different way and may use
|
||||
# different names for equivalent attributes.
|
||||
|
||||
$dict = array();
|
||||
foreach ($vars['caches'] as &$cache_ref)
|
||||
{
|
||||
$dict[$cache_ref['owner']['uuid']] = true;
|
||||
if (isset($cache_ref['latest_logs']))
|
||||
foreach ($cache_ref['latest_logs'] as &$log_ref)
|
||||
$dict[$log_ref['user']['uuid']] = true;
|
||||
}
|
||||
$rs = Db::query("
|
||||
select uuid, user_id
|
||||
from user
|
||||
where uuid in ('".implode("','", array_map('mysql_real_escape_string', array_keys($dict)))."')
|
||||
");
|
||||
while ($row = mysql_fetch_assoc($rs))
|
||||
$dict[$row['uuid']] = $row['user_id'];
|
||||
$vars['user_uuid_to_internal_id'] = &$dict;
|
||||
unset($dict);
|
||||
$ocde_attrnames = Db::select_group_by('id',"
|
||||
select id, name
|
||||
from cache_attrib
|
||||
");
|
||||
$attr_dict = AttrHelper::get_attrdict();
|
||||
}
|
||||
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = "application/gpx; charset=utf-8";
|
||||
$response->content_disposition = 'attachment; filename="results.gpx"';
|
||||
ob_start();
|
||||
Okapi::gettext_domain_init(explode("|", $langpref)); # Consumer gets properly localized GPX file.
|
||||
include 'gpxfile.tpl.php';
|
||||
Okapi::gettext_domain_restore();
|
||||
$response->body = ob_get_clean();
|
||||
return $response;
|
||||
}
|
||||
foreach ($vars['caches'] as &$cache_ref)
|
||||
{
|
||||
$cache_ref['gc_attrs'] = array();
|
||||
foreach ($cache_ref['attr_acodes'] as $acode)
|
||||
{
|
||||
$has_gc_equivs = false;
|
||||
foreach ($vars['attr_index'][$acode]['gc_equivs'] as $gc)
|
||||
{
|
||||
# The assignment via GC-ID as array key will prohibit duplicate
|
||||
# GC attributes, which can result from
|
||||
# - assigning the same GC ID to multiple A-Codes,
|
||||
# - contradicting attributes in one OC listing, e.g. 24/4 + not 24/7.
|
||||
|
||||
$cache_ref['gc_attrs'][$gc['id']] = $gc;
|
||||
$has_gc_equivs = true;
|
||||
}
|
||||
if (!$has_gc_equivs && $vars['gc_ocde_attrs'])
|
||||
{
|
||||
# Generate an OCDE pseudo-GS attribute;
|
||||
# see http://code.google.com/p/opencaching-api/issues/detail?id=190 and
|
||||
# http://code.google.com/p/opencaching-api/issues/detail?id=271.
|
||||
#
|
||||
# Groundspeak uses ID 1..65 (as of June, 2013), and OCDE makeshift
|
||||
# IDs start at 106, so there is space for 40 new GS attributes.
|
||||
|
||||
$internal_id = $attr_dict[$acode]['internal_id'];
|
||||
$cache_ref['gc_attrs'][100 + $internal_id] = array(
|
||||
'inc' => 1,
|
||||
'name' => $ocde_attrnames[$internal_id][0]['name'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* OC sites always used internal user_ids in their generated GPX files.
|
||||
* This might be considered an error in itself (Groundspeak's XML namespace
|
||||
* doesn't allow that), but it very common (Garmin's OpenCaching.COM
|
||||
* also does that). Therefore, for backward-compatibility reasons, OKAPI
|
||||
* will do it the same way. See issue 174.
|
||||
*
|
||||
* Currently, the caches method does not expose "owner.internal_id" and
|
||||
* "latest_logs.user.internal_id" fields, we will read them manually
|
||||
* from the database here. */
|
||||
|
||||
$dict = array();
|
||||
foreach ($vars['caches'] as &$cache_ref)
|
||||
{
|
||||
$dict[$cache_ref['owner']['uuid']] = true;
|
||||
if (isset($cache_ref['latest_logs']))
|
||||
foreach ($cache_ref['latest_logs'] as &$log_ref)
|
||||
$dict[$log_ref['user']['uuid']] = true;
|
||||
}
|
||||
$rs = Db::query("
|
||||
select uuid, user_id
|
||||
from user
|
||||
where uuid in ('".implode("','", array_map('mysql_real_escape_string', array_keys($dict)))."')
|
||||
");
|
||||
while ($row = mysql_fetch_assoc($rs))
|
||||
$dict[$row['uuid']] = $row['user_id'];
|
||||
$vars['user_uuid_to_internal_id'] = &$dict;
|
||||
unset($dict);
|
||||
|
||||
# location_source (part 2 of 2)
|
||||
|
||||
if ($location_source != 'default-coords')
|
||||
{
|
||||
$location_change_prefix = $request->get_parameter('location_change_prefix');
|
||||
if (!$location_change_prefix) {
|
||||
$location_change_prefix = '# ';
|
||||
}
|
||||
# lets find requested coords
|
||||
foreach ($vars['caches'] as &$cache_ref)
|
||||
{
|
||||
foreach ($cache_ref['alt_wpts'] as $alt_wpt_key => $alt_wpt)
|
||||
{
|
||||
if ('alt_wpt:'.$alt_wpt['type'] == $location_source)
|
||||
{
|
||||
# Switch locations between primary wpt and alternate wpt.
|
||||
# Also alter the cache name and make sure to append a proper
|
||||
# notice.
|
||||
|
||||
$original_location = $cache_ref['location'];
|
||||
$cache_ref['location'] = $alt_wpt['location'];
|
||||
$cache_ref['name_2'] = $location_change_prefix.$cache_ref['name'];
|
||||
if ($location_source == "alt_wpt:user-coords") {
|
||||
# In case of "user-coords", replace the default warning with a custom-tailored one.
|
||||
$cache_ref['warning_prefix'] = _(
|
||||
"<b>Geocache coordinates have been changed.</b> They have been replaced with ".
|
||||
"your own custom coordinates which you have provided for this geocache."
|
||||
);
|
||||
} else {
|
||||
# Default warning
|
||||
$cache_ref['warning_prefix'] = _(
|
||||
"<b>Geocache coordinates have been changed.</b> Currently they ".
|
||||
"point to one of the alternate waypoints originally described as:"
|
||||
) . " " . $alt_wpt['description'];
|
||||
}
|
||||
# remove current alt waypoint
|
||||
unset($cache_ref['alt_wpts'][$alt_wpt_key]);
|
||||
# add original location as alternate
|
||||
if ($vars['alt_wpts'])
|
||||
{
|
||||
$cache_ref['alt_wpts'][] = array(
|
||||
'name' => $cache_ref['code'].'-DEFAULT-COORDS',
|
||||
'location' => $original_location,
|
||||
'type' => 'default-coords',
|
||||
'type_name' => _("Original geocache location"),
|
||||
'sym' => 'Block, Blue',
|
||||
'description' => sprintf(_("Original (owner-supplied) location of the %s geocache"), $cache_ref['code']),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = "application/gpx; charset=utf-8";
|
||||
$response->content_disposition = 'attachment; filename="results.gpx"';
|
||||
ob_start();
|
||||
Okapi::gettext_domain_init(explode("|", $langpref)); # Consumer gets properly localized GPX file.
|
||||
include 'gpxfile.tpl.php';
|
||||
Okapi::gettext_domain_restore();
|
||||
$response->body = ob_get_clean();
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,182 +1,257 @@
|
||||
<xml>
|
||||
<brief>Retrieve geocaches in GPX format</brief>
|
||||
<issue-id>40</issue-id>
|
||||
<desc>
|
||||
<p>Produces a standards-compliant Geocaching GPX file.</p>
|
||||
<p>Unlike the services/caches/geocaches method responses, GPX files cannot
|
||||
contain names and descriptions in separate multiple languages. This method
|
||||
will attempt to choose the best language based on your preference
|
||||
(see <b>langpref</b> argument).</p>
|
||||
<p>Remember that a full-blown GPX file is much larger than a basic one.
|
||||
This method can produce many various types of GPX files. The simplest list of
|
||||
waypoints takes ~50 times less space than the same list with cache descriptions
|
||||
and log entries included.</p>
|
||||
</desc>
|
||||
<req name='cache_codes'>
|
||||
<p>Pipe-separated list of cache codes which you are interested in.
|
||||
No more than 500 codes are allowed. This CAN be an empty string (it will
|
||||
result in an empty, but valid, GPX file). All invalid cache codes will
|
||||
be skipped without any notice!</p>
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for GPX entities.</p>
|
||||
</opt>
|
||||
<opt name='ns_ground' default='false'>
|
||||
Boolean. If <b>true</b> then response will include
|
||||
<a href='http://www.groundspeak.com/cache/1/0/1/cache.xsd'>Groundspeak's
|
||||
GPX extension</a>. This namespace declares an extra <cache> element
|
||||
used by <a href='http://www.geocaching.com/'>geocaching.com</a> and <b>many others</b>.
|
||||
This namespace was initially associatied with geocaching.com, but now seems to
|
||||
be used in every geocaching GPX file. You probably want to have it.
|
||||
</opt>
|
||||
<opt name='ns_gsak' default='false'>
|
||||
<p>Boolean. If <b>true</b> then response will include
|
||||
<a href='http://www.gsak.net/xmlv1/5/gsak.xsd'>GSAK GPX extension</a>.
|
||||
This namespace declares an extra <wptExtension> element,
|
||||
which allows including "waypoint inheritance" information (parent-child relations).
|
||||
This in turn allows us to include "alternate waypoints" in the response.</p>
|
||||
<p>We know of <b>at least</b> <a href='http://www.gsak.net/'>one tool</a> that
|
||||
makes use of this.</p>
|
||||
</opt>
|
||||
<opt name='ns_ox' default='false'>
|
||||
Boolean. If <b>true</b> then response will include Garmin's
|
||||
<a href='http://www.opencaching.com/xmlschemas/opencaching/1/0/opencaching.xsd'>OpenCaching.com
|
||||
GPX extension</a>. This namespace declares an extra <opencaching> element
|
||||
used by <a href='http://www.opencaching.com/'>Garmin's Opencaching.com</a>.
|
||||
The element includes information on cache difficulty, ratings, tags and images.
|
||||
It is used within Garmin's Geocaching-enabled handheld GPS devices.
|
||||
</opt>
|
||||
<opt name='images' default='descrefs:nonspoilers'>
|
||||
<p>Which images to include (and how to include them). One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no images will be included,</li>
|
||||
<li><b>descrefs:thumblinks</b> - all images will be included as "thumbnail"
|
||||
<img> references at the end of each cache description, with a
|
||||
replacement image used for spoilers; the thumbnails are linked to the
|
||||
large images,</li>
|
||||
<li><b>descrefs:nonspoilers</b> - all non-spoiler images will be included
|
||||
as <img> references at the end of each cache description,</li>
|
||||
<li><b>descrefs:all</b> - all images will be included (including spoilers)
|
||||
as <img> references at the end of each cache description,</li>
|
||||
<li><b>ox:all</b> - all images will be included (including spoilers)
|
||||
as Garmin's <ox:image> references.</li>
|
||||
</ul>
|
||||
<p>Note: When using "descrefs:" mode, remember to set <b>ns_ground</b> to <b>true</b>.
|
||||
The default value is "descrefs:nonspoilers" for compatibilty reasons, but for
|
||||
most applications "descrefs:thumblinks" will be the better choice.</p>
|
||||
<p>Note: When using "ox:" mode, remember to set <b>ns_ox</b> to <b>true</b>. You must also
|
||||
include JPEG files along the GPX for this to work properly - see
|
||||
services/caches/formatters/garmin for more information.</p>
|
||||
<p>In the future, more generic ways of including images in GPX files may emerge.</p>
|
||||
</opt>
|
||||
<opt name='attrs' default='desc:text'>
|
||||
<p>This argument controls whether cache attributes are included and how they are included.
|
||||
Pipe-separated list consisting of any set of the following values:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>desc:text</b> - attributes will be listed (in plain-text) within
|
||||
the cache description (<b>ns_ground</b> has to be <b>true</b>),</li>
|
||||
<li><b>ox:tags</b> - attributes will be listed as Garmin's <i>ox:tag</i>
|
||||
elements (<b>ns_ox</b> has to be <b>true</b>),</li>
|
||||
<li>
|
||||
<p><b>gc:attrs</b> - attributes will be listed as Groundspeak's
|
||||
<i>groundspeak:attribute</i> elements (<b>ns_ground</b> has to be <b>true</b>),
|
||||
compatible with Geocaching.com (see the list
|
||||
<a href='http://www.geocaching.com/about/icons.aspx'>here</a>).</p>
|
||||
<p>Note that most Opencaching attributes don't have Geocaching.com counterparts.
|
||||
Such attributes cannot be included as gc:attrs and will be ignored.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>gc_ocde:attrs</b> - attributes will be listed as Groundspeak's
|
||||
<i>groundspeak:attribute</i> elements (<b>ns_ground</b> has to be <b>true</b>).
|
||||
Opencaching attributes which have no Geocaching.com counterparts will be
|
||||
included according to an Opencaching.DE convention, using "makeshift IDs"
|
||||
which may change in the future.</p>
|
||||
<p>Note that this option is supported only by some OC sites. Other sites will
|
||||
handle <b>gc_ocde:attrs</b> in the same way as <b>gc:attrs</b>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>If you don't want any attributes to be included, you must set the <b>attrs</b>
|
||||
parameter to <b>none</b>. Using an empty string won't work this way - it will
|
||||
trigger the default (<b>desc:text</b>) to be selected, for backward-compatibility.</p>
|
||||
</opt>
|
||||
<opt name='protection_areas' default='desc:auto'>
|
||||
<p>This argument controls whether protection area information is included and how
|
||||
it is included.</p>
|
||||
<ul>
|
||||
<li><b>desc:text</b> - if the cache (probably) is located within one or more
|
||||
protection areas, e.g. a nature reserve, a list of the protection areas will
|
||||
be included in the cache description.</li>
|
||||
<li><b>desc:auto</b> - protection area information may be included in the
|
||||
cache description, depending on the installation.</li>
|
||||
<li><b>none</b> - no protection area information will be included in the
|
||||
GPX data.</li>
|
||||
</ul>
|
||||
<p>Note that information on protection areas may be incomplete or outdated
|
||||
or completely missing on some installations.</p>
|
||||
</opt>
|
||||
<opt name='trackables' default='none'>
|
||||
<p>This argument controls whether information on trackables is included and how it is included.
|
||||
One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no trackables-data will be included,</li>
|
||||
<li><b>desc:list</b> - trackables will be listed (in plain-text) within the cache description,</li>
|
||||
<li><b>desc:count</b> - total number of trackables will be included (in plain-text) within the cache description.</li>
|
||||
</ul>
|
||||
<p>Note: When using "desc:" mode, remember to set <b>ns_ground</b> to <b>true</b>.</p>
|
||||
</opt>
|
||||
<opt name='recommendations' default='none'>
|
||||
<p>This argument controls whether information on recommendations is included and how it is included.
|
||||
One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no recommendations-info will be included,</li>
|
||||
<li><b>desc:count</b> - number of recommendations (and founds) will be included
|
||||
(in plain-text) within the cache description.</li>
|
||||
</ul>
|
||||
<p>Note: When using "desc:" mode, remember to set <b>ns_ground</b> to <b>true</b>.</p>
|
||||
</opt>
|
||||
<opt name='my_notes' default='none'>
|
||||
<p>Allows you to include personal user's notes on each cache. One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - don't include personal notes,</li>
|
||||
<li><b>desc:text</b> - include personal notes as part of the cache description.</li>
|
||||
</ul>
|
||||
<p>Note: You need to use Level 3 Authentication in order to set it to anything else than "none".</p>
|
||||
</opt>
|
||||
<opt name='latest_logs' default='false'>
|
||||
<p>Boolean. If <b>true</b> then response will include a couple of
|
||||
latest log entries for this cache (see also the <b>lpc</b> argument).</p>
|
||||
<p>You <b>must</b> set <b>ns_ground</b> argument to <b>true</b> if you want to use this.</p>
|
||||
</opt>
|
||||
<opt name='lpc' default='10'>
|
||||
Log-entries per cache - the number of log entries included in each returned cache.
|
||||
This should be an integer or a special "all" value. Please note, that the <b>ns_ground</b>
|
||||
and <b>latest_logs</b> arguments must be set to <b>true</b> in order for the logs to be included.
|
||||
</opt>
|
||||
<opt name='alt_wpts' default='false'>
|
||||
<p>Boolean. If <b>true</b> then we will include additional (alternate) waypoints in the response.
|
||||
These are all places associated with the cache.</p>
|
||||
<p>Combine this with <b>ns_gsak</b> if you want the result to include additional references between
|
||||
waypoints and their geocaches. Please note that not many applications are currently able to
|
||||
properly understand GSAK metadata.</p>
|
||||
</opt>
|
||||
<opt name='mark_found' default='false'>
|
||||
<p>Boolean. If <b>true</b> then all caches which are already found, will be marked appropriately
|
||||
(i.e. with an "found cache" symbol).</p>
|
||||
<p>This field requires you to use the <b>user_uuid</b> parameter (or Level 3 Authentication).</p>
|
||||
</opt>
|
||||
<opt name="user_uuid">
|
||||
<p>User'd ID. Required to mark found caches using <b>Level 1</b> Authentication.</p>
|
||||
<p>If you use <b>Level 3</b> Authentication, you shouldn't use this parameter. Or, to be exact:</p>
|
||||
<ul>
|
||||
<li><b>user_uuid</b> will be extracted from the Access Token you use. You don't have to provide it.</li>
|
||||
<li>If you provide <b>user_uuid</b>, then it HAS TO match your Access Token. If it doesn't, OKAPI
|
||||
will respond with HTTP 400 error.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<returns>
|
||||
<p>GPX file. All invalid cache codes will be skipped without any notice!</p>
|
||||
</returns>
|
||||
<brief>Retrieve geocaches in GPX format</brief>
|
||||
<issue-id>40</issue-id>
|
||||
<desc>
|
||||
<p>Produces a standards-compliant Geocaching GPX file.</p>
|
||||
<p>Unlike the services/caches/geocaches method responses, GPX files cannot
|
||||
contain names and descriptions in separate multiple languages. This method
|
||||
will attempt to choose the best language based on your preference
|
||||
(see <b>langpref</b> argument).</p>
|
||||
<p>Remember that a full-blown GPX file is much larger than a basic one.
|
||||
This method can produce many various types of GPX files. The simplest list of
|
||||
waypoints takes ~50 times less space than the same list with cache descriptions
|
||||
and log entries included.</p>
|
||||
<p>Note, that GPX files may contain <a href='%OKAPI:docurl:html%'>unvalidated
|
||||
HTML</a>.</p>
|
||||
</desc>
|
||||
<req name='cache_codes'>
|
||||
<p>Pipe-separated list of cache codes which you are interested in.
|
||||
No more than 500 codes are allowed. This CAN be an empty string (it will
|
||||
result in an empty, but valid, GPX file). All invalid cache codes will
|
||||
be skipped without any notice!</p>
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for GPX entities.</p>
|
||||
</opt>
|
||||
<opt name='ns_ground' default='false'>
|
||||
Boolean. If <b>true</b> then response will include
|
||||
<a href='http://www.groundspeak.com/cache/1/0/1/cache.xsd'>Groundspeak's
|
||||
GPX extension</a>. This namespace declares an extra <cache> element
|
||||
used by <a href='http://www.geocaching.com/'>geocaching.com</a> and <b>many others</b>.
|
||||
This namespace was initially associatied with geocaching.com, but now seems to
|
||||
be used in every geocaching GPX file. You probably want to have it.
|
||||
</opt>
|
||||
<opt name='ns_gsak' default='false'>
|
||||
<p>Boolean. If <b>true</b> then response will include
|
||||
<a href='http://www.gsak.net/xmlv1/5/gsak.xsd'>GSAK GPX extension</a>.
|
||||
This namespace declares an extra <wptExtension> element,
|
||||
which allows including "waypoint inheritance" information (parent-child relations).
|
||||
This in turn allows us to include "alternate waypoints" in the response.</p>
|
||||
<p>We know of <b>at least</b> <a href='http://www.gsak.net/'>one tool</a> that
|
||||
makes use of this.</p>
|
||||
</opt>
|
||||
<opt name='ns_ox' default='false'>
|
||||
Boolean. If <b>true</b> then response will include Garmin's
|
||||
<a href='http://www.opencaching.com/xmlschemas/opencaching/1/0/opencaching.xsd'>OpenCaching.com
|
||||
GPX extension</a>. This namespace declares an extra <opencaching> element
|
||||
used by <a href='http://www.opencaching.com/'>Garmin's Opencaching.com</a>.
|
||||
The element includes information on cache difficulty, ratings, tags and images.
|
||||
It is used within Garmin's Geocaching-enabled handheld GPS devices.
|
||||
</opt>
|
||||
<opt name='images' default='descrefs:nonspoilers'>
|
||||
<p>Which images to include (and how to include them). One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no images will be included,</li>
|
||||
<li><b>descrefs:thumblinks</b> - all images will be included as "thumbnail"
|
||||
<img> references at the end of each cache description, with a
|
||||
replacement image used for spoilers; the thumbnails are linked to the
|
||||
large images,</li>
|
||||
<li><b>descrefs:nonspoilers</b> - all non-spoiler images will be included
|
||||
as <img> references at the end of each cache description,</li>
|
||||
<li><b>descrefs:all</b> - all images will be included (including spoilers)
|
||||
as <img> references at the end of each cache description,</li>
|
||||
<li><b>ox:all</b> - all images will be included (including spoilers)
|
||||
as Garmin's <ox:image> references.</li>
|
||||
</ul>
|
||||
<p>Note: When using "descrefs:" mode, remember to set <b>ns_ground</b> to <b>true</b>.
|
||||
The default value is "descrefs:nonspoilers" for compatibilty reasons, but for
|
||||
most applications "descrefs:thumblinks" will be the better choice.</p>
|
||||
<p>Note: When using "ox:" mode, remember to set <b>ns_ox</b> to <b>true</b>. You must also
|
||||
include JPEG files along the GPX for this to work properly - see
|
||||
services/caches/formatters/garmin for more information.</p>
|
||||
<p>In the future, more generic ways of including images in GPX files may emerge.</p>
|
||||
</opt>
|
||||
<opt name='attrs' default='desc:text'>
|
||||
<p>This argument controls whether cache attributes are included and how they are included.
|
||||
Pipe-separated list consisting of any set of the following values:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>desc:text</b> - attributes will be listed (in plain-text) within
|
||||
the cache description (<b>ns_ground</b> has to be <b>true</b>),</li>
|
||||
<li><b>ox:tags</b> - attributes will be listed as Garmin's <i>ox:tag</i>
|
||||
elements (<b>ns_ox</b> has to be <b>true</b>),</li>
|
||||
<li>
|
||||
<p><b>gc:attrs</b> - attributes will be listed as Groundspeak's
|
||||
<i>groundspeak:attribute</i> elements (<b>ns_ground</b> has to be <b>true</b>),
|
||||
compatible with Geocaching.com (see the list
|
||||
<a href='http://www.geocaching.com/about/icons.aspx'>here</a>).</p>
|
||||
<p>Note that most Opencaching attributes don't have Geocaching.com counterparts.
|
||||
Such attributes cannot be included as gc:attrs and will be ignored.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>gc_ocde:attrs</b> - attributes will be listed as Groundspeak's
|
||||
<i>groundspeak:attribute</i> elements (<b>ns_ground</b> has to be <b>true</b>).
|
||||
Opencaching attributes which have no Geocaching.com counterparts will be
|
||||
included according to an Opencaching.DE convention, using "makeshift IDs"
|
||||
which may change in the future.</p>
|
||||
<p>Note that this option is supported only by some OC sites. Other sites will
|
||||
handle <b>gc_ocde:attrs</b> in the same way as <b>gc:attrs</b>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>If you don't want any attributes to be included, you must set the <b>attrs</b>
|
||||
parameter to <b>none</b>. Using an empty string won't work this way - it will
|
||||
trigger the default (<b>desc:text</b>) to be selected, for backward-compatibility.</p>
|
||||
</opt>
|
||||
<opt name='protection_areas' default='desc:auto'>
|
||||
<p>This argument controls whether protection area information is included and how
|
||||
it is included.</p>
|
||||
<ul>
|
||||
<li><b>desc:text</b> - if the cache (probably) is located within one or more
|
||||
protection areas, e.g. a nature reserve, a list of the protection areas will
|
||||
be included in the cache description.</li>
|
||||
<li><b>desc:auto</b> - protection area information may be included in the
|
||||
cache description, depending on the installation.</li>
|
||||
<li><b>none</b> - no protection area information will be included in the
|
||||
GPX data.</li>
|
||||
</ul>
|
||||
<p>Note that information on protection areas may be incomplete or outdated
|
||||
or completely missing on some installations.</p>
|
||||
</opt>
|
||||
<opt name='trackables' default='none'>
|
||||
<p>This argument controls whether information on trackables is included and how it is included.
|
||||
One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no trackables-data will be included,</li>
|
||||
<li><b>desc:list</b> - trackables will be listed (in plain-text) within the cache description,</li>
|
||||
<li><b>desc:count</b> - total number of trackables will be included (in plain-text) within the cache description.</li>
|
||||
</ul>
|
||||
<p>Note: When using "desc:" mode, remember to set <b>ns_ground</b> to <b>true</b>.</p>
|
||||
</opt>
|
||||
<opt name='recommendations' default='none'>
|
||||
<p>This argument controls whether information on recommendations is included and how it is included.
|
||||
One of the following values:</p>
|
||||
<ul>
|
||||
<li><b>none</b> - no recommendations-info will be included,</li>
|
||||
<li><b>desc:count</b> - number of recommendations (and founds) will be included
|
||||
(in plain-text) within the cache description.</li>
|
||||
</ul>
|
||||
<p>Note: When using "desc:" mode, remember to set <b>ns_ground</b> to <b>true</b>.</p>
|
||||
</opt>
|
||||
<opt name='my_notes' default='none'>
|
||||
<p>Allows you to include personal user's notes on each cache. This parameter
|
||||
takes either <b>none</b> (default value), or pipe separeted list of the
|
||||
following values:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>desc:text</b> - include personal notes as part of the cache
|
||||
description.</li>
|
||||
|
||||
<li>
|
||||
<p><b>gc:personal_note</b> - include personal notes as
|
||||
<groundspeak:personal_note> element (under
|
||||
<groundspeak:cache> element).</p>
|
||||
|
||||
<p><b>Warning:</b> This element is not a part of
|
||||
<i>http://www.groundspeak.com/cache/1/0/1</i> groundspeak schema, but it
|
||||
is a <i>http://www.groundspeak.com/cache/1/0/2</i> schema element. Using
|
||||
this option will generate formally invalid XML file.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Note: You need to use Level 3 Authentication in order to set it to anything else than "none".</p>
|
||||
</opt>
|
||||
<opt name='latest_logs' default='false'>
|
||||
<p>Boolean. If <b>true</b> then response will include a couple of
|
||||
latest log entries for this cache (see also the <b>lpc</b> argument).</p>
|
||||
<p>You <b>must</b> set <b>ns_ground</b> argument to <b>true</b> if you want to use this.</p>
|
||||
</opt>
|
||||
<opt name='lpc' default='10'>
|
||||
Log-entries per cache - the number of log entries included in each returned cache.
|
||||
This should be an integer or a special "all" value. Please note, that the <b>ns_ground</b>
|
||||
and <b>latest_logs</b> arguments must be set to <b>true</b> in order for the logs to be included.
|
||||
</opt>
|
||||
<opt name='alt_wpts' default='false'>
|
||||
<p>Boolean. If <b>true</b> then we will include additional (alternate) waypoints in the response.
|
||||
These are all places associated with the cache.</p>
|
||||
<p>Combine this with <b>ns_gsak</b> if you want the result to include additional references between
|
||||
waypoints and their geocaches. Please note that not many applications are currently able to
|
||||
properly understand GSAK metadata.</p>
|
||||
</opt>
|
||||
<opt name='mark_found' default='false'>
|
||||
<p>Boolean. If <b>true</b> then all caches which are already found, will be marked appropriately
|
||||
(i.e. with an "found cache" symbol).</p>
|
||||
<p>This field requires you to use the <b>user_uuid</b> parameter (or Level 3 Authentication).</p>
|
||||
</opt>
|
||||
<opt name="user_uuid">
|
||||
<p>User'd ID. Required to mark found caches using <b>Level 1</b> Authentication.</p>
|
||||
<p>If you use <b>Level 3</b> Authentication, you shouldn't use this parameter. Or, to be exact:</p>
|
||||
<ul>
|
||||
<li><b>user_uuid</b> will be extracted from the Access Token you use. You don't have to provide it.</li>
|
||||
<li>If you provide <b>user_uuid</b>, then it HAS TO match your Access Token. If it doesn't, OKAPI
|
||||
will respond with HTTP 400 error.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name="location_source" default='default-coords'>
|
||||
<p>If you supply a value, then it must be prefixed with <i>alt_wpt:</i>,
|
||||
and should match one of alternate waypoint types documented in the
|
||||
<a href="%OKAPI:methodretref:services/caches/geocache#alt_wpts%">alt_wpts</a>
|
||||
field returned by <a href="%OKAPI:methodref:services/caches/geocache%">services/caches/geocache</a>
|
||||
method. If the type doesn't match, it will be ignored.</p>
|
||||
|
||||
<p>By default, the <b>lat</b> and <b>lon</b> attributes of the <b><wpt></b> element
|
||||
will return the default coordinates of the cache, as supplied by the owner of the cache.
|
||||
This option allows you to replace these coordinates with other set of coordinates, loaded
|
||||
from the <b>alt_wpts</b> field mentioned above.</p>
|
||||
|
||||
<p>This may have some advantages in some scenarios. For example, if your user
|
||||
is driving a car, he might be more interested in the coordinates of the
|
||||
nearest suitable parking spot than in the coordinates of the geocache itself.
|
||||
If you set <b>location_source</b> to <b>alt_wpt:parking</b> then you'll be
|
||||
pre-fetching parking locations (if provided) without the need of loading all
|
||||
other <b>alternate waypoints</b> in your requests.</p>
|
||||
|
||||
<p>Other use case: setting this to <b>alt_wpt:user-coords</b> allows
|
||||
personalized results in some OC installations.</p>
|
||||
|
||||
<ul>
|
||||
<li>If the type provided doesn't match any alternate waypoints, the default
|
||||
coordinates of the geocache will be used.</li>
|
||||
|
||||
<li>
|
||||
<p>If the type matches exactly one alternate waypoint, then:</p>
|
||||
|
||||
<ul>
|
||||
<li>The <b>lat</b> and <b>lon</b> attributes of the "primary"
|
||||
<b><wpt></b> element will be replaced with the location of
|
||||
the matched alternate waypoint,</li>
|
||||
|
||||
<li>The name of the geocache will be prefixed with the value suppiled in
|
||||
<b><a href="%OKAPI:methodargref:#location_change_prefix%">location_change_prefix</a></b>
|
||||
parameter,</li>
|
||||
|
||||
<li>The desription of the waypoint will be included in the
|
||||
header of the cache description,</li>
|
||||
|
||||
<li>The matched alternate waypoint will be removed from the list
|
||||
of alternate waypoins (in order to avoid duplicate locations),</li>
|
||||
|
||||
<li>Extra alternate waypoint will be created, with the original
|
||||
location of the geocache.</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>If the type provided matches multiple alternate waypoints, then
|
||||
the first one will be chosen.</li>
|
||||
</ul>
|
||||
|
||||
</opt>
|
||||
<opt name="location_change_prefix" default="#">
|
||||
<p>Prefix to be added to the geocache name, in case its location has been changed due to
|
||||
the <b><a href="%OKAPI:methodargref:#location_source%">location_source</a></b> parameter
|
||||
matching any of the alternate waypoint.</p>
|
||||
</opt>
|
||||
<returns>
|
||||
<p>GPX file. All invalid cache codes will be skipped without any notice!</p>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -16,184 +16,192 @@ http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/ca
|
||||
http://geocaching.com.au/geocache/1 http://geocaching.com.au/geocache/1/geocache.xsd
|
||||
http://www.gsak.net/xmlv1/5 http://www.gsak.net/xmlv1/5/gsak.xsd
|
||||
">
|
||||
<name><?= $vars['installation']['site_name'] ?> Geocache Search Results</name>
|
||||
<desc><?= $vars['installation']['site_name'] ?> Geocache Search Results, downloaded via OKAPI - <?= $vars['installation']['okapi_base_url'] . ($vars['alt_wpts'] && $vars['ns_gsak'] ? ' (HasChildren)' : '') ?></desc>
|
||||
<author><?= $vars['installation']['site_name'] ?></author>
|
||||
<url><?= $vars['installation']['site_url'] ?></url>
|
||||
<urlname><?= $vars['installation']['site_name'] ?></urlname>
|
||||
<time><?= date('c') ?></time>
|
||||
<? foreach ($vars['caches'] as $c) { ?>
|
||||
<? if ($c == null) continue; /* This happens when there is an invalid code in cache_codes */ ?>
|
||||
<? list($lat, $lon) = explode("|", $c['location']); ?>
|
||||
<wpt lat="<?= $lat ?>" lon="<?= $lon ?>">
|
||||
<time><?= $c['date_created'] ?></time>
|
||||
<name><?= $c['code'] ?></name>
|
||||
<desc><?= Okapi::xmlescape($c['name']) ?> <?= _("hidden by") ?> <?= Okapi::xmlescape($c['owner']['username']) ?> :: <?= ucfirst($c['type']) ?> Cache (<?= $c['difficulty'] ?>/<?= $c['terrain'] ?><? if ($c['size'] !== null) { echo "/".$c['size']; } else { echo "/X"; } ?>/<?= $c['rating'] ?>)</desc>
|
||||
<url><?= $c['url'] ?></url>
|
||||
<urlname><?= Okapi::xmlescape($c['name']) ?></urlname>
|
||||
<sym><?= ($vars['mark_found'] && $c['is_found']) ? "Geocache Found" : "Geocache" ?></sym>
|
||||
<type>Geocache|<?= $vars['cache_GPX_types'][$c['type']] ?></type>
|
||||
<? if ($vars['ns_ground']) { /* Does user want us to include Groundspeak's <cache> element? */ ?>
|
||||
<groundspeak:cache archived="<?= ($c['status'] == 'Archived') ? "True" : "False" ?>" available="<?= ($c['status'] == 'Available') ? "True" : "False" ?>" id="<?= $c['internal_id'] ?>" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
|
||||
<groundspeak:name><?= Okapi::xmlescape($c['name']) ?></groundspeak:name>
|
||||
<groundspeak:placed_by><?= Okapi::xmlescape($c['owner']['username']) ?></groundspeak:placed_by>
|
||||
<groundspeak:owner id="<?= $vars['user_uuid_to_internal_id'][$c['owner']['uuid']] ?>"><?= Okapi::xmlescape($c['owner']['username']) ?></groundspeak:owner>
|
||||
<groundspeak:type><?= $vars['cache_GPX_types'][$c['type']] ?></groundspeak:type>
|
||||
<groundspeak:container><?= $vars['cache_GPX_sizes'][$c['size2']] ?></groundspeak:container>
|
||||
<? if ($vars['gc_attrs'] || $vars['gc_ocde_attrs']) { /* Does user want us to include groundspeak:attributes? */ ?>
|
||||
<groundspeak:attributes>
|
||||
<?
|
||||
foreach ($c['gc_attrs'] as $gc_id => $gc_attr) {
|
||||
print "<groundspeak:attribute id=\"".$gc_id."\" ";
|
||||
print "inc=\"".$gc_attr['inc']."\">";
|
||||
print Okapi::xmlescape($gc_attr['name']);
|
||||
print "</groundspeak:attribute>";
|
||||
}
|
||||
?>
|
||||
</groundspeak:attributes>
|
||||
<? } ?>
|
||||
<groundspeak:difficulty><?= $c['difficulty'] ?></groundspeak:difficulty>
|
||||
<groundspeak:terrain><?= $c['terrain'] ?></groundspeak:terrain>
|
||||
<groundspeak:long_description html="True">
|
||||
<p>
|
||||
<a href="<?= $c['url'] ?>"><?= Okapi::xmlescape($c['name']) ?></a>
|
||||
<?= _("hidden by") ?> <a href='<?= $c['owner']['profile_url'] ?>'><?= Okapi::xmlescape($c['owner']['username']) ?></a><br/>
|
||||
<? if ($vars['recommendations'] == 'desc:count') { /* Does user want us to include recommendations count? */ ?>
|
||||
<?= sprintf(ngettext("%d recommendation", "%d recommendations", $c['recommendations']), $c['recommendations']) ?>
|
||||
(<?= sprintf(ngettext("found %d time", "found %d times", $c['founds']), $c['founds']) ?>).
|
||||
<? } ?>
|
||||
<? if ($vars['trackables'] == 'desc:count') { /* Does user want us to include trackables count? */ ?>
|
||||
<?= sprintf(ngettext("%d trackable", "%d trackables", $c['trackables_count']), $c['trackables_count']) ?>.
|
||||
<? } ?>
|
||||
</p>
|
||||
<? if (($vars['my_notes'] == 'desc:text') && ($c['my_notes'] != null)) { /* Does user want us to include personal notes? */ ?>
|
||||
<p><b><?= _("Personal notes") ?>:</b> <?= Okapi::xmlescape($c['my_notes']) ?></p>
|
||||
<? } ?>
|
||||
<name><?= $vars['installation']['site_name'] ?> Geocache Search Results</name>
|
||||
<desc><?= $vars['installation']['site_name'] ?> Geocache Search Results, downloaded via OKAPI - <?= $vars['installation']['okapi_base_url'] . ($vars['alt_wpts'] && $vars['ns_gsak'] ? ' (HasChildren)' : '') ?></desc>
|
||||
<author><?= $vars['installation']['site_name'] ?></author>
|
||||
<url><?= $vars['installation']['site_url'] ?></url>
|
||||
<urlname><?= $vars['installation']['site_name'] ?></urlname>
|
||||
<time><?= date('c') ?></time>
|
||||
<? foreach ($vars['caches'] as $c) { ?>
|
||||
<? list($lat, $lon) = explode("|", $c['location']); ?>
|
||||
<wpt lat="<?= $lat ?>" lon="<?= $lon ?>">
|
||||
<time><?= $c['date_created'] ?></time>
|
||||
<name><?= $c['code'] ?></name>
|
||||
<desc><?= Okapi::xmlescape(isset($c['name_2']) ? $c['name_2'] : $c['name']) ?> <?= _("hidden by") ?> <?= Okapi::xmlescape($c['owner']['username']) ?> :: <?= ucfirst($c['type']) ?> Cache (<?= $c['difficulty'] ?>/<?= $c['terrain'] ?><? if ($c['size'] !== null) { echo "/".$c['size']; } else { echo "/X"; } ?>/<?= $c['rating'] ?>)</desc>
|
||||
<url><?= $c['url'] ?></url>
|
||||
<urlname><?= Okapi::xmlescape($c['name']) ?></urlname>
|
||||
<sym><?= ($vars['mark_found'] && $c['is_found']) ? "Geocache Found" : "Geocache" ?></sym>
|
||||
<type>Geocache|<?= $vars['cache_GPX_types'][$c['type']] ?></type>
|
||||
<? if ($vars['ns_ground']) { /* Does user want us to include Groundspeak's <cache> element? */ ?>
|
||||
<groundspeak:cache archived="<?= ($c['status'] == 'Archived') ? "True" : "False" ?>" available="<?= ($c['status'] == 'Available') ? "True" : "False" ?>" id="<?= $c['internal_id'] ?>" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
|
||||
<groundspeak:name><?= Okapi::xmlescape(isset($c['name_2']) ? $c['name_2'] : $c['name']) ?></groundspeak:name>
|
||||
<groundspeak:placed_by><?= Okapi::xmlescape($c['owner']['username']) ?></groundspeak:placed_by>
|
||||
<groundspeak:owner id="<?= $vars['user_uuid_to_internal_id'][$c['owner']['uuid']] ?>"><?= Okapi::xmlescape($c['owner']['username']) ?></groundspeak:owner>
|
||||
<groundspeak:type><?= $vars['cache_GPX_types'][$c['type']] ?></groundspeak:type>
|
||||
<groundspeak:container><?= $vars['cache_GPX_sizes'][$c['size2']] ?></groundspeak:container>
|
||||
<? if ($vars['gc_attrs'] || $vars['gc_ocde_attrs']) { /* Does user want us to include groundspeak:attributes? */ ?>
|
||||
<groundspeak:attributes>
|
||||
<?
|
||||
foreach ($c['gc_attrs'] as $gc_id => $gc_attr) {
|
||||
print "<groundspeak:attribute id=\"".$gc_id."\" ";
|
||||
print "inc=\"".$gc_attr['inc']."\">";
|
||||
print Okapi::xmlescape($gc_attr['name']);
|
||||
print "</groundspeak:attribute>";
|
||||
}
|
||||
?>
|
||||
</groundspeak:attributes>
|
||||
<? } ?>
|
||||
<groundspeak:difficulty><?= $c['difficulty'] ?></groundspeak:difficulty>
|
||||
<groundspeak:terrain><?= $c['terrain'] ?></groundspeak:terrain>
|
||||
<? if ($c['short_description']) { ?>
|
||||
<groundspeak:short_description html="False"><?= Okapi::xmlescape($c['short_description']) ?></groundspeak:short_description>
|
||||
<? } ?>
|
||||
<groundspeak:long_description html="True">
|
||||
<? if (isset($c['warning_prefix'])) { ?>
|
||||
<p style='font-size: 120%'><?= Okapi::xmlescape($c['warning_prefix']) ?></p>
|
||||
<? } ?>
|
||||
<p>
|
||||
<a href="<?= $c['url'] ?>"><?= Okapi::xmlescape($c['name']) ?></a>
|
||||
<?= _("hidden by") ?> <a href='<?= $c['owner']['profile_url'] ?>'><?= Okapi::xmlescape($c['owner']['username']) ?></a><br/>
|
||||
<? if ($vars['recommendations'] == 'desc:count') { /* Does user want us to include recommendations count? */ ?>
|
||||
<?= sprintf(ngettext("%d recommendation", "%d recommendations", $c['recommendations']), $c['recommendations']) ?>
|
||||
(<?= sprintf(ngettext("found %d time", "found %d times", $c['founds']), $c['founds']) ?>).
|
||||
<? } ?>
|
||||
<? if ($vars['trackables'] == 'desc:count') { /* Does user want us to include trackables count? */ ?>
|
||||
<?= sprintf(ngettext("%d trackable", "%d trackables", $c['trackables_count']), $c['trackables_count']) ?>.
|
||||
<? } ?>
|
||||
</p>
|
||||
<? if ((in_array('desc:text', $vars['my_notes'])) && ($c['my_notes'] != null)) { /* Does user want us to include personal notes? */ ?>
|
||||
<p><b><?= _("Personal notes") ?>:</b><br><?= Okapi::xmlescape(nl2br($c['my_notes'])) ?></p>
|
||||
<? } ?>
|
||||
|
||||
<? if (in_array('desc:text', $vars['attrs']) && count($c['attrnames']) > 0) { /* Does user want us to include attributes? */ ?>
|
||||
<p><?= _("Attributes") ?>:</p>
|
||||
<ul><li><?= implode("</li><li>", $c['attrnames']) ?></li></ul>
|
||||
<? } ?>
|
||||
<? if ($vars['trackables'] == 'desc:list' && count($c['trackables']) > 0) { /* Does user want us to include trackables list? */ ?>
|
||||
<p><?= _("Trackables") ?>:</p>
|
||||
<ul>
|
||||
<? foreach ($c['trackables'] as $t) { ?>
|
||||
<li><a href='<?= Okapi::xmlescape($t['url']) ?>'><?= Okapi::xmlescape($t['name']) ?></a> (<?= $t['code'] ?>)</li>
|
||||
<? } ?>
|
||||
</ul>
|
||||
<? } ?>
|
||||
<?= Okapi::xmlescape($c['description']) ?>
|
||||
<? if ((strpos($vars['images'], "descrefs:") === 0) && count($c['images']) > 0) { /* Does user want us to include <img> references in cache descriptions? */
|
||||
if ($vars['images'] == "descrefs:thumblinks") { ?>
|
||||
<h2><?= _("Images") ?> (<?= count($c['images']) ?>)</h2>
|
||||
<div>
|
||||
<? foreach ($c['images'] as $img) { ?>
|
||||
<div style='float:left; padding:6px'><a href='<?= Okapi::xmlescape($img['url']) ?>'><img src='<?= Okapi::xmlescape($img['thumb_url']) ?>'></a><br>
|
||||
<?= Okapi::xmlescape($img['caption']) ?></div>
|
||||
<? } ?>
|
||||
</div>
|
||||
<? } else {
|
||||
# We will split images into two subcategories: spoilers and nonspoilers.
|
||||
$spoilers = array();
|
||||
$nonspoilers = array();
|
||||
foreach ($c['images'] as $img)
|
||||
if ($img['is_spoiler']) $spoilers[] = $img;
|
||||
else $nonspoilers[] = $img;
|
||||
?>
|
||||
<? if (count($nonspoilers) > 0) { ?>
|
||||
<h2><?= _("Images") ?> (<?= count($nonspoilers) ?>)</h2>
|
||||
<? foreach ($nonspoilers as $img) { ?>
|
||||
<p><img src='<?= Okapi::xmlescape($img['url']) ?>'><br>
|
||||
<?= Okapi::xmlescape($img['caption']) ?></p>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? if (count($spoilers) > 0 && $vars['images'] == 'descrefs:all') { ?>
|
||||
<h2><?= _("Spoilers") ?> (<?= count($spoilers) ?>)</h2>
|
||||
<? foreach ($spoilers as $img) { ?>
|
||||
<p><img src='<?= Okapi::xmlescape($img['url']) ?>'><br>
|
||||
<?= Okapi::xmlescape($img['caption']) ?></p>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? if ((strpos($vars['images'], "ox:") === 0) && count($c['images']) > 0) { /* Include image descriptions (for ox:image numbers)? */ ?>
|
||||
<p><?= _("Image descriptions") ?>:</p>
|
||||
<ul>
|
||||
<? foreach ($c['images'] as $no => $img) { ?>
|
||||
<li><?= $img['unique_caption'] ?>. <?= Okapi::xmlescape($img['caption']) ?></li>
|
||||
<? } ?>
|
||||
</ul>
|
||||
<? } ?>
|
||||
<? if ($vars['protection_areas'] == 'desc:text' && count($c['protection_areas'])) { ?>
|
||||
<p><?= _("The cache probably is located in the following protection areas:") ?></p>
|
||||
<ul>
|
||||
<? foreach($c['protection_areas'] as $protection_area) { ?>
|
||||
<li><?= Okapi::xmlescape($protection_area['type'])." - ".Okapi::xmlescape($protection_area['name']) ?></li>
|
||||
<? } ?>
|
||||
</ul;>
|
||||
<? } ?>
|
||||
</groundspeak:long_description>
|
||||
<groundspeak:encoded_hints><?= Okapi::xmlescape($c['hint2']) ?></groundspeak:encoded_hints>
|
||||
<? if ($vars['latest_logs']) { /* Does user want us to include latest log entries? */ ?>
|
||||
<groundspeak:logs>
|
||||
<? foreach ($c['latest_logs'] as $log) { ?>
|
||||
<groundspeak:log id="<?= $log['internal_id'] ?>">
|
||||
<groundspeak:date><?= $log['date'] ?></groundspeak:date>
|
||||
<groundspeak:type><?= $log['type'] ?></groundspeak:type>
|
||||
<groundspeak:finder id="<?= $vars['user_uuid_to_internal_id'][$log['user']['uuid']] ?>"><?= Okapi::xmlescape($log['user']['username']) ?></groundspeak:finder>
|
||||
<groundspeak:text encoded="False"><?= $log['was_recommended'] ? "(*) ": "" ?><?= Okapi::xmlescape($log['comment']) ?></groundspeak:text>
|
||||
</groundspeak:log>
|
||||
<? } ?>
|
||||
</groundspeak:logs>
|
||||
<? } ?>
|
||||
<? /* groundspeak:travelbugs - does it actually DO anything? WRTODO */ ?>
|
||||
</groundspeak:cache>
|
||||
<? } ?>
|
||||
<? if ($vars['ns_ox']) { /* Does user want us to include Garmin's <opencaching> element? */ ?>
|
||||
<ox:opencaching xmlns:ox="http://www.opencaching.com/xmlschemas/opencaching/1/0">
|
||||
<ox:ratings>
|
||||
<? if ($c['rating'] !== null) { ?><ox:awesomeness><?= $c['rating'] ?></ox:awesomeness><? } ?>
|
||||
<ox:difficulty><?= $c['difficulty'] ?></ox:difficulty>
|
||||
<? if ($c['oxsize'] !== null) { ?><ox:size><?= $c['oxsize'] ?></ox:size><? } ?>
|
||||
<ox:terrain><?= $c['terrain'] ?></ox:terrain>
|
||||
</ox:ratings>
|
||||
<? if (in_array('ox:tags', $vars['attrs']) && count($c['attrnames']) > 0) { /* Does user want us to include ox:tags? */ ?>
|
||||
<ox:tags><ox:tag><?= implode("</ox:tag><ox:tag>", $c['attrnames']) ?></ox:tag></ox:tags>
|
||||
<? } ?>
|
||||
<? if ((strpos($vars['images'], "ox:") === 0) && count($c['images']) > 0) { /* Does user want us to include ox:image references? */ ?>
|
||||
<ox:images>
|
||||
<? foreach ($c['images'] as $no => $img) { ?>
|
||||
<ox:image>
|
||||
<ox:name><?= $img['unique_caption'] ?>.jpg</ox:name>
|
||||
<ox:size>0</ox:size>
|
||||
<ox:required>false</ox:required>
|
||||
<ox:spoiler><?= ($img['is_spoiler'] ? "true" : "false") ?></ox:spoiler>
|
||||
</ox:image>
|
||||
<? } ?>
|
||||
</ox:images>
|
||||
<? } ?>
|
||||
</ox:opencaching>
|
||||
<? } ?>
|
||||
</wpt>
|
||||
<? if ($vars['alt_wpts']) { ?>
|
||||
<? foreach ($c['alt_wpts'] as $wpt) { ?>
|
||||
<? list($lat, $lon) = explode("|", $wpt['location']); ?>
|
||||
<wpt lat="<?= $lat ?>" lon="<?= $lon ?>">
|
||||
<time><?= $c['date_created'] ?></time>
|
||||
<name><?= Okapi::xmlescape($wpt['name']) ?></name>
|
||||
<cmt><?= Okapi::xmlescape($wpt['description']) ?></cmt>
|
||||
<desc><?= Okapi::xmlescape($wpt['type_name']) ?></desc>
|
||||
<url><?= $c['url'] ?></url>
|
||||
<urlname><?= Okapi::xmlescape($c['name']) ?></urlname>
|
||||
<sym><?= $wpt['sym'] ?></sym>
|
||||
<type>Waypoint|<?= $wpt['sym'] ?></type>
|
||||
<? if ($vars['ns_gsak']) { ?>
|
||||
<gsak:wptExtension xmlns:gsak="http://www.gsak.net/xmlv1/5">
|
||||
<gsak:Parent><?= $c['code'] ?></gsak:Parent>
|
||||
</gsak:wptExtension>
|
||||
<? } ?>
|
||||
</wpt>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? if (in_array('desc:text', $vars['attrs']) && count($c['attrnames']) > 0) { /* Does user want us to include attributes? */ ?>
|
||||
<p><?= _("Attributes") ?>:</p>
|
||||
<ul><li><?= implode("</li><li>", $c['attrnames']) ?></li></ul>
|
||||
<? } ?>
|
||||
<? if ($vars['trackables'] == 'desc:list' && count($c['trackables']) > 0) { /* Does user want us to include trackables list? */ ?>
|
||||
<p><?= _("Trackables") ?>:</p>
|
||||
<ul>
|
||||
<? foreach ($c['trackables'] as $t) { ?>
|
||||
<li><a href='<?= Okapi::xmlescape($t['url']) ?>'><?= Okapi::xmlescape($t['name']) ?></a> (<?= $t['code'] ?>)</li>
|
||||
<? } ?>
|
||||
</ul>
|
||||
<? } ?>
|
||||
<?= Okapi::xmlescape($c['description']) ?>
|
||||
<? if ((strpos($vars['images'], "descrefs:") === 0) && count($c['images']) > 0) { /* Does user want us to include <img> references in cache descriptions? */
|
||||
if ($vars['images'] == "descrefs:thumblinks") { ?>
|
||||
<h2><?= _("Images") ?> (<?= count($c['images']) ?>)</h2>
|
||||
<div>
|
||||
<? foreach ($c['images'] as $img) { ?>
|
||||
<div style='float:left; padding:6px'><a href='<?= Okapi::xmlescape($img['url']) ?>'><img src='<?= Okapi::xmlescape($img['thumb_url']) ?>'></a><br>
|
||||
<?= Okapi::xmlescape($img['caption']) ?></div>
|
||||
<? } ?>
|
||||
</div>
|
||||
<? } else {
|
||||
# We will split images into two subcategories: spoilers and nonspoilers.
|
||||
$spoilers = array();
|
||||
$nonspoilers = array();
|
||||
foreach ($c['images'] as $img)
|
||||
if ($img['is_spoiler']) $spoilers[] = $img;
|
||||
else $nonspoilers[] = $img;
|
||||
?>
|
||||
<? if (count($nonspoilers) > 0) { ?>
|
||||
<h2><?= _("Images") ?> (<?= count($nonspoilers) ?>)</h2>
|
||||
<? foreach ($nonspoilers as $img) { ?>
|
||||
<p><img src='<?= Okapi::xmlescape($img['url']) ?>'><br>
|
||||
<?= Okapi::xmlescape($img['caption']) ?></p>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? if (count($spoilers) > 0 && $vars['images'] == 'descrefs:all') { ?>
|
||||
<h2><?= _("Spoilers") ?> (<?= count($spoilers) ?>)</h2>
|
||||
<? foreach ($spoilers as $img) { ?>
|
||||
<p><img src='<?= Okapi::xmlescape($img['url']) ?>'><br>
|
||||
<?= Okapi::xmlescape($img['caption']) ?></p>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? if ((strpos($vars['images'], "ox:") === 0) && count($c['images']) > 0) { /* Include image descriptions (for ox:image numbers)? */ ?>
|
||||
<p><?= _("Image descriptions") ?>:</p>
|
||||
<ul>
|
||||
<? foreach ($c['images'] as $no => $img) { ?>
|
||||
<li><?= $img['unique_caption'] ?>. <?= Okapi::xmlescape($img['caption']) ?></li>
|
||||
<? } ?>
|
||||
</ul>
|
||||
<? } ?>
|
||||
<? if ($vars['protection_areas'] == 'desc:text' && count($c['protection_areas'])) { ?>
|
||||
<p><?= _("The cache probably is located in the following protection areas:") ?></p>
|
||||
<ul>
|
||||
<? foreach($c['protection_areas'] as $protection_area) { ?>
|
||||
<li><?= Okapi::xmlescape($protection_area['type'])." - ".Okapi::xmlescape($protection_area['name']) ?></li>
|
||||
<? } ?>
|
||||
</ul;>
|
||||
<? } ?>
|
||||
</groundspeak:long_description>
|
||||
<groundspeak:encoded_hints><?= Okapi::xmlescape($c['hint2']) ?></groundspeak:encoded_hints>
|
||||
<? if ((in_array('gc:personal_note', $vars['my_notes'])) && ($c['my_notes'] != null)) { /* Does user want us to include personal notes? -> Issue 294 */ ?>
|
||||
<groundspeak:personal_note><?= Okapi::xmlescape($c['my_notes']) ?></groundspeak:personal_note>
|
||||
<? } ?>
|
||||
<? if ($vars['latest_logs']) { /* Does user want us to include latest log entries? */ ?>
|
||||
<groundspeak:logs>
|
||||
<? foreach ($c['latest_logs'] as $log) { ?>
|
||||
<groundspeak:log id="<?= $log['internal_id'] ?>">
|
||||
<groundspeak:date><?= $log['date'] ?></groundspeak:date>
|
||||
<groundspeak:type><?= $log['type'] ?></groundspeak:type>
|
||||
<groundspeak:finder id="<?= $vars['user_uuid_to_internal_id'][$log['user']['uuid']] ?>"><?= Okapi::xmlescape($log['user']['username']) ?></groundspeak:finder>
|
||||
<groundspeak:text encoded="False"><?= $log['was_recommended'] ? "(*) ": "" ?><?= Okapi::xmlescape($log['comment']) ?></groundspeak:text>
|
||||
</groundspeak:log>
|
||||
<? } ?>
|
||||
</groundspeak:logs>
|
||||
<? } ?>
|
||||
<? /* groundspeak:travelbugs - does it actually DO anything? WRTODO */ ?>
|
||||
</groundspeak:cache>
|
||||
<? } ?>
|
||||
<? if ($vars['ns_ox']) { /* Does user want us to include Garmin's <opencaching> element? */ ?>
|
||||
<ox:opencaching xmlns:ox="http://www.opencaching.com/xmlschemas/opencaching/1/0">
|
||||
<ox:ratings>
|
||||
<? if ($c['rating'] !== null) { ?><ox:awesomeness><?= $c['rating'] ?></ox:awesomeness><? } ?>
|
||||
<ox:difficulty><?= $c['difficulty'] ?></ox:difficulty>
|
||||
<? if ($c['oxsize'] !== null) { ?><ox:size><?= $c['oxsize'] ?></ox:size><? } ?>
|
||||
<ox:terrain><?= $c['terrain'] ?></ox:terrain>
|
||||
</ox:ratings>
|
||||
<? if (in_array('ox:tags', $vars['attrs']) && count($c['attrnames']) > 0) { /* Does user want us to include ox:tags? */ ?>
|
||||
<ox:tags><ox:tag><?= implode("</ox:tag><ox:tag>", $c['attrnames']) ?></ox:tag></ox:tags>
|
||||
<? } ?>
|
||||
<? if ((strpos($vars['images'], "ox:") === 0) && count($c['images']) > 0) { /* Does user want us to include ox:image references? */ ?>
|
||||
<ox:images>
|
||||
<? foreach ($c['images'] as $no => $img) { ?>
|
||||
<ox:image>
|
||||
<ox:name><?= $img['unique_caption'] ?>.jpg</ox:name>
|
||||
<ox:size>0</ox:size>
|
||||
<ox:required>false</ox:required>
|
||||
<ox:spoiler><?= ($img['is_spoiler'] ? "true" : "false") ?></ox:spoiler>
|
||||
</ox:image>
|
||||
<? } ?>
|
||||
</ox:images>
|
||||
<? } ?>
|
||||
</ox:opencaching>
|
||||
<? } ?>
|
||||
</wpt>
|
||||
<? if ($vars['alt_wpts']) { ?>
|
||||
<? foreach ($c['alt_wpts'] as $wpt) { ?>
|
||||
<? list($lat, $lon) = explode("|", $wpt['location']); ?>
|
||||
<wpt lat="<?= $lat ?>" lon="<?= $lon ?>">
|
||||
<time><?= $c['date_created'] ?></time>
|
||||
<name><?= Okapi::xmlescape($wpt['name']) ?></name>
|
||||
<cmt><?= Okapi::xmlescape($wpt['description']) ?></cmt>
|
||||
<desc><?= Okapi::xmlescape($wpt['type_name']) ?></desc>
|
||||
<url><?= $c['url'] ?></url>
|
||||
<urlname><?= Okapi::xmlescape($c['name']) ?></urlname>
|
||||
<sym><?= $wpt['sym'] ?></sym>
|
||||
<type>Waypoint|<?= $wpt['sym'] ?></type>
|
||||
<? if ($vars['ns_gsak']) { ?>
|
||||
<gsak:wptExtension xmlns:gsak="http://www.gsak.net/xmlv1/5">
|
||||
<gsak:Parent><?= $c['code'] ?></gsak:Parent>
|
||||
</gsak:wptExtension>
|
||||
<? } ?>
|
||||
</wpt>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
</gpx>
|
||||
|
||||
@@ -12,51 +12,51 @@ use okapi\services\caches\search\SearchAssistant;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$cache_code = $request->get_parameter('cache_code');
|
||||
if (!$cache_code) throw new ParamMissing('cache_code');
|
||||
if (strpos($cache_code, "|") !== false) throw new InvalidParam('cache_code');
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "code|name|location|type|status";
|
||||
$log_fields = $request->get_parameter('log_fields');
|
||||
if (!$log_fields) $log_fields = "uuid|date|user|type|comment";
|
||||
$lpc = $request->get_parameter('lpc');
|
||||
if (!$lpc) $lpc = 10;
|
||||
$attribution_append = $request->get_parameter('attribution_append');
|
||||
if (!$attribution_append) $attribution_append = 'full';
|
||||
$params = array(
|
||||
'cache_codes' => $cache_code,
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
'attribution_append' => $attribution_append,
|
||||
'lpc' => $lpc,
|
||||
'log_fields' => $log_fields
|
||||
);
|
||||
$my_location = $request->get_parameter('my_location');
|
||||
if ($my_location)
|
||||
$params['my_location'] = $my_location;
|
||||
$user_uuid = $request->get_parameter('user_uuid');
|
||||
if ($user_uuid)
|
||||
$params['user_uuid'] = $user_uuid;
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$cache_code = $request->get_parameter('cache_code');
|
||||
if (!$cache_code) throw new ParamMissing('cache_code');
|
||||
if (strpos($cache_code, "|") !== false) throw new InvalidParam('cache_code');
|
||||
$langpref = $request->get_parameter('langpref');
|
||||
if (!$langpref) $langpref = "en";
|
||||
$fields = $request->get_parameter('fields');
|
||||
if (!$fields) $fields = "code|name|location|type|status";
|
||||
$log_fields = $request->get_parameter('log_fields');
|
||||
if (!$log_fields) $log_fields = "uuid|date|user|type|comment";
|
||||
$lpc = $request->get_parameter('lpc');
|
||||
if (!$lpc) $lpc = 10;
|
||||
$attribution_append = $request->get_parameter('attribution_append');
|
||||
if (!$attribution_append) $attribution_append = 'full';
|
||||
$params = array(
|
||||
'cache_codes' => $cache_code,
|
||||
'langpref' => $langpref,
|
||||
'fields' => $fields,
|
||||
'attribution_append' => $attribution_append,
|
||||
'lpc' => $lpc,
|
||||
'log_fields' => $log_fields
|
||||
);
|
||||
$my_location = $request->get_parameter('my_location');
|
||||
if ($my_location)
|
||||
$params['my_location'] = $my_location;
|
||||
$user_uuid = $request->get_parameter('user_uuid');
|
||||
if ($user_uuid)
|
||||
$params['user_uuid'] = $user_uuid;
|
||||
|
||||
# There's no need to validate the fields/lpc parameters as the 'geocaches'
|
||||
# method does this (it will raise a proper exception on invalid values).
|
||||
# There's no need to validate the fields/lpc parameters as the 'geocaches'
|
||||
# method does this (it will raise a proper exception on invalid values).
|
||||
|
||||
$results = OkapiServiceRunner::call('services/caches/geocaches', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, $params));
|
||||
$result = $results[$cache_code];
|
||||
if ($result === null)
|
||||
throw new InvalidParam('cache_code', "This cache does not exist.");
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
$results = OkapiServiceRunner::call('services/caches/geocaches', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, $params));
|
||||
$result = $results[$cache_code];
|
||||
if ($result === null)
|
||||
throw new InvalidParam('cache_code', "This cache does not exist.");
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,410 +1,440 @@
|
||||
<xml>
|
||||
<brief>Retrieve information on a single geocache</brief>
|
||||
<issue-id>19</issue-id>
|
||||
<desc>
|
||||
<p>Retrieve information on a single geocache.</p>
|
||||
</desc>
|
||||
<req name='cache_code'>Unique code of the geocache</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for fields like
|
||||
<b>name</b> and <b>description</b>.</p>
|
||||
<p>Please note, that you may also access caches' descriptions in all
|
||||
available languages. If you want to do this, you should use fields
|
||||
<b>names</b>, <b>descriptions</b> (etc.) instead of <b>name</b> and
|
||||
<b>description</b> (etc.).</p>
|
||||
</opt>
|
||||
<opt name='fields' default='code|name|location|type|status'>
|
||||
<p>Pipe-separated list of field names which you are interested with.
|
||||
Selected fields will be included in the response. See below for the
|
||||
list of available fields.</p>
|
||||
</opt>
|
||||
<opt name='attribution_append' default='full'>
|
||||
<p>By default, OKAPI appends the value of <b>attribution_note</b> field to all the
|
||||
cache descriptions. If you would like to display the attribution note separately,
|
||||
you may use this parameter. Use one of the following values:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>full</b> - OKAPI will append the attribution note to the descriptions of the
|
||||
geocache. The language of the note will match the language of the description
|
||||
(i.e. each value in <b>descriptions</b> may contain attribution notes in
|
||||
a different language).
|
||||
</li>
|
||||
<li>
|
||||
<p><b>none</b> - OKAPI will not append the attribution note to geocache
|
||||
descriptions. You will use the <b>attribution_note</b> instead (which depends
|
||||
on the <b>langpref</b> parameter).</p>
|
||||
|
||||
<p><b>Important note:</b> You are still <b>required</b> to display the
|
||||
<b>attribution_note</b> field in some other way.</p>
|
||||
</li>
|
||||
<li>
|
||||
<b>static</b> - OKAPI will append a "static" attribution note to the descriptions
|
||||
of the geocache. This might equal the "full" attribution note, but not necessarilly,
|
||||
since the "full" note may contain a current date
|
||||
(<a href='https://code.google.com/p/opencaching-api/issues/detail?id=178'>why?</a>),
|
||||
and the "static" note will not. This is implemented primarily for internal use
|
||||
(i.e. the replicate module). Usually you should not use it, because on some
|
||||
installations the static note will not be sufficient to meet the data license
|
||||
requirements.
|
||||
</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name='lpc' default='10'>
|
||||
Log-entries per cache - the number of logs returned in the <b>latest_logs</b> field.
|
||||
This should be an integer or a special "all" value. Please note, that you must include
|
||||
the <b>latest_logs</b> field in <b>fields</b> in order to see the log entries.
|
||||
</opt>
|
||||
<opt name='log_fields' default='uuid|date|user|type|comment'>
|
||||
Pipe-separated list of log fields to include in the <b>latest_logs</b> field.
|
||||
For valid field names, see <b>logs/entry</b> method.
|
||||
</opt>
|
||||
<opt name='my_location'>
|
||||
<p>The reference point for cache distance and bearing calculation (typically - the user's location),
|
||||
in the "lat|lon" format. This parameter is required when accessing <b>distance</b> and/or <b>bearing</b>
|
||||
fields.</p>
|
||||
<p>Use positive numbers for latitudes in the northern hemisphere and
|
||||
longitudes in the eastern hemisphere (and negative for southern and
|
||||
western hemispheres accordingly). These are full degrees with a dot
|
||||
as a decimal point (ex. "54.3|22.3").</p>
|
||||
</opt>
|
||||
<opt name="user_uuid">
|
||||
<p>User'd ID. Required to access fields like <b>is_found</b> using <b>Level 1</b> Authentication.</p>
|
||||
<p>Please note that if you want to access private fields (like <b>my_notes</b>), then
|
||||
this parameter won't help you. You have to use <b>Level 3</b> Authentication instead.</p>
|
||||
<p>If you use <b>Level 3</b> Authentication, you shouldn't use this parameter. Or, to be exact:</p>
|
||||
<ul>
|
||||
<li><b>user_uuid</b> will be extracted from the Access Token you use. You don't have to provide it.</li>
|
||||
<li>If you provide <b>user_uuid</b>, then it HAS TO match your Access Token. If it doesn't, OKAPI
|
||||
will respond with HTTP 400 error.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of fields you have selected. Currently available fields:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>code</b> - unique Opencaching code of the geocache,</li>
|
||||
<li><b>name</b> - name of the geocache,</li>
|
||||
<li><b>names</b> - a dictionary (language code => plain-text string) of
|
||||
names of the geocache (at this time, there will be only one language,
|
||||
but this may change in future),</li>
|
||||
<li><b>location</b> - location of the cache in the "lat|lon" format
|
||||
(<i>lat</i> and <i>lon</i> are in full degrees with a dot as a decimal point),</li>
|
||||
<li>
|
||||
<p><b>type</b> - cache type. This might be <b>pretty much everything</b>,
|
||||
but there are some predefined types that you might want to treat
|
||||
in a special way (separate icons etc.). Primary types include: </p>
|
||||
<ul>
|
||||
<li><b>Traditional</b>,</li>
|
||||
<li><b>Multi</b>,</li>
|
||||
<li><b>Quiz</b>,</li>
|
||||
<li><b>Virtual</b>,</li>
|
||||
<li><b>Event</b>,</li>
|
||||
<li><i>(any other value is valid too)</i></li>
|
||||
</ul>
|
||||
<p><b>Event</b> is a peculiar type of geocache which is NOT a geocache
|
||||
at all, but it <b>is</b> stored as a geocache in OC database (this design
|
||||
decision is old as the OC network itself!). Just keep in mind, that
|
||||
in case of Event Caches, some fields may have a little different meaning
|
||||
than you would tell by their name.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>status</b> - cache status. Valid cache status codes currently include:</p>
|
||||
<ul>
|
||||
<li><b>Available</b> - Cache is available and ready for search,</li>
|
||||
<li><b>Temporarily unavailable</b> - Cache is probably unavailable (i.e. in need of maintenance)</li>
|
||||
<li><b>Archived</b> - Cache is permanently unavailable (moved to the archives).</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>url</b> - URL of the cache's web page,</li>
|
||||
<li>
|
||||
<p><b>owner</b> - dictionary of:</p>
|
||||
<ul>
|
||||
<li><b>uuid</b> - geocache owner's user ID,</li>
|
||||
<li><b>username</b> - name of the user,</li>
|
||||
<li><b>profile_url</b> - URL of the user profile page,</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>gc_code</b> - Geocaching.com code (GC code) of the geocache
|
||||
<b>or null</b> if the cache is not listed on GC or the GC code is
|
||||
unknown.</p>
|
||||
|
||||
<p>Please note that this information is supplied by cache owners
|
||||
and it is often missing, obsolete or otherwise incorrect.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>distance</b> - float, the distance to a cache, in meters.
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>bearing</b> - float, the absolute bearing to the cache, measured in degrees from north,
|
||||
<b>or null</b> if it cannot be calculated (i.e. when you are exactly at the target's location).
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>bearing2</b> - string, the absolute bearing to the cache, represented as a typical direction
|
||||
string of length of 1 or 2 characters (ex. "N", "NE", "E", "SE", etc.), or "n/a" if it cannot be calculated.
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>bearing3</b> - string, the absolute bearing to the cache, represented as a typical direction
|
||||
string of length of 1 or 2 or 3 characters (ex. "N", "NNE", "NE", "ENE", etc.), or "n/a" if it cannot be calculated.
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_found</b> - boolean, true if the user already found this cache.
|
||||
See also <b>found_status</b> parameter of the services/caches/search/all
|
||||
method.</p>
|
||||
<p>This field requires you to use the <b>user_uuid</b> parameter
|
||||
(or Level 3 Authentication). Please note, that this will also return <b>true</b>
|
||||
for attended Event Caches.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_not_found</b> - boolean, true if the user has submitted "Didn't find it" log entry for this cache.</p>
|
||||
<p>This field requires you to use the <b>user_uuid</b> parameter (or Level 3 Authentication).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_watched</b> - boolean, true if the user is watching this cache. You may consider highlighting
|
||||
such geocaches in some fashion, as the users may use this functionality to temporarily mark geocaches
|
||||
of particular interest (i.e. geocaches they plan to find today).</p>
|
||||
<p>This is private data. You will need Level 3 Authentication to access this field.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_ignored</b> - boolean, true if the user is ignoring this cache. (See also <b>exclude_ignored</b>
|
||||
parameter of all search methods.)</p>
|
||||
<p>This is private data. You will need Level 3 Authentication to access this field.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>founds</b> - number of times the geocache was successfully found
|
||||
(or attended, in case of Event Caches),</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>notfounds</b> - number of times the geocache was not found
|
||||
(in case of Event Caches this will always be zero),</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>willattends</b> - in case of Event Caches, this is the number of
|
||||
"Will attend" log entries. In case of any other cache type, it will
|
||||
be <b>zero</b> (not null, for <a href='https://code.google.com/p/opencaching-api/issues/detail?id=233'>backward
|
||||
compatibility</a>),</p>
|
||||
</li>
|
||||
<li class='deprecated'>
|
||||
<b>size</b> - deprecated
|
||||
(<a href='http://code.google.com/p/opencaching-api/issues/detail?id=155'>why?</a>),
|
||||
use <b>size2</b> instead. Float (between 1 and 5), size rating of the container, or
|
||||
<b>null</b> if geocache does not have a container,
|
||||
</li>
|
||||
<li>
|
||||
<p><b>size2</b> - string indicating the size of the container, so called
|
||||
"size2 code". One of the following values:
|
||||
'none', 'nano', 'micro', 'small', 'regular', 'large', 'xlarge', 'other'.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>oxsize</b> - float (between 1 and 5) or null, this is a size rating
|
||||
variant, compatible with the one used by opencaching.com (and lately,
|
||||
Garmin GPS devices).</p>
|
||||
<p><b>Note:</b> The mapping is undocumented and may change without notice.</p>
|
||||
<p><b>Note:</b> Some of OC's size values cannot be properly mapped to <b>oxsize</b>,
|
||||
i.e. the 'other' size.</p>
|
||||
</li>
|
||||
<li><b>difficulty</b> - float (between 1 and 5), difficulty rating of the cache,</li>
|
||||
<li><b>terrain</b> - float (between 1 and 5), terrain rating of the cache,</li>
|
||||
<li>
|
||||
<b>trip_time</b> - float, approximate total amount of time needed to
|
||||
find the cache, in hours; this will usually include the time to reach the
|
||||
cache location <em>and</em> go back (from/to a parking spot, etc.);
|
||||
<b>null</b> if unknown,
|
||||
</li>
|
||||
<li><b>trip_distance</b> - float, approximate total distance needed to
|
||||
find the cache, in kilometers; this will usually include the time to reach the
|
||||
cache location <em>and</em> go back (from/to a parking spot, etc.);
|
||||
<b>null</b> if unknown,
|
||||
</li>
|
||||
<li>
|
||||
<p><b>rating</b> - float (between 1 and 5), an overall rating of the cache,
|
||||
or <b>null</b> when the geocache does not have a sufficient amount of votes
|
||||
to have a rating.</p>
|
||||
<p>Please note: some OC installations do not use the rating/voting system. The <b>rating</b> will
|
||||
always be <b>null</b> on such installations.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>rating_votes</b> - number of votes submitted for the rating of this cache.</p>
|
||||
<p>Please note: some OC installations do not use the rating/voting system. The <b>rating_votes</b> will
|
||||
always be <b>0</b> on such installations.</p>
|
||||
</li>
|
||||
<li><b>recommendations</b> - number of recommendations for this cache,</li>
|
||||
<li><b>req_passwd</b> - boolean; states if this cache requires a password
|
||||
in order to submit a "Found it" log entry,</li>
|
||||
<li><b>description</b> - HTML string, description of the cache,</li>
|
||||
<li><b>descriptions</b> - a dictionary (language code => HTML string) of cache
|
||||
descriptions,</li>
|
||||
<li class="deprecated"><b>hint</b> - HTML-encoded string, cache hints/spoilers;
|
||||
deprecated (<a href="http://code.google.com/p/opencaching-api/issues/detail?id=261">why?</a>),
|
||||
use <b>hint2</b> instead,</li>
|
||||
<li class="deprecated"><b>hints</b> - a dictionary (language code =>
|
||||
HTML-encoded string) of cache hints/spoilers; deprecated, use hints2 instead,</li>
|
||||
<li><b>hint2</b> - plain-text string, cache hints/spoilers; in general, hints
|
||||
should not be displayed to the user unless user specifically asks for them,</li>
|
||||
<li><b>hints2</b> - a dictionary (language code =>
|
||||
plain-text string) of cache hints/spoilers,</li>
|
||||
<li>
|
||||
<p><b>images</b> - list of dictionaries, each dictionary represents one
|
||||
image saved along the cache description; each dictionary has the
|
||||
following structure:</p>
|
||||
<ul>
|
||||
<li><b>uuid</b> - UUID of the image,</li>
|
||||
<li><b>url</b> - URL of the image,</li>
|
||||
<li><b>thumb_url</b> - URL of a small (thumb) version of the image,</li>
|
||||
<li><b>caption</b> - plain-text string, caption of the image,</li>
|
||||
<li><b>unique_caption</b> - plain-text string, to be used as a filename
|
||||
for Garmin's crappy images implementation (currently, they get image
|
||||
caption from the image's filename itself),</li>
|
||||
<li><b>is_spoiler</b> - boolean, if <b>true</b> then the image is
|
||||
a spoiler image and should not be displayed to the user unless
|
||||
the user explicitly asks for it,</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>preview_image</b> - On some installations, owners may select one of the <b>images</b>
|
||||
(see above) as a preview image. You are encouraged to display it as a 'teaser'
|
||||
for this cache. On other installations this functionality is disabled and you
|
||||
will always get the <b>null</b> value here.</p>
|
||||
<brief>Retrieve information on a single geocache</brief>
|
||||
<issue-id>19</issue-id>
|
||||
<desc>
|
||||
<p>Retrieve information on a single geocache.</p>
|
||||
</desc>
|
||||
<req name='cache_code'>Unique code of the geocache</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for fields like
|
||||
<b>name</b> and <b>description</b>.</p>
|
||||
<p>Please note, that you may also access caches' descriptions in all
|
||||
available languages. If you want to do this, you should use fields
|
||||
<b>names</b>, <b>descriptions</b> (etc.) instead of <b>name</b> and
|
||||
<b>description</b> (etc.).</p>
|
||||
</opt>
|
||||
<opt name='fields' default='code|name|location|type|status'>
|
||||
<p>Pipe-separated list of field names which you are interested with.
|
||||
Selected fields will be included in the response. See below for the
|
||||
list of available fields.</p>
|
||||
</opt>
|
||||
<opt name='attribution_append' default='full'>
|
||||
<p>By default, OKAPI appends the value of <b>attribution_note</b> field to all the
|
||||
cache descriptions. If you would like to display the attribution note separately,
|
||||
you may use this parameter. Use one of the following values:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>full</b> - OKAPI will append the attribution note to the descriptions of the
|
||||
geocache. The language of the note will match the language of the description
|
||||
(i.e. each value in <b>descriptions</b> may contain attribution notes in
|
||||
a different language).
|
||||
</li>
|
||||
<li>
|
||||
<p><b>none</b> - OKAPI will not append the attribution note to geocache
|
||||
descriptions. You will use the <b>attribution_note</b> instead (which depends
|
||||
on the <b>langpref</b> parameter).</p>
|
||||
|
||||
<p>The value of <b>preview_image</b> is either <b>null</b> or a dictionary describing
|
||||
an image. The structure of this dictionary is the same as of a single entry on
|
||||
the <b>images</b> list described above.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>attr_acodes</b> - unordered list of OKAPI geocache-attribute IDs (A-codes) with
|
||||
which the cache was tagged. Use the <b>attrs</b> module to retrieve information on
|
||||
these attributes.</p>
|
||||
</li>
|
||||
<li>
|
||||
<b>attrnames</b> - if you don't want to dig into <b>attr_acodes</b> just now, then
|
||||
you can use these as a simple alternative. <b>attrnames</b> is an unordered list of
|
||||
names of the attributes with which the cache was tagged; the language will be
|
||||
selected based on the <b>langpref</b> parameter.
|
||||
</li>
|
||||
<li>
|
||||
<p><b>attribution_note</b> - the proper attribution note for the cache listing according
|
||||
to the local OC site's Data License. By default, this note is also appended to geocache
|
||||
descriptions (see the <b>attribution_append</b> parameter).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>latest_logs</b> - a couple of latest log entries in the cache.
|
||||
The format is the same as the one returned by the services/logs/logs method.</p>
|
||||
<p>Notice: The number of logs returned can be set with the <b>lpc</b> option.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>my_notes</b> - user's notes on the cache, in plain-text, or <b>null</b>
|
||||
if user hadn't defined any notes.</p>
|
||||
<p>This field requires you to use the <b>Level 3</b> Authentication.</p>
|
||||
</li>
|
||||
<li><b>trackables_count</b> - a total number of trackables hidden within the cache.</li>
|
||||
<li>
|
||||
<p><b>trackables</b> - list of dictionaries, each dictionary represents one
|
||||
trackable hidden within the cache container; each dictionary has the
|
||||
following structure:</p>
|
||||
<ul>
|
||||
<li><b>code</b> - code of the trackable,</li>
|
||||
<li><b>name</b> - plain text name of the trackable,</li>
|
||||
<li><b>url</b> - trackable's own webpage address <b>or null</b>, if OKAPI
|
||||
cannot automatically determine this address.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>alt_wpts</b> - list of alternate/additional waypoints associated
|
||||
with this geocache. Each item is a dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>name</b> - plain-text, short, unique "codename" for the waypoint,</li>
|
||||
<li><b>location</b> - location of the waypoint in the "lat|lon" format
|
||||
(<i>lat</i> and <i>lon</i> are in full degrees with a dot as a decimal point),</li>
|
||||
<li><b>type</b> - string, unique identifier for the type of waypoint; one
|
||||
of the following: <b>parking</b>, <b>path</b>, <b>stage</b>,
|
||||
<b>physical-stage</b>, <b>virtual-stage</b>, <b>final</b>, <b>poi</b>, <b>other</b>;
|
||||
more types may be added; unknown types should be treated as <b>other</b>,
|
||||
</li>
|
||||
<li><b>type_name</b> - string, the human-readable name of the waypoint type,
|
||||
e.g. "Parking area" or "Final location"; the language will be selected
|
||||
based on the langpref argument,
|
||||
</li>
|
||||
<li>
|
||||
<b>sym</b> - string, one of commonly recognized waypoint symbol
|
||||
names, originally introduced by Garmin in their devices and GPX
|
||||
files (e.g. "Flag, Green" or "Parking Area"),
|
||||
</li>
|
||||
<li><b>description</b> - plain-text longer description of the waypoint.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>country</b> - name of the country the cache is placed in;
|
||||
may be empty ("") if the country is unknown.</p>
|
||||
<p><b>Note:</b> This data is user-supplied and is not validated in
|
||||
any way. Consider using external geocoding services instead. Also,
|
||||
currently you have no way of knowing in which language it will appear
|
||||
in (but it *may* start to vary on the value of your <b>langpref</b>
|
||||
parameter in the future).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>state</b> - name of the state the cache is placed in;
|
||||
may be empty ("") if the state is unknown.</p>
|
||||
<p><b>Note:</b> On some installations this data is user-supplied and
|
||||
is not validated in any way. Other installations calculate it from
|
||||
cache coordinates but may have problems in border regions.
|
||||
Consider using external geocoding services instead. Also,
|
||||
currently you have no way of knowing in which language it will appear
|
||||
in (but it *may* start to vary on the value of your <b>langpref</b>
|
||||
parameter in the future).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>protection_areas</b> - list of dictionaries, each representing a
|
||||
protection area in which the cache probably is located; each dictionary
|
||||
has the following structure:</p>
|
||||
<ul>
|
||||
<li><b>type</b> - the type of the protection area, e.g.
|
||||
"National Nature Reserve",</li>
|
||||
<li><b>name</b> - the name of the protection area, e.g.
|
||||
"East Dartmoor Woods and Heaths".</li>
|
||||
</ul>
|
||||
<p>The types and names currently are in a local language of the OC site but
|
||||
may be translated depending on the <b>langpref</b> parameter in the future.</p>
|
||||
<p>Note that this information is not authoritative. It may be outdated
|
||||
or incomplete, and it is completely missing on some OC installations.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>last_found</b> - date and time (ISO 8601) when the
|
||||
geocache was last found <b>or null</b> when it hasn't been yet found.</p>
|
||||
<p>Note, that some Opencaching servers don't store the exact times along
|
||||
with the log entries.</p>
|
||||
</li>
|
||||
<li><b>last_modified</b> - date and time (ISO 8601) when the
|
||||
geocache was last modified (changed status, attributes, etc.),</li>
|
||||
<li><b>date_created</b> - date and time (ISO 8601) when the
|
||||
geocache was listed at the Opencaching site,</li>
|
||||
<li><b>date_hidden</b> - date and time (ISO 8601) when
|
||||
<ul>
|
||||
<li>the geocache was first hidden (for physical caches), or </li>
|
||||
<li>the geocache was first published (for virtual caches), or</li>
|
||||
<li>the event takes place (for event caches),</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!-- Note: I think cache uuids should not be ever revealed to the public.
|
||||
We have already one universally unique key - the cache code. It is uncommon
|
||||
to have multiple universally unique keys. -->
|
||||
<li><b>internal_id</b> - internal ID of the cache (<b>do not</b> use
|
||||
this, unless you know what you're doing; use the "code" as an identifier).</li>
|
||||
</ul>
|
||||
<p><b>Important note:</b> You are still <b>required</b> to display the
|
||||
<b>attribution_note</b> field in some other way.</p>
|
||||
</li>
|
||||
<li>
|
||||
<b>static</b> - OKAPI will append a "static" attribution note to the descriptions
|
||||
of the geocache. This might equal the "full" attribution note, but not necessarilly,
|
||||
since the "full" note may contain a current date
|
||||
(<a href='https://code.google.com/p/opencaching-api/issues/detail?id=178'>why?</a>),
|
||||
and the "static" note will not. This is implemented primarily for internal use
|
||||
(i.e. the replicate module). Usually you should not use it, because on some
|
||||
installations the static note will not be sufficient to meet the data license
|
||||
requirements.
|
||||
</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name='lpc' default='10'>
|
||||
Log-entries per cache - the number of logs returned in the <b>latest_logs</b> field.
|
||||
This should be an integer or a special "all" value. Please note, that you must include
|
||||
the <b>latest_logs</b> field in <b>fields</b> in order to see the log entries.
|
||||
</opt>
|
||||
<opt name='log_fields' default='uuid|date|user|type|comment'>
|
||||
Pipe-separated list of log fields to include in the <b>latest_logs</b> field.
|
||||
For valid field names, see <b>logs/entry</b> method.
|
||||
</opt>
|
||||
<opt name='my_location'>
|
||||
<p>The reference point for cache distance and bearing calculation (typically - the user's location),
|
||||
in the "lat|lon" format. This parameter is required when accessing <b>distance</b> and/or <b>bearing</b>
|
||||
fields.</p>
|
||||
<p>Use positive numbers for latitudes in the northern hemisphere and
|
||||
longitudes in the eastern hemisphere (and negative for southern and
|
||||
western hemispheres accordingly). These are full degrees with a dot
|
||||
as a decimal point (ex. "54.3|22.3").</p>
|
||||
</opt>
|
||||
<opt name="user_uuid">
|
||||
<p>User'd ID. Required to access fields like <b>is_found</b> using <b>Level 1</b> Authentication.</p>
|
||||
<p>Please note that if you want to access private fields (like <b>my_notes</b>), then
|
||||
this parameter won't help you. You have to use <b>Level 3</b> Authentication instead.</p>
|
||||
<p>If you use <b>Level 3</b> Authentication, you shouldn't use this parameter. Or, to be exact:</p>
|
||||
<ul>
|
||||
<li><b>user_uuid</b> will be extracted from the Access Token you use. You don't have to provide it.</li>
|
||||
<li>If you provide <b>user_uuid</b>, then it HAS TO match your Access Token. If it doesn't, OKAPI
|
||||
will respond with HTTP 400 error.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of fields you have selected. Currently available fields:</p>
|
||||
|
||||
<p>For example, for <i>geocache?cache_code=OP3D96&fields=type</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"type": "Traditional"}</pre>
|
||||
<p>If given cache code does not exist, the method will
|
||||
respond with an HTTP 400 error.</p>
|
||||
</returns>
|
||||
<ul>
|
||||
<li><b>code</b> - unique Opencaching code of the geocache,</li>
|
||||
<li><b>name</b> - name of the geocache,</li>
|
||||
<li><b>names</b> - a dictionary (language code => plain-text string) of
|
||||
names of the geocache (at this time, there will be only one language,
|
||||
but this may change in future),</li>
|
||||
<li>
|
||||
<b>location</b> - location of the cache in the "lat|lon" format
|
||||
(<i>lat</i> and <i>lon</i> are in full degrees with a dot as a decimal point),
|
||||
</li>
|
||||
<li>
|
||||
<p><b>type</b> - cache type. This might be <b>pretty much everything</b>,
|
||||
but there are some predefined types that you might want to treat
|
||||
in a special way (separate icons etc.). Primary types include: </p>
|
||||
<ul>
|
||||
<li><b>Traditional</b>,</li>
|
||||
<li><b>Multi</b>,</li>
|
||||
<li><b>Quiz</b>,</li>
|
||||
<li><b>Virtual</b>,</li>
|
||||
<li><b>Event</b>,</li>
|
||||
<li><i>(any other value is valid too)</i></li>
|
||||
</ul>
|
||||
<p><b>Event</b> is a peculiar type of geocache which is NOT a geocache
|
||||
at all, but it <b>is</b> stored as a geocache in OC database (this design
|
||||
decision is old as the OC network itself!). Just keep in mind, that
|
||||
in case of Event Caches, some fields may have a little different meaning
|
||||
than you would tell by their name.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>status</b> - cache status. Valid cache status codes currently include:</p>
|
||||
<ul>
|
||||
<li><b>Available</b> - Cache is available and ready for search,</li>
|
||||
<li><b>Temporarily unavailable</b> - Cache is probably unavailable (i.e. in need of maintenance)</li>
|
||||
<li><b>Archived</b> - Cache is permanently unavailable (moved to the archives).</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>url</b> - URL of the cache's web page,</li>
|
||||
<li>
|
||||
<p><b>owner</b> - dictionary of:</p>
|
||||
<ul>
|
||||
<li><b>uuid</b> - geocache owner's user ID,</li>
|
||||
<li><b>username</b> - name of the user,</li>
|
||||
<li><b>profile_url</b> - URL of the user profile page,</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>gc_code</b> - Geocaching.com code (GC code) of the geocache
|
||||
<b>or null</b> if the cache is not listed on GC or the GC code is
|
||||
unknown.</p>
|
||||
|
||||
<p>Please note that this information is supplied by cache owners
|
||||
and it is often missing, obsolete or otherwise incorrect.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>distance</b> - float, the distance to a cache, in meters.
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>bearing</b> - float, the absolute bearing to the cache, measured in degrees from north,
|
||||
<b>or null</b> if it cannot be calculated (i.e. when you are exactly at the target's location).
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>bearing2</b> - string, the absolute bearing to the cache, represented as a typical direction
|
||||
string of length of 1 or 2 characters (ex. "N", "NE", "E", "SE", etc.), or "n/a" if it cannot be calculated.
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>bearing3</b> - string, the absolute bearing to the cache, represented as a typical direction
|
||||
string of length of 1 or 2 or 3 characters (ex. "N", "NNE", "NE", "ENE", etc.), or "n/a" if it cannot be calculated.
|
||||
This requires <b>my_location</b> parameter to be provided.</p>
|
||||
<p>Please note, that sometimes it is faster to compute this yourself, on client-side, instead of querying OKAPI.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_found</b> - boolean, true if the user already found this cache.
|
||||
See also <b>found_status</b> parameter of the services/caches/search/all
|
||||
method.</p>
|
||||
<p>This field requires you to use the <b>user_uuid</b> parameter
|
||||
(or Level 3 Authentication). Please note, that this will also return <b>true</b>
|
||||
for attended Event Caches.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_not_found</b> - boolean, true if the user has submitted "Didn't find it" log entry for this cache.</p>
|
||||
<p>This field requires you to use the <b>user_uuid</b> parameter (or Level 3 Authentication).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_watched</b> - boolean, true if the user is watching this cache. You may consider highlighting
|
||||
such geocaches in some fashion, as the users may use this functionality to temporarily mark geocaches
|
||||
of particular interest (i.e. geocaches they plan to find today).</p>
|
||||
<p>This is private data. You will need Level 3 Authentication to access this field.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>is_ignored</b> - boolean, true if the user is ignoring this cache. (See also <b>exclude_ignored</b>
|
||||
parameter of all search methods.)</p>
|
||||
<p>This is private data. You will need Level 3 Authentication to access this field.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>founds</b> - number of times the geocache was successfully found
|
||||
(or attended, in case of Event Caches),</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>notfounds</b> - number of times the geocache was not found
|
||||
(in case of Event Caches this will always be zero),</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>willattends</b> - in case of Event Caches, this is the number of
|
||||
"Will attend" log entries. In case of any other cache type, it will
|
||||
be <b>zero</b> (not null, for <a href='https://code.google.com/p/opencaching-api/issues/detail?id=233'>backward
|
||||
compatibility</a>),</p>
|
||||
</li>
|
||||
<li class='deprecated'>
|
||||
<b>size</b> - deprecated
|
||||
(<a href='http://code.google.com/p/opencaching-api/issues/detail?id=155'>why?</a>),
|
||||
use <b>size2</b> instead. Float (between 1 and 5), size rating of the container, or
|
||||
<b>null</b> if geocache does not have a container,
|
||||
</li>
|
||||
<li>
|
||||
<p><b>size2</b> - string indicating the size of the container, so called
|
||||
"size2 code". One of the following values:
|
||||
'none', 'nano', 'micro', 'small', 'regular', 'large', 'xlarge', 'other'.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>oxsize</b> - float (between 1 and 5) or null, this is a size rating
|
||||
variant, compatible with the one used by opencaching.com (and lately,
|
||||
Garmin GPS devices).</p>
|
||||
<p><b>Note:</b> The mapping is undocumented and may change without notice.</p>
|
||||
<p><b>Note:</b> Some of OC's size values cannot be properly mapped to <b>oxsize</b>,
|
||||
i.e. the 'other' size.</p>
|
||||
</li>
|
||||
<li><b>difficulty</b> - float (between 1 and 5), difficulty rating of the cache,</li>
|
||||
<li><b>terrain</b> - float (between 1 and 5), terrain rating of the cache,</li>
|
||||
<li>
|
||||
<b>trip_time</b> - float, approximate total amount of time needed to
|
||||
find the cache, in hours; this will usually include the time to reach the
|
||||
cache location <em>and</em> go back (from/to a parking spot, etc.);
|
||||
<b>null</b> if unknown,
|
||||
</li>
|
||||
<li><b>trip_distance</b> - float, approximate total distance needed to
|
||||
find the cache, in kilometers; this will usually include the time to reach the
|
||||
cache location <em>and</em> go back (from/to a parking spot, etc.);
|
||||
<b>null</b> if unknown,
|
||||
</li>
|
||||
<li>
|
||||
<p><b>rating</b> - float (between 1 and 5), an overall rating of the cache,
|
||||
or <b>null</b> when the geocache does not have a sufficient amount of votes
|
||||
to have a rating.</p>
|
||||
<p>Please note: some OC installations do not use the rating/voting system. The <b>rating</b> will
|
||||
always be <b>null</b> on such installations.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>rating_votes</b> - number of votes submitted for the rating of this cache.</p>
|
||||
<p>Please note: some OC installations do not use the rating/voting system. The <b>rating_votes</b> will
|
||||
always be <b>0</b> on such installations.</p>
|
||||
</li>
|
||||
<li><b>recommendations</b> - number of recommendations for this cache,</li>
|
||||
<li><b>req_passwd</b> - boolean; states if this cache requires a password
|
||||
in order to submit a "Found it" log entry,</li>
|
||||
<li><b>short_description</b> - a plaintext string with a single line (very short)
|
||||
description of the cache (kind of a "tagline text"),</li>
|
||||
<li><b>short_descriptions</b> - a dictionary (language code =>
|
||||
plaintext string) of short cache descriptions,</li>
|
||||
<li><b>description</b> - <a href='%OKAPI:docurl:html%'>HTML string</a>,
|
||||
description of the cache,</li>
|
||||
<li><b>descriptions</b> - a dictionary (language code =>
|
||||
<a href='%OKAPI:docurl:html%'>HTML string</a>) of cache descriptions,</li>
|
||||
<li class="deprecated"><b>hint</b> - <a href='%OKAPI:docurl:html%'>HTML-encoded</a>
|
||||
string, cache hints/spoilers; deprecated
|
||||
(<a href="http://code.google.com/p/opencaching-api/issues/detail?id=261">why?</a>),
|
||||
use <b>hint2</b> instead,</li>
|
||||
<li class="deprecated"><b>hints</b> - a dictionary (language code =>
|
||||
<a href='%OKAPI:docurl:html%'>HTML-encoded</a> string) of cache hints/spoilers;
|
||||
deprecated, use hints2 instead,</li>
|
||||
<li><b>hint2</b> - plain-text string, cache hints/spoilers; in general, hints
|
||||
should not be displayed to the user unless user specifically asks for them,</li>
|
||||
<li><b>hints2</b> - a dictionary (language code =>
|
||||
plain-text string) of cache hints/spoilers,</li>
|
||||
<li>
|
||||
<p><b>images</b> - list of dictionaries, each dictionary represents one
|
||||
image saved along the cache description; each dictionary has the
|
||||
following structure:</p>
|
||||
<ul>
|
||||
<li><b>uuid</b> - UUID of the image,</li>
|
||||
<li><b>url</b> - URL of the image,</li>
|
||||
<li><b>thumb_url</b> - URL of a small (thumb) version of the image,</li>
|
||||
<li><b>caption</b> - plain-text string, caption of the image,</li>
|
||||
<li><b>unique_caption</b> - plain-text string, to be used as a filename
|
||||
for Garmin's crappy images implementation (currently, they get image
|
||||
caption from the image's filename itself),</li>
|
||||
<li><b>is_spoiler</b> - boolean, if <b>true</b> then the image is
|
||||
a spoiler image and should not be displayed to the user unless
|
||||
the user explicitly asks for it,</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>preview_image</b> - On some installations, owners may select one of the <b>images</b>
|
||||
(see above) as a preview image. You are encouraged to display it as a 'teaser'
|
||||
for this cache. On other installations this functionality is disabled and you
|
||||
will always get the <b>null</b> value here.</p>
|
||||
|
||||
<p>The value of <b>preview_image</b> is either <b>null</b> or a dictionary describing
|
||||
an image. The structure of this dictionary is the same as of a single entry on
|
||||
the <b>images</b> list described above.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>attr_acodes</b> - unordered list of OKAPI geocache-attribute IDs (A-codes) with
|
||||
which the cache was tagged. Use the <b>attrs</b> module to retrieve information on
|
||||
these attributes.</p>
|
||||
</li>
|
||||
<li>
|
||||
<b>attrnames</b> - if you don't want to dig into <b>attr_acodes</b> just now, then
|
||||
you can use these as a simple alternative. <b>attrnames</b> is an unordered list of
|
||||
names of the attributes with which the cache was tagged; the language will be
|
||||
selected based on the <b>langpref</b> parameter.
|
||||
</li>
|
||||
<li>
|
||||
<p><b>attribution_note</b> - the proper attribution note for the cache listing according
|
||||
to the local OC site's Data License. By default, this note is also appended to geocache
|
||||
descriptions (see the <b>attribution_append</b> parameter).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>latest_logs</b> - a couple of latest log entries in the cache.
|
||||
The format is the same as the one returned by the services/logs/logs method.</p>
|
||||
<p>Notice: The number of logs returned can be set with the <b>lpc</b> option.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>my_notes</b> - user's notes on the cache, in plain-text, or <b>null</b>
|
||||
if user hadn't defined any notes.</p>
|
||||
<p>This field requires you to use the <b>Level 3</b> Authentication.</p>
|
||||
</li>
|
||||
<li><b>trackables_count</b> - a total number of trackables hidden within the cache.</li>
|
||||
<li>
|
||||
<p><b>trackables</b> - list of dictionaries, each dictionary represents one
|
||||
trackable hidden within the cache container; each dictionary has the
|
||||
following structure:</p>
|
||||
<ul>
|
||||
<li><b>code</b> - code of the trackable,</li>
|
||||
<li><b>name</b> - plain text name of the trackable,</li>
|
||||
<li><b>url</b> - trackable's own webpage address <b>or null</b>, if OKAPI
|
||||
cannot automatically determine this address.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li id="ret_alt_wpts">
|
||||
<p><b>alt_wpts</b> - list of alternate/additional waypoints associated
|
||||
with this geocache. Each item is a dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>name</b> - plain-text, short, unique "codename" for the waypoint,</li>
|
||||
<li><b>location</b> - location of the waypoint in the "lat|lon" format
|
||||
(<i>lat</i> and <i>lon</i> are in full degrees with a dot as a decimal point),</li>
|
||||
<li>
|
||||
<p><b>type</b> - string, unique identifier for the type of waypoint;
|
||||
one of the following:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>parking</b>, <b>path</b>, <b>stage</b>, <b>physical-stage</b>,
|
||||
<b>virtual-stage</b>, <b>final</b>, <b>poi</b>, <b>other</b> - used by
|
||||
OC itself, for detailed descriptions of these you'll have to refer to
|
||||
external Opencaching documenation,</li>
|
||||
|
||||
<li><b>user-coords</b> - extra coordinates supplied <i>by the user who
|
||||
had found the cache</i> (NOT the owner of the cache), most probably
|
||||
pointing to the final location of the cache (e.g. a quiz cache);
|
||||
this type of waypoint is available only in some installations and only
|
||||
if you're using Level 3 Authentication,</li>
|
||||
|
||||
<li>more types may be added at any moment; unknown types should be
|
||||
treated as <b>other</b>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<b>type_name</b> - string, the human-readable name of the waypoint type,
|
||||
e.g. "Parking area" or "Final location"; the language will be selected
|
||||
based on the langpref argument,
|
||||
</li>
|
||||
<li>
|
||||
<p><b>sym</b> - string, one of commonly recognized waypoint symbol
|
||||
names, originally introduced by Garmin in their devices and GPX
|
||||
files (e.g. "Flag, Green" or "Parking Area").</p>
|
||||
|
||||
<p>These symbol codes are only suggestions. They are understood by
|
||||
Garmin-related software and devices. If you don't know how to display such
|
||||
symbols, you are welcome to use any symbol you'd like in your
|
||||
application.</p>
|
||||
</li>
|
||||
<li><b>description</b> - plain-text longer description of the waypoint.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>country</b> - name of the country the cache is placed in;
|
||||
may be empty ("") if the country is unknown.</p>
|
||||
<p><b>Note:</b> This data is user-supplied and is not validated in
|
||||
any way. Consider using external geocoding services instead. Also,
|
||||
currently you have no way of knowing in which language it will appear
|
||||
in (but it *may* start to vary on the value of your <b>langpref</b>
|
||||
parameter in the future).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>state</b> - name of the state the cache is placed in;
|
||||
may be empty ("") if the state is unknown.</p>
|
||||
<p><b>Note:</b> On some installations this data is user-supplied and
|
||||
is not validated in any way. Other installations calculate it from
|
||||
cache coordinates but may have problems in border regions.
|
||||
Consider using external geocoding services instead. Also,
|
||||
currently you have no way of knowing in which language it will appear
|
||||
in (but it *may* start to vary on the value of your <b>langpref</b>
|
||||
parameter in the future).</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>protection_areas</b> - list of dictionaries, each representing a
|
||||
protection area in which the cache probably is located; each dictionary
|
||||
has the following structure:</p>
|
||||
<ul>
|
||||
<li><b>type</b> - the type of the protection area, e.g.
|
||||
"National Nature Reserve",</li>
|
||||
<li><b>name</b> - the name of the protection area, e.g.
|
||||
"East Dartmoor Woods and Heaths".</li>
|
||||
</ul>
|
||||
<p>The types and names currently are in a local language of the OC site but
|
||||
may be translated depending on the <b>langpref</b> parameter in the future.</p>
|
||||
<p>Note that this information is not authoritative. It may be outdated
|
||||
or incomplete, and it is completely missing on some OC installations.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><b>last_found</b> - date and time (ISO 8601) when the
|
||||
geocache was last found <b>or null</b> when it hasn't been yet found.</p>
|
||||
<p>Note, that some Opencaching servers don't store the exact times along
|
||||
with the log entries.</p>
|
||||
</li>
|
||||
<li><b>last_modified</b> - date and time (ISO 8601) when the
|
||||
geocache was last modified (changed status, attributes, etc.),</li>
|
||||
<li><b>date_created</b> - date and time (ISO 8601) when the
|
||||
geocache was listed at the Opencaching site,</li>
|
||||
<li><b>date_hidden</b> - date and time (ISO 8601) when
|
||||
<ul>
|
||||
<li>the geocache was first hidden (for physical caches), or </li>
|
||||
<li>the geocache was first published (for virtual caches), or</li>
|
||||
<li>the event takes place (for event caches),</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!-- Note: I think cache uuids should not be ever revealed to the public.
|
||||
We have already one universally unique key - the cache code. It is uncommon
|
||||
to have multiple universally unique keys. -->
|
||||
<li><b>internal_id</b> - internal ID of the cache (<b>do not</b> use
|
||||
this, unless you know what you're doing; use the "code" as an identifier).</li>
|
||||
</ul>
|
||||
|
||||
<p>For example, for <i>geocache?cache_code=OP3D96&fields=type</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"type": "Traditional"}</pre>
|
||||
<p>If given cache code does not exist, the method will
|
||||
respond with an HTTP 400 error.</p>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -1,51 +1,54 @@
|
||||
<xml>
|
||||
<brief>Retrieve information on multiple geocaches</brief>
|
||||
<issue-id>20</issue-id>
|
||||
<desc>
|
||||
<p>This method works like the services/caches/geocache method, but works
|
||||
with multiple geocaches (instead of only one).</p>
|
||||
</desc>
|
||||
<req name='cache_codes'>
|
||||
<p>Pipe-separated list of cache cache codes. These represent the
|
||||
geocaches you are interested in. No more than 500 codes are allowed.
|
||||
Unlike in the "geocache" method, this CAN be an empty string (it will
|
||||
result in an empty, but valid, response).</p>
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for fields like
|
||||
<b>name</b> and <b>description</b>.</p>
|
||||
<p>Please note, that you may also access caches' descriptions in all
|
||||
available languages. If you want to do this, you should use fields
|
||||
<b>names</b>, <b>descriptions</b> (etc.) instead of <b>name</b> and
|
||||
<b>description</b> (etc.).</p>
|
||||
</opt>
|
||||
<opt name='fields' default='code|name|location|type|status'>
|
||||
<p>Same as in the services/caches/geocache method. Pipe-separated list
|
||||
of field names which you are interested with.
|
||||
See services/caches/geocache method for a list available values.</p>
|
||||
</opt>
|
||||
<opt name='attribution_append' default='full'>
|
||||
<p>Same as in the services/caches/geocache method.</p>
|
||||
</opt>
|
||||
<opt name='lpc' default='10'>
|
||||
Same as in the services/caches/geocache method.
|
||||
</opt>
|
||||
<opt name='log_fields' default='uuid|date|user|type|comment'>
|
||||
Same as in the services/caches/geocache method.
|
||||
</opt>
|
||||
<opt name='user_uuid'>
|
||||
Same as in the services/caches/geocache method.
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary. Cache codes you provide will be mapped to dictionary keys,
|
||||
and each value will be a dictionary of fields you have selected.</p>
|
||||
<p>For example, for <i>geocaches?cache_codes=OP3D96|OC124&fields=type</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"OP3D96": {"type": "Traditional"}, "OC124": null}</pre>
|
||||
<p>Value of <b>null</b> means that the given cache haven't been found.
|
||||
(This behavior is different than in the services/caches/geocache method, which
|
||||
responds with an HTTP 400 error in such case.)</p>
|
||||
</returns>
|
||||
<brief>Retrieve information on multiple geocaches</brief>
|
||||
<issue-id>20</issue-id>
|
||||
<desc>
|
||||
<p>This method works like the services/caches/geocache method, but works
|
||||
with multiple geocaches (instead of only one).</p>
|
||||
</desc>
|
||||
<req name='cache_codes'>
|
||||
<p>Pipe-separated list of cache cache codes. These represent the
|
||||
geocaches you are interested in. No more than 500 codes are allowed.
|
||||
Unlike in the "geocache" method, this CAN be an empty string (it will
|
||||
result in an empty, but valid, response).</p>
|
||||
</req>
|
||||
<opt name='langpref' default='en'>
|
||||
<p>Pipe-separated list of ISO 639-1 language codes. This indicates the
|
||||
order of preference in which language will be chosen for fields like
|
||||
<b>name</b> and <b>description</b>.</p>
|
||||
<p>Please note, that you may also access caches' descriptions in all
|
||||
available languages. If you want to do this, you should use fields
|
||||
<b>names</b>, <b>descriptions</b> (etc.) instead of <b>name</b> and
|
||||
<b>description</b> (etc.).</p>
|
||||
</opt>
|
||||
<opt name='fields' default='code|name|location|type|status'>
|
||||
<p>Same as in the services/caches/geocache method. Pipe-separated list
|
||||
of field names which you are interested with.
|
||||
See services/caches/geocache method for a list available values.</p>
|
||||
</opt>
|
||||
<opt name='attribution_append' default='full'>
|
||||
<p>Same as in the services/caches/geocache method.</p>
|
||||
</opt>
|
||||
<opt name='lpc' default='10'>
|
||||
Same as in the services/caches/geocache method.
|
||||
</opt>
|
||||
<opt name='log_fields' default='uuid|date|user|type|comment'>
|
||||
Same as in the services/caches/geocache method.
|
||||
</opt>
|
||||
<opt name='my_location'>
|
||||
Same as in the services/caches/geocache method.
|
||||
</opt>
|
||||
<opt name='user_uuid'>
|
||||
Same as in the services/caches/geocache method.
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary. Cache codes you provide will be mapped to dictionary keys,
|
||||
and each value will be a dictionary of fields you have selected.</p>
|
||||
<p>For example, for <i>geocaches?cache_codes=OP3D96|OC124&fields=type</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"OP3D96": {"type": "Traditional"}, "OC124": null}</pre>
|
||||
<p>Value of <b>null</b> means that the given cache haven't been found.
|
||||
(This behavior is different than in the services/caches/geocache method, which
|
||||
responds with an HTTP 400 error in such case.)</p>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -23,230 +23,246 @@ require_once 'tiletree.inc.php';
|
||||
|
||||
class ReplicateListener
|
||||
{
|
||||
public static function receive($changelog)
|
||||
{
|
||||
# This will be called every time new items arrive from replicate module's
|
||||
# changelog. The format of $changelog is described in the replicate module
|
||||
# (NOT the entire response, just the "changelog" key).
|
||||
public static function receive($changelog)
|
||||
{
|
||||
# This will be called every time new items arrive from replicate module's
|
||||
# changelog. The format of $changelog is described in the replicate module
|
||||
# (NOT the entire response, just the "changelog" key).
|
||||
|
||||
foreach ($changelog as $c)
|
||||
{
|
||||
if ($c['object_type'] == 'geocache')
|
||||
{
|
||||
if ($c['change_type'] == 'replace')
|
||||
self::handle_geocache_replace($c);
|
||||
else
|
||||
self::handle_geocache_delete($c);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($changelog as $c)
|
||||
{
|
||||
if ($c['object_type'] == 'geocache')
|
||||
{
|
||||
if ($c['change_type'] == 'replace')
|
||||
self::handle_geocache_replace($c);
|
||||
else
|
||||
self::handle_geocache_delete($c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function reset($mail_admins = true)
|
||||
{
|
||||
# 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 a little slower.
|
||||
public static function reset($mail_admins = true)
|
||||
{
|
||||
# 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 a little slower.
|
||||
|
||||
Db::execute("delete from okapi_tile_status");
|
||||
Db::execute("delete from okapi_tile_caches");
|
||||
}
|
||||
Db::execute("delete from okapi_tile_status");
|
||||
Db::execute("delete from okapi_tile_caches");
|
||||
}
|
||||
|
||||
private static function handle_geocache_replace($c)
|
||||
{
|
||||
# Check if any relevant geocache attributes have changed.
|
||||
# We will pick up "our" copy of the cache from zero-zoom level.
|
||||
private static function handle_geocache_replace($c)
|
||||
{
|
||||
# Check if any relevant geocache attributes have changed.
|
||||
# We will pick up "our" copy of the cache from zero-zoom level.
|
||||
|
||||
try {
|
||||
$cache = OkapiServiceRunner::call("services/caches/geocache", new OkapiInternalRequest(new OkapiInternalConsumer(), null, array(
|
||||
'cache_code' => $c['object_key']['code'],
|
||||
'fields' => 'internal_id|code|name|location|type|status|rating|recommendations|founds|trackables_count'
|
||||
)));
|
||||
} catch (InvalidParam $e) {
|
||||
# Unprobable, but possible. Ignore changelog entry.
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$cache = OkapiServiceRunner::call("services/caches/geocache", new OkapiInternalRequest(new OkapiInternalConsumer(), null, array(
|
||||
'cache_code' => $c['object_key']['code'],
|
||||
'fields' => 'internal_id|code|name|location|type|status|rating|recommendations|founds|trackables_count'
|
||||
)));
|
||||
} catch (InvalidParam $e) {
|
||||
# Unprobable, but possible. Ignore changelog entry.
|
||||
return;
|
||||
}
|
||||
|
||||
$theirs = TileTree::generate_short_row($cache);
|
||||
$ours = mysql_fetch_row(Db::query("
|
||||
select cache_id, z21x, z21y, status, type, rating, flags
|
||||
from okapi_tile_caches
|
||||
where
|
||||
z=0
|
||||
and cache_id = '".mysql_real_escape_string($cache['internal_id'])."'
|
||||
"));
|
||||
if (!$ours)
|
||||
{
|
||||
# Aaah, a new geocache! How nice... ;)
|
||||
# Fetch our copy of the cache.
|
||||
|
||||
self::add_geocache_to_cached_tiles($theirs);
|
||||
}
|
||||
elseif (($ours[1] != $theirs[1]) || ($ours[2] != $theirs[2])) # z21x & z21y fields
|
||||
{
|
||||
# Location changed.
|
||||
$ours = mysql_fetch_row(Db::query("
|
||||
select cache_id, z21x, z21y, status, type, rating, flags
|
||||
from okapi_tile_caches
|
||||
where
|
||||
z=0
|
||||
and cache_id = '".mysql_real_escape_string($cache['internal_id'])."'
|
||||
"));
|
||||
|
||||
self::remove_geocache_from_cached_tiles($ours[0]);
|
||||
self::add_geocache_to_cached_tiles($theirs);
|
||||
}
|
||||
elseif ($ours != $theirs)
|
||||
{
|
||||
self::update_geocache_attributes_in_cached_tiles($theirs);
|
||||
}
|
||||
else
|
||||
{
|
||||
# No need to update anything. This is very common (i.e. when the
|
||||
# cache was simply found, not actually changed). Replicate module generates
|
||||
# many updates which do not influence our cache.
|
||||
}
|
||||
}
|
||||
# Caches near the poles caused our computations to break here. We will
|
||||
# ignore such caches!
|
||||
|
||||
private static function remove_geocache_from_cached_tiles($cache_id)
|
||||
{
|
||||
# Simply remove all traces of this geocache from all tiles.
|
||||
# This includes all references along tiles' borders, etc.
|
||||
list($lat, $lon) = explode("|", $cache['location']);
|
||||
if ((floatval($lat) >= 89.99) || (floatval($lat) <= -89.99)) {
|
||||
if ($ours) {
|
||||
self::remove_geocache_from_cached_tiles($ours[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Db::execute("
|
||||
delete from okapi_tile_caches
|
||||
where cache_id = '".mysql_real_escape_string($cache_id)."'
|
||||
");
|
||||
# Compute the new row for okapi_tile_caches. Compare with the old one.
|
||||
|
||||
# Note, that after this operation, okapi_tile_status may be out-of-date.
|
||||
# There might exist some rows with status==2, but they should be in status==1.
|
||||
# Currently, we can ignore this, because status==1 is just a shortcut to
|
||||
# avoid making unnecessary queries.
|
||||
}
|
||||
$theirs = TileTree::generate_short_row($cache);
|
||||
if (!$ours)
|
||||
{
|
||||
# Aaah, a new geocache! How nice... ;)
|
||||
|
||||
private static function add_geocache_to_cached_tiles(&$row)
|
||||
{
|
||||
# This one is the most complicated. We need to identify all tiles
|
||||
# where the cache should be present. This include 22 obvious "exact match"
|
||||
# tiles (one per each zoom level), *and* all "just outside the border"
|
||||
# tiles (one geocache can be present in up to 4 tiles per zoom level).
|
||||
# This gives us max. 88 tiles to add the geocache to.
|
||||
self::add_geocache_to_cached_tiles($theirs);
|
||||
}
|
||||
elseif (($ours[1] != $theirs[1]) || ($ours[2] != $theirs[2])) # z21x & z21y fields
|
||||
{
|
||||
# Location changed.
|
||||
|
||||
$tiles_to_update = array();
|
||||
self::remove_geocache_from_cached_tiles($ours[0]);
|
||||
self::add_geocache_to_cached_tiles($theirs);
|
||||
}
|
||||
elseif ($ours != $theirs)
|
||||
{
|
||||
self::update_geocache_attributes_in_cached_tiles($theirs);
|
||||
}
|
||||
else
|
||||
{
|
||||
# No need to update anything. This is very common (i.e. when the
|
||||
# cache was simply found, not actually changed). Replicate module generates
|
||||
# many updates which do not influence our cache.
|
||||
}
|
||||
}
|
||||
|
||||
# We will begin at zoom 21 and then go down to zoom 0.
|
||||
private static function remove_geocache_from_cached_tiles($cache_id)
|
||||
{
|
||||
# Simply remove all traces of this geocache from all tiles.
|
||||
# This includes all references along tiles' borders, etc.
|
||||
|
||||
$z21x = $row[1];
|
||||
$z21y = $row[2];
|
||||
$ex = $z21x >> 8; # initially, z21x / <tile width>
|
||||
$ey = $z21y >> 8; # initially, z21y / <tile height>
|
||||
for ($zoom = 21; $zoom >= 0; $zoom--, $ex >>= 1, $ey >>= 1)
|
||||
{
|
||||
# ($ex, $ey) points to the "exact match" tile. We need to determine
|
||||
# tile-range to check for "just outside the border" tiles. We will
|
||||
# go with the simple approach and check all 1+8 bordering tiles.
|
||||
Db::execute("
|
||||
delete from okapi_tile_caches
|
||||
where cache_id = '".mysql_real_escape_string($cache_id)."'
|
||||
");
|
||||
|
||||
$tiles_in_this_region = array();
|
||||
for ($x=$ex-1; $x<=$ex+1; $x++)
|
||||
for ($y=$ey-1; $y<=$ey+1; $y++)
|
||||
if (($x >= 0) && ($x < 1<<$zoom) && ($y >= 0) && ($y < 1<<$zoom))
|
||||
$tiles_in_this_region[] = array($x, $y);
|
||||
# Note, that after this operation, okapi_tile_status may be out-of-date.
|
||||
# There might exist some rows with status==2, but they should be in status==1.
|
||||
# Currently, we can ignore this, because status==1 is just a shortcut to
|
||||
# avoid making unnecessary queries.
|
||||
}
|
||||
|
||||
foreach ($tiles_in_this_region as $coords)
|
||||
{
|
||||
list($x, $y) = $coords;
|
||||
private static function add_geocache_to_cached_tiles(&$row)
|
||||
{
|
||||
# This one is the most complicated. We need to identify all tiles
|
||||
# where the cache should be present. This include 22 obvious "exact match"
|
||||
# tiles (one per each zoom level), *and* all "just outside the border"
|
||||
# tiles (one geocache can be present in up to 4 tiles per zoom level).
|
||||
# This gives us max. 88 tiles to add the geocache to.
|
||||
|
||||
$scale = 8 + 21 - $zoom;
|
||||
$margin = 1 << ($scale - 3); # 32px of current $zoom level, measured in z21 pixels.
|
||||
$tiles_to_update = array();
|
||||
|
||||
$left_z21x = ($x << $scale) - $margin;
|
||||
$right_z21x = (($x + 1) << $scale) + $margin;
|
||||
$top_z21y = ($y << $scale) - $margin;
|
||||
$bottom_z21y = (($y + 1) << $scale) + $margin;
|
||||
# We will begin at zoom 21 and then go down to zoom 0.
|
||||
|
||||
if ($z21x < $left_z21x)
|
||||
continue;
|
||||
if ($z21x > $right_z21x)
|
||||
continue;
|
||||
if ($z21y < $top_z21y)
|
||||
continue;
|
||||
if ($z21y > $bottom_z21y)
|
||||
continue;
|
||||
$z21x = $row[1];
|
||||
$z21y = $row[2];
|
||||
$ex = $z21x >> 8; # initially, z21x / <tile width>
|
||||
$ey = $z21y >> 8; # initially, z21y / <tile height>
|
||||
for ($zoom = 21; $zoom >= 0; $zoom--, $ex >>= 1, $ey >>= 1)
|
||||
{
|
||||
# ($ex, $ey) points to the "exact match" tile. We need to determine
|
||||
# tile-range to check for "just outside the border" tiles. We will
|
||||
# go with the simple approach and check all 1+8 bordering tiles.
|
||||
|
||||
# We found a match. Store it for later.
|
||||
$tiles_in_this_region = array();
|
||||
for ($x=$ex-1; $x<=$ex+1; $x++)
|
||||
for ($y=$ey-1; $y<=$ey+1; $y++)
|
||||
if (($x >= 0) && ($x < 1<<$zoom) && ($y >= 0) && ($y < 1<<$zoom))
|
||||
$tiles_in_this_region[] = array($x, $y);
|
||||
|
||||
$tiles_to_update[] = array($zoom, $x, $y);
|
||||
}
|
||||
}
|
||||
foreach ($tiles_in_this_region as $coords)
|
||||
{
|
||||
list($x, $y) = $coords;
|
||||
|
||||
# We have a list of all possible tiles that need updating.
|
||||
# Most of these tiles aren't cached at all. We need to update
|
||||
# only the cached ones.
|
||||
$scale = 8 + 21 - $zoom;
|
||||
$margin = 1 << ($scale - 3); # 32px of current $zoom level, measured in z21 pixels.
|
||||
|
||||
$alternatives_escaped = array();
|
||||
foreach ($tiles_to_update as $coords)
|
||||
{
|
||||
list($z, $x, $y) = $coords;
|
||||
$alternatives_escaped[] = "(
|
||||
z = '".mysql_real_escape_string($z)."'
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
)";
|
||||
}
|
||||
if (count($alternatives_escaped) > 0)
|
||||
{
|
||||
Db::execute("
|
||||
replace into okapi_tile_caches (
|
||||
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
|
||||
)
|
||||
select
|
||||
z, x, y,
|
||||
'".mysql_real_escape_string($row[0])."',
|
||||
'".mysql_real_escape_string($row[1])."',
|
||||
'".mysql_real_escape_string($row[2])."',
|
||||
'".mysql_real_escape_string($row[3])."',
|
||||
'".mysql_real_escape_string($row[4])."',
|
||||
".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").",
|
||||
'".mysql_real_escape_string($row[6])."'
|
||||
from okapi_tile_status
|
||||
where
|
||||
(".implode(" or ", $alternatives_escaped).")
|
||||
and status in (1,2)
|
||||
");
|
||||
$left_z21x = ($x << $scale) - $margin;
|
||||
$right_z21x = (($x + 1) << $scale) + $margin;
|
||||
$top_z21y = ($y << $scale) - $margin;
|
||||
$bottom_z21y = (($y + 1) << $scale) + $margin;
|
||||
|
||||
# We might have just filled some empty tiles (status 1) with data.
|
||||
# We need to update their status to 2.
|
||||
if ($z21x < $left_z21x)
|
||||
continue;
|
||||
if ($z21x > $right_z21x)
|
||||
continue;
|
||||
if ($z21y < $top_z21y)
|
||||
continue;
|
||||
if ($z21y > $bottom_z21y)
|
||||
continue;
|
||||
|
||||
Db::execute("
|
||||
update okapi_tile_status
|
||||
set status=2
|
||||
where
|
||||
(".implode(" or ", $alternatives_escaped).")
|
||||
and status=1
|
||||
");
|
||||
}
|
||||
# We found a match. Store it for later.
|
||||
|
||||
# And that's all. That should do the trick.
|
||||
}
|
||||
$tiles_to_update[] = array($zoom, $x, $y);
|
||||
}
|
||||
}
|
||||
|
||||
private static function update_geocache_attributes_in_cached_tiles(&$row)
|
||||
{
|
||||
# Update all attributes (for all levels). Note, that we don't need to
|
||||
# update location ($row[1] and $row[2]) - this method is called ONLY
|
||||
# when location stayed untouched!
|
||||
# We have a list of all possible tiles that need updating.
|
||||
# Most of these tiles aren't cached at all. We need to update
|
||||
# only the cached ones.
|
||||
|
||||
Db::execute("
|
||||
update okapi_tile_caches
|
||||
set
|
||||
status = '".mysql_real_escape_string($row[3])."',
|
||||
type = '".mysql_real_escape_string($row[4])."',
|
||||
rating = ".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").",
|
||||
flags = '".mysql_real_escape_string($row[6])."'
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($row[0])."'
|
||||
");
|
||||
}
|
||||
$alternatives_escaped = array();
|
||||
foreach ($tiles_to_update as $coords)
|
||||
{
|
||||
list($z, $x, $y) = $coords;
|
||||
$alternatives_escaped[] = "(
|
||||
z = '".mysql_real_escape_string($z)."'
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
)";
|
||||
}
|
||||
if (count($alternatives_escaped) > 0)
|
||||
{
|
||||
Db::execute("
|
||||
replace into okapi_tile_caches (
|
||||
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
|
||||
)
|
||||
select
|
||||
z, x, y,
|
||||
'".mysql_real_escape_string($row[0])."',
|
||||
'".mysql_real_escape_string($row[1])."',
|
||||
'".mysql_real_escape_string($row[2])."',
|
||||
'".mysql_real_escape_string($row[3])."',
|
||||
'".mysql_real_escape_string($row[4])."',
|
||||
".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").",
|
||||
'".mysql_real_escape_string($row[6])."'
|
||||
from okapi_tile_status
|
||||
where
|
||||
(".implode(" or ", $alternatives_escaped).")
|
||||
and status in (1,2)
|
||||
");
|
||||
|
||||
private static function handle_geocache_delete($c)
|
||||
{
|
||||
# Simply delete the cache at all zoom levels.
|
||||
# We might have just filled some empty tiles (status 1) with data.
|
||||
# We need to update their status to 2.
|
||||
|
||||
$cache_id = Db::select_value("
|
||||
select cache_id
|
||||
from caches
|
||||
where wp_oc='".mysql_real_escape_string($c['object_key']['code'])."'
|
||||
");
|
||||
self::remove_geocache_from_cached_tiles($cache_id);
|
||||
}
|
||||
Db::execute("
|
||||
update okapi_tile_status
|
||||
set status=2
|
||||
where
|
||||
(".implode(" or ", $alternatives_escaped).")
|
||||
and status=1
|
||||
");
|
||||
}
|
||||
|
||||
# And that's all. That should do the trick.
|
||||
}
|
||||
|
||||
private static function update_geocache_attributes_in_cached_tiles(&$row)
|
||||
{
|
||||
# Update all attributes (for all levels). Note, that we don't need to
|
||||
# update location ($row[1] and $row[2]) - this method is called ONLY
|
||||
# when location stayed untouched!
|
||||
|
||||
Db::execute("
|
||||
update okapi_tile_caches
|
||||
set
|
||||
status = '".mysql_real_escape_string($row[3])."',
|
||||
type = '".mysql_real_escape_string($row[4])."',
|
||||
rating = ".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").",
|
||||
flags = '".mysql_real_escape_string($row[6])."'
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($row[0])."'
|
||||
");
|
||||
}
|
||||
|
||||
private static function handle_geocache_delete($c)
|
||||
{
|
||||
# Simply delete the cache at all zoom levels.
|
||||
|
||||
$cache_id = Db::select_value("
|
||||
select cache_id
|
||||
from caches
|
||||
where wp_oc='".mysql_real_escape_string($c['object_key']['code'])."'
|
||||
");
|
||||
self::remove_geocache_from_cached_tiles($cache_id);
|
||||
}
|
||||
}
|
||||
@@ -29,200 +29,200 @@ require_once($GLOBALS['rootpath']."okapi/services/caches/search/searching.inc.ph
|
||||
|
||||
class WebService
|
||||
{
|
||||
/**
|
||||
* Should be always true. You may temporarily set it to false, when you're
|
||||
* testing/debugging the tile renderer.
|
||||
*/
|
||||
private static $USE_ETAGS_CACHE = true;
|
||||
/**
|
||||
* Should be always true. You may temporarily set it to false, when you're
|
||||
* testing/debugging the tile renderer.
|
||||
*/
|
||||
private static $USE_ETAGS_CACHE = true;
|
||||
|
||||
/**
|
||||
* Should be always true. You may temporarily set it to false, when you're
|
||||
* testing/debugging the tile renderer.
|
||||
*/
|
||||
private static $USE_IMAGE_CACHE = true;
|
||||
/**
|
||||
* Should be always true. You may temporarily set it to false, when you're
|
||||
* testing/debugging the tile renderer.
|
||||
*/
|
||||
private static $USE_IMAGE_CACHE = true;
|
||||
|
||||
/**
|
||||
* Should be always true. You may temporarily set it to false, when you're
|
||||
* testing/debugging. Grep the code to check when this flag is used.
|
||||
*/
|
||||
private static $USE_OTHER_CACHE = true;
|
||||
/**
|
||||
* Should be always true. You may temporarily set it to false, when you're
|
||||
* testing/debugging. Grep the code to check when this flag is used.
|
||||
*/
|
||||
private static $USE_OTHER_CACHE = true;
|
||||
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 3
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 3
|
||||
);
|
||||
}
|
||||
|
||||
private static function require_uint($request, $name, $min_value = 0)
|
||||
{
|
||||
$val = $request->get_parameter($name);
|
||||
if ($val === null)
|
||||
throw new ParamMissing($name);
|
||||
$ret = intval($val);
|
||||
if ($ret < 0 || ("$ret" !== $val))
|
||||
throw new InvalidParam($name, "Expecting non-negative integer.");
|
||||
return $ret;
|
||||
}
|
||||
private static function require_uint($request, $name, $min_value = 0)
|
||||
{
|
||||
$val = $request->get_parameter($name);
|
||||
if ($val === null)
|
||||
throw new ParamMissing($name);
|
||||
$ret = intval($val);
|
||||
if ($ret < 0 || ("$ret" !== $val))
|
||||
throw new InvalidParam($name, "Expecting non-negative integer.");
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$checkpointA_started = microtime(true);
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$checkpointA_started = microtime(true);
|
||||
|
||||
# Make sure the request is internal.
|
||||
# Make sure the request is internal.
|
||||
|
||||
if (!in_array($request->consumer->key, array('internal', 'facade')))
|
||||
throw new BadRequest("Your Consumer Key has not been allowed to access this method.");
|
||||
if (!in_array($request->consumer->key, array('internal', 'facade')))
|
||||
throw new BadRequest("Your Consumer Key has not been allowed to access this method.");
|
||||
|
||||
# zoom, x, y - required tile-specific parameters.
|
||||
# zoom, x, y - required tile-specific parameters.
|
||||
|
||||
$zoom = self::require_uint($request, 'z');
|
||||
if ($zoom > 21)
|
||||
throw new InvalidParam('z', "Maximum value for this parameter is 21.");
|
||||
$x = self::require_uint($request, 'x');
|
||||
$y = self::require_uint($request, 'y');
|
||||
if ($x >= 1<<$zoom)
|
||||
throw new InvalidParam('x', "Should be in 0..".((1<<$zoom) - 1).".");
|
||||
if ($y >= 1<<$zoom)
|
||||
throw new InvalidParam('y', "Should be in 0..".((1<<$zoom) - 1).".");
|
||||
$zoom = self::require_uint($request, 'z');
|
||||
if ($zoom > 21)
|
||||
throw new InvalidParam('z', "Maximum value for this parameter is 21.");
|
||||
$x = self::require_uint($request, 'x');
|
||||
$y = self::require_uint($request, 'y');
|
||||
if ($x >= 1<<$zoom)
|
||||
throw new InvalidParam('x', "Should be in 0..".((1<<$zoom) - 1).".");
|
||||
if ($y >= 1<<$zoom)
|
||||
throw new InvalidParam('y', "Should be in 0..".((1<<$zoom) - 1).".");
|
||||
|
||||
# Now, we will create a search set (or use one previously created).
|
||||
# Instead of creating a new OkapiInternalRequest object, we will pass
|
||||
# the current request directly. We can do that, because we inherit all
|
||||
# of the "save" method's parameters.
|
||||
# Now, we will create a search set (or use one previously created).
|
||||
# Instead of creating a new OkapiInternalRequest object, we will pass
|
||||
# the current request directly. We can do that, because we inherit all
|
||||
# of the "save" method's parameters.
|
||||
|
||||
$search_set = OkapiServiceRunner::call('services/caches/search/save', $request);
|
||||
$set_id = $search_set['set_id'];
|
||||
$search_set = OkapiServiceRunner::call('services/caches/search/save', $request);
|
||||
$set_id = $search_set['set_id'];
|
||||
|
||||
# Get caches which are present in the result set AND within the tile
|
||||
# (+ those around the borders).
|
||||
# Get caches which are present in the result set AND within the tile
|
||||
# (+ those around the borders).
|
||||
|
||||
$rs = TileTree::query_fast($zoom, $x, $y, $set_id);
|
||||
$rows = array();
|
||||
if ($rs !== null)
|
||||
{
|
||||
while ($row = mysql_fetch_row($rs))
|
||||
$rows[] = $row;
|
||||
unset($row);
|
||||
}
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointA", null,
|
||||
microtime(true) - $checkpointA_started);
|
||||
$checkpointB_started = microtime(true);
|
||||
$rs = TileTree::query_fast($zoom, $x, $y, $set_id);
|
||||
$rows = array();
|
||||
if ($rs !== null)
|
||||
{
|
||||
while ($row = mysql_fetch_row($rs))
|
||||
$rows[] = $row;
|
||||
unset($row);
|
||||
}
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointA", null,
|
||||
microtime(true) - $checkpointA_started);
|
||||
$checkpointB_started = microtime(true);
|
||||
|
||||
# Add dynamic, user-related flags.
|
||||
# Add dynamic, user-related flags.
|
||||
|
||||
if (count($rows) > 0)
|
||||
{
|
||||
# Load user-related cache ids.
|
||||
if (count($rows) > 0)
|
||||
{
|
||||
# Load user-related cache ids.
|
||||
|
||||
$cache_key = "tileuser/".$request->token->user_id;
|
||||
$user = self::$USE_OTHER_CACHE ? Cache::get($cache_key) : null;
|
||||
if ($user === null)
|
||||
{
|
||||
$user = array();
|
||||
$cache_key = "tileuser/".$request->token->user_id;
|
||||
$user = self::$USE_OTHER_CACHE ? Cache::get($cache_key) : null;
|
||||
if ($user === null)
|
||||
{
|
||||
$user = array();
|
||||
|
||||
# Ignored caches.
|
||||
# Ignored caches.
|
||||
|
||||
$rs = Db::query("
|
||||
select cache_id
|
||||
from cache_ignore
|
||||
where user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
");
|
||||
$user['ignored'] = array();
|
||||
while (list($cache_id) = mysql_fetch_row($rs))
|
||||
$user['ignored'][$cache_id] = true;
|
||||
$rs = Db::query("
|
||||
select cache_id
|
||||
from cache_ignore
|
||||
where user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
");
|
||||
$user['ignored'] = array();
|
||||
while (list($cache_id) = mysql_fetch_row($rs))
|
||||
$user['ignored'][$cache_id] = true;
|
||||
|
||||
# Found caches.
|
||||
# Found caches.
|
||||
|
||||
$rs = Db::query("
|
||||
select distinct cache_id
|
||||
from cache_logs
|
||||
where
|
||||
user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
and type = 1
|
||||
and ".((Settings::get('OC_BRANCH') == 'oc.pl') ? "deleted = 0" : "true")."
|
||||
");
|
||||
$user['found'] = array();
|
||||
while (list($cache_id) = mysql_fetch_row($rs))
|
||||
$user['found'][$cache_id] = true;
|
||||
$rs = Db::query("
|
||||
select distinct cache_id
|
||||
from cache_logs
|
||||
where
|
||||
user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
and type = 1
|
||||
and ".((Settings::get('OC_BRANCH') == 'oc.pl') ? "deleted = 0" : "true")."
|
||||
");
|
||||
$user['found'] = array();
|
||||
while (list($cache_id) = mysql_fetch_row($rs))
|
||||
$user['found'][$cache_id] = true;
|
||||
|
||||
# Own caches.
|
||||
# Own caches.
|
||||
|
||||
$rs = Db::query("
|
||||
select distinct cache_id
|
||||
from caches
|
||||
where user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
");
|
||||
$user['own'] = array();
|
||||
while (list($cache_id) = mysql_fetch_row($rs))
|
||||
$user['own'][$cache_id] = true;
|
||||
$rs = Db::query("
|
||||
select distinct cache_id
|
||||
from caches
|
||||
where user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
");
|
||||
$user['own'] = array();
|
||||
while (list($cache_id) = mysql_fetch_row($rs))
|
||||
$user['own'][$cache_id] = true;
|
||||
|
||||
Cache::set($cache_key, $user, 30);
|
||||
}
|
||||
Cache::set($cache_key, $user, 30);
|
||||
}
|
||||
|
||||
# Add extra flags to geocaches.
|
||||
# Add extra flags to geocaches.
|
||||
|
||||
foreach ($rows as &$row_ref)
|
||||
{
|
||||
# Add the "found" flag (to indicate that this cache needs
|
||||
# to be drawn as found) and the "own" flag (to indicate that
|
||||
# the current user is the owner).
|
||||
foreach ($rows as &$row_ref)
|
||||
{
|
||||
# Add the "found" flag (to indicate that this cache needs
|
||||
# to be drawn as found) and the "own" flag (to indicate that
|
||||
# the current user is the owner).
|
||||
|
||||
if (isset($user['found'][$row_ref[0]]))
|
||||
$row_ref[6] |= TileTree::$FLAG_FOUND; # $row[6] is "flags"
|
||||
if (isset($user['own'][$row_ref[0]]))
|
||||
$row_ref[6] |= TileTree::$FLAG_OWN; # $row[6] is "flags"
|
||||
}
|
||||
}
|
||||
if (isset($user['found'][$row_ref[0]]))
|
||||
$row_ref[6] |= TileTree::$FLAG_FOUND; # $row[6] is "flags"
|
||||
if (isset($user['own'][$row_ref[0]]))
|
||||
$row_ref[6] |= TileTree::$FLAG_OWN; # $row[6] is "flags"
|
||||
}
|
||||
}
|
||||
|
||||
# Compute the image hash/fingerprint. This will be used both for ETags
|
||||
# and internal cache ($cache_key).
|
||||
# Compute the image hash/fingerprint. This will be used both for ETags
|
||||
# and internal cache ($cache_key).
|
||||
|
||||
$tile = new DefaultTileRenderer($zoom, $rows);
|
||||
$image_fingerprint = $tile->get_unique_hash();
|
||||
$tile = new DefaultTileRenderer($zoom, $rows);
|
||||
$image_fingerprint = $tile->get_unique_hash();
|
||||
|
||||
# Start creating response.
|
||||
# Start creating response.
|
||||
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = $tile->get_content_type();
|
||||
$response->cache_control = "Cache-Control: private, max-age=600";
|
||||
$response->etag = 'W/"'.$image_fingerprint.'"';
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = $tile->get_content_type();
|
||||
$response->cache_control = "Cache-Control: private, max-age=600";
|
||||
$response->etag = 'W/"'.$image_fingerprint.'"';
|
||||
|
||||
# Check if the request didn't include the same ETag.
|
||||
# Check if the request didn't include the same ETag.
|
||||
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointB", null,
|
||||
microtime(true) - $checkpointB_started);
|
||||
$checkpointC_started = microtime(true);
|
||||
if (self::$USE_ETAGS_CACHE && ($request->etag == $response->etag))
|
||||
{
|
||||
# Hit. Report the content was unmodified.
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointB", null,
|
||||
microtime(true) - $checkpointB_started);
|
||||
$checkpointC_started = microtime(true);
|
||||
if (self::$USE_ETAGS_CACHE && ($request->etag == $response->etag))
|
||||
{
|
||||
# Hit. Report the content was unmodified.
|
||||
|
||||
$response->etag = null;
|
||||
$response->status = "304 Not Modified";
|
||||
return $response;
|
||||
}
|
||||
$response->etag = null;
|
||||
$response->status = "304 Not Modified";
|
||||
return $response;
|
||||
}
|
||||
|
||||
# Check if the image was recently rendered and is kept in image cache.
|
||||
# Check if the image was recently rendered and is kept in image cache.
|
||||
|
||||
$cache_key = "tile/".$image_fingerprint;
|
||||
$response->body = self::$USE_IMAGE_CACHE ? Cache::get($cache_key) : null;
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointC", null,
|
||||
microtime(true) - $checkpointC_started);
|
||||
$checkpointD_started = microtime(true);
|
||||
if ($response->body !== null)
|
||||
{
|
||||
# Hit. We will use the cached version of the image.
|
||||
$cache_key = "tile/".$image_fingerprint;
|
||||
$response->body = self::$USE_IMAGE_CACHE ? Cache::get($cache_key) : null;
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointC", null,
|
||||
microtime(true) - $checkpointC_started);
|
||||
$checkpointD_started = microtime(true);
|
||||
if ($response->body !== null)
|
||||
{
|
||||
# Hit. We will use the cached version of the image.
|
||||
|
||||
return $response;
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
# Miss. Render the image. Cache the result.
|
||||
# Miss. Render the image. Cache the result.
|
||||
|
||||
$response->body = $tile->render();
|
||||
Cache::set_scored($cache_key, $response->body);
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointD", null,
|
||||
microtime(true) - $checkpointD_started);
|
||||
$response->body = $tile->render();
|
||||
Cache::set_scored($cache_key, $response->body);
|
||||
OkapiServiceRunner::save_stats_extra("caches/map/tile/checkpointD", null,
|
||||
microtime(true) - $checkpointD_started);
|
||||
|
||||
return $response;
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<xml>
|
||||
<brief>Get cache map tile</brief>
|
||||
<issue-id>150</issue-id>
|
||||
<desc>
|
||||
<p><b>CLOSED BETA</b> version. Due to long-term performance tests, currently
|
||||
this method is not publicly accessible. Let us know if you're interested
|
||||
in using it.</p>
|
||||
<p>Use this method to retrieve a tile-map of all caches included in your search
|
||||
result.</p>
|
||||
</desc>
|
||||
<req name='z'>Zoom level (0..21).</req>
|
||||
<req name='x'>Tile number on the X axis.</req>
|
||||
<req name='y'>Tile number on the Y axis.</req>
|
||||
<import-params method="services/caches/search/save"/>
|
||||
<returns>
|
||||
The PNG image with the requested map tile.
|
||||
</returns>
|
||||
<brief>Get cache map tile</brief>
|
||||
<issue-id>150</issue-id>
|
||||
<desc>
|
||||
<p><b>CLOSED BETA</b> version. Due to long-term performance tests, currently
|
||||
this method is not publicly accessible. Let us know if you're interested
|
||||
in using it.</p>
|
||||
<p>Use this method to retrieve a tile-map of all caches included in your search
|
||||
result.</p>
|
||||
</desc>
|
||||
<req name='z'>Zoom level (0..21).</req>
|
||||
<req name='x'>Tile number on the X axis.</req>
|
||||
<req name='y'>Tile number on the Y axis.</req>
|
||||
<import-params method="services/caches/search/save"/>
|
||||
<returns>
|
||||
The PNG image with the requested map tile.
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -21,274 +21,283 @@ use okapi\OkapiLock;
|
||||
|
||||
class TileTree
|
||||
{
|
||||
# Static flags (stored in the database).
|
||||
public static $FLAG_STAR = 0x01;
|
||||
public static $FLAG_HAS_TRACKABLES = 0x02;
|
||||
public static $FLAG_NOT_YET_FOUND = 0x04;
|
||||
# Static flags (stored in the database).
|
||||
public static $FLAG_STAR = 0x01;
|
||||
public static $FLAG_HAS_TRACKABLES = 0x02;
|
||||
public static $FLAG_NOT_YET_FOUND = 0x04;
|
||||
|
||||
# Dynamic flags (added at runtime).
|
||||
public static $FLAG_FOUND = 0x0100;
|
||||
public static $FLAG_OWN = 0x0200;
|
||||
public static $FLAG_NEW = 0x0400;
|
||||
public static $FLAG_DRAW_CAPTION = 0x0800;
|
||||
# Dynamic flags (added at runtime).
|
||||
public static $FLAG_FOUND = 0x0100;
|
||||
public static $FLAG_OWN = 0x0200;
|
||||
public static $FLAG_NEW = 0x0400;
|
||||
public static $FLAG_DRAW_CAPTION = 0x0800;
|
||||
|
||||
/**
|
||||
* Return null if not computed, 1 if computed and empty, 2 if computed and not empty.
|
||||
*/
|
||||
public static function get_tile_status($zoom, $x, $y)
|
||||
{
|
||||
return Db::select_value("
|
||||
select status
|
||||
from okapi_tile_status
|
||||
where
|
||||
z = '".mysql_real_escape_string($zoom)."'
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
");
|
||||
}
|
||||
/**
|
||||
* Return null if not computed, 1 if computed and empty, 2 if computed and not empty.
|
||||
*/
|
||||
public static function get_tile_status($zoom, $x, $y)
|
||||
{
|
||||
return Db::select_value("
|
||||
select status
|
||||
from okapi_tile_status
|
||||
where
|
||||
z = '".mysql_real_escape_string($zoom)."'
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return MySQL's result set iterator over all caches which are present
|
||||
* in the given result set AND in the given tile.
|
||||
*
|
||||
* Each row is an array of the following format:
|
||||
* list(cache_id, $pixel_x, $pixel_y, status, type, rating, flags, count).
|
||||
*
|
||||
* Note that $pixels can also be negative or >=256 (up to a margin of 32px).
|
||||
* Count is the number of other caches "eclipsed" by this geocache (such
|
||||
* eclipsed geocaches are not included in the result).
|
||||
*/
|
||||
public static function query_fast($zoom, $x, $y, $set_id)
|
||||
{
|
||||
# First, we check if the cache-set for this tile was already computed
|
||||
# (and if it was, was it empty).
|
||||
/**
|
||||
* Return MySQL's result set iterator over all caches which are present
|
||||
* in the given result set AND in the given tile.
|
||||
*
|
||||
* Each row is an array of the following format:
|
||||
* list(cache_id, $pixel_x, $pixel_y, status, type, rating, flags, count).
|
||||
*
|
||||
* Note that $pixels can also be negative or >=256 (up to a margin of 32px).
|
||||
* Count is the number of other caches "eclipsed" by this geocache (such
|
||||
* eclipsed geocaches are not included in the result).
|
||||
*/
|
||||
public static function query_fast($zoom, $x, $y, $set_id)
|
||||
{
|
||||
# First, we check if the cache-set for this tile was already computed
|
||||
# (and if it was, was it empty).
|
||||
|
||||
$status = self::get_tile_status($zoom, $x, $y);
|
||||
if ($status === null) # Not yet computed.
|
||||
{
|
||||
# Note, that computing the tile does not involve taking any
|
||||
# search parameters.
|
||||
$status = self::get_tile_status($zoom, $x, $y);
|
||||
if ($status === null) # Not yet computed.
|
||||
{
|
||||
# Note, that computing the tile does not involve taking any
|
||||
# search parameters.
|
||||
|
||||
$status = self::compute_tile($zoom, $x, $y);
|
||||
}
|
||||
$status = self::compute_tile($zoom, $x, $y);
|
||||
}
|
||||
|
||||
if ($status === 1) # Computed and empty.
|
||||
{
|
||||
# This tile was already computed and it is empty.
|
||||
return null;
|
||||
}
|
||||
if ($status === 1) # Computed and empty.
|
||||
{
|
||||
# This tile was already computed and it is empty.
|
||||
return null;
|
||||
}
|
||||
|
||||
# If we got here, then the tile is computed and not empty (status 2).
|
||||
# If we got here, then the tile is computed and not empty (status 2).
|
||||
|
||||
$tile_upper_x = $x << 8;
|
||||
$tile_leftmost_y = $y << 8;
|
||||
$tile_upper_x = $x << 8;
|
||||
$tile_leftmost_y = $y << 8;
|
||||
|
||||
$zoom_escaped = "'".mysql_real_escape_string($zoom)."'";
|
||||
$tile_upper_x_escaped = "'".mysql_real_escape_string($tile_upper_x)."'";
|
||||
$tile_leftmost_y_escaped = "'".mysql_real_escape_string($tile_leftmost_y)."'";
|
||||
return Db::query("
|
||||
select
|
||||
otc.cache_id,
|
||||
cast(otc.z21x >> (21 - $zoom_escaped) as signed) - $tile_upper_x_escaped as px,
|
||||
cast(otc.z21y >> (21 - $zoom_escaped) as signed) - $tile_leftmost_y_escaped as py,
|
||||
otc.status, otc.type, otc.rating, otc.flags, count(*)
|
||||
from
|
||||
okapi_tile_caches otc,
|
||||
okapi_search_results osr
|
||||
where
|
||||
z = $zoom_escaped
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
and otc.cache_id = osr.cache_id
|
||||
and osr.set_id = '".mysql_real_escape_string($set_id)."'
|
||||
group by
|
||||
z21x >> (3 + (21 - $zoom_escaped)),
|
||||
z21y >> (3 + (21 - $zoom_escaped))
|
||||
order by
|
||||
z21y >> (3 + (21 - $zoom_escaped)),
|
||||
z21x >> (3 + (21 - $zoom_escaped))
|
||||
");
|
||||
}
|
||||
$zoom_escaped = "'".mysql_real_escape_string($zoom)."'";
|
||||
$tile_upper_x_escaped = "'".mysql_real_escape_string($tile_upper_x)."'";
|
||||
$tile_leftmost_y_escaped = "'".mysql_real_escape_string($tile_leftmost_y)."'";
|
||||
return Db::query("
|
||||
select
|
||||
otc.cache_id,
|
||||
cast(otc.z21x >> (21 - $zoom_escaped) as signed) - $tile_upper_x_escaped as px,
|
||||
cast(otc.z21y >> (21 - $zoom_escaped) as signed) - $tile_leftmost_y_escaped as py,
|
||||
otc.status, otc.type, otc.rating, otc.flags, count(*)
|
||||
from
|
||||
okapi_tile_caches otc,
|
||||
okapi_search_results osr
|
||||
where
|
||||
z = $zoom_escaped
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
and otc.cache_id = osr.cache_id
|
||||
and osr.set_id = '".mysql_real_escape_string($set_id)."'
|
||||
group by
|
||||
z21x >> (3 + (21 - $zoom_escaped)),
|
||||
z21y >> (3 + (21 - $zoom_escaped))
|
||||
order by
|
||||
z21y >> (3 + (21 - $zoom_escaped)),
|
||||
z21x >> (3 + (21 - $zoom_escaped))
|
||||
");
|
||||
}
|
||||
|
||||
/**
|
||||
* Precache the ($zoom, $x, $y) slot in the okapi_tile_caches table.
|
||||
*/
|
||||
public static function compute_tile($zoom, $x, $y)
|
||||
{
|
||||
$time_started = microtime(true);
|
||||
/**
|
||||
* Precache the ($zoom, $x, $y) slot in the okapi_tile_caches table.
|
||||
*/
|
||||
public static function compute_tile($zoom, $x, $y)
|
||||
{
|
||||
$time_started = microtime(true);
|
||||
|
||||
# Note, that multiple threads may try to compute tiles simulatanously.
|
||||
# For low-level tiles, this can be expensive. WRTODO: Think of some
|
||||
# appropriate locks.
|
||||
# Note, that multiple threads may try to compute tiles simulatanously.
|
||||
# For low-level tiles, this can be expensive. WRTODO: Think of some
|
||||
# appropriate locks.
|
||||
|
||||
$status = self::get_tile_status($zoom, $x, $y);
|
||||
if ($status !== null)
|
||||
return $status;
|
||||
$status = self::get_tile_status($zoom, $x, $y);
|
||||
if ($status !== null)
|
||||
return $status;
|
||||
|
||||
if ($zoom === 0)
|
||||
{
|
||||
# When computing zoom zero, we don't have a parent to speed up
|
||||
# the computation. We need to use the caches table. Note, that
|
||||
# zoom level 0 contains *entire world*, so we don't have to use
|
||||
# any WHERE condition in the following query.
|
||||
if ($zoom === 0)
|
||||
{
|
||||
# When computing zoom zero, we don't have a parent to speed up
|
||||
# the computation. We need to use the caches table. Note, that
|
||||
# zoom level 0 contains *entire world*, so we don't have to use
|
||||
# any WHERE condition in the following query.
|
||||
|
||||
# This can be done a little faster (without the use of internal requests),
|
||||
# but there is *no need* to - this query is run seldom and is cached.
|
||||
# This can be done a little faster (without the use of internal requests),
|
||||
# but there is *no need* to - this query is run seldom and is cached.
|
||||
|
||||
$params = array();
|
||||
$params['status'] = "Available|Temporarily unavailable|Archived"; # we want them all
|
||||
$params['limit'] = "10000000"; # no limit
|
||||
$params = array();
|
||||
$params['status'] = "Available|Temporarily unavailable|Archived"; # we want them all
|
||||
$params['limit'] = "10000000"; # no limit
|
||||
|
||||
$internal_request = new OkapiInternalRequest(new OkapiInternalConsumer(), null, $params);
|
||||
$internal_request->skip_limits = true;
|
||||
$response = OkapiServiceRunner::call("services/caches/search/all", $internal_request);
|
||||
$cache_codes = $response['results'];
|
||||
$internal_request = new OkapiInternalRequest(new OkapiInternalConsumer(), null, $params);
|
||||
$internal_request->skip_limits = true;
|
||||
$response = OkapiServiceRunner::call("services/caches/search/all", $internal_request);
|
||||
$cache_codes = $response['results'];
|
||||
|
||||
$internal_request = new OkapiInternalRequest(new OkapiInternalConsumer(), null, array(
|
||||
'cache_codes' => implode('|', $cache_codes),
|
||||
'fields' => 'internal_id|code|name|location|type|status|rating|recommendations|founds|trackables_count'
|
||||
));
|
||||
$internal_request->skip_limits = true;
|
||||
$caches = OkapiServiceRunner::call("services/caches/geocaches", $internal_request);
|
||||
$internal_request = new OkapiInternalRequest(new OkapiInternalConsumer(), null, array(
|
||||
'cache_codes' => implode('|', $cache_codes),
|
||||
'fields' => 'internal_id|code|name|location|type|status|rating|recommendations|founds|trackables_count'
|
||||
));
|
||||
$internal_request->skip_limits = true;
|
||||
$caches = OkapiServiceRunner::call("services/caches/geocaches", $internal_request);
|
||||
|
||||
foreach ($caches as $cache)
|
||||
{
|
||||
$row = self::generate_short_row($cache);
|
||||
Db::execute("
|
||||
replace into okapi_tile_caches (
|
||||
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
|
||||
) values (
|
||||
0, 0, 0,
|
||||
'".mysql_real_escape_string($row[0])."',
|
||||
'".mysql_real_escape_string($row[1])."',
|
||||
'".mysql_real_escape_string($row[2])."',
|
||||
'".mysql_real_escape_string($row[3])."',
|
||||
'".mysql_real_escape_string($row[4])."',
|
||||
".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").",
|
||||
'".mysql_real_escape_string($row[6])."'
|
||||
);
|
||||
");
|
||||
}
|
||||
$status = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
# We will use the parent tile to compute the contents of this tile.
|
||||
foreach ($caches as $cache)
|
||||
{
|
||||
$row = self::generate_short_row($cache);
|
||||
if (!$row) {
|
||||
/* Some caches cannot be included, e.g. the ones near the poles. */
|
||||
continue;
|
||||
}
|
||||
Db::execute("
|
||||
replace into okapi_tile_caches (
|
||||
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
|
||||
) values (
|
||||
0, 0, 0,
|
||||
'".mysql_real_escape_string($row[0])."',
|
||||
'".mysql_real_escape_string($row[1])."',
|
||||
'".mysql_real_escape_string($row[2])."',
|
||||
'".mysql_real_escape_string($row[3])."',
|
||||
'".mysql_real_escape_string($row[4])."',
|
||||
".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").",
|
||||
'".mysql_real_escape_string($row[6])."'
|
||||
);
|
||||
");
|
||||
}
|
||||
$status = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
# We will use the parent tile to compute the contents of this tile.
|
||||
|
||||
$parent_zoom = $zoom - 1;
|
||||
$parent_x = $x >> 1;
|
||||
$parent_y = $y >> 1;
|
||||
$parent_zoom = $zoom - 1;
|
||||
$parent_x = $x >> 1;
|
||||
$parent_y = $y >> 1;
|
||||
|
||||
$status = self::get_tile_status($parent_zoom, $parent_x, $parent_y);
|
||||
if ($status === null) # Not computed.
|
||||
{
|
||||
$time_started = microtime(true);
|
||||
$status = self::compute_tile($parent_zoom, $parent_x, $parent_y);
|
||||
}
|
||||
$status = self::get_tile_status($parent_zoom, $parent_x, $parent_y);
|
||||
if ($status === null) # Not computed.
|
||||
{
|
||||
$time_started = microtime(true);
|
||||
$status = self::compute_tile($parent_zoom, $parent_x, $parent_y);
|
||||
}
|
||||
|
||||
if ($status === 1) # Computed and empty.
|
||||
{
|
||||
# No need to check.
|
||||
}
|
||||
else # Computed, not empty.
|
||||
{
|
||||
$scale = 8 + 21 - $zoom;
|
||||
$parentcenter_z21x = (($parent_x << 1) | 1) << $scale;
|
||||
$parentcenter_z21y = (($parent_y << 1) | 1) << $scale;
|
||||
$margin = 1 << ($scale - 2);
|
||||
$left_z21x = (($parent_x << 1) << $scale) - $margin;
|
||||
$right_z21x = ((($parent_x + 1) << 1) << $scale) + $margin;
|
||||
$top_z21y = (($parent_y << 1) << $scale) - $margin;
|
||||
$bottom_z21y = ((($parent_y + 1) << 1) << $scale) + $margin;
|
||||
if ($status === 1) # Computed and empty.
|
||||
{
|
||||
# No need to check.
|
||||
}
|
||||
else # Computed, not empty.
|
||||
{
|
||||
$scale = 8 + 21 - $zoom;
|
||||
$parentcenter_z21x = (($parent_x << 1) | 1) << $scale;
|
||||
$parentcenter_z21y = (($parent_y << 1) | 1) << $scale;
|
||||
$margin = 1 << ($scale - 2);
|
||||
$left_z21x = (($parent_x << 1) << $scale) - $margin;
|
||||
$right_z21x = ((($parent_x + 1) << 1) << $scale) + $margin;
|
||||
$top_z21y = (($parent_y << 1) << $scale) - $margin;
|
||||
$bottom_z21y = ((($parent_y + 1) << 1) << $scale) + $margin;
|
||||
|
||||
# Choose the right quarter.
|
||||
# |1 2|
|
||||
# |3 4|
|
||||
# Choose the right quarter.
|
||||
# |1 2|
|
||||
# |3 4|
|
||||
|
||||
if ($x & 1) # 2 or 4
|
||||
$left_z21x = $parentcenter_z21x - $margin;
|
||||
else # 1 or 3
|
||||
$right_z21x = $parentcenter_z21x + $margin;
|
||||
if ($y & 1) # 3 or 4
|
||||
$top_z21y = $parentcenter_z21y - $margin;
|
||||
else # 1 or 2
|
||||
$bottom_z21y = $parentcenter_z21y + $margin;
|
||||
if ($x & 1) # 2 or 4
|
||||
$left_z21x = $parentcenter_z21x - $margin;
|
||||
else # 1 or 3
|
||||
$right_z21x = $parentcenter_z21x + $margin;
|
||||
if ($y & 1) # 3 or 4
|
||||
$top_z21y = $parentcenter_z21y - $margin;
|
||||
else # 1 or 2
|
||||
$bottom_z21y = $parentcenter_z21y + $margin;
|
||||
|
||||
# Cache the result.
|
||||
# Cache the result.
|
||||
|
||||
Db::execute("
|
||||
replace into okapi_tile_caches (
|
||||
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
|
||||
)
|
||||
select
|
||||
'".mysql_real_escape_string($zoom)."',
|
||||
'".mysql_real_escape_string($x)."',
|
||||
'".mysql_real_escape_string($y)."',
|
||||
cache_id, z21x, z21y, status, type, rating, flags
|
||||
from okapi_tile_caches
|
||||
where
|
||||
z = '".mysql_real_escape_string($parent_zoom)."'
|
||||
and x = '".mysql_real_escape_string($parent_x)."'
|
||||
and y = '".mysql_real_escape_string($parent_y)."'
|
||||
and z21x between $left_z21x and $right_z21x
|
||||
and z21y between $top_z21y and $bottom_z21y
|
||||
");
|
||||
$test = Db::select_value("
|
||||
select 1
|
||||
from okapi_tile_caches
|
||||
where
|
||||
z = '".mysql_real_escape_string($zoom)."'
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
limit 1;
|
||||
");
|
||||
if ($test)
|
||||
$status = 2;
|
||||
else
|
||||
$status = 1;
|
||||
}
|
||||
}
|
||||
Db::execute("
|
||||
replace into okapi_tile_caches (
|
||||
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
|
||||
)
|
||||
select
|
||||
'".mysql_real_escape_string($zoom)."',
|
||||
'".mysql_real_escape_string($x)."',
|
||||
'".mysql_real_escape_string($y)."',
|
||||
cache_id, z21x, z21y, status, type, rating, flags
|
||||
from okapi_tile_caches
|
||||
where
|
||||
z = '".mysql_real_escape_string($parent_zoom)."'
|
||||
and x = '".mysql_real_escape_string($parent_x)."'
|
||||
and y = '".mysql_real_escape_string($parent_y)."'
|
||||
and z21x between $left_z21x and $right_z21x
|
||||
and z21y between $top_z21y and $bottom_z21y
|
||||
");
|
||||
$test = Db::select_value("
|
||||
select 1
|
||||
from okapi_tile_caches
|
||||
where
|
||||
z = '".mysql_real_escape_string($zoom)."'
|
||||
and x = '".mysql_real_escape_string($x)."'
|
||||
and y = '".mysql_real_escape_string($y)."'
|
||||
limit 1;
|
||||
");
|
||||
if ($test)
|
||||
$status = 2;
|
||||
else
|
||||
$status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Mark tile as computed.
|
||||
# Mark tile as computed.
|
||||
|
||||
Db::execute("
|
||||
replace into okapi_tile_status (z, x, y, status)
|
||||
values (
|
||||
'".mysql_real_escape_string($zoom)."',
|
||||
'".mysql_real_escape_string($x)."',
|
||||
'".mysql_real_escape_string($y)."',
|
||||
'".mysql_real_escape_string($status)."'
|
||||
);
|
||||
");
|
||||
Db::execute("
|
||||
replace into okapi_tile_status (z, x, y, status)
|
||||
values (
|
||||
'".mysql_real_escape_string($zoom)."',
|
||||
'".mysql_real_escape_string($x)."',
|
||||
'".mysql_real_escape_string($y)."',
|
||||
'".mysql_real_escape_string($status)."'
|
||||
);
|
||||
");
|
||||
|
||||
return $status;
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert OKAPI's cache object to a short database row to be inserted
|
||||
* into okapi_tile_caches table. Returns the list of the following attributes:
|
||||
* cache_id, z21x, z21y, status, type, rating, flags (rating might be null!).
|
||||
*/
|
||||
public static function generate_short_row($cache)
|
||||
{
|
||||
list($lat, $lon) = explode("|", $cache['location']);
|
||||
list($z21x, $z21y) = self::latlon_to_z21xy($lat, $lon);
|
||||
$flags = 0;
|
||||
if (($cache['founds'] > 6) && (($cache['recommendations'] / $cache['founds']) > 0.3))
|
||||
$flags |= self::$FLAG_STAR;
|
||||
if ($cache['trackables_count'] > 0)
|
||||
$flags |= self::$FLAG_HAS_TRACKABLES;
|
||||
if ($cache['founds'] == 0)
|
||||
$flags |= self::$FLAG_NOT_YET_FOUND;
|
||||
return array($cache['internal_id'], $z21x, $z21y, Okapi::cache_status_name2id($cache['status']),
|
||||
Okapi::cache_type_name2id($cache['type']), $cache['rating'], $flags);
|
||||
}
|
||||
/**
|
||||
* Convert OKAPI's cache object to a short database row to be inserted
|
||||
* into okapi_tile_caches table. Returns the list of the following attributes:
|
||||
* cache_id, z21x, z21y, status, type, rating, flags (rating might be null!).
|
||||
*/
|
||||
public static function generate_short_row($cache)
|
||||
{
|
||||
list($lat, $lon) = explode("|", $cache['location']);
|
||||
try {
|
||||
list($z21x, $z21y) = self::latlon_to_z21xy($lat, $lon);
|
||||
} catch (Exception $e) {
|
||||
/* E.g. division by zero, if the cache is placed at the north pole. */
|
||||
return false;
|
||||
}
|
||||
$flags = 0;
|
||||
if (($cache['founds'] > 6) && (($cache['recommendations'] / $cache['founds']) > 0.3))
|
||||
$flags |= self::$FLAG_STAR;
|
||||
if ($cache['trackables_count'] > 0)
|
||||
$flags |= self::$FLAG_HAS_TRACKABLES;
|
||||
if ($cache['founds'] == 0)
|
||||
$flags |= self::$FLAG_NOT_YET_FOUND;
|
||||
return array($cache['internal_id'], $z21x, $z21y, Okapi::cache_status_name2id($cache['status']),
|
||||
Okapi::cache_type_name2id($cache['type']), $cache['rating'], $flags);
|
||||
}
|
||||
|
||||
private static function latlon_to_z21xy($lat, $lon)
|
||||
{
|
||||
$offset = 128 << 21;
|
||||
$x = round($offset + ($offset * $lon / 180));
|
||||
$y = round($offset - $offset/pi() * log((1 + sin($lat * pi() / 180)) / (1 - sin($lat * pi() / 180))) / 2);
|
||||
return array($x, $y);
|
||||
}
|
||||
private static function latlon_to_z21xy($lat, $lon)
|
||||
{
|
||||
$offset = 128 << 21;
|
||||
$x = round($offset + ($offset * $lon / 180));
|
||||
$y = round($offset - $offset/pi() * log((1 + sin($lat * pi() / 180)) / (1 - sin($lat * pi() / 180))) / 2);
|
||||
return array($x, $y);
|
||||
}
|
||||
}
|
||||
@@ -17,74 +17,74 @@ use okapi\Settings;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 3
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 3
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# User is already verified (via OAuth), but we need to verify the
|
||||
# cache code (check if it exists). We will simply call a geocache method
|
||||
# on it - this will also throw a proper exception if it doesn't exist.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# User is already verified (via OAuth), but we need to verify the
|
||||
# cache code (check if it exists). We will simply call a geocache method
|
||||
# on it - this will also throw a proper exception if it doesn't exist.
|
||||
|
||||
$cache_code = $request->get_parameter('cache_code');
|
||||
if ($cache_code == null)
|
||||
throw new ParamMissing('cache_code');
|
||||
$geocache = OkapiServiceRunner::call('services/caches/geocache', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array('cache_code' => $cache_code, 'fields' => 'internal_id')));
|
||||
$cache_code = $request->get_parameter('cache_code');
|
||||
if ($cache_code == null)
|
||||
throw new ParamMissing('cache_code');
|
||||
$geocache = OkapiServiceRunner::call('services/caches/geocache', new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array('cache_code' => $cache_code, 'fields' => 'internal_id')));
|
||||
|
||||
# watched
|
||||
# watched
|
||||
|
||||
if ($tmp = $request->get_parameter('watched'))
|
||||
{
|
||||
if (!in_array($tmp, array('true', 'false', 'unchanged')))
|
||||
throw new InvalidParam('watched', $tmp);
|
||||
if ($tmp == 'true')
|
||||
Db::execute("
|
||||
insert ignore into cache_watches (cache_id, user_id)
|
||||
values (
|
||||
'".mysql_real_escape_string($geocache['internal_id'])."',
|
||||
'".mysql_real_escape_string($request->token->user_id)."'
|
||||
);
|
||||
");
|
||||
elseif ($tmp == 'false')
|
||||
Db::execute("
|
||||
delete from cache_watches
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($geocache['internal_id'])."'
|
||||
and user_id = '".mysql_real_escape_string($request->token->user_id)."';
|
||||
");
|
||||
}
|
||||
if ($tmp = $request->get_parameter('watched'))
|
||||
{
|
||||
if (!in_array($tmp, array('true', 'false', 'unchanged')))
|
||||
throw new InvalidParam('watched', $tmp);
|
||||
if ($tmp == 'true')
|
||||
Db::execute("
|
||||
insert ignore into cache_watches (cache_id, user_id)
|
||||
values (
|
||||
'".mysql_real_escape_string($geocache['internal_id'])."',
|
||||
'".mysql_real_escape_string($request->token->user_id)."'
|
||||
);
|
||||
");
|
||||
elseif ($tmp == 'false')
|
||||
Db::execute("
|
||||
delete from cache_watches
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($geocache['internal_id'])."'
|
||||
and user_id = '".mysql_real_escape_string($request->token->user_id)."';
|
||||
");
|
||||
}
|
||||
|
||||
# ignored
|
||||
# ignored
|
||||
|
||||
if ($tmp = $request->get_parameter('ignored'))
|
||||
{
|
||||
if (!in_array($tmp, array('true', 'false', 'unchanged')))
|
||||
throw new InvalidParam('ignored', $tmp);
|
||||
if ($tmp == 'true')
|
||||
Db::execute("
|
||||
insert ignore into cache_ignore (cache_id, user_id)
|
||||
values (
|
||||
'".mysql_real_escape_string($geocache['internal_id'])."',
|
||||
'".mysql_real_escape_string($request->token->user_id)."'
|
||||
);
|
||||
");
|
||||
elseif ($tmp == 'false')
|
||||
Db::execute("
|
||||
delete from cache_ignore
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($geocache['internal_id'])."'
|
||||
and user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
");
|
||||
}
|
||||
if ($tmp = $request->get_parameter('ignored'))
|
||||
{
|
||||
if (!in_array($tmp, array('true', 'false', 'unchanged')))
|
||||
throw new InvalidParam('ignored', $tmp);
|
||||
if ($tmp == 'true')
|
||||
Db::execute("
|
||||
insert ignore into cache_ignore (cache_id, user_id)
|
||||
values (
|
||||
'".mysql_real_escape_string($geocache['internal_id'])."',
|
||||
'".mysql_real_escape_string($request->token->user_id)."'
|
||||
);
|
||||
");
|
||||
elseif ($tmp == 'false')
|
||||
Db::execute("
|
||||
delete from cache_ignore
|
||||
where
|
||||
cache_id = '".mysql_real_escape_string($geocache['internal_id'])."'
|
||||
and user_id = '".mysql_real_escape_string($request->token->user_id)."'
|
||||
");
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'success' => true,
|
||||
);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
$result = array(
|
||||
'success' => true,
|
||||
);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<xml>
|
||||
<brief>Mark cache as watched or ignored</brief>
|
||||
<issue-id>166</issue-id>
|
||||
<desc>
|
||||
<p>This method allows your users to mark the geocache as <b>watched</b> or
|
||||
<b>ignored</b>.
|
||||
Read the docs on separate parameters for details.</p>
|
||||
</desc>
|
||||
<req name='cache_code'>
|
||||
<p>Code of the geocache.</p>
|
||||
</req>
|
||||
<opt name='watched' default='unchanged'>
|
||||
<p>Mark (or unmark) the cache as watched. This should be <b>true</b>,
|
||||
<b>false</b> or <b>unchanged</b>. You may access the current state of this
|
||||
flag with the <b>is_watched</b> field of the geocache method.</p>
|
||||
</opt>
|
||||
<opt name='ignored' default='unchanged'>
|
||||
<p>Mark (or unmark) the cache as ignored. This should be <b>true</b>,
|
||||
<b>false</b> or <b>unchanged</b>. You may access the current state of this
|
||||
flag with the <b>is_ignored</b> field of the geocache method.</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>success</b> - true, if all went well.</li>
|
||||
</ul>
|
||||
<p>Please note, that currently this will <b>always</b> be true! Nothing can go
|
||||
wrong as long as you pass your parameters in a right way (and if you don't,
|
||||
you will get an HTTP 400 response). If you have received an HTTP 200 response,
|
||||
then you may assume that all went well.</p>
|
||||
</returns>
|
||||
<brief>Mark cache as watched or ignored</brief>
|
||||
<issue-id>166</issue-id>
|
||||
<desc>
|
||||
<p>This method allows your users to mark the geocache as <b>watched</b> or
|
||||
<b>ignored</b>.
|
||||
Read the docs on separate parameters for details.</p>
|
||||
</desc>
|
||||
<req name='cache_code'>
|
||||
<p>Code of the geocache.</p>
|
||||
</req>
|
||||
<opt name='watched' default='unchanged'>
|
||||
<p>Mark (or unmark) the cache as watched. This should be <b>true</b>,
|
||||
<b>false</b> or <b>unchanged</b>. You may access the current state of this
|
||||
flag with the <b>is_watched</b> field of the geocache method.</p>
|
||||
</opt>
|
||||
<opt name='ignored' default='unchanged'>
|
||||
<p>Mark (or unmark) the cache as ignored. This should be <b>true</b>,
|
||||
<b>false</b> or <b>unchanged</b>. You may access the current state of this
|
||||
flag with the <b>is_ignored</b> field of the geocache method.</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>success</b> - true, if all went well.</li>
|
||||
</ul>
|
||||
<p>Please note, that currently this will <b>always</b> be true! Nothing can go
|
||||
wrong as long as you pass your parameters in a right way (and if you don't,
|
||||
you will get an HTTP 400 response). If you have received an HTTP 200 response,
|
||||
then you may assume that all went well.</p>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -20,17 +20,18 @@ require_once('searching.inc.php');
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$search_params = SearchAssistant::get_common_search_params($request);
|
||||
$result = SearchAssistant::get_common_search_result($search_params);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
$search_assistant = new SearchAssistant($request);
|
||||
$search_assistant->prepare_common_search_params();
|
||||
$result = $search_assistant->get_common_search_result();
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,205 +1,209 @@
|
||||
<xml>
|
||||
<brief>Search for geocaches</brief>
|
||||
<issue-id>15</issue-id>
|
||||
<desc>
|
||||
<p>Search for geocaches using some simple filters.
|
||||
All of them are optional, but you surely want to use at least some of them.</p>
|
||||
<ul>
|
||||
<li>If you're looking for a way to keep your geocaching database in sync with ours,
|
||||
have a peek at the <b>replicate</b> module.</li>
|
||||
<li>Usually you will want to use search_and_retrieve method instead of this one.
|
||||
This way, you can get much more data in <b>one request</b>.</li>
|
||||
</ul>
|
||||
</desc>
|
||||
<opt name='type'>
|
||||
<p>Pipe-separated list of cache type codes. If given, the results will be limited
|
||||
to the given cache types. For a list of cache type codes, see services/caches/geocache
|
||||
method.</p>
|
||||
<p><b>Notice:</b> If you want to include all cache types <b>except</b>
|
||||
given ones, prepend your list with the "-" sign.</p>
|
||||
</opt>
|
||||
<opt name='status' default='Available'>
|
||||
<p>Pipe-separated list of status codes. Only caches matching any of the given
|
||||
statuses will included in the response. For a list of cache status codes, see
|
||||
services/caches/geocache method.</p>
|
||||
</opt>
|
||||
<opt name='owner_uuid'>
|
||||
<p>Pipe-separated list of user IDs. If given, the list of returned caches
|
||||
will be limited to those owned by the given users.</p>
|
||||
<p><b>Notice:</b> User ID and Username are two different things!</p>
|
||||
<p><b>Notice:</b> If you want to include all caches <b>except</b> the ones
|
||||
owned by the given users, prepend your list with the "-" sign.</p>
|
||||
</opt>
|
||||
<opt name='name'>
|
||||
<p>UTF-8 encoded string - the name (or part of the name) of the cache.</p>
|
||||
<p>Allowed wildcard characters:</p>
|
||||
<ul>
|
||||
<li>asterisk ("*") will match any string of characters,</li>
|
||||
<li>underscore ("_") will match any single character.</li>
|
||||
</ul>
|
||||
<p>Name matching is case-insensitive. Maximum length for the <b>name</b> parameter
|
||||
is 100 characters.</p>
|
||||
<p><b>Examples:</b></p>
|
||||
<ul>
|
||||
<li>"name=the *" returns caches which name starts with "the " (or "The ", etc.),</li>
|
||||
<li>"name=water tower" returns caches which have <b>exactly</b> that name (case insensitive),</li>
|
||||
<li>"name=*water tower*" will match caches like "Beautiful Water Tower II",</li>
|
||||
<li>"name=*tower_" will match "Water Towers" but will <b>not</b> match "Water Tower".</li>
|
||||
</ul>
|
||||
<p><b>Notice:</b> Cache code and name are two different things - if you want to
|
||||
find a cache by its code, use the services/caches/geocache method.</p>
|
||||
</opt>
|
||||
<opt name='terrain' default='1-5'>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with terrain rating between these numbers (inclusive) will be returned.</p>
|
||||
</opt>
|
||||
<opt name='difficulty' default='1-5'>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with difficulty rating between these numbers (inclusive) will be returned.</p>
|
||||
</opt>
|
||||
<opt name='size' class='deprecated'>
|
||||
<p>Deprecated. Please use <b>size2</b> instead - this will allow you to
|
||||
differentiate "nano" vs. "micro" and "none" vs. "other" sizes
|
||||
(<a href='http://code.google.com/p/opencaching-api/issues/detail?id=155'>details</a>).</p>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with size attribute between these numbers (inclusive) will be returned
|
||||
(1 - micro, 5 - very big).</p>
|
||||
<p><b>Notice:</b> If you use this parameter, all caches which do not have a container
|
||||
(like Event or Virtual caches) will be excluded from the results. If you want caches
|
||||
with no container included, append "|X" suffix to the value of this parameter
|
||||
(e.g. "3-5|X").</p>
|
||||
</opt>
|
||||
<opt name='size2'>
|
||||
<p>Pipe-separated list of "size2 codes". Only matching caches will be
|
||||
included. The codes are: 'none', 'nano', 'micro', 'small', 'regular',
|
||||
'large', 'xlarge', 'other'.</p>
|
||||
<p><b>Note:</b> Not all OC servers use all of these. I.e. OCPL does not
|
||||
have 'nano' nor 'other' caches (but it might have them in the future).</p>
|
||||
</opt>
|
||||
<opt name='rating'>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with an overall rating between these numbers (inclusive) will be returned
|
||||
(1 - poor, 5 - excellent).</p>
|
||||
<p><b>Notice:</b> If you use this parameter, all caches with too few votes will be
|
||||
excluded from results. If you still want unrated caches included, append "|X" suffix
|
||||
to the value of this parameter (e.g. "3-5|X").</p>
|
||||
<p><b>Notice:</b> Some OC installations do not provide ratings for their geocaches.
|
||||
On such installation, this parameter will be ignored.</p>
|
||||
</opt>
|
||||
<opt name='min_rcmds'>
|
||||
<p>There are two possible value-types for this argument:</p>
|
||||
<ul>
|
||||
<li>Integer N. If <i>N</i> given, the result will contain only those caches which have
|
||||
at least <i>N</i> recommendations.</li>
|
||||
<li>Integer N with a percent sign appended (e.g. "20%"). The result will contain
|
||||
only those caches which have at last <i>N%</i> ratio of recommendations/founds.
|
||||
Please note, that this is useful only with conjunction with <b>min_founds</b>
|
||||
parameter.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name='min_founds'>
|
||||
<p>Integer N. If <i>N</i> given, the result will contain only those caches which have
|
||||
been found at least <i>N</i> times. Useful if you want to skip "unverified" caches.</p>
|
||||
</opt>
|
||||
<opt name='max_founds'>
|
||||
<p>Integer N. If <i>N</i> given, the result will contain only those caches which have
|
||||
been found at most <i>N</i> times. Useful for FTF hunters.</p>
|
||||
</opt>
|
||||
<opt name='modified_since'>
|
||||
<p>A date and time string. This should be in ISO 8601 format (currently any
|
||||
format acceptable by PHP's <a href='http://pl2.php.net/strtotime'>strtotime</a>
|
||||
function also will do, but most of them don't handle time zones properly,
|
||||
try to use ISO 8601!).</p>
|
||||
<p>If given, the list of returned geocaches will be limited to those which were
|
||||
created or modified since that date. (Note: currently caches do not get
|
||||
"modified" when user makes a log entry.)</p>
|
||||
</opt>
|
||||
<opt name='found_status' default='either'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed with an Access Token
|
||||
(you will need to use <b>Level 3</b> Authentication).</p>
|
||||
<p>Should be one of the following:</p>
|
||||
<ul>
|
||||
<li><b>found_only</b> - only caches found by the user will be returned,</li>
|
||||
<li><b>notfound_only</b> - only caches <b>not</b> found by the user will be returned,</li>
|
||||
<li><b>either</b> - all caches will be returned.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name='found_by'>
|
||||
<p>User UUID. If given, the response will only include geocaches found by
|
||||
the given user.</p>
|
||||
</opt>
|
||||
<opt name='not_found_by'>
|
||||
<p>User UUID. If given, the response will only include geocaches not found by
|
||||
the given user.</p>
|
||||
</opt>
|
||||
<opt name='watched_only' default='false'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed with an Access Token
|
||||
(you will need to use <b>Level 3</b> Authentication).</p>
|
||||
<p>Boolean. If set to <b>true</b>, only caches which the user has marked as watched
|
||||
will be included in the result. This might be used to temporarily mark geocaches
|
||||
of particular interest (e.g. "all the caches I plan to find today").</p>
|
||||
</opt>
|
||||
<opt name='exclude_ignored' default='false'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed
|
||||
with an Access Token (you will need to use <b>Level 3</b> Authentication).</p>
|
||||
<p>Boolean. If set to <b>true</b>, caches which the user has marked as ignored
|
||||
will not be included in the result.</p>
|
||||
</opt>
|
||||
<opt name='exclude_my_own' default='false'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed
|
||||
with an Access Token (you will need to use <b>Level 3</b> Authentication).
|
||||
See <b>owner_uuid</b> parameter if you don't want to use OAuth.</p>
|
||||
<p>Boolean. If set to <b>true</b>, caches which the user is an owner of will
|
||||
not be included in the result.</p>
|
||||
</opt>
|
||||
<opt name='with_trackables_only' default='false'>
|
||||
Boolean. If set to <b>true</b>, only caches with at least one trackable
|
||||
will be included in the result.
|
||||
</opt>
|
||||
<opt name='ftf_hunter' default='false'>
|
||||
Boolean. If set to <b>true</b>, only caches which have not yet been
|
||||
found <b>by anyone</b> will be included.
|
||||
</opt>
|
||||
<opt name='set_and'>
|
||||
<p>ID of a set previously created with the <b>search/save</b> method.
|
||||
If given, the results are <a href='http://en.wikipedia.org/wiki/Logical_conjunction'>AND</a>ed
|
||||
together with this set.</p>
|
||||
<p>If you want to list the set contents only, please note the default
|
||||
value of the <b>status</b> parameter! You may want to override it
|
||||
in order to include unavailable and/or archived geocaches within the set.</p>
|
||||
</opt>
|
||||
<opt name='limit' default='100'>
|
||||
<p>Integer in range 1..500. Maximum number of cache codes returned.</p>
|
||||
</opt>
|
||||
<opt name='offset' default='0'>
|
||||
<p>An offset, the amount of items to skip at the beginning of the result. Combined with limit
|
||||
allows pagination of the result set. Please note, that the sum of offset and limit still cannot
|
||||
exceed 500. You MAY NOT use this method to list all the caches, it is for searching only.
|
||||
Have a peek at the <b>replicate</b> module if you need all the caches.</p>
|
||||
</opt>
|
||||
<opt name='order_by'>
|
||||
<p>Pipe separated list of fields to order the results by. Prefix the field name with
|
||||
a '-' sign to indicate a descending order.</p>
|
||||
<p>Currently, fields which you can order by include: <b>code</b>, <b>name</b>,
|
||||
<b>founds</b>, <b>rcmds</b>, <b>rcmds%</b> (tell us if you want more).</p>
|
||||
<p><b>Examples:</b></p>
|
||||
<ul>
|
||||
<li>to order by cache name use "order_by=name" or "order_by=+name",</li>
|
||||
<li>to have the largest caches in front, use "order_by=-size",</li>
|
||||
<li>multicolumn sorting is also allowed, ex. "order_by=-founds|-size|distance"</li>
|
||||
</ul>
|
||||
<p><b>Note:</b> Try to avoid executing separate OKAPI request every time you
|
||||
want to sort the data which you <b>already have</b>. Consider caching and
|
||||
sorting on client side. This will speed up things for both sides.</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>results</b> - a list of cache codes,</li>
|
||||
<li><b>more</b> - boolean, <b>true</b> means that there were more
|
||||
results for your query, but they were not returned because of the
|
||||
<b>limit</b> parameter.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Search for geocaches</brief>
|
||||
<issue-id>15</issue-id>
|
||||
<desc>
|
||||
<p>Search for geocaches using some simple filters.
|
||||
All of them are optional, but you surely want to use at least some of them.</p>
|
||||
<ul>
|
||||
<li>If you're looking for a way to keep your geocaching database in sync with ours,
|
||||
have a peek at the <b>replicate</b> module.</li>
|
||||
<li>Usually you will want to use search_and_retrieve method instead of this one.
|
||||
This way, you can get much more data in <b>one request</b>.</li>
|
||||
</ul>
|
||||
</desc>
|
||||
<opt name='type'>
|
||||
<p>Pipe-separated list of cache type codes. If given, the results will be limited
|
||||
to the given cache types. For a list of cache type codes, see services/caches/geocache
|
||||
method.</p>
|
||||
<p><b>Notice:</b> If you want to include all cache types <b>except</b>
|
||||
given ones, prepend your list with the "-" sign.</p>
|
||||
</opt>
|
||||
<opt name='status' default='Available'>
|
||||
<p>Pipe-separated list of status codes. Only caches matching any of the given
|
||||
statuses will included in the response. For a list of cache status codes, see
|
||||
services/caches/geocache method.</p>
|
||||
</opt>
|
||||
<opt name='owner_uuid'>
|
||||
<p>Pipe-separated list of user IDs. If given, the list of returned caches
|
||||
will be limited to those owned by the given users.</p>
|
||||
<p><b>Notice:</b> User ID and Username are two different things!</p>
|
||||
<p><b>Notice:</b> If you want to include all caches <b>except</b> the ones
|
||||
owned by the given users, prepend your list with the "-" sign.</p>
|
||||
</opt>
|
||||
<opt name='name'>
|
||||
<p>UTF-8 encoded string - the name (or part of the name) of the cache.</p>
|
||||
<p>Allowed wildcard characters:</p>
|
||||
<ul>
|
||||
<li>asterisk ("*") will match any string of characters,</li>
|
||||
<li>underscore ("_") will match any single character.</li>
|
||||
</ul>
|
||||
<p>Name matching is case-insensitive. Maximum length for the <b>name</b> parameter
|
||||
is 100 characters.</p>
|
||||
<p><b>Examples:</b></p>
|
||||
<ul>
|
||||
<li>"name=the *" returns caches which name starts with "the " (or "The ", etc.),</li>
|
||||
<li>"name=water tower" returns caches which have <b>exactly</b> that name (case insensitive),</li>
|
||||
<li>"name=*water tower*" will match caches like "Beautiful Water Tower II",</li>
|
||||
<li>"name=*tower_" will match "Water Towers" but will <b>not</b> match "Water Tower".</li>
|
||||
</ul>
|
||||
<p><b>Notice:</b> Cache code and name are two different things - if you want to
|
||||
find a cache by its code, use the services/caches/geocache method.</p>
|
||||
</opt>
|
||||
<opt name='terrain' default='1-5'>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with terrain rating between these numbers (inclusive) will be returned.</p>
|
||||
</opt>
|
||||
<opt name='difficulty' default='1-5'>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with difficulty rating between these numbers (inclusive) will be returned.</p>
|
||||
</opt>
|
||||
<opt name='size' class='deprecated'>
|
||||
<p>Deprecated. Please use <b>size2</b> instead - this will allow you to
|
||||
differentiate "nano" vs. "micro" and "none" vs. "other" sizes
|
||||
(<a href='http://code.google.com/p/opencaching-api/issues/detail?id=155'>details</a>).</p>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with size attribute between these numbers (inclusive) will be returned
|
||||
(1 - micro, 5 - very big).</p>
|
||||
<p><b>Notice:</b> If you use this parameter, all caches which do not have a container
|
||||
(like Event or Virtual caches) will be excluded from the results. If you want caches
|
||||
with no container included, append "|X" suffix to the value of this parameter
|
||||
(e.g. "3-5|X").</p>
|
||||
</opt>
|
||||
<opt name='size2'>
|
||||
<p>Pipe-separated list of "size2 codes". Only matching caches will be
|
||||
included. The codes are: 'none', 'nano', 'micro', 'small', 'regular',
|
||||
'large', 'xlarge', 'other'.</p>
|
||||
<p><b>Note:</b> Not all OC servers use all of these. I.e. OCPL does not
|
||||
have 'nano' nor 'other' caches (but it might have them in the future).</p>
|
||||
</opt>
|
||||
<opt name='rating'>
|
||||
<p>A string "X-Y", where X and Y are integers between 1 and 5, and X <= Y.
|
||||
Only caches with an overall rating between these numbers (inclusive) will be returned
|
||||
(1 - poor, 5 - excellent).</p>
|
||||
<p><b>Notice:</b> If you use this parameter, all caches with too few votes will be
|
||||
excluded from results. If you still want unrated caches included, append "|X" suffix
|
||||
to the value of this parameter (e.g. "3-5|X").</p>
|
||||
<p><b>Notice:</b> Some OC installations do not provide ratings for their geocaches.
|
||||
On such installation, this parameter will be ignored.</p>
|
||||
</opt>
|
||||
<opt name='min_rcmds'>
|
||||
<p>There are two possible value-types for this argument:</p>
|
||||
<ul>
|
||||
<li>Integer N. If <i>N</i> given, the result will contain only those caches which have
|
||||
at least <i>N</i> recommendations.</li>
|
||||
<li>Integer N with a percent sign appended (e.g. "20%"). The result will contain
|
||||
only those caches which have at last <i>N%</i> ratio of recommendations/founds.
|
||||
Please note, that this is useful only with conjunction with <b>min_founds</b>
|
||||
parameter.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name='min_founds'>
|
||||
<p>Integer N. If <i>N</i> given, the result will contain only those caches which have
|
||||
been found at least <i>N</i> times. Useful if you want to skip "unverified" caches.</p>
|
||||
</opt>
|
||||
<opt name='max_founds'>
|
||||
<p>Integer N. If <i>N</i> given, the result will contain only those caches which have
|
||||
been found at most <i>N</i> times. Useful for FTF hunters.</p>
|
||||
</opt>
|
||||
<opt name='modified_since'>
|
||||
<p>A date and time string. This should be in ISO 8601 format (currently any
|
||||
format acceptable by PHP's <a href='http://pl2.php.net/strtotime'>strtotime</a>
|
||||
function also will do, but most of them don't handle time zones properly,
|
||||
try to use ISO 8601!).</p>
|
||||
<p>If given, the list of returned geocaches will be limited to those which were
|
||||
created or modified since that date. (Note: currently caches do not get
|
||||
"modified" when user makes a log entry.)</p>
|
||||
</opt>
|
||||
<opt name='found_status' default='either'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed with an Access Token
|
||||
(you will need to use <b>Level 3</b> Authentication).</p>
|
||||
<p>Should be one of the following:</p>
|
||||
<ul>
|
||||
<li><b>found_only</b> - only caches found by the user will be returned,</li>
|
||||
<li><b>notfound_only</b> - only caches <b>not</b> found by the user will be returned,</li>
|
||||
<li><b>either</b> - all caches will be returned.</li>
|
||||
</ul>
|
||||
</opt>
|
||||
<opt name='found_by'>
|
||||
<p>User UUID. If given, the response will only include geocaches found by
|
||||
the given user.</p>
|
||||
</opt>
|
||||
<opt name='not_found_by'>
|
||||
<p>User UUID. If given, the response will only include geocaches not found by
|
||||
the given user.</p>
|
||||
</opt>
|
||||
<opt name='watched_only' default='false'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed with an Access Token
|
||||
(you will need to use <b>Level 3</b> Authentication).</p>
|
||||
<p>Boolean. If set to <b>true</b>, only caches which the user has marked as watched
|
||||
will be included in the result. This might be used to temporarily mark geocaches
|
||||
of particular interest (e.g. "all the caches I plan to find today").</p>
|
||||
</opt>
|
||||
<opt name='exclude_ignored' default='false'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed
|
||||
with an Access Token (you will need to use <b>Level 3</b> Authentication).</p>
|
||||
<p>Boolean. If set to <b>true</b>, caches which the user has marked as ignored
|
||||
will not be included in the result.</p>
|
||||
</opt>
|
||||
<opt name='exclude_my_own' default='false'>
|
||||
<p><b>Notice:</b> This parameter may be used only for requests signed
|
||||
with an Access Token (you will need to use <b>Level 3</b> Authentication).
|
||||
See <b>owner_uuid</b> parameter if you don't want to use OAuth.</p>
|
||||
<p>Boolean. If set to <b>true</b>, caches which the user is an owner of will
|
||||
not be included in the result.</p>
|
||||
</opt>
|
||||
<opt name='with_trackables_only' default='false'>
|
||||
Boolean. If set to <b>true</b>, only caches with at least one trackable
|
||||
will be included in the result.
|
||||
</opt>
|
||||
<opt name='ftf_hunter' default='false'>
|
||||
Boolean. If set to <b>true</b>, only caches which have not yet been
|
||||
found <b>by anyone</b> will be included.
|
||||
</opt>
|
||||
<opt name='set_and'>
|
||||
<p>ID of a set previously created with the <b>search/save</b> method.
|
||||
If given, the results are <a href='http://en.wikipedia.org/wiki/Logical_conjunction'>AND</a>ed
|
||||
together with this set.</p>
|
||||
<p>If you want to list the set contents only, please note the default
|
||||
value of the <b>status</b> parameter! You may want to override it
|
||||
in order to include unavailable and/or archived geocaches within the set.</p>
|
||||
</opt>
|
||||
<opt name='limit' default='100'>
|
||||
<p>Integer in range 1..500. Maximum number of cache codes returned.</p>
|
||||
</opt>
|
||||
<opt name='offset' default='0'>
|
||||
<p>An offset, the amount of items to skip at the beginning of the result. Combined with limit
|
||||
allows pagination of the result set. Please note, that the sum of offset and limit still cannot
|
||||
exceed 500. You MAY NOT use this method to list all the caches, it is for searching only.
|
||||
Have a peek at the <b>replicate</b> module if you need all the caches.</p>
|
||||
</opt>
|
||||
<opt name='order_by'>
|
||||
<p>Pipe separated list of fields to order the results by. Prefix the field name with
|
||||
a '-' sign to indicate a descending order.</p>
|
||||
<p>Currently, fields which you can order by include: <b>code</b>, <b>name</b>,
|
||||
<b>founds</b>, <b>rcmds</b>, <b>rcmds%</b> (tell us if you want more).</p>
|
||||
<p><b>Examples:</b></p>
|
||||
<ul>
|
||||
<li>to order by cache name use "order_by=name" or "order_by=+name",</li>
|
||||
<li>to have the most recommended caches in front, use "order_by=-rcmds%",</li>
|
||||
<li>multicolumn sorting is also allowed, ex. "order_by=-founds|name"</li>
|
||||
</ul>
|
||||
<p><b>Note:</b> Try to avoid executing separate OKAPI request every time you
|
||||
want to sort the data which you <b>already have</b>. Consider caching and
|
||||
sorting on client side. This will speed up things for both sides.</p>
|
||||
<p><b>Note:</b> For most other methods (like <b>bbox</b> and <b>nearest</b>),
|
||||
the default order is <i>by the distance from the center</i>. If you supply
|
||||
custom <b>order_by</b> parameter, then we will try to order by your preference
|
||||
first, and then by the distance later.</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>results</b> - a list of cache codes,</li>
|
||||
<li><b>more</b> - boolean, <b>true</b> means that there were more
|
||||
results for your query, but they were not returned because of the
|
||||
<b>limit</b> parameter.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
@@ -12,76 +12,83 @@ use okapi\services\caches\search\SearchAssistant;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# You may wonder, why there are no parameters like "bbox" or "center" in the
|
||||
# "search/all" method. This is *intentional* and should be kept this way.
|
||||
# Such parameters would fall in conflict with each other and - in result -
|
||||
# make the documentation very fuzzy. That's why they were intentionally
|
||||
# left out of the "search/all" method, and put in separate (individual) ones.
|
||||
# It's much easier to grasp their meaning this way.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# You may wonder, why there are no parameters like "bbox" or "center" in the
|
||||
# "search/all" method. This is *intentional* and should be kept this way.
|
||||
# Such parameters would fall in conflict with each other and - in result -
|
||||
# make the documentation very fuzzy. That's why they were intentionally
|
||||
# left out of the "search/all" method, and put in separate (individual) ones.
|
||||
# It's much easier to grasp their meaning this way.
|
||||
|
||||
$tmp = $request->get_parameter('bbox');
|
||||
if (!$tmp)
|
||||
throw new ParamMissing('bbox');
|
||||
$parts = explode('|', $tmp);
|
||||
if (count($parts) != 4)
|
||||
throw new InvalidParam('bbox', "Expecting 4 pipe-separated parts, got ".count($parts).".");
|
||||
foreach ($parts as &$part_ref)
|
||||
{
|
||||
if (!preg_match("/^-?[0-9]+(\.?[0-9]*)$/", $part_ref))
|
||||
throw new InvalidParam('bbox', "'$part_ref' is not a valid float number.");
|
||||
$part_ref = floatval($part_ref);
|
||||
}
|
||||
list($bbsouth, $bbwest, $bbnorth, $bbeast) = $parts;
|
||||
if ($bbnorth <= $bbsouth)
|
||||
throw new InvalidParam('bbox', "Northern edge must be situated to the north of the southern edge.");
|
||||
if ($bbeast == $bbwest)
|
||||
throw new InvalidParam('bbox', "Eastern edge longitude is the same as the western one.");
|
||||
if ($bbnorth > 90 || $bbnorth < -90 || $bbsouth > 90 || $bbsouth < -90)
|
||||
throw new InvalidParam('bbox', "Latitudes have to be within -90..90 range.");
|
||||
if ($bbeast > 180 || $bbeast < -180 || $bbwest > 180 || $bbwest < -180)
|
||||
throw new InvalidParam('bbox', "Longitudes have to be within -180..180 range.");
|
||||
$tmp = $request->get_parameter('bbox');
|
||||
if (!$tmp)
|
||||
throw new ParamMissing('bbox');
|
||||
$parts = explode('|', $tmp);
|
||||
if (count($parts) != 4)
|
||||
throw new InvalidParam('bbox', "Expecting 4 pipe-separated parts, got ".count($parts).".");
|
||||
foreach ($parts as &$part_ref)
|
||||
{
|
||||
if (!preg_match("/^-?[0-9]+(\.?[0-9]*)$/", $part_ref))
|
||||
throw new InvalidParam('bbox', "'$part_ref' is not a valid float number.");
|
||||
$part_ref = floatval($part_ref);
|
||||
}
|
||||
list($bbsouth, $bbwest, $bbnorth, $bbeast) = $parts;
|
||||
if ($bbnorth <= $bbsouth)
|
||||
throw new InvalidParam('bbox', "Northern edge must be situated to the north of the southern edge.");
|
||||
if ($bbeast == $bbwest)
|
||||
throw new InvalidParam('bbox', "Eastern edge longitude is the same as the western one.");
|
||||
if ($bbnorth > 90 || $bbnorth < -90 || $bbsouth > 90 || $bbsouth < -90)
|
||||
throw new InvalidParam('bbox', "Latitudes have to be within -90..90 range.");
|
||||
if ($bbeast > 180 || $bbeast < -180 || $bbwest > 180 || $bbwest < -180)
|
||||
throw new InvalidParam('bbox', "Longitudes have to be within -180..180 range.");
|
||||
|
||||
# Construct SQL conditions for the specified bounding box.
|
||||
# Construct SQL conditions for the specified bounding box.
|
||||
|
||||
$where_conds = array();
|
||||
$where_conds[] = "caches.latitude between '".mysql_real_escape_string($bbsouth)."' and '".mysql_real_escape_string($bbnorth)."'";
|
||||
if ($bbeast > $bbwest)
|
||||
{
|
||||
# Easy one.
|
||||
$where_conds[] = "caches.longitude between '".mysql_real_escape_string($bbwest)."' and '".mysql_real_escape_string($bbeast)."'";
|
||||
}
|
||||
else
|
||||
{
|
||||
# We'll have to assume that this box goes through the 180-degree meridian.
|
||||
# For example, $bbwest = 179 and $bbeast = -179.
|
||||
$where_conds[] = "(caches.longitude > '".mysql_real_escape_string($bbwest)."' or caches.longitude < '".mysql_real_escape_string($bbeast)."')";
|
||||
}
|
||||
$search_assistant = new SearchAssistant($request);
|
||||
$search_assistant->prepare_common_search_params();
|
||||
$search_assistant->prepare_location_search_params();
|
||||
|
||||
#
|
||||
# In the method description, we promised to return caches ordered by the *rough*
|
||||
# distance from the center of the bounding box. We'll use ORDER BY with a simplified
|
||||
# distance formula and combine it with the LIMIT clause to get the best results.
|
||||
#
|
||||
$where_conds = array();
|
||||
$where_conds[] = $search_assistant->get_latitude_expr()." between '".mysql_real_escape_string($bbsouth)."' and '".mysql_real_escape_string($bbnorth)."'";
|
||||
if ($bbeast > $bbwest)
|
||||
{
|
||||
# Easy one.
|
||||
$where_conds[] = $search_assistant->get_longitude_expr()." between '".mysql_real_escape_string($bbwest)."' and '".mysql_real_escape_string($bbeast)."'";
|
||||
}
|
||||
else
|
||||
{
|
||||
# We'll have to assume that this box goes through the 180-degree meridian.
|
||||
# For example, $bbwest = 179 and $bbeast = -179.
|
||||
$where_conds[] = "(".$search_assistant->get_longitude_expr()." > '".mysql_real_escape_string($bbwest)
|
||||
."' or ".$search_assistant->get_longitude_expr()." < '".mysql_real_escape_string($bbeast)."')";
|
||||
}
|
||||
|
||||
$center_lat = ($bbsouth + $bbnorth) / 2.0;
|
||||
$center_lon = ($bbwest + $bbeast) / 2.0;
|
||||
#
|
||||
# In the method description, we promised to return caches ordered by the *rough*
|
||||
# distance from the center of the bounding box. We'll use ORDER BY with a simplified
|
||||
# distance formula and combine it with the LIMIT clause to get the best results.
|
||||
#
|
||||
|
||||
$search_params = SearchAssistant::get_common_search_params($request);
|
||||
$search_params['where_conds'] = array_merge($where_conds, $search_params['where_conds']);
|
||||
$search_params['order_by'][] = Okapi::get_distance_sql($center_lat, $center_lon,
|
||||
"caches.latitude", "caches.longitude"); # not replaced; added to the end!
|
||||
$center_lat = ($bbsouth + $bbnorth) / 2.0;
|
||||
$center_lon = ($bbwest + $bbeast) / 2.0;
|
||||
|
||||
$result = SearchAssistant::get_common_search_result($search_params);
|
||||
$search_params = $search_assistant->get_search_params();
|
||||
$search_params['where_conds'] = array_merge($where_conds, $search_params['where_conds']);
|
||||
$search_params['order_by'][] = Okapi::get_distance_sql($center_lat, $center_lon,
|
||||
$search_assistant->get_latitude_expr(),
|
||||
$search_assistant->get_longitude_expr()); # not replaced; added to the end!
|
||||
$search_assistant->set_search_params($search_params);
|
||||
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
$result = $search_assistant->get_common_search_result();
|
||||
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
<xml>
|
||||
<brief>Search for caches within specified bounding box</brief>
|
||||
<issue-id>16</issue-id>
|
||||
<desc>
|
||||
<p>This method is similar to the search/all method, but the results
|
||||
are restricted to the caches situated within a given bounding box
|
||||
(a rectangle on the map).</p>
|
||||
<p>Unless overriden, results are ordered by the distance from the center of the bounding
|
||||
box. This means, that if you hit the limit of geocaches
|
||||
returned, you will receive the ones that are in the middle of your
|
||||
box, and miss the ones on the edges.</p>
|
||||
<p>Usually you will want to use search_and_retrieve method instead of this one.
|
||||
This way, you can get much more data in <b>one request</b>.</p>
|
||||
</desc>
|
||||
<req name='bbox'>
|
||||
<p>The bounding box within to search for caches. The box is defined
|
||||
by a string in "<b>S|W|N|E</b>" format, where:</p>
|
||||
<ul>
|
||||
<li><b>S</b> stands for southern edge latitude of the box,</li>
|
||||
<li><b>W</b> stands for western edge longitude of the box,</li>
|
||||
<li><b>N</b> stands for northern edge latitude of the box,</li>
|
||||
<li><b>E</b> stands for eastern edge longitude of the box.</li>
|
||||
</ul>
|
||||
<p>Use positive numbers for latitudes in the northern hemisphere and
|
||||
longitudes in the eastern hemisphere (and negative for southern and
|
||||
western hemispheres accordingly). These are full degrees with a dot
|
||||
as a decimal point (ex. "48.7|15.8|54|24.9").</p>
|
||||
</req>
|
||||
<import-params method='services/caches/search/all'/>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>Same format as in the search/all method.</p>
|
||||
</returns>
|
||||
<brief>Search for caches within specified bounding box</brief>
|
||||
<issue-id>16</issue-id>
|
||||
<desc>
|
||||
<p>This method is similar to the search/all method, but the results
|
||||
are restricted to the caches situated within a given bounding box
|
||||
(a rectangle on the map).</p>
|
||||
<p>Unless overriden, results are ordered by the distance from the center of the bounding
|
||||
box. This means, that if you hit the limit of geocaches
|
||||
returned, you will receive the ones that are in the middle of your
|
||||
box, and miss the ones on the edges.</p>
|
||||
<p>Usually you will want to use search_and_retrieve method instead of this one.
|
||||
This way, you can get much more data in <b>one request</b>.</p>
|
||||
</desc>
|
||||
<req name='bbox'>
|
||||
<p>The bounding box within to search for caches. The box is defined
|
||||
by a string in "<b>S|W|N|E</b>" format, where:</p>
|
||||
<ul>
|
||||
<li><b>S</b> stands for southern edge latitude of the box,</li>
|
||||
<li><b>W</b> stands for western edge longitude of the box,</li>
|
||||
<li><b>N</b> stands for northern edge latitude of the box,</li>
|
||||
<li><b>E</b> stands for eastern edge longitude of the box.</li>
|
||||
</ul>
|
||||
<p>Use positive numbers for latitudes in the northern hemisphere and
|
||||
longitudes in the eastern hemisphere (and negative for southern and
|
||||
western hemispheres accordingly). These are full degrees with a dot
|
||||
as a decimal point (ex. "48.7|15.8|54|24.9").</p>
|
||||
</req>
|
||||
<opt name='location_source' default='default-coords'>
|
||||
Same as in the <a href="%OKAPI:methodargref:services/caches/search/nearest#location_source%">
|
||||
services/caches/search/nearest</a> method.
|
||||
</opt>
|
||||
<import-params method='services/caches/search/all'/>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>Same format as in the search/all method.</p>
|
||||
</returns>
|
||||
</xml>
|
||||
|
||||
@@ -13,165 +13,165 @@ use okapi\Db;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one of: array('cache_code', 'OPXXXX'), array('internal_id', '12345'),
|
||||
* array('uuid', 'A408C3...') or null.
|
||||
*/
|
||||
private static function get_cache_key($url)
|
||||
{
|
||||
# Determine our own domain.
|
||||
/**
|
||||
* Returns one of: array('cache_code', 'OPXXXX'), array('internal_id', '12345'),
|
||||
* array('uuid', 'A408C3...') or null.
|
||||
*/
|
||||
private static function get_cache_key($url)
|
||||
{
|
||||
# Determine our own domain.
|
||||
|
||||
static $host = null;
|
||||
static $length = null;
|
||||
if ($host == null)
|
||||
{
|
||||
$host = parse_url(Settings::get('SITE_URL'), PHP_URL_HOST);
|
||||
if (strpos($host, "www.") === 0)
|
||||
$host = substr($host, 4);
|
||||
$length = strlen($host);
|
||||
}
|
||||
static $host = null;
|
||||
static $length = null;
|
||||
if ($host == null)
|
||||
{
|
||||
$host = parse_url(Settings::get('SITE_URL'), PHP_URL_HOST);
|
||||
if (strpos($host, "www.") === 0)
|
||||
$host = substr($host, 4);
|
||||
$length = strlen($host);
|
||||
}
|
||||
|
||||
# Parse the URL
|
||||
# Parse the URL
|
||||
|
||||
$uri = parse_url($url);
|
||||
if ($uri == false)
|
||||
return null;
|
||||
if ((!isset($uri['scheme'])) || (!in_array($uri['scheme'], array('http', 'https'))))
|
||||
return null;
|
||||
if ((!isset($uri['host'])) || (substr($uri['host'], -$length) != $host))
|
||||
return null;
|
||||
if (!isset($uri['path']))
|
||||
return null;
|
||||
if (preg_match("#^/(O[A-Z][A-Z0-9]{4,5})$#", $uri['path'], $matches))
|
||||
{
|
||||
# Some servers allow "http://oc.xx/<cache_code>" shortcut.
|
||||
return array('cache_code', $matches[1]);
|
||||
}
|
||||
$parts = array();
|
||||
if (isset($uri['query']))
|
||||
$parts = array_merge($parts, explode('&', $uri['query']));
|
||||
if (isset($uri['fragment']))
|
||||
$parts = array_merge($parts, explode('&', $uri['fragment']));
|
||||
foreach ($parts as $param)
|
||||
{
|
||||
$item = explode('=', $param, 2);
|
||||
if (count($item) != 2)
|
||||
continue;
|
||||
$key = $item[0];
|
||||
$value = $item[1];
|
||||
if ($key == 'wp')
|
||||
return array('cache_code', $value);
|
||||
if ($key == 'cacheid')
|
||||
return array('internal_id', $value);
|
||||
if ($key == 'uuid')
|
||||
return array('uuid', $value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$uri = parse_url($url);
|
||||
if ($uri == false)
|
||||
return null;
|
||||
if ((!isset($uri['scheme'])) || (!in_array($uri['scheme'], array('http', 'https'))))
|
||||
return null;
|
||||
if ((!isset($uri['host'])) || (substr($uri['host'], -$length) != $host))
|
||||
return null;
|
||||
if (!isset($uri['path']))
|
||||
return null;
|
||||
if (preg_match("#^/(O[A-Z][A-Z0-9]{4,5})$#", $uri['path'], $matches))
|
||||
{
|
||||
# Some servers allow "http://oc.xx/<cache_code>" shortcut.
|
||||
return array('cache_code', $matches[1]);
|
||||
}
|
||||
$parts = array();
|
||||
if (isset($uri['query']))
|
||||
$parts = array_merge($parts, explode('&', $uri['query']));
|
||||
if (isset($uri['fragment']))
|
||||
$parts = array_merge($parts, explode('&', $uri['fragment']));
|
||||
foreach ($parts as $param)
|
||||
{
|
||||
$item = explode('=', $param, 2);
|
||||
if (count($item) != 2)
|
||||
continue;
|
||||
$key = $item[0];
|
||||
$value = $item[1];
|
||||
if ($key == 'wp')
|
||||
return array('cache_code', $value);
|
||||
if ($key == 'cacheid')
|
||||
return array('internal_id', $value);
|
||||
if ($key == 'uuid')
|
||||
return array('uuid', $value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Retrieve the list of URLs to check.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Retrieve the list of URLs to check.
|
||||
|
||||
$tmp = $request->get_parameter('urls');
|
||||
if (!$tmp)
|
||||
throw new ParamMissing('urls');
|
||||
$urls = explode('|', $tmp);
|
||||
$as_dict = $request->get_parameter('as_dict');
|
||||
if (!$as_dict) $as_dict = 'false';
|
||||
if (!in_array($as_dict, array('true', 'false')))
|
||||
throw new InvalidParam('as_dict');
|
||||
$as_dict = ($as_dict == 'true');
|
||||
$tmp = $request->get_parameter('urls');
|
||||
if (!$tmp)
|
||||
throw new ParamMissing('urls');
|
||||
$urls = explode('|', $tmp);
|
||||
$as_dict = $request->get_parameter('as_dict');
|
||||
if (!$as_dict) $as_dict = 'false';
|
||||
if (!in_array($as_dict, array('true', 'false')))
|
||||
throw new InvalidParam('as_dict');
|
||||
$as_dict = ($as_dict == 'true');
|
||||
|
||||
# Generate the lists of keys.
|
||||
# Generate the lists of keys.
|
||||
|
||||
$results = array();
|
||||
$urls_with = array(
|
||||
'cache_code' => array(),
|
||||
'internal_id' => array(),
|
||||
'uuid' => array()
|
||||
);
|
||||
foreach ($urls as &$url_ref)
|
||||
{
|
||||
$key = self::get_cache_key($url_ref);
|
||||
if ($key != null)
|
||||
$urls_with[$key[0]][$url_ref] = $key[1];
|
||||
else
|
||||
$results[$url_ref] = null;
|
||||
}
|
||||
$results = array();
|
||||
$urls_with = array(
|
||||
'cache_code' => array(),
|
||||
'internal_id' => array(),
|
||||
'uuid' => array()
|
||||
);
|
||||
foreach ($urls as &$url_ref)
|
||||
{
|
||||
$key = self::get_cache_key($url_ref);
|
||||
if ($key != null)
|
||||
$urls_with[$key[0]][$url_ref] = $key[1];
|
||||
else
|
||||
$results[$url_ref] = null;
|
||||
}
|
||||
|
||||
# Include 'cache_code' references.
|
||||
# Include 'cache_code' references.
|
||||
|
||||
foreach ($urls_with['cache_code'] as $url => $cache_code)
|
||||
$results[$url] = $cache_code;
|
||||
foreach ($urls_with['cache_code'] as $url => $cache_code)
|
||||
$results[$url] = $cache_code;
|
||||
|
||||
# Include 'internal_id' references.
|
||||
# Include 'internal_id' references.
|
||||
|
||||
$internal_ids = array_values($urls_with['internal_id']);
|
||||
if (count($internal_ids) > 0)
|
||||
{
|
||||
$rs = Db::query("
|
||||
select cache_id, wp_oc
|
||||
from caches
|
||||
where
|
||||
cache_id in ('".implode("','", array_map('mysql_real_escape_string', $internal_ids))."')
|
||||
and status in (1,2,3)
|
||||
");
|
||||
$dict = array();
|
||||
while ($row = mysql_fetch_assoc($rs))
|
||||
$dict[$row['cache_id']] = $row['wp_oc'];
|
||||
foreach ($urls_with['internal_id'] as $url => $internal_id)
|
||||
{
|
||||
if (isset($dict[$internal_id]))
|
||||
$results[$url] = $dict[$internal_id];
|
||||
else
|
||||
$results[$url] = null;
|
||||
}
|
||||
}
|
||||
$internal_ids = array_values($urls_with['internal_id']);
|
||||
if (count($internal_ids) > 0)
|
||||
{
|
||||
$rs = Db::query("
|
||||
select cache_id, wp_oc
|
||||
from caches
|
||||
where
|
||||
cache_id in ('".implode("','", array_map('mysql_real_escape_string', $internal_ids))."')
|
||||
and status in (1,2,3)
|
||||
");
|
||||
$dict = array();
|
||||
while ($row = mysql_fetch_assoc($rs))
|
||||
$dict[$row['cache_id']] = $row['wp_oc'];
|
||||
foreach ($urls_with['internal_id'] as $url => $internal_id)
|
||||
{
|
||||
if (isset($dict[$internal_id]))
|
||||
$results[$url] = $dict[$internal_id];
|
||||
else
|
||||
$results[$url] = null;
|
||||
}
|
||||
}
|
||||
|
||||
# Include 'uuid' references.
|
||||
# Include 'uuid' references.
|
||||
|
||||
$uuids = array_values($urls_with['uuid']);
|
||||
if (count($uuids) > 0)
|
||||
{
|
||||
$rs = Db::query("
|
||||
select uuid, wp_oc
|
||||
from caches
|
||||
where
|
||||
uuid in ('".implode("','", array_map('mysql_real_escape_string', $uuids))."')
|
||||
and status in (1,2,3)
|
||||
");
|
||||
$dict = array();
|
||||
while ($row = mysql_fetch_assoc($rs))
|
||||
$dict[$row['uuid']] = $row['wp_oc'];
|
||||
foreach ($urls_with['uuid'] as $url => $uuid)
|
||||
{
|
||||
if (isset($dict[$uuid]))
|
||||
$results[$url] = $dict[$uuid];
|
||||
else
|
||||
$results[$url] = null;
|
||||
}
|
||||
}
|
||||
$uuids = array_values($urls_with['uuid']);
|
||||
if (count($uuids) > 0)
|
||||
{
|
||||
$rs = Db::query("
|
||||
select uuid, wp_oc
|
||||
from caches
|
||||
where
|
||||
uuid in ('".implode("','", array_map('mysql_real_escape_string', $uuids))."')
|
||||
and status in (1,2,3)
|
||||
");
|
||||
$dict = array();
|
||||
while ($row = mysql_fetch_assoc($rs))
|
||||
$dict[$row['uuid']] = $row['wp_oc'];
|
||||
foreach ($urls_with['uuid'] as $url => $uuid)
|
||||
{
|
||||
if (isset($dict[$uuid]))
|
||||
$results[$url] = $dict[$uuid];
|
||||
else
|
||||
$results[$url] = null;
|
||||
}
|
||||
}
|
||||
|
||||
# Format the results according to the 'as_dict' parameter.
|
||||
# Format the results according to the 'as_dict' parameter.
|
||||
|
||||
if ($as_dict)
|
||||
return Okapi::formatted_response($request, $results);
|
||||
else
|
||||
{
|
||||
$cache_codes = array();
|
||||
foreach ($results as $url => $cache_code)
|
||||
if ($cache_code != null)
|
||||
$cache_codes[$cache_code] = true;
|
||||
$flattened = array('results' => array_keys($cache_codes));
|
||||
return Okapi::formatted_response($request, $flattened);
|
||||
}
|
||||
}
|
||||
if ($as_dict)
|
||||
return Okapi::formatted_response($request, $results);
|
||||
else
|
||||
{
|
||||
$cache_codes = array();
|
||||
foreach ($results as $url => $cache_code)
|
||||
if ($cache_code != null)
|
||||
$cache_codes[$cache_code] = true;
|
||||
$flattened = array('results' => array_keys($cache_codes));
|
||||
return Okapi::formatted_response($request, $flattened);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
<xml>
|
||||
<brief>Resolve cache references from given URLs</brief>
|
||||
<issue-id>116</issue-id>
|
||||
<desc>
|
||||
<p>Given a set of URLs, determine codes of geocaches referenced within them.</p>
|
||||
<p>This might be useful if you have a link to an Opencaching geocache page, but you're
|
||||
not able to extract cache code from such link (and you need the cache code to operate
|
||||
on a cache using OKAPI). Geocache pages may be referenced using various types of URLs,
|
||||
only some of them contain the cache code.</p>
|
||||
</desc>
|
||||
<req name='urls'>
|
||||
<p>Pipe-separated list of URLs. No more than 500.</p>
|
||||
</req>
|
||||
<opt name='as_dict' default='false'>
|
||||
<p>If <b>false</b>, then the result of this method will be compatible with
|
||||
search/all method (and therefore can be used with search_and_retrieve).</p>
|
||||
<p>If <b>true</b>, then the result will be a dictionary. Your URLs will be
|
||||
mapped to the keys of this dictionary. Each value will be either a string
|
||||
(cache code) or null (if no cache code was found for the given URL).</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>As described in the <b>as_dict</b> parameter.</p>
|
||||
<p>Examples:</p>
|
||||
<p>For <i>by_urls?urls=url1|url2|url3</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"results": ["OP28F9"]}</pre>
|
||||
<p>For <i>by_urls?urls=url1|url2|url3&as_dict=true</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"url1": "OP28F9", "url2": null, "url3": "OP28F9"}</pre>
|
||||
</returns>
|
||||
<brief>Resolve cache references from given URLs</brief>
|
||||
<issue-id>116</issue-id>
|
||||
<desc>
|
||||
<p>Given a set of URLs, determine codes of geocaches referenced within them.</p>
|
||||
<p>This might be useful if you have a link to an Opencaching geocache page, but you're
|
||||
not able to extract cache code from such link (and you need the cache code to operate
|
||||
on a cache using OKAPI). Geocache pages may be referenced using various types of URLs,
|
||||
only some of them contain the cache code.</p>
|
||||
</desc>
|
||||
<req name='urls'>
|
||||
<p>Pipe-separated list of URLs. No more than 500.</p>
|
||||
</req>
|
||||
<opt name='as_dict' default='false'>
|
||||
<p>If <b>false</b>, then the result of this method will be compatible with
|
||||
search/all method (and therefore can be used with search_and_retrieve).</p>
|
||||
<p>If <b>true</b>, then the result will be a dictionary. Your URLs will be
|
||||
mapped to the keys of this dictionary. Each value will be either a string
|
||||
(cache code) or null (if no cache code was found for the given URL).</p>
|
||||
</opt>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>As described in the <b>as_dict</b> parameter.</p>
|
||||
<p>Examples:</p>
|
||||
<p>For <i>by_urls?urls=url1|url2|url3</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"results": ["OP28F9"]}</pre>
|
||||
<p>For <i>by_urls?urls=url1|url2|url3&as_dict=true</i>
|
||||
query, the result might look something link this:</p>
|
||||
<pre>{"url1": "OP28F9", "url2": null, "url3": "OP28F9"}</pre>
|
||||
</returns>
|
||||
</xml>
|
||||
|
||||
@@ -12,75 +12,82 @@ use okapi\services\caches\search\SearchAssistant;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# You may wonder, why there are no parameters like "bbox" or "center" in the
|
||||
# "search/all" method. This is *intentional* and should be kept this way.
|
||||
# Such parameters would fall in conflict with each other and - in result -
|
||||
# make the documentation very fuzzy. That's why they were intentionally
|
||||
# left out of the "search/all" method, and put in separate (individual) ones.
|
||||
# It's much easier to grasp their meaning this way.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# You may wonder, why there are no parameters like "bbox" or "center" in the
|
||||
# "search/all" method. This is *intentional* and should be kept this way.
|
||||
# Such parameters would fall in conflict with each other and - in result -
|
||||
# make the documentation very fuzzy. That's why they were intentionally
|
||||
# left out of the "search/all" method, and put in separate (individual) ones.
|
||||
# It's much easier to grasp their meaning this way.
|
||||
|
||||
$tmp = $request->get_parameter('center');
|
||||
if (!$tmp)
|
||||
throw new ParamMissing('center');
|
||||
$parts = explode('|', $tmp);
|
||||
if (count($parts) != 2)
|
||||
throw new InvalidParam('center', "Expecting 2 pipe-separated parts, got ".count($parts).".");
|
||||
foreach ($parts as &$part_ref)
|
||||
{
|
||||
if (!preg_match("/^-?[0-9]+(\.?[0-9]*)$/", $part_ref))
|
||||
throw new InvalidParam('center', "'$part_ref' is not a valid float number.");
|
||||
$part_ref = floatval($part_ref);
|
||||
}
|
||||
list($center_lat, $center_lon) = $parts;
|
||||
if ($center_lat > 90 || $center_lat < -90)
|
||||
throw new InvalidParam('center', "Latitudes have to be within -90..90 range.");
|
||||
if ($center_lon > 180 || $center_lon < -180)
|
||||
throw new InvalidParam('center', "Longitudes have to be within -180..180 range.");
|
||||
$tmp = $request->get_parameter('center');
|
||||
if (!$tmp)
|
||||
throw new ParamMissing('center');
|
||||
$parts = explode('|', $tmp);
|
||||
if (count($parts) != 2)
|
||||
throw new InvalidParam('center', "Expecting 2 pipe-separated parts, got ".count($parts).".");
|
||||
foreach ($parts as &$part_ref)
|
||||
{
|
||||
if (!preg_match("/^-?[0-9]+(\.?[0-9]*)$/", $part_ref))
|
||||
throw new InvalidParam('center', "'$part_ref' is not a valid float number.");
|
||||
$part_ref = floatval($part_ref);
|
||||
}
|
||||
list($center_lat, $center_lon) = $parts;
|
||||
if ($center_lat > 90 || $center_lat < -90)
|
||||
throw new InvalidParam('center', "Latitudes have to be within -90..90 range.");
|
||||
if ($center_lon > 180 || $center_lon < -180)
|
||||
throw new InvalidParam('center', "Longitudes have to be within -180..180 range.");
|
||||
|
||||
#
|
||||
# In the method description, we promised to return caches ordered by the *rough*
|
||||
# distance from the center point. We'll use ORDER BY with a simplified distance
|
||||
# formula and combine it with the LIMIT clause to get the best results.
|
||||
#
|
||||
#
|
||||
# In the method description, we promised to return caches ordered by the *rough*
|
||||
# distance from the center point. We'll use ORDER BY with a simplified distance
|
||||
# formula and combine it with the LIMIT clause to get the best results.
|
||||
#
|
||||
|
||||
$distance_formula = Okapi::get_distance_sql($center_lat, $center_lon, "caches.latitude", "caches.longitude");
|
||||
$search_assistant = new SearchAssistant($request);
|
||||
$search_assistant->prepare_common_search_params();
|
||||
$search_assistant->prepare_location_search_params();
|
||||
$distance_formula = Okapi::get_distance_sql(
|
||||
$center_lat, $center_lon,
|
||||
$search_assistant->get_latitude_expr(), $search_assistant->get_longitude_expr()
|
||||
);
|
||||
|
||||
# 'radius' parameter is optional. If not given, we'll have to calculate the
|
||||
# distance for every cache in the database.
|
||||
# 'radius' parameter is optional. If not given, we'll have to calculate the
|
||||
# distance for every cache in the database.
|
||||
|
||||
$where_conds = array();
|
||||
$radius = null;
|
||||
if ($tmp = $request->get_parameter('radius'))
|
||||
{
|
||||
if (!preg_match("/^-?[0-9]+(\.?[0-9]*)$/", $tmp))
|
||||
throw new InvalidParam('radius', "'$tmp' is not a valid float number.");
|
||||
$radius = floatval($tmp);
|
||||
if ($radius <= 0)
|
||||
throw new InvalidParam('radius', "Has to be a positive number.");
|
||||
$radius *= 1000; # this one is given in kilemeters, converting to meters!
|
||||
$where_conds[] = "$distance_formula <= '".mysql_real_escape_string($radius)."'";
|
||||
}
|
||||
$where_conds = array();
|
||||
$radius = null;
|
||||
if ($tmp = $request->get_parameter('radius'))
|
||||
{
|
||||
if (!preg_match("/^-?[0-9]+(\.?[0-9]*)$/", $tmp))
|
||||
throw new InvalidParam('radius', "'$tmp' is not a valid float number.");
|
||||
$radius = floatval($tmp);
|
||||
if ($radius <= 0)
|
||||
throw new InvalidParam('radius', "Has to be a positive number.");
|
||||
$radius *= 1000; # this one is given in kilemeters, converting to meters!
|
||||
$where_conds[] = "$distance_formula <= '".mysql_real_escape_string($radius)."'";
|
||||
}
|
||||
|
||||
$search_params = SearchAssistant::get_common_search_params($request);
|
||||
$search_params['where_conds'] = array_merge($where_conds, $search_params['where_conds']);
|
||||
$search_params['order_by'][] = $distance_formula; # not replaced; added to the end!
|
||||
$search_params = $search_assistant->get_search_params();
|
||||
$search_params['where_conds'] = array_merge($where_conds, $search_params['where_conds']);
|
||||
$search_params['order_by'][] = $distance_formula; # not replaced; added to the end!
|
||||
$search_assistant->set_search_params($search_params);
|
||||
|
||||
$result = SearchAssistant::get_common_search_result($search_params);
|
||||
if ($radius == null)
|
||||
{
|
||||
# 'more' is meaningless in this case, we'll remove it.
|
||||
unset($result['more']);
|
||||
}
|
||||
$result = $search_assistant->get_common_search_result();
|
||||
if ($radius == null)
|
||||
{
|
||||
# 'more' is meaningless in this case, we'll remove it.
|
||||
unset($result['more']);
|
||||
}
|
||||
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,44 @@
|
||||
<xml>
|
||||
<brief>Search for nearest geocaches</brief>
|
||||
<issue-id>17</issue-id>
|
||||
<desc>
|
||||
<p>Find the nearest geocaches. Unless overriden, results are ordered by the distance from
|
||||
the given center point.</p>
|
||||
<p>Usually you will want to use search_and_retrieve method instead of this one.
|
||||
This way, you can get much more data in <b>one request</b>.</p>
|
||||
</desc>
|
||||
<req name='center'>
|
||||
<p>The center point (typically - the user's location), in the
|
||||
"lat|lon" format.</p>
|
||||
<p>Use positive numbers for latitudes in the northern hemisphere and
|
||||
longitudes in the eastern hemisphere (and negative for southern and
|
||||
western hemispheres accordingly). These are full degrees with a dot
|
||||
as a decimal point (ex. "54.3|22.3").</p>
|
||||
</req>
|
||||
<opt name='radius'>
|
||||
<p>Maximal distance (from the center point) for the cache to
|
||||
be included in the results. Unlike in most other places, this
|
||||
distance is given <b>in kilometers</b> instead of meters
|
||||
(it can contain a floating point though).</p>
|
||||
</opt>
|
||||
<import-params method='services/caches/search/all'/>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>Same format as in the search/all method. The <b>more</b> key will
|
||||
be skipped when no <b>radius</b> argument is given.</p>
|
||||
</returns>
|
||||
<brief>Search for nearest geocaches</brief>
|
||||
<issue-id>17</issue-id>
|
||||
<desc>
|
||||
<p>Find the nearest geocaches. Unless overriden, results are ordered by the distance from
|
||||
the given center point.</p>
|
||||
<p>Usually you will want to use search_and_retrieve method instead of this one.
|
||||
This way, you can get much more data in <b>one request</b>.</p>
|
||||
</desc>
|
||||
<req name='center'>
|
||||
<p>The center point (typically - the user's location), in the
|
||||
"lat|lon" format.</p>
|
||||
<p>Use positive numbers for latitudes in the northern hemisphere and
|
||||
longitudes in the eastern hemisphere (and negative for southern and
|
||||
western hemispheres accordingly). These are full degrees with a dot
|
||||
as a decimal point (ex. "54.3|22.3").</p>
|
||||
</req>
|
||||
<opt name='radius'>
|
||||
<p>Maximal distance (from the center point) for the cache to
|
||||
be included in the results. Unlike in most other places, this
|
||||
distance is given <b>in kilometers</b> instead of meters
|
||||
(it can contain a floating point though).</p>
|
||||
</opt>
|
||||
<opt name='location_source' default='default-coords'>
|
||||
<p>In general, this parameter should take the same value as in the
|
||||
<a href="%OKAPI:methodargref:services/caches/formatters/gpx#location_source%">
|
||||
services/caches/formatters/gpx</a> method, but currently <u>only two values are
|
||||
supported</u>: <b>default-coords</b> and <b>alt_wpt:user-coords</b>.</p>
|
||||
|
||||
<p>Allows you to search among alternate locations of the geocache,
|
||||
instead of the default one. Particularily useful with <b>alt_wpt:user-coords</b>
|
||||
alternate waypoint.</p>
|
||||
|
||||
<p>Please note, that if you plan on using this option in conjunction
|
||||
with <b>search_and_retrieve</b> method, then you'd probably want to use
|
||||
the same option in your <i>retr_method</i> too (if available).</p>
|
||||
</opt>
|
||||
<import-params method='services/caches/search/all'/>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>Same format as in the search/all method. The <b>more</b> key will
|
||||
be skipped when no <b>radius</b> argument is given.</p>
|
||||
</returns>
|
||||
</xml>
|
||||
|
||||
@@ -14,169 +14,171 @@ use okapi\services\caches\search\SearchAssistant;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get [set_id, date_created, expires] for the given params_hash
|
||||
* (or [null, null, null] if not found).
|
||||
*/
|
||||
private static function find_param_set($params_hash, $ref_max_age)
|
||||
{
|
||||
$tmp = Db::select_row("
|
||||
select
|
||||
id as id,
|
||||
unix_timestamp(date_created) as date_created,
|
||||
unix_timestamp(expires) as expires
|
||||
from okapi_search_sets
|
||||
where
|
||||
params_hash = '".mysql_real_escape_string($params_hash)."'
|
||||
and date_add(date_created, interval '".mysql_real_escape_string($ref_max_age)."' second) > now()
|
||||
order by id desc
|
||||
limit 1
|
||||
");
|
||||
if ($tmp === null)
|
||||
return array(null, null, null);
|
||||
return array($tmp['id'], $tmp['date_created'], $tmp['expires']);
|
||||
}
|
||||
/**
|
||||
* Get [set_id, date_created, expires] for the given params_hash
|
||||
* (or [null, null, null] if not found).
|
||||
*/
|
||||
private static function find_param_set($params_hash, $ref_max_age)
|
||||
{
|
||||
$tmp = Db::select_row("
|
||||
select
|
||||
id as id,
|
||||
unix_timestamp(date_created) as date_created,
|
||||
unix_timestamp(expires) as expires
|
||||
from okapi_search_sets
|
||||
where
|
||||
params_hash = '".mysql_real_escape_string($params_hash)."'
|
||||
and date_add(date_created, interval '".mysql_real_escape_string($ref_max_age)."' second) > now()
|
||||
order by id desc
|
||||
limit 1
|
||||
");
|
||||
if ($tmp === null)
|
||||
return array(null, null, null);
|
||||
return array($tmp['id'], $tmp['date_created'], $tmp['expires']);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# "Cache control" parameters.
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# "Cache control" parameters.
|
||||
|
||||
$tmp = $request->get_parameter('min_store');
|
||||
if ($tmp === null) $tmp = "300";
|
||||
$min_store = intval($tmp);
|
||||
if (("$min_store" !== $tmp) ||($min_store < 0) || ($min_store > 64800))
|
||||
throw new InvalidParam('min_store', "Has to be in the 0..64800 range.");
|
||||
$tmp = $request->get_parameter('min_store');
|
||||
if ($tmp === null) $tmp = "300";
|
||||
$min_store = intval($tmp);
|
||||
if (("$min_store" !== $tmp) ||($min_store < 0) || ($min_store > 64800))
|
||||
throw new InvalidParam('min_store', "Has to be in the 0..64800 range.");
|
||||
|
||||
$tmp = $request->get_parameter('ref_max_age');
|
||||
if ($tmp === null) $tmp = "300";
|
||||
if ($tmp == "nolimit") $tmp = "9999999";
|
||||
$ref_max_age = intval($tmp);
|
||||
if (("$ref_max_age" !== $tmp) || ($ref_max_age < 300))
|
||||
throw new InvalidParam('ref_max_age', "Has to be >=300.");
|
||||
$tmp = $request->get_parameter('ref_max_age');
|
||||
if ($tmp === null) $tmp = "300";
|
||||
if ($tmp == "nolimit") $tmp = "9999999";
|
||||
$ref_max_age = intval($tmp);
|
||||
if (("$ref_max_age" !== $tmp) || ($ref_max_age < 300))
|
||||
throw new InvalidParam('ref_max_age', "Has to be >=300.");
|
||||
|
||||
# Search params.
|
||||
# Search params.
|
||||
|
||||
$search_params = SearchAssistant::get_common_search_params($request);
|
||||
$tables = array_merge(
|
||||
array('caches'),
|
||||
$search_params['extra_tables']
|
||||
);
|
||||
$where_conds = array_merge(
|
||||
array('caches.wp_oc is not null'),
|
||||
$search_params['where_conds']
|
||||
);
|
||||
unset($search_params);
|
||||
$search_assistant = new SearchAssistant($request);
|
||||
$search_assistant->prepare_common_search_params();
|
||||
$search_params = $search_assistant->get_search_params();
|
||||
$tables = array_merge(
|
||||
array('caches'),
|
||||
$search_params['extra_tables']
|
||||
);
|
||||
$where_conds = array_merge(
|
||||
array('caches.wp_oc is not null'),
|
||||
$search_params['where_conds']
|
||||
);
|
||||
unset($search_params);
|
||||
|
||||
# Generate, or retrieve an existing set, and return the result.
|
||||
# All user-supplied data in $tables and $where_conds MUST be escaped!
|
||||
# Generate, or retrieve an existing set, and return the result.
|
||||
# All user-supplied data in $tables and $where_conds MUST be escaped!
|
||||
|
||||
$result = self::get_set($tables, $where_conds, $min_store, $ref_max_age);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
$result = self::get_set($tables, $where_conds, $min_store, $ref_max_age);
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Important: YOU HAVE TO make sure $tables and $where_conds don't contain
|
||||
* unescaped user-supplied data!
|
||||
*/
|
||||
public static function get_set($tables, $where_conds, $min_store, $ref_max_age)
|
||||
{
|
||||
# Compute the "params hash".
|
||||
/**
|
||||
* Important: YOU HAVE TO make sure $tables and $where_conds don't contain
|
||||
* unescaped user-supplied data!
|
||||
*/
|
||||
public static function get_set($tables, $where_conds, $min_store, $ref_max_age)
|
||||
{
|
||||
# Compute the "params hash".
|
||||
|
||||
$params_hash = md5(serialize(array($tables, $where_conds)));
|
||||
$params_hash = md5(serialize(array($tables, $where_conds)));
|
||||
|
||||
# Check if there exists an entry for this hash, which also meets the
|
||||
# given freshness criteria.
|
||||
# Check if there exists an entry for this hash, which also meets the
|
||||
# given freshness criteria.
|
||||
|
||||
list($set_id, $date_created, $expires) = self::find_param_set($params_hash, $ref_max_age);
|
||||
if ($set_id === null)
|
||||
{
|
||||
# To avoid generating the same results by multiple threads at once
|
||||
# (the "tile" method uses the "save" method, so the problem is
|
||||
# quite real!), we will acquire a write-lock here.
|
||||
list($set_id, $date_created, $expires) = self::find_param_set($params_hash, $ref_max_age);
|
||||
if ($set_id === null)
|
||||
{
|
||||
# To avoid generating the same results by multiple threads at once
|
||||
# (the "tile" method uses the "save" method, so the problem is
|
||||
# quite real!), we will acquire a write-lock here.
|
||||
|
||||
$lock = OkapiLock::get("search-results-writer");
|
||||
$lock->acquire();
|
||||
$lock = OkapiLock::get("search-results-writer");
|
||||
$lock->acquire();
|
||||
|
||||
try
|
||||
{
|
||||
# Make sure we were the first to acquire the lock.
|
||||
try
|
||||
{
|
||||
# Make sure we were the first to acquire the lock.
|
||||
|
||||
list($set_id, $date_created, $expires) = self::find_param_set($params_hash, $ref_max_age);
|
||||
if ($set_id === null)
|
||||
{
|
||||
# We are in the first thread which have acquired the lock.
|
||||
# We will proceed with result-set creation. Other threads
|
||||
# will be waiting until we finish.
|
||||
list($set_id, $date_created, $expires) = self::find_param_set($params_hash, $ref_max_age);
|
||||
if ($set_id === null)
|
||||
{
|
||||
# We are in the first thread which have acquired the lock.
|
||||
# We will proceed with result-set creation. Other threads
|
||||
# will be waiting until we finish.
|
||||
|
||||
Db::execute("
|
||||
insert into okapi_search_sets (params_hash, date_created, expires)
|
||||
values (
|
||||
'processing in progress',
|
||||
now(),
|
||||
date_add(now(), interval '".mysql_real_escape_string($min_store + 60)."' second)
|
||||
)
|
||||
");
|
||||
$set_id = Db::last_insert_id();
|
||||
$date_created = time();
|
||||
$expires = $date_created + $min_store + 60;
|
||||
Db::execute("
|
||||
insert into okapi_search_results (set_id, cache_id)
|
||||
select distinct
|
||||
'".mysql_real_escape_string($set_id)."',
|
||||
caches.cache_id
|
||||
from ".implode(", ", $tables)."
|
||||
where (".implode(") and (", $where_conds).")
|
||||
");
|
||||
Db::execute("
|
||||
insert into okapi_search_sets (params_hash, date_created, expires)
|
||||
values (
|
||||
'processing in progress',
|
||||
now(),
|
||||
date_add(now(), interval '".mysql_real_escape_string($min_store + 60)."' second)
|
||||
)
|
||||
");
|
||||
$set_id = Db::last_insert_id();
|
||||
$date_created = time();
|
||||
$expires = $date_created + $min_store + 60;
|
||||
Db::execute("
|
||||
insert into okapi_search_results (set_id, cache_id)
|
||||
select distinct
|
||||
'".mysql_real_escape_string($set_id)."',
|
||||
caches.cache_id
|
||||
from ".implode(", ", $tables)."
|
||||
where (".implode(") and (", $where_conds).")
|
||||
");
|
||||
|
||||
# Lock barrier, to make sure the data is visible by other
|
||||
# sessions. See http://bugs.mysql.com/bug.php?id=36618
|
||||
# Lock barrier, to make sure the data is visible by other
|
||||
# sessions. See http://bugs.mysql.com/bug.php?id=36618
|
||||
|
||||
Db::execute("lock table okapi_search_results write");
|
||||
Db::execute("unlock tables");
|
||||
Db::execute("lock table okapi_search_results write");
|
||||
Db::execute("unlock tables");
|
||||
|
||||
Db::execute("
|
||||
update okapi_search_sets
|
||||
set params_hash = '".mysql_real_escape_string($params_hash)."'
|
||||
where id = '".mysql_real_escape_string($set_id)."'
|
||||
");
|
||||
} else {
|
||||
# Some other thread acquired the lock before us and it has
|
||||
# generated the result set. We don't need to do anything.
|
||||
}
|
||||
$lock->release();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
# SQL error? Make sure the lock is released and rethrow.
|
||||
Db::execute("
|
||||
update okapi_search_sets
|
||||
set params_hash = '".mysql_real_escape_string($params_hash)."'
|
||||
where id = '".mysql_real_escape_string($set_id)."'
|
||||
");
|
||||
} else {
|
||||
# Some other thread acquired the lock before us and it has
|
||||
# generated the result set. We don't need to do anything.
|
||||
}
|
||||
$lock->release();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
# SQL error? Make sure the lock is released and rethrow.
|
||||
|
||||
$lock->release();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
$lock->release();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
# If we got an old set, we may need to expand its lifetime in order to
|
||||
# meet user's "min_store" criterium.
|
||||
# If we got an old set, we may need to expand its lifetime in order to
|
||||
# meet user's "min_store" criterium.
|
||||
|
||||
if (time() + $min_store > $expires)
|
||||
{
|
||||
Db::execute("
|
||||
update okapi_search_sets
|
||||
set expires = date_add(now(), interval '".mysql_real_escape_string($min_store + 60)."' second)
|
||||
where id = '".mysql_real_escape_string($set_id)."'
|
||||
");
|
||||
}
|
||||
if (time() + $min_store > $expires)
|
||||
{
|
||||
Db::execute("
|
||||
update okapi_search_sets
|
||||
set expires = date_add(now(), interval '".mysql_real_escape_string($min_store + 60)."' second)
|
||||
where id = '".mysql_real_escape_string($set_id)."'
|
||||
");
|
||||
}
|
||||
|
||||
return array(
|
||||
'set_id' => "$set_id",
|
||||
'generated_at' => date('c', $date_created),
|
||||
'expires' => date('c', $expires),
|
||||
);
|
||||
}
|
||||
return array(
|
||||
'set_id' => "$set_id",
|
||||
'generated_at' => date('c', $date_created),
|
||||
'expires' => date('c', $expires),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
<xml>
|
||||
<brief>Save a search result set</brief>
|
||||
<issue-id>163</issue-id>
|
||||
<desc>
|
||||
<p>This works similar to the <b>search/all</b> method, but the returned
|
||||
set of geocaches is temporarilly stored, instead of being directly
|
||||
returned to you.</p>
|
||||
<p>You may want to use this method when you don't want your search
|
||||
results modified while the user is browsing through them, page by page.
|
||||
To view a portion of a saved search, use the <b>search/all</b>
|
||||
method with proper <b>set_and</b> <u>and <b>status</b></u> (!)
|
||||
parameters.</p>
|
||||
</desc>
|
||||
<opt name='min_store' default="300">
|
||||
The amount of time (in seconds) after which you allow OKAPI to delete
|
||||
the set (OKAPI <b>may</b> remove it, but doesn't have to).
|
||||
The maximum allowed value is 64800 (18 hours).
|
||||
</opt>
|
||||
<opt name='ref_max_age' default="300">
|
||||
<p>If OKAPI finds an existing result set which was created for your
|
||||
search query, it may return the ID of this existing set (and possibly
|
||||
extend its lifetime so it fits your <b>min_store</b>). What is the
|
||||
maximum age of the existing result set which you are willing to accept?</p>
|
||||
<p>This should be an integer (in seconds) <b>or</b> a special
|
||||
<b>nolimit</b> value. It must be greater or equal to 300 (5 minutes).</p>
|
||||
</opt>
|
||||
<import-params method='services/caches/search/all' except="offset|limit|order_by"/>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>set_id</b> - string, the identifier of your saved set,
|
||||
for future reference.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
<brief>Save a search result set</brief>
|
||||
<issue-id>163</issue-id>
|
||||
<desc>
|
||||
<p>This works similar to the <b>search/all</b> method, but the returned
|
||||
set of geocaches is temporarilly stored, instead of being directly
|
||||
returned to you.</p>
|
||||
<p>You may want to use this method when you don't want your search
|
||||
results modified while the user is browsing through them, page by page.
|
||||
To view a portion of a saved search, use the <b>search/all</b>
|
||||
method with proper <b>set_and</b> <u>and <b>status</b></u> (!)
|
||||
parameters.</p>
|
||||
</desc>
|
||||
<opt name='min_store' default="300">
|
||||
The amount of time (in seconds) after which you allow OKAPI to delete
|
||||
the set (OKAPI <b>may</b> remove it, but doesn't have to).
|
||||
The maximum allowed value is 64800 (18 hours).
|
||||
</opt>
|
||||
<opt name='ref_max_age' default="300">
|
||||
<p>If OKAPI finds an existing result set which was created for your
|
||||
search query, it may return the ID of this existing set (and possibly
|
||||
extend its lifetime so it fits your <b>min_store</b>). What is the
|
||||
maximum age of the existing result set which you are willing to accept?</p>
|
||||
<p>This should be an integer (in seconds) <b>or</b> a special
|
||||
<b>nolimit</b> value. It must be greater or equal to 300 (5 minutes).</p>
|
||||
</opt>
|
||||
<import-params method='services/caches/search/all' except="offset|limit|order_by"/>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>set_id</b> - string, the identifier of your saved set,
|
||||
for future reference.</li>
|
||||
</ul>
|
||||
</returns>
|
||||
</xml>
|
||||
|
||||
@@ -13,109 +13,109 @@ use okapi\BadRequest;
|
||||
|
||||
class WebService
|
||||
{
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
public static function options()
|
||||
{
|
||||
return array(
|
||||
'min_auth_level' => 1
|
||||
);
|
||||
}
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Check search method
|
||||
$search_method = $request->get_parameter('search_method');
|
||||
if (!$search_method)
|
||||
throw new ParamMissing('search_method');
|
||||
if (strpos($search_method, "services/caches/search/") !== 0)
|
||||
throw new InvalidParam('search_method', "Should begin with 'services/caches/search/'.");
|
||||
if (!OkapiServiceRunner::exists($search_method))
|
||||
throw new InvalidParam('search_method', "Method does not exist: '$search_method'");
|
||||
$search_params = $request->get_parameter('search_params');
|
||||
if (!$search_params)
|
||||
throw new ParamMissing('search_params');
|
||||
$search_params = json_decode($search_params, true);
|
||||
if (!is_array($search_params))
|
||||
throw new InvalidParam('search_params', "Should be a JSON-encoded dictionary");
|
||||
public static function call(OkapiRequest $request)
|
||||
{
|
||||
# Check search method
|
||||
$search_method = $request->get_parameter('search_method');
|
||||
if (!$search_method)
|
||||
throw new ParamMissing('search_method');
|
||||
if (strpos($search_method, "services/caches/search/") !== 0)
|
||||
throw new InvalidParam('search_method', "Should begin with 'services/caches/search/'.");
|
||||
if (!OkapiServiceRunner::exists($search_method))
|
||||
throw new InvalidParam('search_method', "Method does not exist: '$search_method'");
|
||||
$search_params = $request->get_parameter('search_params');
|
||||
if (!$search_params)
|
||||
throw new ParamMissing('search_params');
|
||||
$search_params = json_decode($search_params, true);
|
||||
if (!is_array($search_params))
|
||||
throw new InvalidParam('search_params', "Should be a JSON-encoded dictionary");
|
||||
|
||||
# Check retrieval method
|
||||
$retr_method = $request->get_parameter('retr_method');
|
||||
if (!$retr_method)
|
||||
throw new ParamMissing('retr_method');
|
||||
if (!OkapiServiceRunner::exists($retr_method))
|
||||
throw new InvalidParam('retr_method', "Method does not exist: '$retr_method'");
|
||||
$retr_params = $request->get_parameter('retr_params');
|
||||
if (!$retr_params)
|
||||
throw new ParamMissing('retr_params');
|
||||
$retr_params = json_decode($retr_params, true);
|
||||
if (!is_array($retr_params))
|
||||
throw new InvalidParam('retr_params', "Should be a JSON-encoded dictionary");
|
||||
# Check retrieval method
|
||||
$retr_method = $request->get_parameter('retr_method');
|
||||
if (!$retr_method)
|
||||
throw new ParamMissing('retr_method');
|
||||
if (!OkapiServiceRunner::exists($retr_method))
|
||||
throw new InvalidParam('retr_method', "Method does not exist: '$retr_method'");
|
||||
$retr_params = $request->get_parameter('retr_params');
|
||||
if (!$retr_params)
|
||||
throw new ParamMissing('retr_params');
|
||||
$retr_params = json_decode($retr_params, true);
|
||||
if (!is_array($retr_params))
|
||||
throw new InvalidParam('retr_params', "Should be a JSON-encoded dictionary");
|
||||
|
||||
self::map_values_to_strings($search_params);
|
||||
self::map_values_to_strings($retr_params);
|
||||
self::map_values_to_strings($search_params);
|
||||
self::map_values_to_strings($retr_params);
|
||||
|
||||
# Wrapped?
|
||||
$wrap = $request->get_parameter('wrap');
|
||||
if ($wrap == null) throw new ParamMissing('wrap');
|
||||
if (!in_array($wrap, array('true', 'false')))
|
||||
throw new InvalidParam('wrap');
|
||||
$wrap = ($wrap == 'true');
|
||||
# Wrapped?
|
||||
$wrap = $request->get_parameter('wrap');
|
||||
if ($wrap == null) throw new ParamMissing('wrap');
|
||||
if (!in_array($wrap, array('true', 'false')))
|
||||
throw new InvalidParam('wrap');
|
||||
$wrap = ($wrap == 'true');
|
||||
|
||||
# Run search method
|
||||
try
|
||||
{
|
||||
$search_result = OkapiServiceRunner::call($search_method, new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, $search_params));
|
||||
}
|
||||
catch (BadRequest $e)
|
||||
{
|
||||
throw new InvalidParam('search_params', "Search method responded with the ".
|
||||
"following error message: ".$e->getMessage());
|
||||
}
|
||||
# Run search method
|
||||
try
|
||||
{
|
||||
$search_result = OkapiServiceRunner::call($search_method, new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, $search_params));
|
||||
}
|
||||
catch (BadRequest $e)
|
||||
{
|
||||
throw new InvalidParam('search_params', "Search method responded with the ".
|
||||
"following error message: ".$e->getMessage());
|
||||
}
|
||||
|
||||
# Run retrieval method
|
||||
try
|
||||
{
|
||||
$retr_result = OkapiServiceRunner::call($retr_method, new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array_merge($retr_params,
|
||||
array('cache_codes' => implode("|", $search_result['results'])))));
|
||||
}
|
||||
catch (BadRequest $e)
|
||||
{
|
||||
throw new InvalidParam('retr_params', "Retrieval method responded with the ".
|
||||
"following error message: ".$e->getMessage());
|
||||
}
|
||||
# Run retrieval method
|
||||
try
|
||||
{
|
||||
$retr_result = OkapiServiceRunner::call($retr_method, new OkapiInternalRequest(
|
||||
$request->consumer, $request->token, array_merge($retr_params,
|
||||
array('cache_codes' => implode("|", $search_result['results'])))));
|
||||
}
|
||||
catch (BadRequest $e)
|
||||
{
|
||||
throw new InvalidParam('retr_params', "Retrieval method responded with the ".
|
||||
"following error message: ".$e->getMessage());
|
||||
}
|
||||
|
||||
if ($wrap)
|
||||
{
|
||||
# $retr_result might be a PHP object, but also might be a binary response
|
||||
# (e.g. a GPX file).
|
||||
if ($retr_result instanceof OkapiHttpResponse)
|
||||
$result = array('results' => $retr_result->get_body());
|
||||
else
|
||||
$result = array('results' => $retr_result);
|
||||
foreach ($search_result as $key => &$value_ref)
|
||||
if ($key != 'results')
|
||||
$result[$key] = $value_ref;
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($retr_result instanceof OkapiHttpResponse)
|
||||
return $retr_result;
|
||||
else
|
||||
return Okapi::formatted_response($request, $retr_result);
|
||||
}
|
||||
}
|
||||
if ($wrap)
|
||||
{
|
||||
# $retr_result might be a PHP object, but also might be a binary response
|
||||
# (e.g. a GPX file).
|
||||
if ($retr_result instanceof OkapiHttpResponse)
|
||||
$result = array('results' => $retr_result->get_body());
|
||||
else
|
||||
$result = array('results' => $retr_result);
|
||||
foreach ($search_result as $key => &$value_ref)
|
||||
if ($key != 'results')
|
||||
$result[$key] = $value_ref;
|
||||
return Okapi::formatted_response($request, $result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($retr_result instanceof OkapiHttpResponse)
|
||||
return $retr_result;
|
||||
else
|
||||
return Okapi::formatted_response($request, $retr_result);
|
||||
}
|
||||
}
|
||||
|
||||
private static function map_values_to_strings(&$dict)
|
||||
{
|
||||
foreach (array_keys($dict) as $key)
|
||||
{
|
||||
$val = $dict[$key];
|
||||
if (is_numeric($val) || is_string($val))
|
||||
$dict[$key] = (string)$val;
|
||||
else
|
||||
throw new BadRequest("Invalid value format for key: ".$key);
|
||||
}
|
||||
}
|
||||
private static function map_values_to_strings(&$dict)
|
||||
{
|
||||
foreach (array_keys($dict) as $key)
|
||||
{
|
||||
$val = $dict[$key];
|
||||
if (is_numeric($val) || is_string($val))
|
||||
$dict[$key] = (string)$val;
|
||||
else
|
||||
throw new BadRequest("Invalid value format for key: ".$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
<xml>
|
||||
<brief>Search for caches and retrieve formatted results</brief>
|
||||
<issue-id>18</issue-id>
|
||||
<desc>
|
||||
<p>We think that searching and retrieving data are two different things
|
||||
and that's why they were cleanly separated in the documentation (put in
|
||||
separate methods). This was done primarily to keep the docs clean.
|
||||
This method allows you to do a quick search+retrieve task in one request.</p>
|
||||
<p>All services/caches/search/* methods respond with a list of cache codes.
|
||||
Then you have to use other method (like services/caches/geocaches) to
|
||||
retrieve the names and locations, based on those cache codes. The
|
||||
<b>search_and_retrieve</b> method allows you to do these two steps in one
|
||||
method call.</p>
|
||||
<p>First, you have to choose both methods and their parameters - one method
|
||||
which returns the cache codes, and the other one, that responds
|
||||
with additional data for the given caches.</p>
|
||||
</desc>
|
||||
<req name='search_method'>
|
||||
<p>Name of the search method (begin with "services/").</p>
|
||||
<p>E.g. <i>services/caches/search/nearest</i>.</p>
|
||||
</req>
|
||||
<req name='search_params'>
|
||||
<p>JSON-formatted dictionary of parameters to be passed on
|
||||
to the search method.</p>
|
||||
<p>E.g. <i>{"center": "49|19", "status": "Available"}</i>.</p>
|
||||
</req>
|
||||
<req name='retr_method'>
|
||||
<p>Name of the retrieval method (begin with "services/").</p>
|
||||
<p>E.g. <i>services/caches/geocaches</i>.</p>
|
||||
</req>
|
||||
<req name='retr_params'>
|
||||
<p>JSON-formatted dictionary of parameters to be passed on
|
||||
to the retrieval method.</p>
|
||||
<p>E.g. <i>{"fields": "name|location|type"}</i></p>
|
||||
<p>The method will be called with one additional parameter - <b>cache_codes</b>.
|
||||
These will be the cache codes collected from the results of the search method.</p>
|
||||
</req>
|
||||
<req name='wrap'>
|
||||
<p>Boolean.</p>
|
||||
<ul>
|
||||
<li>If <b>true</b>, then results will be wrapped in an additional
|
||||
object, in order to include any additional data received along with the
|
||||
search_method response (i.e. the <b>more</b> value).</li>
|
||||
<li>If <b>false</b>, then this method will return exactly what the
|
||||
<b>retr_method</b> will respond with.</li>
|
||||
</ul>
|
||||
</req>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>If <b>wrap</b> is <b>true</b>, then the method will return a
|
||||
dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>results</b> - anything the retrival method
|
||||
responds with (as long as it's not an error).</li>
|
||||
<li>any extra keys and values received as a response of
|
||||
the search_method (i.e. the <b>more</b> variable).</li>
|
||||
</ul>
|
||||
<p>If <b>wrap</b> is <b>false</b>, then the method will return
|
||||
anything the retrieval methods responds with (along with its HTTP headers).</p>
|
||||
<p><b>Example:</b></p>
|
||||
<pre>search_and_retrieve<br/>?search_method=services/caches/search/bbox<br/>&search_params={"bbox":"49|19|50|20","limit":"1"}<br/>&retr_method=services/caches/geocaches<br/>&retr_params={"fields":"location"}<br/>&wrap=false</pre>
|
||||
<p>Possible output:<br/><code>{"OP205A": {"location": "49.572417|19.525867"}}</code></p>
|
||||
<p>The same example with <i>wrap=true</i> would return:<br/><code>{"results": {"OP205A": {"location": "49.572417|19.525867"}}, "more": true}</code></p>
|
||||
</returns>
|
||||
<brief>Search for caches and retrieve formatted results</brief>
|
||||
<issue-id>18</issue-id>
|
||||
<desc>
|
||||
<p>We think that searching and retrieving data are two different things
|
||||
and that's why they were cleanly separated in the documentation (put in
|
||||
separate methods). This was done primarily to keep the docs clean.
|
||||
This method allows you to do a quick search+retrieve task in one request.</p>
|
||||
<p>All services/caches/search/* methods respond with a list of cache codes.
|
||||
Then you have to use other method (like services/caches/geocaches) to
|
||||
retrieve the names and locations, based on those cache codes. The
|
||||
<b>search_and_retrieve</b> method allows you to do these two steps in one
|
||||
method call.</p>
|
||||
<p>First, you have to choose both methods and their parameters - one method
|
||||
which returns the cache codes, and the other one, that responds
|
||||
with additional data for the given caches.</p>
|
||||
</desc>
|
||||
<req name='search_method'>
|
||||
<p>Name of the search method (begin with "services/").</p>
|
||||
<p>E.g. <i>services/caches/search/nearest</i>.</p>
|
||||
</req>
|
||||
<req name='search_params'>
|
||||
<p>JSON-formatted dictionary of parameters to be passed on
|
||||
to the search method.</p>
|
||||
<p>E.g. <i>{"center": "49|19", "status": "Available"}</i>.</p>
|
||||
</req>
|
||||
<req name='retr_method'>
|
||||
<p>Name of the retrieval method (begin with "services/").</p>
|
||||
<p>E.g. <i>services/caches/geocaches</i>.</p>
|
||||
</req>
|
||||
<req name='retr_params'>
|
||||
<p>JSON-formatted dictionary of parameters to be passed on
|
||||
to the retrieval method.</p>
|
||||
<p>E.g. <i>{"fields": "name|location|type"}</i></p>
|
||||
<p>The method will be called with one additional parameter - <b>cache_codes</b>.
|
||||
These will be the cache codes collected from the results of the search method.</p>
|
||||
</req>
|
||||
<req name='wrap'>
|
||||
<p>Boolean.</p>
|
||||
<ul>
|
||||
<li>If <b>true</b>, then results will be wrapped in an additional
|
||||
object, in order to include any additional data received along with the
|
||||
search_method response (i.e. the <b>more</b> value).</li>
|
||||
<li>If <b>false</b>, then this method will return exactly what the
|
||||
<b>retr_method</b> will respond with.</li>
|
||||
</ul>
|
||||
</req>
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>If <b>wrap</b> is <b>true</b>, then the method will return a
|
||||
dictionary of the following structure:</p>
|
||||
<ul>
|
||||
<li><b>results</b> - anything the retrival method
|
||||
responds with (as long as it's not an error).</li>
|
||||
<li>any extra keys and values received as a response of
|
||||
the search_method (i.e. the <b>more</b> variable).</li>
|
||||
</ul>
|
||||
<p>If <b>wrap</b> is <b>false</b>, then the method will return
|
||||
anything the retrieval methods responds with (along with its HTTP headers).</p>
|
||||
<p><b>Example:</b></p>
|
||||
<pre>search_and_retrieve<br/>?search_method=services/caches/search/bbox<br/>&search_params={"bbox":"49|19|50|20","limit":"1"}<br/>&retr_method=services/caches/geocaches<br/>&retr_params={"fields":"location"}<br/>&wrap=false</pre>
|
||||
<p>Possible output:<br/><code>{"OP205A": {"location": "49.572417|19.525867"}}</code></p>
|
||||
<p>The same example with <i>wrap=true</i> would return:<br/><code>{"results": {"OP205A": {"location": "49.572417|19.525867"}}, "more": true}</code></p>
|
||||
</returns>
|
||||
</xml>
|
||||