Add gpx import feature (closes #14)

This commit is contained in:
Bartek Fabiszewski 2017-05-09 09:06:23 +02:00
parent a6f3ed1162
commit 33b581b47a
12 changed files with 170 additions and 16 deletions

View File

@ -106,7 +106,7 @@ select {
cursor: pointer;
}
#user, #track, #summary, #export, #other, #units {
#user, #track, #summary, #export, #import, #other, #units {
padding-bottom: 10px;
}
#summary span {

View File

@ -189,12 +189,21 @@
</div>
<div id="export">
<u><?= $lang["download"] ?></u><br>
<a class="menulink" href="javascript:void(0);" onclick="load('kml', userid, trackid);">kml</a>
<a class="menulink" href="javascript:void(0);" onclick="load('gpx', userid, trackid);">gpx</a>
<u><?= $lang["export"] ?></u><br>
<a class="menulink" href="javascript:void(0);" onclick="exportFile('kml', userid, trackid);">kml</a>
<a class="menulink" href="javascript:void(0);" onclick="exportFile('gpx', userid, trackid);">gpx</a>
</div>
<?php if ($user->isValid): ?>
<div id="import">
<u><?= $lang["import"] ?></u><br>
<form id="importForm" enctype="multipart/form-data" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1048576" />
<input type="file" id="inputFile" name="gpx" style="display:none" onchange="importFile(this)" />
</form>
<a class="menulink" href="javascript:void(0);" onclick="document.getElementById('inputFile').click();">gpx</a>
</div>
<div id="admin_menu">
<u><?= $lang["adminmenu"] ?></u><br>
<?php if ($user->isAdmin): ?>

View File

@ -217,11 +217,42 @@ function getPopupHtml(p, i, count) {
return popup;
}
function load(type, userid, trackid) {
var url = 'utils/download.php?type=' + type + '&userid=' + userid + '&trackid=' + trackid;
function exportFile(type, userid, trackid) {
var url = 'utils/export.php?type=' + type + '&userid=' + userid + '&trackid=' + trackid;
window.location.assign(url);
}
function importFile(input){
var xhr = getXHR();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var xml = xhr.responseXML;
var message = "";
if (xml) {
var root = xml.getElementsByTagName('root');
if (root.length && getNode(root[0], 'error') == 0) {
trackId = getNode(root[0], 'trackid');
getTracks(userid);
loadTrack(userid, trackId, 1);
return;
}
errorMsg = getNode(root[0], 'message');
if (errorMsg) { message = errorMsg; }
}
alert(lang['actionfailure'] + '\n' + message);
xhr = null;
}
}
xhr.upload.onprogress = function(e) {
console.log(e.loaded, e.total)
}
xhr.upload.onload = function(e) {
console.log('file upload')
}
xhr.open("POST", "utils/import.php", true);
xhr.send(new FormData(input.parentElement));
}
function updateSummary(l, d, s) {
var t = document.getElementById('summary');
if (latest == 0) {

View File

@ -25,7 +25,7 @@ $lang["track"] = "Route";
$lang["latest"] = "letzte Position";
$lang["autoreload"] = "Autoneuladen";
$lang["reload"] = "Neuladen";
$lang["download"] = "Download Daten";
$lang["export"] = "Download Daten";
$lang["chart"] = "Höhentabelle";
$lang["close"] = "Schließen";
$lang["time"] = "Zeit";

View File

@ -54,7 +54,7 @@ $lang["track"] = "Track";
$lang["latest"] = "latest position";
$lang["autoreload"] = "autoreload";
$lang["reload"] = "Reload now";
$lang["download"] = "Download data";
$lang["export"] = "Export track";
$lang["chart"] = "Altitudes chart";
$lang["close"] = "close";
$lang["time"] = "Time";
@ -114,5 +114,7 @@ $lang["passrules"][3] = "It should contain at least one lower case letter, one u
$lang["owntrackswarn"] = "Your can only edit your own tracks";
$lang["gmauthfailure"] = "There may be problem with Google Maps API key on this page";
$lang["gmapilink"] = "You may find more information about API keys on <a target=\"_blank\" href=\"https://developers.google.com/maps/documentation/javascript/get-api-key\">this Google webpage</a>";
$lang["import"] = "Import track";
$lang["iparsefailure"] = "Parsing failed";
$lang["idatafailure"] = "No track data in imported file";
?>

View File

@ -25,7 +25,7 @@ $lang["track"] = "Rastro";
$lang["latest"] = "última posición";
$lang["autoreload"] = "autorecarga";
$lang["reload"] = "Recargar ahora";
$lang["download"] = "Descargar datos";
$lang["export"] = "Descargar datos";
$lang["chart"] = "Gráfico de altitudes";
$lang["close"] = "cerrar";
$lang["time"] = "Hora";

View File

@ -25,7 +25,7 @@ $lang["track"] = "Piste";
$lang["latest"] = "dernière position";
$lang["autoreload"] = "rechargement automatique";
$lang["reload"] = "Recharger maintenant";
$lang["download"] = "Télécharger les données";
$lang["export"] = "Télécharger les données";
$lang["chart"] = "Courbes d'altitudes";
$lang["close"] = "fermer";
$lang["time"] = "Temps";

View File

@ -25,7 +25,7 @@ $lang["track"] = "Útvonal";
$lang["latest"] = "Utolsó rögzített pont";
$lang["autoreload"] = "Automatikus frissítés";
$lang["reload"] = "Frissítés most";
$lang["download"] = "Adatok letöltése";
$lang["export"] = "Adatok letöltése";
$lang["chart"] = "Magasság diagramm";
$lang["close"] = "Bezár";
$lang["time"] = "Rögzítés ideje";

View File

@ -54,7 +54,7 @@ $lang["track"] = "Traccia";
$lang["latest"] = "ultima posizione";
$lang["autoreload"] = "auto-ricarica";
$lang["reload"] = "Ricarica ora";
$lang["download"] = "Scarica dati";
$lang["export"] = "Scarica dati";
$lang["chart"] = "Grafico altitudine";
$lang["close"] = "chiudi";
$lang["time"] = "Ora";

View File

@ -49,7 +49,7 @@ $lang["track"] = "Trasa";
$lang["latest"] = "ostatnia pozycja";
$lang["autoreload"] = "odświeżaj";
$lang["reload"] = "Odśwież teraz";
$lang["download"] = "Pobierz dane";
$lang["export"] = "Eksportuj trasę";
$lang["chart"] = "Wykres przewyższeń";
$lang["close"] = "zamknij";
$lang["time"] = "Czas";
@ -109,5 +109,8 @@ $lang["passrules"][3] = "Powinno ono zawierać przynajmniej jedną małą, jedn
$lang["owntrackswarn"] = "Możesz edytować tylko swoje własne trasy";
$lang["gmauthfailure"] = "Prawdopodobnie na tej stronie występuje problem z kluczem API Google Maps";
$lang["gmapilink"] = "Więcej informacji o kluczach API znajdziesz <a target=\"_blank\" href=\"https://developers.google.com/maps/documentation/javascript/get-api-key\">pod tym linkiem</a>";
$lang["import"] = "Importuj trasę";
$lang["iparsefailure"] = "Błąd parsowania pliku";
$lang["idatafailure"] = "Brak trasy w importowanym pliku";
?>

View File

@ -182,7 +182,7 @@ if ($trackId && $userId) {
$xml->writeAttribute("version", "1.1");
$xml->startElement("metadata");
$xml->writeElement("name", $positionsArr[0]->trackName);
$xml->writeElement("time", str_replace(" ", "T", $positionsArr[0]->time));
$xml->writeElement("time", gmdate("Y-m-d\TH:i:s\Z", strtotime($positionsArr[0]->time)));
$xml->endElement();
$xml->startElement("trk");
$xml->writeElement("name", $positionsArr[0]->trackName);
@ -200,7 +200,7 @@ if ($trackId && $userId) {
$xml->writeAttribute("lat", $position->latitude);
$xml->writeAttribute("lon", $position->longitude);
if (!is_null($position->altitude)) { $xml->writeElement("ele", $position->altitude); }
$xml->writeElement("time", str_replace(" ", "T", $position->time));
$xml->writeElement("time", gmdate("Y-m-d\TH:i:s\Z", strtotime($position->time)));
$xml->writeElement("name", ++$i);
$xml->startElement("desc");
$description =

109
utils/import.php Executable file
View File

@ -0,0 +1,109 @@
<?php
/* μlogger
*
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
require_once(dirname(__DIR__) . "/auth.php"); // sets $user
require_once(ROOT_DIR . "/helpers/track.php");
require_once(ROOT_DIR . "/helpers/position.php");
/**
* Exit with xml response
* @param boolean $isError Error if true
* @param string $errorMessage Optional error message
*/
function exitWithStatus($isError, $errorMessage = NULL, $trackId = NULL) {
header("Content-type: text/xml");
$xml = new XMLWriter();
$xml->openURI("php://output");
$xml->startDocument("1.0");
$xml->setIndent(true);
$xml->startElement('root');
$xml->writeElement("error", (int) $isError);
if ($isError) {
$xml->writeElement("message", $errorMessage);
} else {
$xml->writeElement("trackid", $trackId);
}
$xml->endElement();
$xml->endDocument();
$xml->flush();
exit;
}
if (!$user->isValid) {
exitWithStatus(true, $lang["servererror"]);
}
$sizeMax = 10 * 1024 * 1024; //FIXME: set to php limits
$gpxFile = NULL;
$gpxUpload = $_FILES["gpx"];
if ($gpxUpload["error"] == UPLOAD_ERR_OK && $gpxUpload["size"] < $sizeMax) {
$gpxFile = $gpxUpload["tmp_name"];
$gpxName = basename($gpxUpload["name"]);
}
$gpx = false;
libxml_use_internal_errors(true);
if ($gpxFile && file_exists($gpxFile)) {
$gpx = simplexml_load_file($gpxFile);
}
if ($gpx === false) {
$message = $lang["iparsefailure"];
$parserMessages = [];
foreach(libxml_get_errors() as $parseError) {
$parserMessages[] = $parseError->message;
}
$parserMessage = implode(", ", $parserMessages);
if (!empty($parserMessage)) {
$message .= ": $parserMessage";
}
if ($gpxUpload["error"] != UPLOAD_ERR_OK) {
$message .= " (" . $gpxUpload["error"] . ")";
}
exitWithStatus(true, $message);
}
else if (empty($gpx->trk)) {
exitWithStatus(true, $lang["idatafailure"]);
}
$trackName = empty($gpx->trk->name) ? $gpxName : $gpx->trk->name->__toString();
$metaName = empty($gpx->metadata->name) ? NULL : $gpx->metadata->name->__toString();
$track = new uTrack();
$trackId = $track->add($user->id, $trackName, $metaName);
if ($trackId === false) {
exitWithStatus(true, $lang["servererror"]);
break;
}
$position = new uPosition();
foreach($gpx->trk->trkseg as $segment) {
foreach($segment->trkpt as $point) {
$ret = $position->add($user->id, $trackId,
strtotime($point->time), $point["lat"], $point["lon"], $point->ele,
NULL, NULL, NULL, "gps", NULL, NULL);
if ($ret === false) {
exitWithStatus(true, $lang["servererror"]);
}
}
}
// return track id
exitWithStatus(false, NULL, $trackId);
?>