import favorites from gpx file

This commit is contained in:
Julien Veyssier 2019-04-03 20:26:21 +02:00
Родитель 41feedbaf5
Коммит cef6fc5fbf
5 изменённых файлов: 237 добавлений и 2 удалений

Просмотреть файл

@ -39,5 +39,6 @@ return [
['name' => 'favorites#exportAllFavorites', 'url' => '/export/favorites', 'verb' => 'GET'],
['name' => 'favorites#exportFavorites', 'url' => '/export/favorites', 'verb' => 'POST'],
['name' => 'favorites#importFavorites', 'url' => '/import/favorites', 'verb' => 'POST'],
]
];

Просмотреть файл

@ -180,6 +180,19 @@ FavoritesController.prototype = {
that.exportDisplayedFavorites();
});
// import favorites
$('body').on('click', '#import-favorites', function(e) {
OC.dialogs.filepicker(
t('maps', 'Import favorites from gpx file'),
function(targetPath) {
that.importFavorites(targetPath);
},
false,
null,
true
);
});
this.cluster = L.markerClusterGroup({
//iconCreateFunction: function(cluster) {
// return L.divIcon({ html: '<div>' + cluster.getChildCount() + '</div>' });
@ -492,6 +505,19 @@ FavoritesController.prototype = {
},
deleteCategory: function(cat) {
// favorites (just in case the category is not empty)
var favids = [];
for (favid in this.categoryMarkers[cat]) {
favids.push(favid);
}
for (var i=0; i < favids.length; i++) {
var favid = favids[i];
this.categoryLayers[cat].removeLayer(this.markers[favid]);
delete this.favorites[favid];
delete this.markers[favid];
delete this.categoryMarkers[cat][favid];
}
// category
this.map.removeLayer(this.categoryLayers[cat]);
delete this.categoryLayers[cat];
delete this.categoryMarkers[cat];
@ -888,5 +914,34 @@ FavoritesController.prototype = {
OC.Notification.showTemporary(t('maps', 'Failed to export favorites'));
});
},
importFavorites: function(path) {
$('#navigation-favorites').addClass('icon-loading-small');
var that = this;
var req = {
path: path
};
var url = OC.generateUrl('/apps/maps/import/favorites');
$.ajax({
type: 'POST',
url: url,
data: req,
async: true
}).done(function (response) {
OC.Notification.showTemporary(t('maps', '{nb} favorites imported from {path}', {nb: response, path: path}));
var catToDel = [];
for (var cat in that.categoryLayers) {
catToDel.push(cat);
}
for (var i=0; i < catToDel.length; i++) {
that.deleteCategory(catToDel[i]);
}
that.getFavorites();
}).always(function (response) {
$('#navigation-favorites').removeClass('icon-loading-small');
}).fail(function() {
OC.Notification.showTemporary(t('maps', 'Failed to import favorites'));
});
},
}

Просмотреть файл

@ -32,6 +32,13 @@ use OCP\Share;
use OCA\Maps\Service\FavoritesService;
function endswith($string, $test) {
$strlen = strlen($string);
$testlen = strlen($test);
if ($testlen > $strlen) return false;
return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}
class FavoritesController extends Controller {
private $userId;
@ -140,7 +147,7 @@ class FavoritesController extends Controller {
* @NoAdminRequired
*/
public function exportAllFavorites() {
return $this->exportFavorites(null, null, null, true);
return $this->exportFavorites([], null, null, true);
}
/**
@ -187,4 +194,35 @@ class FavoritesController extends Controller {
return new DataResponse('/Maps/'.$filename);
}
/**
* @NoAdminRequired
*/
public function importFavorites($path) {
$userFolder = $this->userfolder;
$cleanpath = str_replace(array('../', '..\\'), '', $path);
if ($userFolder->nodeExists($cleanpath)){
$file = $userFolder->get($cleanpath);
if ($file->getType() === \OCP\Files\FileInfo::TYPE_FILE and
$file->isReadable()){
if (endswith($file->getName(), '.gpx') or endswith($file->getName(), '.GPX')) {
$nbImported = $this->favoritesService->importFavorites($this->userId, $file);
return new DataResponse($nbImported);
}
else {
// invalid extension
return new DataResponse('Invalid file extension', 400);
}
}
else {
// directory or not readable
return new DataResponse('Impossible to read the file', 400);
}
}
else {
// does not exist
return new DataResponse('File does not exist', 400);
}
}
}

Просмотреть файл

@ -22,6 +22,11 @@ class FavoritesService {
private $logger;
private $qb;
private $currentFavorite;
private $currentFavoritesList;
private $nbImported;
private $importUserId;
public function __construct (ILogger $logger, IL10N $l10n) {
$this->l10n = $l10n;
$this->logger = $logger;
@ -139,6 +144,48 @@ class FavoritesService {
return $favoriteId;
}
public function addMultipleFavoritesToDB($userId, $favoriteList) {
$nowTimeStamp = (new \DateTime())->getTimestamp();
$qb = $this->qb;
$values = [];
foreach ($favoriteList as $fav) {
$name = (!array_key_exists('name', $fav) or !$fav['name']) ? 'no name' : $fav['name'];
$ts = (!array_key_exists('date_created', $fav) or !is_numeric($fav['date_created'])) ? $nowTimeStamp : $fav['date_created'];
if (
!array_key_exists('lat', $fav) or !is_numeric($fav['lat']) or
!array_key_exists('lng', $fav) or !is_numeric($fav['lng'])
) {
continue;
}
else {
$lat = floatval($fav['lat']);
$lng = floatval($fav['lng']);
}
$category = (!array_key_exists('category', $fav) or !$fav['category']) ? 'no category' : $fav['category'];
$comment = (!array_key_exists('comment', $fav) or !$fav['comment']) ? null : $fav['comment'];
$extensions = (!array_key_exists('extensions', $fav) or !$fav['extensions']) ? null : $fav['extensions'];
array_push($values, [
'user_id' => $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR),
'name' => $qb->createNamedParameter($name, IQueryBuilder::PARAM_STR),
'date_created' => $qb->createNamedParameter($ts, IQueryBuilder::PARAM_INT),
'date_modified' => $qb->createNamedParameter($nowTimeStamp, IQueryBuilder::PARAM_INT),
'lat' => $qb->createNamedParameter($lat, IQueryBuilder::PARAM_LOB),
'lng' => $qb->createNamedParameter($lng, IQueryBuilder::PARAM_LOB),
'category' => $qb->createNamedParameter($category, IQueryBuilder::PARAM_STR),
'comment' => $qb->createNamedParameter($comment, IQueryBuilder::PARAM_STR),
'extensions' => $qb->createNamedParameter($extensions, IQueryBuilder::PARAM_STR)
]);
}
foreach ($values as $v) {
$qb->insert('maps_favorites');
$qb->values($v);
// TODO make one request
$req = $qb->execute();
$qb = $qb->resetQueryParts();
}
}
public function editFavoriteInDB($id, $name, $lat, $lng, $category, $comment, $extensions) {
$nowTimeStamp = (new \DateTime())->getTimestamp();
$qb = $this->qb;
@ -300,8 +347,96 @@ class FavoritesService {
fwrite($fileHandler, $gpxText);
$favIndex = $favIndex + $chunkSize;
}
$gpxEnd .= '</gpx>' . "\n";
$gpxEnd = '</gpx>' . "\n";
fwrite($fileHandler, $gpxEnd);
}
public function importFavorites($userId, $file) {
$this->nbImported = 0;
$this->currentFavoritesList = [];
$this->importUserId = $userId;
$xml_parser = xml_parser_create();
xml_set_object($xml_parser, $this);
xml_set_element_handler($xml_parser, 'gpxStartElement', 'gpxEndElement');
xml_set_character_data_handler($xml_parser, 'gpxDataElement');
$fp = $file->fopen('r');
while ($data = fread($fp, 4096000)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
$this->logger->error(
'Exception in '.$file->getName().' parsing at line '.
xml_get_current_line_number($xml_parser).' : '.
xml_error_string(xml_get_error_code($xml_parser)),
array('app' => 'maps')
);
return 5;
}
}
fclose($fp);
xml_parser_free($xml_parser);
return $this->nbImported;
}
private function gpxStartElement($parser, $name, $attrs) {
//$points, array($lat, $lon, $ele, $timestamp, $acc, $bat, $sat, $ua, $speed, $bearing)
$this->currentXmlTag = $name;
if ($name === 'WPT') {
$this->currentFavorite = [];
if (array_key_exists('LAT', $attrs)) {
$this->currentFavorite['lat'] = floatval($attrs['LAT']);
}
if (array_key_exists('LON', $attrs)) {
$this->currentFavorite['lng'] = floatval($attrs['LON']);
}
}
//var_dump($attrs);
}
private function gpxEndElement($parser, $name) {
if ($name === 'GPX') {
// create last bunch
if (count($this->currentFavoritesList) > 0) {
$this->addMultipleFavoritesToDB($this->importUserId, $this->currentFavoritesList);
}
unset($this->currentFavoritesList);
}
else if ($name === 'WPT') {
// store favorite
$this->nbImported++;
array_push($this->currentFavoritesList, $this->currentFavorite);
// if we have enough favorites, we create them and clean the array
if (count($this->currentFavoritesList) >= 3) {
$this->addMultipleFavoritesToDB($this->importUserId, $this->currentFavoritesList);
unset($this->currentFavoritesList);
$this->currentFavoritesList = [];
}
}
}
private function gpxDataElement($parser, $data) {
$d = trim($data);
if (!empty($d)) {
if ($this->currentXmlTag === 'NAME') {
$this->currentFavorite['name'] = $d;
}
else if ($this->currentXmlTag === 'TIME') {
$time = new \DateTime($d);
$timestamp = $time->getTimestamp();
$this->currentFavorite['date_created'] = $timestamp;
}
else if ($this->currentXmlTag === 'TYPE') {
$this->currentFavorite['category'] = $d;
}
else if ($this->currentXmlTag === 'DESC') {
$this->currentFavorite['comment'] = $d;
}
else if ($this->currentXmlTag === 'MAPS-EXTENSIONS') {
$this->currentFavorite['extensions'] = $d;
}
}
}
}

Просмотреть файл

@ -54,6 +54,12 @@
<span><?php p($l->t('Export displayed favorites')); ?></span>
</a>
</li>
<li>
<a href="#" id="import-favorites">
<span class="icon-folder"></span>
<span><?php p($l->t('Import favorites from gpx files')); ?></span>
</a>
</li>
<li>
<a href="#" id="select-all-categories">
<span class="icon-category-enabled"></span>