mirror of
https://github.com/nextcloud/maps.git
synced 2026-01-12 15:46:09 +00:00
ref: https://github.com/nextcloud/maps/compare/copilot/fix-1288 Signed-off-by: umgfoin <umgfoin@users.noreply.github.com>
550 lines
18 KiB
PHP
550 lines
18 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Nextcloud - Maps
|
|
*
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
* later. See the COPYING file.
|
|
*
|
|
* @author Julien Veyssier <eneiluj@posteo.net>
|
|
* @author Paul Schwörer <hello@paulschwoerer.de>
|
|
* @copyright Julien Veyssier 2019
|
|
* @copyright Paul Schwörer 2019
|
|
*/
|
|
|
|
namespace OCA\Maps\Controller;
|
|
|
|
use OCA\Maps\DB\FavoriteShareMapper;
|
|
use OCA\Maps\Service\FavoritesService;
|
|
use OCP\App\IAppManager;
|
|
use OCP\AppFramework\Controller;
|
|
use OCP\AppFramework\Db\DoesNotExistException;
|
|
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
|
use OCP\AppFramework\Http;
|
|
use OCP\AppFramework\Http\DataResponse;
|
|
use OCP\Files\Folder;
|
|
use OCP\Files\NotFoundException;
|
|
use OCP\IConfig;
|
|
use OCP\IDateTimeZone;
|
|
use OCP\IGroupManager;
|
|
use OCP\IL10N;
|
|
use OCP\IRequest;
|
|
use OCP\IServerContainer;
|
|
use OCP\IUserManager;
|
|
use OCP\Share\IManager;
|
|
|
|
class FavoritesController extends Controller {
|
|
|
|
private string $userId;
|
|
private \OCP\Files\Folder $userFolder;
|
|
private IConfig $config;
|
|
private string $appVersion;
|
|
private IManager $shareManager;
|
|
private IUserManager $userManager;
|
|
private IGroupManager $groupManager;
|
|
private string $dbtype;
|
|
private IL10N $l;
|
|
private FavoritesService $favoritesService;
|
|
private IDateTimeZone $dateTimeZone;
|
|
private ?string $defaultFavoritsJSON;
|
|
protected $appName;
|
|
|
|
/* @var FavoriteShareMapper */
|
|
private $favoriteShareMapper;
|
|
|
|
public function __construct($AppName,
|
|
IRequest $request,
|
|
IServerContainer $serverContainer,
|
|
IConfig $config,
|
|
IManager $shareManager,
|
|
IAppManager $appManager,
|
|
IUserManager $userManager,
|
|
IGroupManager $groupManager,
|
|
IL10N $l,
|
|
FavoritesService $favoritesService,
|
|
IDateTimeZone $dateTimeZone,
|
|
FavoriteShareMapper $favoriteShareMapper,
|
|
$UserId) {
|
|
parent::__construct($AppName, $request);
|
|
$this->favoritesService = $favoritesService;
|
|
$this->dateTimeZone = $dateTimeZone;
|
|
$this->appName = $AppName;
|
|
$this->appVersion = $config->getAppValue('maps', 'installed_version');
|
|
$this->userId = $UserId;
|
|
$this->userManager = $userManager;
|
|
$this->groupManager = $groupManager;
|
|
$this->l = $l;
|
|
$this->dbtype = $config->getSystemValue('dbtype');
|
|
// IConfig object
|
|
$this->config = $config;
|
|
if ($UserId !== '' and $UserId !== null and $serverContainer !== null) {
|
|
// path of user files folder relative to DATA folder
|
|
$this->userFolder = $serverContainer->getUserFolder($UserId);
|
|
}
|
|
$this->shareManager = $shareManager;
|
|
$this->favoriteShareMapper = $favoriteShareMapper;
|
|
$this->defaultFavoritsJSON = json_encode([
|
|
'type' => 'FeatureCollection',
|
|
'features' => []
|
|
], JSON_PRETTY_PRINT);
|
|
}
|
|
|
|
/**
|
|
* @param \OCP\Files\Folder $folder
|
|
* @return mixed
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
private function getJSONFavoritesFile(\OCP\Files\Folder $folder): \OCP\Files\Node {
|
|
try {
|
|
$file = $folder->get('.favorites.json');
|
|
} catch (NotFoundException $e) {
|
|
$file = $folder->newFile('.favorites.json', $content = $this->defaultFavoritsJSON);
|
|
}
|
|
return $file;
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param ?int $myMapId
|
|
* @return DataResponse
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function getFavorites(?int $myMapId = null): DataResponse {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$favorites = $this->favoritesService->getFavoritesFromDB($this->userId);
|
|
} else {
|
|
$folders = $this->userFolder->getById($myMapId);
|
|
$folder = array_shift($folders);
|
|
$file = $this->getJSONFavoritesFile($folder);
|
|
$favorites = $this->favoritesService->getFavoritesFromJSON($file);
|
|
}
|
|
return new DataResponse($favorites);
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param string|null $name
|
|
* @param float $lat
|
|
* @param float $lng
|
|
* @param string|null $category
|
|
* @param string|null $comment
|
|
* @param string|null $extensions
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws NotFoundException
|
|
* @throws \OCP\Files\InvalidPathException
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function addFavorite(?string $name, float $lat, float $lng, ?string $category, ?string $comment, ?string $extensions, ?int $myMapId = null): DataResponse {
|
|
if (is_numeric($lat) && is_numeric($lng)) {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$favoriteId = $this->favoritesService->addFavoriteToDB($this->userId, $name, $lat, $lng, $category, $comment, $extensions);
|
|
$favorite = $this->favoritesService->getFavoriteFromDB($favoriteId);
|
|
return new DataResponse($favorite);
|
|
} else {
|
|
$folders = $this->userFolder->getById($myMapId);
|
|
if (!empty($folders) && $this->userFolder->getId() === $myMapId) {
|
|
$folders[] = $this->userFolder;
|
|
}
|
|
$folder = array_shift($folders);
|
|
if (is_null($folder)) {
|
|
return new DataResponse('Map not found', 404);
|
|
}
|
|
$file = $this->getJSONFavoritesFile($folder);
|
|
$favoriteId = $this->favoritesService->addFavoriteToJSON($file, $name, $lat, $lng, $category, $comment, $extensions);
|
|
$favorite = $this->favoritesService->getFavoriteFromJSON($file, $favoriteId);
|
|
return new DataResponse($favorite);
|
|
}
|
|
|
|
} else {
|
|
return new DataResponse($this->l->t('Invalid values'), 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param array $favorites
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws NotFoundException
|
|
* @throws \OCP\Files\InvalidPathException
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function addFavorites(array $favorites, ?int $myMapId = null): DataResponse {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$favoritesAfter = [];
|
|
foreach ($favorites as $favorite) {
|
|
if (is_numeric($favorite->lat) && is_numeric($favorite->lng)) {
|
|
$favoriteId = $this->favoritesService->addFavoriteToDB($this->userId, $favorite->name, $favorite->lat, $favorite->lng, $favorite->category, $favorite->comment, $favorite->extensions);
|
|
$favoritesAfter[] = $this->favoritesService->getFavoriteFromDB($favoriteId);
|
|
} else {
|
|
return new DataResponse('invalid values', 400);
|
|
}
|
|
}
|
|
return new DataResponse($favoritesAfter);
|
|
} else {
|
|
$folders = $this->userFolder->getById($myMapId);
|
|
if (!empty($folders) && $this->userFolder->getId() === $myMapId) {
|
|
$folders[] = $this->userFolder;
|
|
}
|
|
$folder = array_shift($folders);
|
|
if (is_null($folder)) {
|
|
return new DataResponse('Map not found', 404);
|
|
}
|
|
$file = $this->getJSONFavoritesFile($folder);
|
|
$favoriteIds = $this->favoritesService->addFavoritesToJSON($file, $favorites);
|
|
$favoritesAfter = [];
|
|
foreach ($this->favoritesService->getFavoritesFromJSON($file) as $favorite) {
|
|
if (in_array($favorite['id'], $favoriteIds)) {
|
|
$favoritesAfter[] = $favorite;
|
|
}
|
|
};
|
|
return new DataResponse($favoritesAfter);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param int $id
|
|
* @param string|null $name
|
|
* @param float $lat
|
|
* @param float $lng
|
|
* @param string|null $category
|
|
* @param string|null $comment
|
|
* @param string|null $extensions
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function editFavorite(int $id, ?string $name, float $lat, float $lng, ?string $category, ?string $comment, ?string $extensions, ?int $myMapId = null): DataResponse {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$favorite = $this->favoritesService->getFavoriteFromDB($id, $this->userId);
|
|
if ($favorite !== null) {
|
|
if (($lat === null || is_numeric($lat)) &&
|
|
($lng === null || is_numeric($lng))
|
|
) {
|
|
$this->favoritesService->editFavoriteInDB($id, $name, $lat, $lng, $category, $comment, $extensions);
|
|
$editedFavorite = $this->favoritesService->getFavoriteFromDB($id);
|
|
return new DataResponse($editedFavorite);
|
|
} else {
|
|
return new DataResponse($this->l->t('invalid values'), 400);
|
|
}
|
|
} else {
|
|
return new DataResponse($this->l->t('no such favorite'), 400);
|
|
}
|
|
} else {
|
|
$folders = $this->userFolder->getById($myMapId);
|
|
$folder = array_shift($folders);
|
|
$file = $this->getJSONFavoritesFile($folder);
|
|
$favorite = $this->favoritesService->getFavoriteFromJSON($file, $id, $this->userId);
|
|
if ($favorite !== null) {
|
|
if (($lat === null || is_numeric($lat)) &&
|
|
($lng === null || is_numeric($lng))
|
|
) {
|
|
$this->favoritesService->editFavoriteInJSON($file, $id, $name, $lat, $lng, $category, $comment, $extensions);
|
|
$editedFavorite = $this->favoritesService->getFavoriteFromJSON($file, $id);
|
|
return new DataResponse($editedFavorite);
|
|
} else {
|
|
return new DataResponse($this->l->t('invalid values'), 400);
|
|
}
|
|
} else {
|
|
return new DataResponse($this->l->t('no such favorite'), 400);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param array $categories
|
|
* @param string $newName
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws \OCP\DB\Exception
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function renameCategories(array $categories, string $newName, ?int $myMapId = null): DataResponse {
|
|
if (is_array($categories)) {
|
|
foreach ($categories as $cat) {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$this->favoritesService->renameCategoryInDB($this->userId, $cat, $newName);
|
|
|
|
// Rename share if one exists
|
|
try {
|
|
$share = $this->favoriteShareMapper->findByOwnerAndCategory($this->userId, $cat);
|
|
$share->setCategory($newName);
|
|
$this->favoriteShareMapper->update($share);
|
|
} catch (DoesNotExistException|MultipleObjectsReturnedException $e) {
|
|
}
|
|
} else {
|
|
$folders = $this->userFolder->getById($myMapId);
|
|
$folder = array_shift($folders);
|
|
$file = $this->getJSONFavoritesFile($folder);
|
|
$this->favoritesService->renameCategoryInJSON($file, $cat, $newName);
|
|
}
|
|
}
|
|
}
|
|
return new DataResponse('RENAMED');
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param int $id
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function deleteFavorite(int $id, ?int $myMapId = null): DataResponse {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$favorite = $this->favoritesService->getFavoriteFromDB($id, $this->userId);
|
|
if ($favorite !== null) {
|
|
$this->favoritesService->deleteFavoriteFromDB($id);
|
|
return new DataResponse('DELETED');
|
|
}
|
|
return new DataResponse($this->l->t('no such favorite'), 400);
|
|
}
|
|
$folders = $this->userFolder->getById($myMapId);
|
|
$folder = array_shift($folders);
|
|
$file = $this->getJSONFavoritesFile($folder);
|
|
if ($this->favoritesService->deleteFavoriteFromJSON($file, $id) > 0) {
|
|
return new DataResponse('DELETED');
|
|
}
|
|
return new DataResponse($this->l->t('no such favorite'), 400);
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param array $ids
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function deleteFavorites(array $ids, ?int $myMapId = null): DataResponse {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$this->favoritesService->deleteFavoritesFromDB($ids, $this->userId);
|
|
} else {
|
|
$folders = $this->userFolder->getById($myMapId);
|
|
$folder = array_shift($folders);
|
|
$file = $this->getJSONFavoritesFile($folder);
|
|
$this->favoritesService->deleteFavoritesFromJSON($file, $ids);
|
|
}
|
|
return new DataResponse('DELETED');
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws \OCP\Files\NotPermittedException
|
|
* @throws \OC\User\NoUserException
|
|
*/
|
|
public function getSharedCategories(?int $myMapId = null): DataResponse {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$categories = $this->favoriteShareMapper->findAllByOwner($this->userId);
|
|
} else {
|
|
$categories = $this->favoriteShareMapper->findAllByMapId($this->userId, $myMapId);
|
|
}
|
|
|
|
return new DataResponse($categories);
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param string $category
|
|
* @return DataResponse
|
|
*/
|
|
public function shareCategory(string $category): DataResponse {
|
|
if ($this->favoritesService->countFavorites($this->userId, [$category], null, null) === 0) {
|
|
return new DataResponse($this->l->t('Unknown category'), Http::STATUS_BAD_REQUEST);
|
|
}
|
|
|
|
$share = $this->favoriteShareMapper->findOrCreateByOwnerAndCategory($this->userId, $category);
|
|
|
|
if ($share === null) {
|
|
return new DataResponse($this->l->t('Error sharing favorite'), Http::STATUS_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
return new DataResponse($share);
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param string $category
|
|
* @return DataResponse
|
|
*/
|
|
public function unShareCategory(string $category): DataResponse {
|
|
if ($this->favoritesService->countFavorites($this->userId, [$category], null, null) === 0) {
|
|
return new DataResponse($this->l->t('Unknown category'), Http::STATUS_BAD_REQUEST);
|
|
}
|
|
|
|
$didExist = $this->favoriteShareMapper->removeByOwnerAndCategory($this->userId, $category);
|
|
|
|
return new DataResponse([
|
|
'did_exist' => $didExist
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param string $category
|
|
* @param int $targetMapId
|
|
* @param int|null $myMapId
|
|
* @return DataResponse
|
|
* @throws DoesNotExistException
|
|
* @throws MultipleObjectsReturnedException
|
|
* @throws \OCP\Files\NotPermittedException
|
|
* @throws \OC\User\NoUserException
|
|
*/
|
|
public function addShareCategoryToMap(string $category, int $targetMapId, ?int $myMapId = null): DataResponse {
|
|
if (is_null($myMapId) || $myMapId === '') {
|
|
$share = $this->favoriteShareMapper->findByOwnerAndCategory($this->userId, $category);
|
|
} else {
|
|
$share = $this->favoriteShareMapper->findByMapIdAndCategory($this->userId, $myMapId, $category);
|
|
}
|
|
$folders = $this->userFolder->getById($targetMapId);
|
|
$folder = array_shift($folders);
|
|
if (!($folder instanceof Folder)) {
|
|
return new DataResponse($this->l->t('Map not Found'), 404);
|
|
}
|
|
try {
|
|
$file = $folder->get('.favorite_shares.json');
|
|
} catch (NotFoundException $e) {
|
|
$file = $folder->newFile('.favorite_shares.json', $content = '[]');
|
|
}
|
|
$data = json_decode($file->getContent(), true);
|
|
foreach ($data as $s) {
|
|
if ($s->token === $share->token) {
|
|
return new DataResponse($this->l->t('Share was already on map'));
|
|
}
|
|
}
|
|
$share->id = count($data);
|
|
$data[] = $share;
|
|
$file->putContent(json_encode($data, JSON_PRETTY_PRINT));
|
|
return new DataResponse('Done');
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param string $category
|
|
* @param int $myMapId
|
|
* @return DataResponse
|
|
*/
|
|
public function removeShareCategoryFromMap(string $category, int $myMapId): DataResponse {
|
|
$d = $this->favoriteShareMapper->removeByMapIdAndCategory($this->userId, $myMapId, $category);
|
|
if (is_null($d)) {
|
|
return new DataResponse('Failed', 500);
|
|
}
|
|
return new DataResponse('Done');
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param array|null $categoryList
|
|
* @param int|null $begin
|
|
* @param int|null $end
|
|
* @param bool $all
|
|
* @return DataResponse
|
|
* @throws NotFoundException
|
|
* @throws \OCP\Files\NotPermittedException
|
|
*/
|
|
public function exportFavorites(?array $categoryList = null, ?int $begin = null, ?int $end = null, bool $all = false): DataResponse {
|
|
// sorry about ugly categoryList management:
|
|
// when an empty list is passed in http request, we get null here
|
|
if ($categoryList === null or (is_array($categoryList) and count($categoryList) === 0)) {
|
|
$response = new DataResponse($this->l->t('Nothing to export'), 400);
|
|
return $response;
|
|
}
|
|
|
|
// create /Maps directory if necessary
|
|
$userFolder = $this->userFolder;
|
|
if (!$userFolder->nodeExists('/Maps')) {
|
|
$userFolder->newFolder('Maps');
|
|
}
|
|
if ($userFolder->nodeExists('/Maps')) {
|
|
$mapsFolder = $userFolder->get('/Maps');
|
|
if (!($mapsFolder instanceof Folder)) {
|
|
$response = new DataResponse($this->l->t('/Maps is not a directory'), 400);
|
|
return $response;
|
|
} elseif (!$mapsFolder->isCreatable()) {
|
|
$response = new DataResponse($this->l->t('/Maps directory is not writeable'), 400);
|
|
return $response;
|
|
}
|
|
} else {
|
|
$response = new DataResponse($this->l->t('Impossible to create /Maps directory'), 400);
|
|
return $response;
|
|
}
|
|
|
|
$nbFavorites = $this->favoritesService->countFavorites($this->userId, $categoryList, $begin, $end);
|
|
if ($nbFavorites === 0) {
|
|
$response = new DataResponse($this->l->t('Nothing to export'), 400);
|
|
return $response;
|
|
}
|
|
|
|
// generate export file name
|
|
$prefix = $all ? '' : 'filtered-';
|
|
$tz = $this->dateTimeZone->getTimeZone();
|
|
$now = new \DateTime('now', $tz);
|
|
$dateStr = $now->format('Y-m-d H:i:s (P)');
|
|
$filename = $dateStr . ' ' . $prefix . 'favorites.gpx';
|
|
|
|
if ($mapsFolder->nodeExists($filename)) {
|
|
$mapsFolder->get($filename)->delete();
|
|
}
|
|
$file = $mapsFolder->newFile($filename);
|
|
$handler = $file->fopen('w');
|
|
|
|
$this->favoritesService->exportFavorites($this->userId, $handler, $categoryList, $begin, $end, $this->appVersion);
|
|
|
|
fclose($handler);
|
|
$file->touch();
|
|
return new DataResponse('/Maps/' . $filename);
|
|
}
|
|
|
|
/**
|
|
* @NoAdminRequired
|
|
* @param string $path
|
|
* @return DataResponse
|
|
* @throws NotFoundException
|
|
* @throws \OCP\Files\InvalidPathException
|
|
*/
|
|
public function importFavorites(string $path): DataResponse {
|
|
$userFolder = $this->userFolder;
|
|
$cleanpath = str_replace(['../', '..\\'], '', $path);
|
|
|
|
if ($userFolder->nodeExists($cleanpath)) {
|
|
$file = $userFolder->get($cleanpath);
|
|
if ($file->getType() === \OCP\Files\FileInfo::TYPE_FILE and
|
|
$file->isReadable()) {
|
|
$lowerFileName = strtolower($file->getName());
|
|
if ($this->endswith($lowerFileName, '.gpx') or $this->endswith($lowerFileName, '.kml') or $this->endswith($lowerFileName, '.kmz') or $this->endswith($lowerFileName, '.json') or $this->endswith($lowerFileName, '.geojson')) {
|
|
$result = $this->favoritesService->importFavorites($this->userId, $file);
|
|
return new DataResponse($result);
|
|
} else {
|
|
// invalid extension
|
|
return new DataResponse($this->l->t('Invalid file extension'), 400);
|
|
}
|
|
} else {
|
|
// directory or not readable
|
|
return new DataResponse($this->l->t('Impossible to read the file'), 400);
|
|
}
|
|
} else {
|
|
// does not exist
|
|
return new DataResponse($this->l->t('File does not exist'), 400);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $string
|
|
* @param string $test
|
|
* @return bool
|
|
*/
|
|
private function endswith(string $string, string $test): bool {
|
|
$strlen = strlen($string);
|
|
$testlen = strlen($test);
|
|
if ($testlen > $strlen) {
|
|
return false;
|
|
}
|
|
return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
|
|
}
|
|
|
|
}
|