Die Umgebung
Ich betreibe einen lokalen OwnCloud-Server, der primär für gemeinsame Kalender (4 Stück) genutzt wird. Die Clients sind drei iPhones, ein iPad, drei Thunderbirds mit Lightning.
Das Problem
Meine Frau verwaltet Ihre Termine in der Praxis über ihr iPad und synct mal über ein VPN, mal über WLAN. Manchmal auch ein paar Tage lang nicht.
Jedenfalls ist es bislang in den letzten sechs Monaten zwei Mal vorgekommen, daß Termine von ihr verschwunden sind. Darf nicht passieren, Sie hat Kundenkontakte.
Nun ja, erst mal in die Datenbank von OwnCloud geschaut. Ach ne, das darf ja wohl nicht wahr sein. Da werden doch tatsächlich Einträge aus der Termin-Tabelle wirklich gelöscht.
Klar, Speicherplatz ist so kostbar, da muß man schon auf jedes Byte schauen.
Also an sich keine Möglichkeit, rauszukriegen, wann der Termin verschwunden ist.
Hab dann mal über meine (täglichen) Backups manuell eruiert, wann der Termin verschwunden ist, hilft aber natürlich nicht wirklich weiter.
Was ich haben will
Löschvorgänge dürfen keine Einträge löschen, sondern sollen nur ein delete-flag setzen. Am Besten mit einem Löschen nur mit Nachfrage, wenn das System selber was löschen will. Hat unser Palm Organizer selig schon gekonnt, sollte also nicht so schwer sein.
Aber ich bau natürlich nicht die OwnCloud um, so viel Zeit habe ich nicht.
Die Lösung
Bei Löschvorgängen, egal ob vom Benutzer oder vom System angestoßen, werden die Einträge in eine „Backup“-Tabelle kopiert und als Termin einem neuen Kalender „gelöscht“ zugewiesen.
Wenn jetzt ein Termin gelöscht wird, kann ich nachschauen, wann das passierte und was für ein Termin das war.
Außerdem erscheint der gelöschte Termin als neuer Termin im gelöscht-Kalender (auf rot gestellt), so kann ich verifizieren, ob der wirklich gelöscht werden soll.
Die Backup-Tabelle
Ich habe die Tabelle oc_clndr_objects mit phpMyAdmin ohne Inhalt als Tabelle oc_clndr_delete_objects kopiert und um die Felder id (Autoincrement), timestamp und converted (bool) ergänzt. Die id der Originaltabelle habe ich in objectid umbenannt.
Der Trigger
Damit diese Tabelle beim Löschen mit den Einträgen befüllt wird, brauche ich einen Trigger auf der Tabelle oc_clndr_objects. Der muß als BEFORE DELETE angelegt werden und sieht so aus:
BEGIN
/* Gewünschten Kalender abfragen */
if old.calendarid = 7 THEN
/* Eintrag in die delete-Tabelle schreiben */
INSERT INTO oc_clndr_delete_objects (objectid,calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES (old.id,old.calendarid,old.objecttype,old.startdate,old.enddate,old.repeating,old.summary,old.calendardata,old.uri,old.lastmodified);
END IF;
END
Der CRON-Job
Bei mysql ist es leider nicht möglich, in einem Trigger die auslösende Tabelle zu bearbeiten, deshalb kann der neue Eintrag nur über einen CRON-Job erzeugt werden.
Ich mache das mit der folgenden PHP-Datei, die vom CRON-Dienst alle 15 Minuten aufgerufen wird:
<?php
$link=mysql_connect(„localhost“,“xxx“,“xxx“);
$db = „owncloud“;
mysql_select_db($db, $link);
// Kalendereinträge
$sql=“Insert into oc_clndr_objects (id,calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) „;
$sql=$sql.“SELECT objectid,13,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified FROM oc_clndr_delete_objects „;
$sql=$sql.“WHERE calendarid=7 AND converted<>1″;
$res=mysql_query($sql);
$sql=“Update oc_clndr_delete_objects SET converted=1 WHERE calendarid=7 AND converted<>1“;
$res=mysql_query($sql);
?>
Ein paar Hinweise zum Schluss
Das System hat mittlerweile einige Updates und den Umzug auf einen anderen Server mitgemacht.
Die Updates laufen ohne Probleme durch, Trigger und Cron funktionieren weiterhin.
Beim Umziehen der OwnCloud auf einen anderen Server:
- Beim Umzug der Datenbank wird der Trigger ebenfalls übertragen – fein
- Die php-Datei ebenfalls umziehen
- Den Cron-Job neu einrichten und testen, ich muß bald auf mysqli umstellen, php spuckt Warnungen aus:
PHP Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /var/www/owncloud/prevent_delete.php on line 7
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /var/www/owncloud/prevent_delete.php on line 7