diff --git a/bin/dbsv-update.php b/bin/dbsv-update.php
index 4249d5ac..080e6e51 100644
--- a/bin/dbsv-update.php
+++ b/bin/dbsv-update.php
@@ -44,6 +44,20 @@
} while ($db_version > 0);
+ // Now and then a maintain.php update should be inserted, because multiple
+ // mutations may be run in one batch, and future mutations may depend on
+ // changed triggers, which may not be obvious.
+ // Of course, a trigger update mutation can also be inserted directly before a
+ // mutation which needs it. (But take care that maintain.php at that point does
+ // not depend on database changes which will be done by that mutation ...)
+
+ function update_triggers()
+ {
+ global $opt;
+ system('php ' . $opt['rootpath'] . 'doc/sql/stored-proc/maintain.php');
+ }
+
+
// Database mutations
// - must be consecutively numbered
// - should behave well if run multiple times
@@ -246,4 +260,9 @@
sql("ALTER TABLE `caches` ADD INDEX `wp_gc_maintained` (`wp_gc_maintained`)");
}
+ function dbv_113() // preventive trigger update
+ {
+ update_triggers();
+ }
+
?>
\ No newline at end of file
diff --git a/htdocs/dbmaintain.php b/htdocs/dbmaintain.php
index f8bc7feb..75ebf60f 100644
--- a/htdocs/dbmaintain.php
+++ b/htdocs/dbmaintain.php
@@ -27,6 +27,7 @@
$procedures[] = 'sp_updateall_cachelog_picturestat';
$procedures[] = 'sp_updateall_cache_listingdates';
$procedures[] = 'sp_updateall_cachelog_logdates';
+ $procedures[] = 'sp_updateall_rating_dates';
$tpl->assign('procedures', $procedures);
@@ -58,6 +59,8 @@
sql("CALL sp_updateall_cache_listingdates(@c)");
else if ($proc == 'sp_updateall_cachelog_logdates')
sql("CALL sp_updateall_cachelog_logdates(@c)");
+ else if ($proc == 'sp_updateall_rating_dates')
+ sql("CALL sp_updateall_rating_dates(@c)");
else
{
$bError = true;
diff --git a/htdocs/doc/sql/static-data/data.sql b/htdocs/doc/sql/static-data/data.sql
index b698f2e1..42f926f8 100644
--- a/htdocs/doc/sql/static-data/data.sql
+++ b/htdocs/doc/sql/static-data/data.sql
@@ -2507,6 +2507,7 @@ INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('2086', 'unknown
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('2087', 'Show on map', '2013-04-25 23:00:00');
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('2089', 'disabled[pl]', '2013-04-25 23:00:00');
INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('2090', 'archived[pl]', '2013-04-25 23:00:00');
+INSERT INTO `sys_trans` (`id`, `text`, `last_modified`) VALUES ('2091', 'Test for and fix inconsistencies in database tables', '2013-04-25 23:00:00');
-- Table sys_trans_ref
SET NAMES 'utf8';
@@ -5496,7 +5497,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 ('670', 'DE', 'Trefferquote', '2010-08-28 11:48:06');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('671', 'DE', 'Es können keine Empfehlungen gegeben werden, da keine weiteren Bewertungen vorliegen.', '2010-08-28 11:48:06');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('672', 'DE', 'Datenbankwartung', '2010-08-28 11:48:06');
-INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('673', 'DE', 'DB Maintainance', '2010-08-28 11:48:06');
+INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('673', 'DE', 'Datenbankwartung', '2010-08-28 11:48:06');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('674', 'DE', '%1 hat %2 Einträge korrigiert', '2010-08-28 11:48:06');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('675', 'DE', 'Ausführen', '2010-08-28 11:48:06');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('676', 'DE', 'Senden', '2010-08-28 11:48:06');
@@ -6465,6 +6466,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 ('2087', 'DE', 'auf Karte anzeigen', '2013-04-25 23:00:00');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('2089', 'DE', 'deaktivierte', '2013-04-25 23:00:00');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('2090', 'DE', 'archivierte', '2013-04-25 23:00:00');
+INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('2091', 'DE', 'Sucht und behebt Inkonsistenzen in Datenbanktabellen', '2013-04-25 23:00:00');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('1', 'EN', 'Reorder IDs \r', '2010-09-02 00:15:30');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('2', 'EN', 'The database could not be reconnected.', '2010-08-28 11:48:07');
INSERT INTO `sys_trans_text` (`trans_id`, `lang`, `text`, `last_modified`) VALUES ('3', 'EN', 'Testing – please do not login', '2010-08-28 11:48:07');
diff --git a/htdocs/doc/sql/stored-proc/maintain.php b/htdocs/doc/sql/stored-proc/maintain.php
index c07ca724..eb6a1424 100644
--- a/htdocs/doc/sql/stored-proc/maintain.php
+++ b/htdocs/doc/sql/stored-proc/maintain.php
@@ -8,7 +8,7 @@
***************************************************************************/
- $opt['rootpath'] = '../../../';
+ $opt['rootpath'] = dirname(__FILE__) . '/../../../';
require_once($opt['rootpath'] . 'lib/clicompatbase.inc.php');
if (!file_exists($opt['rootpath'] . 'util/mysql_root/sql_root.inc.php'))
@@ -252,6 +252,17 @@
SET nModified = nModified + ROW_COUNT();
END;");
+ /* update log modification date when rating changed, so that it is resent via
+ XML interface; see issue #244 */
+ sql_dropProcedure('sp_update_cachelog_rating');
+ sql("CREATE PROCEDURE sp_update_cachelog_rating (IN nCacheId INT, IN nUserID INT, IN dRatingDate DATETIME)
+ BEGIN
+ IF (ISNULL(@XMLSYNC) OR @XMLSYNC!=1) THEN
+ UPDATE `cache_logs` SET `last_modified`=NOW()
+ WHERE `cache_logs`.`cache_id`=nCacheId AND `cache_logs`.`user_id`=nUserID AND `cache_logs`.`date`=dRatingDate;
+ END IF;
+ END;");
+
// set caches.desc_languages of given cacheid and fill cache_desc_prefered
sql_dropProcedure('sp_update_caches_descLanguages');
sql("CREATE PROCEDURE sp_update_caches_descLanguages (IN nCacheId INT(10) UNSIGNED)
@@ -515,6 +526,19 @@
SET nModified=nModified+ROW_COUNT();
END;");
+ // Update out-of-sync rating dates. These probably were caused by rating-related
+ // bugs when deleting one of multiple found logs and when changing the log type
+ // (9 mismatches within ~9 months up to June 2013).
+ sql_dropProcedure('sp_updateall_rating_dates');
+ sql("CREATE PROCEDURE sp_updateall_rating_dates (OUT nModified INT)
+ BEGIN
+ UPDATE `cache_rating` SET `rating_date` =
+ (SELECT `date` FROM `cache_logs` WHERE `cache_logs`.`cache_id`=`cache_rating`.`cache_id` AND `cache_logs`.`user_id`=`cache_rating`.`user_id` AND `cache_logs`.`type` IN (1,7) ORDER BY `date` LIMIT 1)
+ WHERE (SELECT COUNT(*) FROM `cache_logs` WHERE `cache_logs`.`cache_id`=`cache_rating`.`cache_id` AND `cache_logs`.`user_id`=`cache_rating`.`user_id` AND `cache_logs`.`date`=`cache_rating`.`rating_date` AND `type` IN (1,7))=0;
+ /* will set rating_date to 0000-00...:00 for orphan records */
+ SET nModified=ROW_COUNT();
+ END;");
+
// notify users with matching watch radius about this cache
sql_dropProcedure('sp_notify_new_cache');
sql("CREATE PROCEDURE sp_notify_new_cache (IN nCacheId INT(10) UNSIGNED, IN nLongitude DOUBLE, IN nLatitude DOUBLE)
@@ -966,6 +990,7 @@
FOR EACH ROW
BEGIN
CALL sp_update_topratingstat(NEW.`cache_id`, FALSE);
+ CALL sp_update_cachelog_rating(NEW.`cache_id`, NEW.`user_id`, NEW.`rating_date`);
END;");
sql_dropTrigger('cacheRatingAfterUpdate');
@@ -975,6 +1000,8 @@
IF NEW.`cache_id`!=OLD.`cache_id` THEN
CALL sp_update_topratingstat(OLD.`cache_id`, TRUE);
CALL sp_update_topratingstat(NEW.`cache_id`, FALSE);
+ CALL sp_update_cachelog_rating(OLD.`cache_id`, OLD.`user_id`, OLD.`rating_date`);
+ CALL sp_update_cachelog_rating(NEW.`cache_id`, NEW.`user_id`, NEW.`rating_date`);
END IF;
END;");
@@ -983,6 +1010,7 @@
FOR EACH ROW
BEGIN
CALL sp_update_topratingstat(OLD.`cache_id`, TRUE);
+ CALL sp_update_cachelog_rating(OLD.`cache_id`, OLD.`user_id`, OLD.`rating_date`);
END;");
sql_dropTrigger('cacheVisitsBeforeInsert');
diff --git a/htdocs/doc/xml/xml11.htm b/htdocs/doc/xml/xml11.htm
index 70521ed0..f69d520a 100644
--- a/htdocs/doc/xml/xml11.htm
+++ b/htdocs/doc/xml/xml11.htm
@@ -44,9 +44,17 @@
Das <date>-Element von Logs enthält nun auch die Uhrzeit. 00:00:00 bedeutet, dass keine Uhrzeit geloggt wurde; alles andere bedeutet, dass mit Stunde und Minute geloggt wurde.
Element für Bildeigenschaften von <attributes> in <picattr> umbenannt, um Kollisionen mit dem Cache-Attribut-Element zu vermeiden.
Vorschaubild-Flag (preview) zu <picattr> hinzugefügt.
-
zusätzliche Logtypen 9 (archiviert), 10 (kann gesucht werden), 11 (momentan nicht verfügbar) und 13 (gesperrt)
+
zusätzliche Logtypen 9 (archiviert), 10 (kann gesucht werden), 11 (momentan nicht verfügbar) und 13 (gesperrt); Ausgabe als Typ 3 (Hinweis) in älteren XML-Versionen
teamcomment-Flag zum <logtype> hinzugefügt
+
Änderungen in Version 1.4 (Juni 2013)
+
+
Bei Caches wird zusätzlich das Feld listing_lastmodified ausgegeben, das das Gesamt-Änderungsdatum des Listings inklusive hinzugefügten/geänderten/gelöschten Beschreibungen und Bildern enthält. Bei Logs gibt es entsprechend das zusätzliche Feld log_last_modified, das Bilder mit einschließt.
+
Wenn ein User einen Cache empfohlen und diesen mehrfach als "Fund" geloggt hat, wurde bislang bei allen Fundlogs recommended="1" mitgeliefert (allerdings nicht rückwirkend - das war ein Bug. Auch zurückgezogene Empfehlungen wurden nicht immer sofort ausgeliefert).
+ Dieses Verhalten wurde so geändert, dass recommended="1" nur noch bei genau dem Log mitgeliefert wird, mit dem die Empfehlung für den Cache gegeben wurde. Mehrfachempfehlungen sind nicht möglich (und waren es noch nie).
+ Gleichzeitig wurde auch die Darstellung auf opencaching.de geändert: Bei Mehrfach-Fundlogs erscheint der grüne Stern nur noch an einem der Logs.
+ Bei Anwendungen, die das recommended-Flag verwenden wird ein kompletter Neuabruf aller Logs per Version 1.4 empfohlen, weil die alten Daten fehlerhaft sein können. Außerdem sollte die Handhabung von Mehrfachlogs geprüft werden.
+
Der XML-Doctype lautet in allen Versionen "oc11xml".
Ausgabeformat
@@ -74,8 +82,9 @@
Allgemeine XML-Elemente
lastmodified
Datum an dem dieser Datensatz zuletzt geändert wurde. Es werden keine
- Abhängigkeiten berücksichtigt. D.h. Wenn eine Cachebeschreibung geändert wird,
- ändert sich nur deren lastmodified, nicht jedoch das des Caches. Datumsangaben
+ Abhängigkeiten berücksichtigt. D.h. Wenn z.B. eine Cachebeschreibung geändert wird,
+ ändert sich nur deren lastmodified, nicht jedoch das des Caches (hierfür gibt es
+ das separate Feld listing_last_modified.) Datumsangaben
sind immer in der Form "yyyy-mm-dd hh:mm:ss" oder "yyyy-mm-dd"
lastmodified ist das letzte Änderungsdatum des cache-Datensatzes, ohne Änderungen an Cachebeschreibungen oder Bildern. Für das Gesamt-Änderungsdatum des Listings müssen Letztere also mit "eingerechnet" werden. Ein Gesamt-Änderungsdatum des Listings kann bei Bedarf eingebaut werden.
+
lastmodified ist das letzte Änderungsdatum des cache-Datensatzes, ohne Änderungen an Cachebeschreibungen oder Bildern. Das Gesamt-Änderungsdatum steht im Feld listing_lastmodified.
datecreated ist bei mit OC Version 1 und 2 angelegten Caches das Datum, an dem das Listing angelegt wurde, bei mit Version 3 angelegten Caches das Veröffentlichungsdatum. Ab Interface Version 1.2 zeigt das Attribut ispublishdate="1" an, dass es sich um das Veröffentlichungsdatum handelt.
Ab XML-Version 1.2 werden im size-Feld auch Nano-Größen zurückgeliefert. In älteren Interface-Versionen wird stattdessen "micro" ausgegeben.
Es fehlen noch Empfehlungen und zusätzliche Wegpunkte; wird bei Bedarf eingebaut.
Mit ocxml11.php kann stattdessen die Interface-Version 1.1 verwendet werden.
Diese Anfragen werden mit einem kurzen XML-Stream beantwortet, der die
XML-Session-Id zurückgibt. Mit dieser Id können dann die Daten abgerufen
@@ -300,9 +312,9 @@
Summe der Datensätze ist in diesem Beispiel 1205 - es werden also 3 Aufrufe
benötigt (500, 500, 205 Datensätze).
Die Sessionid ist zwei Stunden lang gültig, wobei sich dieser Zeitraum mit jedem
einzelnen Dateiabruf verlängert – zwischen den Einzelabrufen dürfen also
maximal zwei Stunden vergehen. Dauert es länger, müsste eine neue sessionid
@@ -311,14 +323,14 @@
Um alle Ergebnisse in einer Datei abzurufen muss bei dem Aufruf der Paramter
session auf 0 gesetzt werden.
Dei Dateikomprimierung kann mit dem Paramter zip eingestellt weren. Mögliche
Werte sind 0, zip, bzip2, gzip. Null bedeutet hier keine Kompression. Wird
keine Kompression angegeben, wird zip verwendet.
diff --git a/htdocs/editlog.php b/htdocs/editlog.php
index ce0a5936..1e4a4fd2 100644
--- a/htdocs/editlog.php
+++ b/htdocs/editlog.php
@@ -27,6 +27,7 @@
require_once('./lib/logtypes.inc.php');
require($stylepath.'/smilies.inc.php');
require_once($opt['rootpath'] . '../lib/htmlpurifier-4.2.0/library/HTMLPurifier.auto.php');
+ require_once('./lib/recommendation.inc.php');
//Preprocessing
if ($error == false)
@@ -238,7 +239,14 @@
$log_date = date('Y-m-d H:i:s', mktime($log_time_hour+0, $log_time_minute+0, $log_time_second, $log_date_month, $log_date_day, $log_date_year));
- //store changed data
+ // evtl. discard cache recommendation if the log type was changed from
+ // 'found' or 'attended' to something else
+ if (!$top_option)
+ {
+ discard_recommendation($log_id);
+ }
+
+ // store changed data
sql("UPDATE `cache_logs` SET `type`='&1',
`oc_team_comment`='&2',
`date`='&3',
@@ -264,13 +272,29 @@
// update top-list
if ($top_option)
+ {
if ($top_cache)
+ {
sql("INSERT INTO `cache_rating` (`user_id`, `cache_id`, `rating_date`)
- VALUES('&1', '&2','&3')
+ VALUES('&1','&2','&3')
ON DUPLICATE KEY UPDATE `rating_date`='&3'",
$usr['userid'], $log_record['cache_id'], $log_date);
+ // cache_rating.rating_date is updated when it already exists, so that
+ // it stays consistent with cache_logs.date when editing a log date.
+
+ // When editing one of multiple found logs, this will move rating_date
+ // to the last edited record. While this may not always be what the user
+ // expects, it makes sense for two reasons:
+ // 1. It is a safeguard for the case that the log date and rating_date
+ // have gotten out of sync for some reason (which has happend in the
+ // past, probably due to a log-deletion related bug).
+ // 2. It can be used as a tweak to control which log's date is relevant
+ // for the rating, e.g. when logging a second found on a recycled or
+ // renewed cache [listing].
+ }
else
sql("DELETE FROM `cache_rating` WHERE `user_id`='&1' AND `cache_id`='&2'", $usr['userid'], $log_record['cache_id']);
+ }
// do not use slave server for the next time ...
db_slave_exclude();
diff --git a/htdocs/lib/recommendation.inc.php b/htdocs/lib/recommendation.inc.php
new file mode 100644
index 00000000..134208c8
--- /dev/null
+++ b/htdocs/lib/recommendation.inc.php
@@ -0,0 +1,67 @@
+'&3' AND `type` IN (1,7)
+ ORDER BY `date`
+ LIMIT 1",
+ $rLog['cache_id'], $rLog['user_id'], $log_id);
+ $rFirstOtherFound = sql_fetch_assoc($rsFirstOtherFound);
+ sql_free_result($rsFirstOtherFound);
+
+ if ($rLog['is_rating_log'] && $rsFirstOtherFound)
+ {
+ sql("
+ UPDATE `cache_rating`
+ SET `rating_date`='&3'
+ WHERE `cache_id`='&1' AND `user_id`='&2'",
+ $rLog['cache_id'], $rLog['user_id'], $rFirstOtherFound['date']);
+ // This will trigger an cache_logs.last_modified update of the corresponding
+ // log, so that XML interface will resend it with the updated
+ // "recommendation" flag.
+ }
+ else if (!$rsFirstOtherFound)
+ {
+ // This is also called for $rLog['is_rating_log'] == false, so that
+ // even a rating record with inconsistent date gets deleted.
+ sql("
+ DELETE FROM `cache_rating` WHERE `cache_id` = '&1' AND `user_id` = '&2'",
+ $rLog['cache_id'], $rLog['user_id']);
+ }
+ }
+ sql_free_result($rsLog);
+ }
+
+?>
diff --git a/htdocs/lib2/logic/cache.class.php b/htdocs/lib2/logic/cache.class.php
index 4ec4c233..1cf959d8 100644
--- a/htdocs/lib2/logic/cache.class.php
+++ b/htdocs/lib2/logic/cache.class.php
@@ -334,7 +334,7 @@ class cache
IF(ISNULL(`cache_rating`.`cache_id`), 0, `cache_logs`.`type` IN (1,7)) AS `recommended`
FROM $table AS `cache_logs`
INNER JOIN `user` ON `user`.`user_id` = `cache_logs`.`user_id`
- LEFT JOIN `cache_rating` ON `cache_logs`.`cache_id`=`cache_rating`.`cache_id` AND `cache_logs`.`user_id`=`cache_rating`.`user_id`
+ LEFT JOIN `cache_rating` ON `cache_logs`.`cache_id`=`cache_rating`.`cache_id` AND `cache_logs`.`user_id`=`cache_rating`.`user_id` AND `cache_logs`.`date`=`cache_rating`.`rating_date`
".$addjoin."
WHERE `cache_logs`.`cache_id`='&1'
ORDER BY `cache_logs`.`date` DESC, `cache_logs`.`Id` DESC LIMIT &2, &3", $cacheid, $start+0, $count+0);
diff --git a/htdocs/removelog.php b/htdocs/removelog.php
index 885006ae..f76dc63f 100644
--- a/htdocs/removelog.php
+++ b/htdocs/removelog.php
@@ -21,6 +21,7 @@
require_once('./lib/common.inc.php');
require_once($stylepath . '/lib/icons.inc.php');
require_once($rootpath . 'lib2/html2text.class.php');
+ require_once('./lib/recommendation.inc.php');
//Preprocessing
if ($error == false)
@@ -182,18 +183,15 @@
}
sql_free_result($rs);
+ // evtl. discard cache recommendation
+ discard_recommendation($log_id);
+
// move to archive, even if own log (uuids are used for OKAPI replication)
sql("INSERT IGNORE INTO `cache_logs_archived` SELECT *, '0' AS `deletion_date`, '&2' AS `deleted_by`, 0 AS `restored_by` FROM `cache_logs` WHERE `cache_logs`.`id`='&1' LIMIT 1", $log_id, $usr['userid']);
// remove log entry
sql("DELETE FROM `cache_logs` WHERE `cache_logs`.`id`='&1' LIMIT 1", $log_id);
- // remove cache from users top caches, if the only found or attended log
- // of this user was deleted
- sql("DELETE FROM `cache_rating` WHERE `user_id` = '&1' AND `cache_id` = '&2' AND
- 0 = (SELECT COUNT(*) FROM `cache_logs` WHERE `user_id` = '&1' AND `cache_id` = '&2' AND `type` IN (1,7))",
- $log_record['log_user_id'], $log_record['cache_id']);
-
// now tell OKAPI about the deletion;
// this will trigger an okapi_syncbase update, if OKAPI is installed:
sql("UPDATE `cache_logs_archived` SET `deletion_date`=NOW() WHERE `id`='&1'", $log_id);
diff --git a/htdocs/templates2/ocstyle/dbmaintain.tpl b/htdocs/templates2/ocstyle/dbmaintain.tpl
index 4bfd3690..d7e9b919 100644
--- a/htdocs/templates2/ocstyle/dbmaintain.tpl
+++ b/htdocs/templates2/ocstyle/dbmaintain.tpl
@@ -10,8 +10,9 @@
-
{t}Database Maintainance{/t}
-
+
{t}Database maintainance{/t}
+
{t}Test for and fix inconsistencies in database tables{/t}