Merge branch 'repectNoMediaAndNoImage' into nextgovhackathon-master

Signed-off-by: Arne Hamann <git@arne.email>
This commit is contained in:
Arne Hamann
2022-04-25 13:12:30 +02:00
4 changed files with 193 additions and 71 deletions

View File

@ -99,10 +99,16 @@ class ExifGeoData
*/ */
protected static function get_exif_data_array(string $path) : array{ protected static function get_exif_data_array(string $path) : array{
if( function_exists('exif_read_data') ) { if( function_exists('exif_read_data') ) {
$data = @exif_read_data($path, null, true)['EXIF']; $data = @exif_read_data($path, null, true);
if ($data && isset($data[self::LATITUDE]) && isset($data[self::LONGITUDE])) { if ($data && isset($data['EXIF']) && isset($data['EXIF'][self::LATITUDE]) && isset($data['EXIF'][self::LONGITUDE])) {
return $data; return $data['EXIF'];
} } elseif ($data && isset($data['GPS']) && isset($data['GPS'][self::LATITUDE]) && isset($data['GPS'][self::LONGITUDE])) {
$d = $data['GPS'];
if (!isset($d[self::TIMESTAMP]) && isset($data['EXIF'][self::TIMESTAMP])) {
$d[self::TIMESTAMP] = $data['EXIF'][self::TIMESTAMP];
}
return $data['GPS'];
}
} }
$data = new PelDataWindow(file_get_contents($path)); $data = new PelDataWindow(file_get_contents($path));
if (PelJpeg::isValid($data)) { if (PelJpeg::isValid($data)) {
@ -254,7 +260,7 @@ class ExifGeoData
// optional // optional
if (isset($this->exif_data[self::TIMESTAMP])) { if (isset($this->exif_data[self::TIMESTAMP])) {
$t = $this->exif_data[self::TIMESTAMP]; $t = $this->exif_data[self::TIMESTAMP];
$this->timestamp = is_string($t) ? $this->string2time($t) : is_int($t) ? $t : null; $this->timestamp = is_string($t) ? $this->string2time($t) : ( is_int($t) ? $t : null );
} }
} }

View File

@ -12,7 +12,12 @@
namespace OCA\Maps\Service; namespace OCA\Maps\Service;
use OC\Files\Search\SearchBinaryOperator;
use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchQuery;
use OCP\Files\FileInfo; use OCP\Files\FileInfo;
use OCP\Files\Search\ISearchBinaryOperator;
use OCP\Files\Search\ISearchComparison;
use OCP\IL10N; use OCP\IL10N;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use OCP\Files\Storage\IStorage; use OCP\Files\Storage\IStorage;
@ -30,37 +35,41 @@ use OCA\Maps\Service\DevicesService;
class GeophotoService { class GeophotoService {
private $l10n; private $l10n;
private $root;
private $photoMapper; private $photoMapper;
private $logger; private $logger;
private $preview; private $preview;
private $tracksService; private $tracksService;
private $timeorderedPointSets; private $timeorderedPointSets;
private $devicesService; private $devicesService;
private $userfolder;
public function __construct (ILogger $logger, public function __construct (ILogger $logger,
IL10N $l10n,
IRootFolder $root, IRootFolder $root,
IL10N $l10n,
GeophotoMapper $photoMapper, GeophotoMapper $photoMapper,
IPreview $preview, IPreview $preview,
TracksService $tracksService, TracksService $tracksService,
DevicesService $devicesService) { DevicesService $devicesService,
$userId) {
$this->root = $root;
$this->l10n = $l10n; $this->l10n = $l10n;
$this->photoMapper = $photoMapper; $this->photoMapper = $photoMapper;
$this->logger = $logger; $this->logger = $logger;
$this->preview = $preview; $this->preview = $preview;
$this->tracksService = $tracksService; $this->tracksService = $tracksService;
$this->timeorderedPointSets = null; $this->timeorderedPointSets = null;
$this->root = $root; $this->userId = $userId;
$this->devicesService = $devicesService; $this->devicesService = $devicesService;
} }
/** /**
* @param string $userId * @param string $userId
* @param Folder|null $folder * @param bool $respectNomediaAndNoimage=true
* @param Folder|null $folder
* @return array with geodatas of all photos * @return array with geodatas of all photos
*/ */
public function getAllFromDB($userId, $folder=null) { public function getAllFromDB(string $userId, bool $respectNomediaAndNoimage=true, $folder=null) {
$ignoredPaths = $respectNomediaAndNoimage ? $this->getIgnoredPaths($userId, $folder) : [];
$photoEntities = $this->photoMapper->findAll($userId); $photoEntities = $this->photoMapper->findAll($userId);
if (is_null($folder)) { if (is_null($folder)) {
$folder = $this->getFolderForUser($userId); $folder = $this->getFolderForUser($userId);
@ -70,7 +79,7 @@ class GeophotoService {
$previewEnableMimetypes = $this->getPreviewEnabledMimetypes(); $previewEnableMimetypes = $this->getPreviewEnabledMimetypes();
foreach ($photoEntities as $photoEntity) { foreach ($photoEntities as $photoEntity) {
$cacheEntry = $cache->get($photoEntity->getFileId()); $cacheEntry = $cache->get($photoEntity->getFileId());
if ($cacheEntry) { if ($cacheEntry) {
// this path is relative to owner's storage // this path is relative to owner's storage
//$path = $cacheEntry->getPath(); //$path = $cacheEntry->getPath();
// but we want it relative to current user's storage // but we want it relative to current user's storage
@ -82,27 +91,36 @@ class GeophotoService {
if ($file === null) { if ($file === null) {
continue; continue;
} }
$path = $folder->getRelativePath($file->getPath()); $path = $folder->getRelativePath( $file->getPath());
$isRoot = $file === $folder; $isIgnored = false;
foreach ($ignoredPaths as $ignoredPath) {
if (str_starts_with($path, $ignoredPath)) {
$isIgnored = true;
break;
}
}
if (!$isIgnored) {
$isRoot = $file === $folder;
$file_object = new \stdClass(); $file_object = new \stdClass();
$file_object->fileId = $photoEntity->getFileId(); $file_object->fileId = $photoEntity->getFileId();
$file_object->fileid = $file_object->fileId; $file_object->fileid = $file_object->fileId;
$file_object->lat = $photoEntity->getLat(); $file_object->lat = $photoEntity->getLat();
$file_object->lng = $photoEntity->getLng(); $file_object->lng = $photoEntity->getLng();
$file_object->dateTaken = $photoEntity->getDateTaken() ?? \time(); $file_object->dateTaken = $photoEntity->getDateTaken() ?? \time();
$file_object->basename = $isRoot ? '' : $file->getName(); $file_object->basename = $isRoot ? '' : $file->getName();
$file_object->filename = $this->normalizePath($path); $file_object->filename = $this->normalizePath($path);
$file_object->etag = $cacheEntry->getEtag(); $file_object->etag = $cacheEntry->getEtag();
//Not working for NC21 as Viewer requires String representation of permissions //Not working for NC21 as Viewer requires String representation of permissions
// $file_object->permissions = $file->getPermissions(); // $file_object->permissions = $file->getPermissions();
$file_object->type = $file->getType(); $file_object->type = $file->getType();
$file_object->mime = $file->getMimetype(); $file_object->mime = $file->getMimetype();
$file_object->lastmod = $file->getMTime(); $file_object->lastmod = $file->getMTime();
$file_object->size = $file->getSize(); $file_object->size = $file->getSize();
$file_object->path = $path; $file_object->path = $path;
$file_object->hasPreview = in_array($cacheEntry->getMimeType(), $previewEnableMimetypes); $file_object->hasPreview = in_array($cacheEntry->getMimeType(), $previewEnableMimetypes);
$filesById[] = $file_object; $filesById[] = $file_object;
}
} }
} }
shuffle($filesById); shuffle($filesById);
@ -111,9 +129,11 @@ class GeophotoService {
/** /**
* @param string $userId * @param string $userId
* @param bool $respectNomediaAndNoimage
* @return array with geodatas of all nonLocalizedPhotos * @return array with geodatas of all nonLocalizedPhotos
*/ */
public function getNonLocalizedFromDB ($userId) { public function getNonLocalizedFromDB (string $userId, bool $respectNomediaAndNoimage=true) {
$ignoredPaths = $respectNomediaAndNoimage ? $this->getIgnoredPaths($userId) : [];
$foo = $this->loadTimeorderedPointSets($userId); $foo = $this->loadTimeorderedPointSets($userId);
$photoEntities = $this->photoMapper->findAllNonLocalized($userId); $photoEntities = $this->photoMapper->findAllNonLocalized($userId);
$userFolder = $this->getFolderForUser($userId); $userFolder = $this->getFolderForUser($userId);
@ -135,33 +155,41 @@ class GeophotoService {
continue; continue;
} }
$path = $userFolder->getRelativePath( $file->getPath()); $path = $userFolder->getRelativePath( $file->getPath());
$isRoot = $file === $userFolder; $isIgnored = false;
foreach ($ignoredPaths as $ignoredPath) {
$date = $photoEntity->getDateTaken() ?? \time(); if (str_starts_with($path, $ignoredPath)) {
$locations = $this->getLocationGuesses($date); $isIgnored = true;
foreach ($locations as $location) { break;
$file_object = new \stdClass(); }
$file_object->fileId = $photoEntity->getFileId(); }
$file_object->fileid = $file_object->fileId; if (!$isIgnored) {
$file_object->path = $this->normalizePath($path); $isRoot = $file === $userFolder;
$file_object->hasPreview = in_array($cacheEntry->getMimeType(), $previewEnableMimetypes);
$file_object->lat = $location[0];
$file_object->lng = $location[1];
$file_object->dateTaken = $date;
$file_object->basename = $isRoot ? '' : $file->getName();
$file_object->filename = $this->normalizePath($path);
$file_object->etag = $cacheEntry->getEtag();
//Not working for NC21 as Viewer requires String representation of permissions
// $file_object->permissions = $file->getPermissions();
$file_object->type = $file->getType();
$file_object->mime = $file->getMimetype();
$file_object->lastmod = $file->getMTime();
$file_object->size = $file->getSize();
$file_object->path = $path;
$file_object->hasPreview = in_array($cacheEntry->getMimeType(), $previewEnableMimetypes);
$filesById[] = $file_object;
}
$date = $photoEntity->getDateTaken() ?? \time();
$locations = $this->getLocationGuesses($date);
foreach ($locations as $location) {
$file_object = new \stdClass();
$file_object->fileId = $photoEntity->getFileId();
$file_object->fileid = $file_object->fileId;
$file_object->path = $this->normalizePath($path);
$file_object->hasPreview = in_array($cacheEntry->getMimeType(), $previewEnableMimetypes);
$file_object->lat = $location[0];
$file_object->lng = $location[1];
$file_object->dateTaken = $date;
$file_object->basename = $isRoot ? '' : $file->getName();
$file_object->filename = $this->normalizePath($path);
$file_object->etag = $cacheEntry->getEtag();
//Not working for NC21 as Viewer requires String representation of permissions
// $file_object->permissions = $file->getPermissions();
$file_object->type = $file->getType();
$file_object->mime = $file->getMimetype();
$file_object->lastmod = $file->getMTime();
$file_object->size = $file->getSize();
$file_object->path = $path;
$file_object->hasPreview = in_array($cacheEntry->getMimeType(), $previewEnableMimetypes);
$filesById[] = $file_object;
}
}
} }
} }
@ -169,6 +197,40 @@ class GeophotoService {
return $filesById; return $filesById;
} }
/**
* @param $userId
* @param $folder
* @return array
* @throws \OCP\Files\NotFoundException
* @throws \OCP\Files\NotPermittedException
* @throws \OC\User\NoUserException
*/
private function getIgnoredPaths($userId, $folder=null){
$ignoredPaths = [];
$folder = $this->getFolderForUser($userId);
if (is_null($folder)) {
$folder = $this->getFolderForUser($userId);
}
$excludedNodes = $folder->search(new SearchQuery(
new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_AND, [
new SearchBinaryOperator( ISearchBinaryOperator::OPERATOR_NOT, [
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', FileInfo::TYPE_FOLDER)
]),
new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, [
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', '.nomedia'),
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', '.noimage'),
]),
]),
0,
0,
[]
));
foreach($excludedNodes as $node) {
$ignoredPaths[] = $folder->getRelativePath($node->getParent()->getPath());
}
return $ignoredPaths;
}
/** /**
* returns a array of locations for a given date * returns a array of locations for a given date
* @param $dateTaken * @param $dateTaken
@ -301,7 +363,7 @@ class GeophotoService {
* @return Folder * @return Folder
*/ */
private function getFolderForUser ($userId) { private function getFolderForUser ($userId) {
return $this->root->getUserFolder($userId); return $this->root->getUserFolder($userId);
} }
} }

View File

@ -179,6 +179,7 @@ class PhotosControllerTest extends \PHPUnit\Framework\TestCase {
$file->move($userfolder->getPath().'/nc.jpg'); $file->move($userfolder->getPath().'/nc.jpg');
$file = $userfolder->get('nc.jpg'); $file = $userfolder->get('nc.jpg');
$file->touch(); $file->touch();
$this->photoFileService->addPhotoNow($file, 'test');
$filename = 'tests/test_files/nut.jpg'; $filename = 'tests/test_files/nut.jpg';
$handle = fopen($filename, 'rb'); $handle = fopen($filename, 'rb');
@ -197,7 +198,6 @@ class PhotosControllerTest extends \PHPUnit\Framework\TestCase {
// following section is not valid anymore // following section is not valid anymore
// TODO fix photo scan (or make it really better) and then adjust tests ;-) // TODO fix photo scan (or make it really better) and then adjust tests ;-)
/*
$this->photoFileService->addPhotoNow($file, 'test'); $this->photoFileService->addPhotoNow($file, 'test');
$resp = $this->photosController->getPhotosFromDb(); $resp = $this->photosController->getPhotosFromDb();
@ -205,30 +205,77 @@ class PhotosControllerTest extends \PHPUnit\Framework\TestCase {
$this->assertEquals(200, $status); $this->assertEquals(200, $status);
$data = $resp->getData(); $data = $resp->getData();
$this->assertEquals(1, count($data)); $this->assertEquals(1, count($data));
$this->assertEquals('/nc.jpg', $data[0]->path);
// non localized //Test .nomedia repected
$file = $userfolder->newFile('.nomedia');
$resp = $this->photosController->getPhotosFromDb();
$status = $resp->getStatus();
$this->assertEquals(200, $status);
$data = $resp->getData();
$this->assertEquals(0, count($data));
$file->delete();
//Test .noimage repected
$file = $userfolder->newFile('.noimage');
$resp = $this->photosController->getPhotosFromDb();
$status = $resp->getStatus();
$this->assertEquals(200, $status);
$data = $resp->getData();
$this->assertEquals(0, count($data));
$file->delete();
// non localized without track
$resp = $this->photosController->getNonLocalizedPhotosFromDb(); $resp = $this->photosController->getNonLocalizedPhotosFromDb();
$status = $resp->getStatus(); $status = $resp->getStatus();
$this->assertEquals(200, $status); $this->assertEquals(200, $status);
$data = $resp->getData(); $data = $resp->getData();
$this->assertEquals(1, count($data)); $this->assertEquals(0, count($data));
// with track
$filename = 'tests/test_files/testFile1_locationNut.gpx';
$content1 = file_get_contents($filename);
$file = $userfolder->newFile('testFile1_locationNut.gpxx');
$file->putContent($content1);
//$file->touch();
$file = $userfolder->get('testFile1_locationNut.gpxx');
$file->move($userfolder->getPath().'/testFile1_locationNut.gpx');
//echo 'I MOVE TO '.$userfolder->getPath().'/testFile1.gpx'."\n";
$file = $userfolder->get('testFile1_locationNut.gpx');
$file->touch();
$resp = $this->photosController->getNonLocalizedPhotosFromDb();
$status = $resp->getStatus();
$this->assertEquals(200, $status);
$data = $resp->getData();
$this->assertEquals(1, count($data));
$this->assertEquals('/nut.jpg', $data[0]->path); $this->assertEquals('/nut.jpg', $data[0]->path);
foreach ($this->photoFileService->rescan('test') as $path) { //Test .nomedia repected
} $file = $userfolder->newFile('.nomedia');
$resp = $this->photosController->getNonLocalizedPhotosFromDb();
$status = $resp->getStatus();
$this->assertEquals(200, $status);
$data = $resp->getData();
$this->assertEquals(0, count($data));
$file->delete();
$resp = $this->photosController->getPhotosFromDb(); //Test .noimage repected
$status = $resp->getStatus(); $file = $userfolder->newFile('.noimage');
$this->assertEquals(200, $status); $resp = $this->photosController->getNonLocalizedPhotosFromDb();
$data = $resp->getData(); $status = $resp->getStatus();
$this->assertEquals(1, count($data)); $this->assertEquals(200, $status);
$data = $resp->getData();
$this->assertEquals(0, count($data));
$file->delete();
// place photos // place photos
$resp = $this->photosController->placePhotos(['/nut.jpg'], [1.2345], [9.8765]); $resp = $this->photosController->placePhotos(['/nut.jpg'], [1.2345], [9.8765]);
$status = $resp->getStatus(); $status = $resp->getStatus();
$this->assertEquals(200, $status); $this->assertEquals(200, $status);
$data = $resp->getData(); $data = $resp->getData();
$this->assertEquals(1, $data); $this->assertEquals(1, count($data));
$resp = $this->photosController->getPhotosFromDb(); $resp = $this->photosController->getPhotosFromDb();
$status = $resp->getStatus(); $status = $resp->getStatus();
@ -236,19 +283,24 @@ class PhotosControllerTest extends \PHPUnit\Framework\TestCase {
$data = $resp->getData(); $data = $resp->getData();
$this->assertEquals(2, count($data)); $this->assertEquals(2, count($data));
$resp = $this->photosController->getNonLocalizedPhotosFromDb();
$status = $resp->getStatus();
$this->assertEquals(200, $status);
$data = $resp->getData();
$this->assertEquals(0, count($data));
// reset coords // reset coords
$resp = $this->photosController->resetPhotosCoords(['/nut.jpg']); $resp = $this->photosController->resetPhotosCoords(['/nut.jpg']);
$status = $resp->getStatus(); $status = $resp->getStatus();
$this->assertEquals(200, $status); $this->assertEquals(200, $status);
$data = $resp->getData(); $data = $resp->getData();
$this->assertEquals(1, $data); $this->assertEquals(1, count($data));
$resp = $this->photosController->getPhotosFromDb(); $resp = $this->photosController->getPhotosFromDb();
$status = $resp->getStatus(); $status = $resp->getStatus();
$this->assertEquals(200, $status); $this->assertEquals(200, $status);
$data = $resp->getData(); $data = $resp->getData();
$this->assertEquals(1, count($data)); $this->assertEquals(1, count($data));
*/
} }
} }

File diff suppressed because one or more lines are too long