commit
a01305e002
@ -759,7 +759,7 @@ class Okapi
|
||||
{
|
||||
public static $data_store;
|
||||
public static $server;
|
||||
public static $revision = 483; # This gets replaced in automatically deployed packages
|
||||
public static $revision = 500; # This gets replaced in automatically deployed packages
|
||||
private static $okapi_vars = null;
|
||||
|
||||
/** Get a variable stored in okapi_vars. If variable not found, return $default. */
|
||||
@ -1449,10 +1449,6 @@ class Okapi
|
||||
)
|
||||
);
|
||||
|
||||
private static $cache_statuses = array(
|
||||
'Available' => 1, 'Temporarily unavailable' => 2, 'Archived' => 3
|
||||
);
|
||||
|
||||
/** E.g. 'Traditional' => 2. For unknown names throw an Exception. */
|
||||
public static function cache_type_name2id($name)
|
||||
{
|
||||
@ -1479,6 +1475,10 @@ class Okapi
|
||||
return "Other";
|
||||
}
|
||||
|
||||
private static $cache_statuses = array(
|
||||
'Available' => 1, 'Temporarily unavailable' => 2, 'Archived' => 3
|
||||
);
|
||||
|
||||
/** E.g. 'Available' => 1. For unknown names throws an Exception. */
|
||||
public static function cache_status_name2id($name)
|
||||
{
|
||||
@ -1501,6 +1501,64 @@ class Okapi
|
||||
return $reversed[$id];
|
||||
return 'Archived';
|
||||
}
|
||||
|
||||
private static $cache_sizes = array(
|
||||
'none' => 7,
|
||||
'nano' => 8,
|
||||
'micro' => 2,
|
||||
'small' => 3,
|
||||
'regular' => 4,
|
||||
'large' => 5,
|
||||
'xlarge' => 6,
|
||||
'other' => 1,
|
||||
);
|
||||
|
||||
/** E.g. 'micro' => 2. For unknown names throw an Exception. */
|
||||
public static function cache_size2_to_sizeid($size2)
|
||||
{
|
||||
if (isset(self::$cache_sizes[$size2]))
|
||||
return self::$cache_sizes[$size2];
|
||||
throw new Exception("Method cache_size2_to_sizeid called with invalid size2 '$size2'.");
|
||||
}
|
||||
|
||||
/** E.g. 2 => 'micro'. For unknown ids returns "other". */
|
||||
public static function cache_sizeid_to_size2($id)
|
||||
{
|
||||
static $reversed = null;
|
||||
if ($reversed == null)
|
||||
{
|
||||
$reversed = array();
|
||||
foreach (self::$cache_sizes as $key => $value)
|
||||
$reversed[$value] = $key;
|
||||
}
|
||||
if (isset($reversed[$id]))
|
||||
return $reversed[$id];
|
||||
return "other";
|
||||
}
|
||||
|
||||
/** Maps OKAPI's 'size2' values to opencaching.com (OX) size codes. */
|
||||
private static $cache_OX_sizes = array(
|
||||
'none' => null,
|
||||
'nano' => 1.3,
|
||||
'micro' => 2.0,
|
||||
'small' => 3.0,
|
||||
'regular' => 3.8,
|
||||
'large' => 4.6,
|
||||
'xlarge' => 4.9,
|
||||
'other' => null,
|
||||
);
|
||||
|
||||
/**
|
||||
* E.g. 'micro' => 2.0, 'other' => null. For unknown names throw an
|
||||
* Exception. Note, that this is not a bijection ('none' are 'other' are
|
||||
* both null).
|
||||
*/
|
||||
public static function cache_size2_to_oxsize($size2)
|
||||
{
|
||||
if (array_key_exists($size2, self::$cache_OX_sizes))
|
||||
return self::$cache_OX_sizes[$size2];
|
||||
throw new Exception("Method cache_size2_to_oxsize called with invalid size2 '$size2'.");
|
||||
}
|
||||
|
||||
/**
|
||||
* E.g. 'Found it' => 1. For unsupported names throws Exception.
|
||||
@ -1578,9 +1636,18 @@ class Cache
|
||||
* Save object $value under the key $key. Store this object for
|
||||
* $timeout seconds. $key must be a string of max 64 characters in length.
|
||||
* $value might be any serializable PHP object.
|
||||
*
|
||||
* If $timeout is null, then the object will be treated as persistent
|
||||
* (the Cache will do its best to NEVER remove it).
|
||||
*/
|
||||
public static function set($key, $value, $timeout)
|
||||
{
|
||||
if ($timeout == null)
|
||||
{
|
||||
# The current cache implementation is ALWAYS persistent, so we will
|
||||
# just replace it with a big value.
|
||||
$timeout = 100*365*86400;
|
||||
}
|
||||
Db::execute("
|
||||
replace into okapi_cache (`key`, value, expires)
|
||||
values (
|
||||
@ -1613,6 +1680,12 @@ class Cache
|
||||
{
|
||||
if (count($dict) == 0)
|
||||
return;
|
||||
if ($timeout == null)
|
||||
{
|
||||
# The current cache implementation is ALWAYS persistent, so we will
|
||||
# just replace it with a big value.
|
||||
$timeout = 100*365*86400;
|
||||
}
|
||||
$entries = array();
|
||||
foreach ($dict as $key => $value)
|
||||
{
|
||||
|
@ -16,6 +16,7 @@ namespace okapi\cronjobs;
|
||||
|
||||
use Exception;
|
||||
use okapi\Okapi;
|
||||
use okapi\BadRequest;
|
||||
use okapi\Settings;
|
||||
use okapi\OkapiLock;
|
||||
use okapi\OkapiExceptionHandler;
|
||||
@ -43,6 +44,7 @@ class CronJobController
|
||||
new CheckCronTab2(),
|
||||
new ChangeLogWriterJob(),
|
||||
new ChangeLogCleanerJob(),
|
||||
new ChangeLogCheckerJob(),
|
||||
new AdminStatsSender(),
|
||||
new LocaleChecker(),
|
||||
new FulldumpGeneratorJob(),
|
||||
@ -93,13 +95,27 @@ class CronJobController
|
||||
$next_run = $cronjob->get_next_scheduled_run(isset($schedule[$name]) ? $schedule[$name] : time());
|
||||
}
|
||||
$schedule[$name] = $next_run;
|
||||
Cache::set("cron_schedule", $schedule, 30*86400);
|
||||
}
|
||||
}
|
||||
|
||||
# Remove "stale" schedule keys (those which are no longer declared).
|
||||
|
||||
$fixed_schedule = array();
|
||||
foreach (self::get_enabled_cronjobs() as $cronjob)
|
||||
{
|
||||
$name = $cronjob->get_name();
|
||||
$fixed_schedule[$name] = $schedule[$name];
|
||||
}
|
||||
unset($schedule);
|
||||
|
||||
# Return the nearest scheduled event time.
|
||||
|
||||
$nearest = time() + 3600;
|
||||
foreach ($schedule as $name => $time)
|
||||
foreach ($fixed_schedule as $name => $time)
|
||||
if ($time < $nearest)
|
||||
$nearest = $time;
|
||||
Cache::set("cron_schedule", $schedule, 30*86400);
|
||||
Cache::set("cron_schedule", $fixed_schedule, 30*86400);
|
||||
$lock->release();
|
||||
return $nearest;
|
||||
}
|
||||
@ -446,6 +462,22 @@ class ChangeLogWriterJob extends Cron5Job
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Once per day, compares alle caches to the cached versions
|
||||
* kept by the 'replicate' module. If it finds any inconsistencies, it
|
||||
* emails the developers (such inconsistencies shouldn't happen) and it changes
|
||||
* the okapi_syncbase column accordingly. See issue 157.
|
||||
*/
|
||||
class ChangeLogCheckerJob extends Cron5Job
|
||||
{
|
||||
public function get_period() { return 86400; }
|
||||
public function execute()
|
||||
{
|
||||
require_once($GLOBALS['rootpath']."okapi/services/replicate/replicate_common.inc.php");
|
||||
ReplicateCommon::verify_clog_consistency();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Once per week, generates the fulldump archive.
|
||||
*/
|
||||
@ -473,17 +505,26 @@ class TileTreeUpdater extends Cron5Job
|
||||
# No update necessary.
|
||||
} elseif ($tiletree_revision < $current_clog_revision) {
|
||||
require_once($GLOBALS['rootpath']."okapi/services/caches/map/replicate_listener.inc.php");
|
||||
if ($current_clog_revision - $tiletree_revision < 100000) # In the middle of 2012, OCPL generated 30000 entries per week
|
||||
if ($current_clog_revision - $tiletree_revision < 30000) # In the middle of 2012, OCPL generated 30000 entries per week
|
||||
{
|
||||
for ($i=0; $i<100; $i++) # This gives us no more than 20000 (?) at a time.
|
||||
for ($timeout = time() + 240; time() < $timeout; ) # Try to stop after 4 minutes.
|
||||
{
|
||||
$response = OkapiServiceRunner::call('services/replicate/changelog', new OkapiInternalRequest(
|
||||
new OkapiInternalConsumer(), null, array('since' => $tiletree_revision)));
|
||||
\okapi\services\caches\map\ReplicateListener::receive($response['changelog']);
|
||||
$tiletree_revision = $response['revision'];
|
||||
Okapi::set_var('clog_followup_revision', $tiletree_revision);
|
||||
if (!$response['more'])
|
||||
break;
|
||||
try {
|
||||
$response = OkapiServiceRunner::call('services/replicate/changelog', new OkapiInternalRequest(
|
||||
new OkapiInternalConsumer(), null, array('since' => $tiletree_revision)));
|
||||
\okapi\services\caches\map\ReplicateListener::receive($response['changelog']);
|
||||
$tiletree_revision = $response['revision'];
|
||||
Okapi::set_var('clog_followup_revision', $tiletree_revision);
|
||||
if (!$response['more'])
|
||||
break;
|
||||
} catch (BadRequest $e) {
|
||||
# Invalid 'since' parameter? May happen whne crontab was
|
||||
# not working for more than 10 days. Or, just after OKAPI
|
||||
# is installed (and this is the first time this cronjob
|
||||
# if being run).
|
||||
\okapi\services\caches\map\ReplicateListener::reset();
|
||||
Okapi::set_var('clog_followup_revision', $current_clog_revision);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Some kind of bigger update. Resetting TileTree might be a better option.
|
||||
|
@ -27,6 +27,7 @@ class WebService
|
||||
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>") : "").
|
||||
@ -120,16 +121,21 @@ class WebService
|
||||
$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.");
|
||||
|
@ -38,11 +38,12 @@
|
||||
<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> - one of the following values: <i>public</i>,
|
||||
<i>inherited</i> or <i>common-formatting</i> (other values might be
|
||||
introduced in future).</p>
|
||||
<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>
|
||||
|
@ -36,23 +36,16 @@ class WebService
|
||||
'Other' => 'Unknown Cache'
|
||||
);
|
||||
|
||||
/** Maps OpenCaching cache sizes Geocaching.com size codes. */
|
||||
/** Maps OKAPI's 'size2' values to geocaching.com size codes. */
|
||||
public static $cache_GPX_sizes = array(
|
||||
1 => 'Micro',
|
||||
2 => 'Small',
|
||||
3 => 'Regular',
|
||||
4 => 'Large',
|
||||
5 => 'Large',
|
||||
null => 'Virtual'
|
||||
);
|
||||
/** Maps OpenCaching cache sizes opencaching.com (OX) size codes. */
|
||||
public static $cache_OX_sizes = array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 4,
|
||||
4 => 5,
|
||||
5 => 5,
|
||||
null => null
|
||||
'none' => 'Virtual',
|
||||
'nano' => 'Micro',
|
||||
'micro' => 'Micro',
|
||||
'small' => 'Small',
|
||||
'regular' => 'Regular',
|
||||
'large' => 'Large',
|
||||
'xlarge' => 'Large',
|
||||
'other' => 'Other',
|
||||
);
|
||||
|
||||
public static function call(OkapiRequest $request)
|
||||
@ -121,7 +114,7 @@ class WebService
|
||||
# We can get all the data we need from the services/caches/geocaches method.
|
||||
# We don't need to do any additional queries here.
|
||||
|
||||
$fields = 'code|name|location|date_created|url|type|status|size'.
|
||||
$fields = 'code|name|location|date_created|url|type|status|size|size2|oxsize'.
|
||||
'|difficulty|terrain|description|hint|rating|owner|url|internal_id';
|
||||
if ($vars['images'] != 'none')
|
||||
$fields .= "|images";
|
||||
@ -149,7 +142,6 @@ class WebService
|
||||
new OkapiInternalConsumer(), null, array()));
|
||||
$vars['cache_GPX_types'] = self::$cache_GPX_types;
|
||||
$vars['cache_GPX_sizes'] = self::$cache_GPX_sizes;
|
||||
$vars['cache_OX_sizes'] = self::$cache_OX_sizes;
|
||||
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = "text/xml; charset=utf-8";
|
||||
|
@ -35,7 +35,7 @@ http://www.gsak.net/xmlv1/5 http://www.gsak.net/xmlv1/5/gsak.xsd
|
||||
<groundspeak:placed_by><?= htmlspecialchars($c['owner']['username'], ENT_COMPAT, 'UTF-8') ?></groundspeak:placed_by>
|
||||
<groundspeak:owner id="<?= $c['owner']['uuid'] ?>"><?= htmlspecialchars($c['owner']['username'], ENT_COMPAT, 'UTF-8') ?></groundspeak:owner>
|
||||
<groundspeak:type><?= $vars['cache_GPX_types'][$c['type']] ?></groundspeak:type>
|
||||
<groundspeak:container><?= $vars['cache_GPX_sizes'][$c['size']] ?></groundspeak:container>
|
||||
<groundspeak:container><?= $vars['cache_GPX_sizes'][$c['size2']] ?></groundspeak:container>
|
||||
<groundspeak:difficulty><?= $c['difficulty'] ?></groundspeak:difficulty>
|
||||
<groundspeak:terrain><?= $c['terrain'] ?></groundspeak:terrain>
|
||||
<groundspeak:long_description html="True">
|
||||
@ -121,7 +121,7 @@ http://www.gsak.net/xmlv1/5 http://www.gsak.net/xmlv1/5/gsak.xsd
|
||||
<ox:ratings>
|
||||
<? if ($c['rating'] !== null) { ?><ox:awesomeness><?= $c['rating'] ?></ox:awesomeness><? } ?>
|
||||
<ox:difficulty><?= $c['difficulty'] ?></ox:difficulty>
|
||||
<? if ($c['size'] !== null) { ?><ox:size><?= $vars['cache_OX_sizes'][$c['size']] ?></ox:size><? } ?>
|
||||
<? if ($c['oxsize'] !== null) { ?><ox:size><?= $c['oxsize'] ?></ox:size><? } ?>
|
||||
<ox:terrain><?= $c['terrain'] ?></ox:terrain>
|
||||
</ox:ratings>
|
||||
<? if ($vars['attrs'] == 'ox:tags' && count($c['attrnames']) > 0) { /* Does user want us to include ox:tags? */ ?>
|
||||
|
@ -89,8 +89,25 @@
|
||||
</li>
|
||||
<li><b>founds</b> - number of times the geocache was successfully found,</li>
|
||||
<li><b>notfounds</b> - number of times the geocache was not found,</li>
|
||||
<li><b>size</b> - float (between 1 and 5), size rating of the container, or
|
||||
<b>null</b> if geocache does not have a container,</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 od 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>oxcode</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>
|
||||
|
@ -26,7 +26,7 @@ class WebService
|
||||
|
||||
private static $valid_field_names = array('code', 'name', 'names', 'location', 'type',
|
||||
'status', 'url', 'owner', 'distance', 'bearing', 'bearing2', 'bearing3', 'is_found',
|
||||
'is_not_found', 'founds', 'notfounds', 'size', 'difficulty', 'terrain',
|
||||
'is_not_found', 'founds', 'notfounds', 'size', 'size2', 'oxsize', 'difficulty', 'terrain',
|
||||
'rating', 'rating_votes', 'recommendations', 'req_passwd', 'description',
|
||||
'descriptions', 'hint', 'hints', 'images', 'attrnames', 'latest_logs',
|
||||
'my_notes', 'trackables_count', 'trackables', 'alt_wpts', 'last_found',
|
||||
@ -204,7 +204,23 @@ class WebService
|
||||
case 'is_not_found': /* handled separately */ break;
|
||||
case 'founds': $entry['founds'] = $row['founds'] + 0; break;
|
||||
case 'notfounds': $entry['notfounds'] = $row['notfounds'] + 0; break;
|
||||
case 'size': $entry['size'] = ($row['size'] < 7) ? (float)($row['size'] - 1) : null; break;
|
||||
case 'size':
|
||||
# Deprecated. Leave it for backward-compatibility. See issue 155.
|
||||
switch (Okapi::cache_sizeid_to_size2($row['size']))
|
||||
{
|
||||
case 'none': $entry['size'] = null; break;
|
||||
case 'nano': $entry['size'] = 1.0; break; # same as micro
|
||||
case 'micro': $entry['size'] = 1.0; break;
|
||||
case 'small': $entry['size'] = 2.0; break;
|
||||
case 'regular': $entry['size'] = 3.0; break;
|
||||
case 'large': $entry['size'] = 4.0; break;
|
||||
case 'xlarge': $entry['size'] = 5.0; break;
|
||||
case 'other': $entry['size'] = null; break; # same as none
|
||||
default: throw new Exception();
|
||||
}
|
||||
break;
|
||||
case 'size2': $entry['size2'] = Okapi::cache_sizeid_to_size2($row['size']); break;
|
||||
case 'oxsize': $entry['oxsize'] = Okapi::cache_size2_to_oxsize(Okapi::cache_sizeid_to_size2($row['size'])); break;
|
||||
case 'difficulty': $entry['difficulty'] = round($row['difficulty'] / 2.0, 1); break;
|
||||
case 'terrain': $entry['terrain'] = round($row['terrain'] / 2.0, 1); break;
|
||||
case 'rating':
|
||||
|
@ -57,7 +57,10 @@
|
||||
<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'>
|
||||
<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>
|
||||
@ -66,6 +69,13 @@
|
||||
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
|
||||
|
@ -97,6 +97,34 @@ class SearchAssistant
|
||||
$where_conds[] = "caches.type $operator ('".implode("','", array_map('mysql_real_escape_string', $types))."')";
|
||||
}
|
||||
|
||||
#
|
||||
# size2
|
||||
#
|
||||
|
||||
if ($tmp = $request->get_parameter('size2'))
|
||||
{
|
||||
$operator = "in";
|
||||
if ($tmp[0] == '-')
|
||||
{
|
||||
$tmp = substr($tmp, 1);
|
||||
$operator = "not in";
|
||||
}
|
||||
$types = array();
|
||||
foreach (explode("|", $tmp) as $name)
|
||||
{
|
||||
try
|
||||
{
|
||||
$id = Okapi::cache_size2_to_sizeid($name);
|
||||
$types[] = $id;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new InvalidParam('size2', "'$name' is not a valid cache size.");
|
||||
}
|
||||
}
|
||||
$where_conds[] = "caches.size $operator ('".implode("','", array_map('mysql_real_escape_string', $types))."')";
|
||||
}
|
||||
|
||||
#
|
||||
# status - filter by status codes
|
||||
#
|
||||
@ -185,11 +213,17 @@ class SearchAssistant
|
||||
}
|
||||
break;
|
||||
case 'size':
|
||||
# Deprecated. Leave it for backward-compatibility. See issue 155.
|
||||
if (($min == 1) && ($max == 5) && $allow_null) {
|
||||
/* no extra condition necessary */
|
||||
# No extra condition necessary ('other' caches will be
|
||||
# included).
|
||||
} else {
|
||||
# 'other' size caches will NOT be included (user must use the
|
||||
# 'size2' parameter to search these). 'nano' caches will be
|
||||
# included whenever 'micro' caches are included ($min=1).
|
||||
$where_conds[] = "(caches.size between $min+1 and $max+1)".
|
||||
($allow_null ? " or caches.size=7" : "");
|
||||
($allow_null ? " or caches.size=7" : "").
|
||||
(($min == 1) ? " or caches.size=8" : "");
|
||||
}
|
||||
break;
|
||||
case 'rating':
|
||||
|
@ -65,7 +65,6 @@
|
||||
set on him by the OC site. If criteria are not met, the request will
|
||||
end with user error (HTTP 200, success=false).</p>
|
||||
</opt>
|
||||
<!--
|
||||
<opt name='needs_maintenance' default='false'>
|
||||
<p>Set to <b>true</b> if the user thinks that the cache needs some special attension
|
||||
of its owner. Users should describe the reason for maintenance in their comments.</p>
|
||||
@ -75,7 +74,6 @@
|
||||
only one of those entries). Moreover, on some OC servers this flag might be
|
||||
<b>completely ignored</b> (not all OC servers support this feature).</p>
|
||||
</opt>
|
||||
-->
|
||||
<common-format-params/>
|
||||
<returns>
|
||||
<p>A dictionary of the following structure:</p>
|
||||
|
@ -19,7 +19,7 @@ use okapi\Settings;
|
||||
class ReplicateCommon
|
||||
{
|
||||
private static $chunk_size = 200;
|
||||
private static $logged_cache_fields = 'code|names|location|type|status|url|owner|founds|notfounds|size|difficulty|terrain|rating|rating_votes|recommendations|req_passwd|descriptions|hints|images|trackables_count|trackables|alt_wpts|last_found|last_modified|date_created|date_hidden';
|
||||
private static $logged_cache_fields = 'code|names|location|type|status|url|owner|founds|notfounds|size|size2|oxsize|difficulty|terrain|rating|rating_votes|recommendations|req_passwd|descriptions|hints|images|trackables_count|trackables|alt_wpts|last_found|last_modified|date_created|date_hidden';
|
||||
|
||||
private static $logged_log_entry_fields = 'uuid|cache_code|date|user|type|comment';
|
||||
|
||||
@ -69,7 +69,7 @@ class ReplicateCommon
|
||||
/** Check for modifications in the database and update the changelog table accordingly. */
|
||||
public static function update_clog_table()
|
||||
{
|
||||
$now = Db::select_value("select now()");
|
||||
$now = Db::select_value("select date_add(now(), interval -1 minute)"); # See issue 157.
|
||||
$last_update = Okapi::get_var('last_clog_update');
|
||||
if ($last_update === null)
|
||||
$last_update = Db::select_value("select date_add(now(), interval -1 day)");
|
||||
@ -99,7 +99,7 @@ class ReplicateCommon
|
||||
foreach ($cache_code_groups as $cache_codes)
|
||||
{
|
||||
self::generate_changelog_entries('services/caches/geocaches', 'geocache', 'cache_codes',
|
||||
'code', $cache_codes, self::$logged_cache_fields, false, true, 30*86400);
|
||||
'code', $cache_codes, self::$logged_cache_fields, false, true, null);
|
||||
}
|
||||
|
||||
# Same as above, for log entries.
|
||||
@ -147,13 +147,78 @@ class ReplicateCommon
|
||||
Okapi::set_var("clog_revision", $revision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the database and compare the current values of old entries to
|
||||
* the cached values of the same entries. If differences found, update
|
||||
* okapi_syncbase accordingly, and email the admins.
|
||||
*
|
||||
* Currently, only caches are checked (log entries are not).
|
||||
*/
|
||||
public static function verify_clog_consistency()
|
||||
{
|
||||
set_time_limit(0);
|
||||
ignore_user_abort(true);
|
||||
|
||||
# We will SKIP the entries which have been modified SINCE one day ago.
|
||||
# Such entries might have not been seen by the update_clog_table() yet
|
||||
# (e.g. other long-running cronjob is preventing update_clog_table from
|
||||
# running).
|
||||
|
||||
$cache_codes = Db::select_column("
|
||||
select wp_oc
|
||||
from caches
|
||||
where okapi_syncbase < date_add(now(), interval -1 day);
|
||||
");
|
||||
$cache_code_groups = Okapi::make_groups($cache_codes, 50);
|
||||
unset($cache_codes);
|
||||
|
||||
# For each group, get the changelog entries, but don't store them
|
||||
# (the "fulldump" mode). Instead, just update the okapi_syncbase column.
|
||||
|
||||
$sum = 0;
|
||||
foreach ($cache_code_groups as $cache_codes)
|
||||
{
|
||||
$entries = self::generate_changelog_entries(
|
||||
'services/caches/geocaches', 'geocache', 'cache_codes',
|
||||
'code', $cache_codes, self::$logged_cache_fields, true, true, null
|
||||
);
|
||||
foreach ($entries as $entry)
|
||||
{
|
||||
if ($entry['object_type'] != 'geocache')
|
||||
continue;
|
||||
$cache_code = $entry['object_key']['code'];
|
||||
Db::execute("
|
||||
update caches
|
||||
set okapi_syncbase = now()
|
||||
where wp_oc = '".mysql_real_escape_string($cache_code)."'
|
||||
");
|
||||
$sum += 1;
|
||||
}
|
||||
}
|
||||
if ($sum > 0)
|
||||
{
|
||||
Okapi::mail_from_okapi(
|
||||
"rygielski@mimuw.edu.pl",
|
||||
"verify_clog_consistency",
|
||||
"Number of invalid entries fixed: $sum\n\n".
|
||||
print_r(Db::select_all("select * from okapi_vars"), true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate OKAPI changelog entries. This method will call $feeder_method OKAPI
|
||||
* service with the following parameters: array($feeder_keys_param => implode('|', $key_values),
|
||||
* 'fields' => $fields). Then it will generate the changelog, based on the result.
|
||||
* This looks pretty much the same for various object types, that's why it's here.
|
||||
*
|
||||
* If $use_cache is true, then all the dictionaries from $feeder_method will be also
|
||||
* kept in OKAPI cache, for future comparison.
|
||||
* kept in OKAPI cache, for future comparison.
|
||||
*
|
||||
* In normal mode, update the changelog and don't return anything.
|
||||
* In fulldump mode, return the generated changelog entries *instead* of
|
||||
* updating it.
|
||||
*/
|
||||
private static function generate_changelog_entries($feeder_method, $object_type, $feeder_keys_param,
|
||||
$key_name, $key_values, $fields, $fulldump_mode, $use_cache, $cache_timeout = 86400)
|
||||
@ -162,12 +227,21 @@ class ReplicateCommon
|
||||
|
||||
if ($use_cache)
|
||||
{
|
||||
$cache_keys = array();
|
||||
$cache_keys1 = array();
|
||||
$cache_keys2 = array();
|
||||
foreach ($key_values as $key)
|
||||
$cache_keys[] = 'clog#'.$object_type.'#'.$key;
|
||||
$cached_values = Cache::get_many($cache_keys);
|
||||
Cache::delete_many($cache_keys);
|
||||
unset($cache_keys);
|
||||
$cache_keys1[] = 'clog#'.$object_type.'#'.$key;
|
||||
foreach ($key_values as $key)
|
||||
$cache_keys2[] = 'clogmd5#'.$object_type.'#'.$key;
|
||||
$cached_values1 = Cache::get_many($cache_keys1);
|
||||
$cached_values2 = Cache::get_many($cache_keys2);
|
||||
if (!$fulldump_mode)
|
||||
{
|
||||
Cache::delete_many($cache_keys1);
|
||||
Cache::delete_many($cache_keys2);
|
||||
}
|
||||
unset($cache_keys1);
|
||||
unset($cache_keys2);
|
||||
}
|
||||
|
||||
# Get the current values for objects. Compare them with their previous versions
|
||||
@ -185,10 +259,21 @@ class ReplicateCommon
|
||||
# Currently, the object exists.
|
||||
if ($use_cache)
|
||||
{
|
||||
$diff = self::get_diff($cached_values['clog#'.$object_type.'#'.$key], $object);
|
||||
# First, compare the cached hash. The hash has much longer lifetime
|
||||
# than the actual cached object.
|
||||
$cached_md5 = $cached_values2['clogmd5#'.$object_type.'#'.$key];
|
||||
$current_md5 = md5(serialize($object));
|
||||
if ($cached_md5 == $current_md5)
|
||||
{
|
||||
# The object was not changed since it was last replaced.
|
||||
continue;
|
||||
}
|
||||
$diff = self::get_diff($cached_values1['clog#'.$object_type.'#'.$key], $object);
|
||||
if (count($diff) == 0)
|
||||
{
|
||||
# No field has changed since the object was last replaced.
|
||||
# Md5 differs, but diff does not. Weird, but it can happen
|
||||
# (e.g. just after the md5 extension was introduced, or if
|
||||
# md5 somehow expired before the actual object did).
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -201,13 +286,14 @@ class ReplicateCommon
|
||||
if ($use_cache)
|
||||
{
|
||||
# Save the last-published state of the object, for future comparison.
|
||||
$cached_values['clog#'.$object_type.'#'.$key] = $object;
|
||||
$cached_values2['clogmd5#'.$object_type.'#'.$key] = $current_md5;
|
||||
$cached_values1['clog#'.$object_type.'#'.$key] = $object;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# Currently, the object does not exist.
|
||||
if ($use_cache && ($cached_values['clog#'.$object_type.'#'.$key] === false))
|
||||
if ($use_cache && ($cached_values1['clog#'.$object_type.'#'.$key] === false))
|
||||
{
|
||||
# No need to delete, we have already published its deletion.
|
||||
continue;
|
||||
@ -220,7 +306,8 @@ class ReplicateCommon
|
||||
if ($use_cache)
|
||||
{
|
||||
# Cache the fact, that the object was deleted.
|
||||
$cached_values['clog#'.$object_type.'#'.$key] = false;
|
||||
$cached_values2['clogmd5#'.$object_type.'#'.$key] = false;
|
||||
$cached_values1['clog#'.$object_type.'#'.$key] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,7 +334,10 @@ class ReplicateCommon
|
||||
# Update the values kept in OKAPI cache.
|
||||
|
||||
if ($use_cache)
|
||||
Cache::set_many($cached_values, $cache_timeout);
|
||||
{
|
||||
Cache::set_many($cached_values1, $cache_timeout);
|
||||
Cache::set_many($cached_values2, null); # make it persistent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace okapi\views\attrlist;
|
||||
|
||||
use Exception;
|
||||
use okapi\Okapi;
|
||||
use okapi\Cache;
|
||||
use okapi\Db;
|
||||
use okapi\OkapiRequest;
|
||||
use okapi\OkapiRedirectResponse;
|
||||
use okapi\OkapiHttpResponse;
|
||||
use okapi\ParamMissing;
|
||||
use okapi\InvalidParam;
|
||||
use okapi\OkapiServiceRunner;
|
||||
use okapi\OkapiInternalRequest;
|
||||
|
||||
class View
|
||||
{
|
||||
public static function call()
|
||||
{
|
||||
# This is a hidden page for OKAPI developers. It will list all
|
||||
# attributes defined in this OC installation.
|
||||
|
||||
$rs = Db::query("select id, language, text_long from cache_attrib order by id");
|
||||
$dict = array();
|
||||
while ($row = mysql_fetch_assoc($rs))
|
||||
$dict[$row['id']][strtolower($row['language'])] = $row['text_long'];
|
||||
$chunks = array();
|
||||
foreach ($dict as $internal_id => $langs)
|
||||
{
|
||||
$chunks[] = "<attr code='...' internal_id='$internal_id'";
|
||||
$langkeys = array_keys($langs);
|
||||
sort($langkeys);
|
||||
foreach ($langkeys as $langkey)
|
||||
$chunks[] = " $langkey='".$langs[$langkey]."'";
|
||||
$chunks[] = " />\n";
|
||||
}
|
||||
|
||||
$response = new OkapiHttpResponse();
|
||||
$response->content_type = "text/plain; charset=utf-8";
|
||||
$response->body = implode("", $chunks);
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
@ -35,7 +35,7 @@ $m = $vars['method'];
|
||||
<td class='precaption' colspan='3'>
|
||||
<table><tr>
|
||||
<td>Minimum Authentication: <span class='level level<?= $m['auth_options']['min_auth_level'] ?>'>Level <?= $m['auth_options']['min_auth_level'] ?></span></td>
|
||||
<td>(see <a href='<?= $vars['okapi_base_url'] ?>introduction#auth_level'>Authentication Levels</a>)</td>
|
||||
<td>(see <a href='<?= $vars['okapi_base_url'] ?>introduction.html#auth_levels'>Authentication Levels</a>)</td>
|
||||
</tr></table>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -621,4 +621,5 @@ class View
|
||||
private static function ver73() { Db::execute("update okapi_cache set score=1, expires=date_add(now(), interval 360 day) where `key` like 'tile/%'"); }
|
||||
private static function ver74() { Db::execute("update okapi_cache set score=1, expires=date_add(now(), interval 360 day) where `key` like 'tilecaption/%'"); }
|
||||
private static function ver75() { Db::execute("alter table okapi_cache modify column score float default null"); }
|
||||
private static function ver76() { Db::execute("update okapi_cache set expires=date_add(now(), interval 100 year) where `key` like 'clog#geocache#%'"); }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user