Skip to content

Commit 9cd6204

Browse files
authored
Merge pull request #1231 from tetebueno/master
Scan photos of specific directory
2 parents ad3d360 + 8950625 commit 9cd6204

File tree

2 files changed

+109
-88
lines changed

2 files changed

+109
-88
lines changed

lib/Command/RescanPhotos.php

Lines changed: 86 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -26,84 +26,94 @@
2626

2727
class RescanPhotos extends Command {
2828

29-
protected IUserManager $userManager;
30-
protected OutputInterface $output;
31-
protected IManager $encryptionManager;
32-
protected PhotofilesService $photofilesService;
33-
protected IConfig $config;
29+
protected IUserManager $userManager;
30+
protected OutputInterface $output;
31+
protected IManager $encryptionManager;
32+
protected PhotofilesService $photofilesService;
33+
protected IConfig $config;
3434

35-
public function __construct(IUserManager $userManager,
36-
IManager $encryptionManager,
37-
PhotofilesService $photofilesService,
38-
IConfig $config) {
39-
parent::__construct();
40-
$this->userManager = $userManager;
41-
$this->encryptionManager = $encryptionManager;
42-
$this->photofilesService = $photofilesService;
43-
$this->config = $config;
44-
}
35+
public function __construct(
36+
IUserManager $userManager,
37+
IManager $encryptionManager,
38+
PhotofilesService $photofilesService,
39+
IConfig $config) {
40+
parent::__construct();
41+
$this->userManager = $userManager;
42+
$this->encryptionManager = $encryptionManager;
43+
$this->photofilesService = $photofilesService;
44+
$this->config = $config;
45+
}
4546

46-
/**
47-
* @return void
48-
*/
49-
protected function configure() {
50-
$this->setName('maps:scan-photos')
51-
->setDescription('Rescan photos GPS exif data')
52-
->addArgument(
53-
'user_id',
54-
InputArgument::OPTIONAL,
55-
'Rescan photos GPS exif data for the given user'
56-
)
57-
->addOption(
58-
'now',
59-
null,
60-
InputOption::VALUE_NONE,
61-
'Dot the rescan now and not as background jobs. Doing it now might run out of memory.'
62-
);
63-
}
47+
/**
48+
* @return void
49+
*/
50+
protected function configure() {
51+
$this->setName('maps:scan-photos')
52+
->setDescription('Rescan photos GPS exif data')
53+
->addArgument(
54+
'user_id',
55+
InputArgument::OPTIONAL,
56+
'Rescan photos GPS exif data for the given user'
57+
)
58+
->addArgument(
59+
'path',
60+
InputArgument::OPTIONAL,
61+
'Scan photos GPS exif data for the given path under user\'s files without wiping the database.'
62+
)
63+
->addOption(
64+
'now',
65+
null,
66+
InputOption::VALUE_NONE,
67+
'Dot the rescan now and not as background jobs. Doing it now might run out of memory.'
68+
);
69+
}
6470

65-
/**
66-
* @param InputInterface $input
67-
* @param OutputInterface $output
68-
* @return int
69-
*/
70-
protected function execute(InputInterface $input, OutputInterface $output): int {
71-
if ($this->encryptionManager->isEnabled()) {
72-
$output->writeln('Encryption is enabled. Aborted.');
73-
return 1;
74-
}
75-
$this->output = $output;
76-
$userId = $input->getArgument('user_id');
77-
$inBackground = !($input->getOption('now') ?? true);
78-
if ($inBackground) {
79-
echo "Extracting coordinates from photo is performed in a BackgroundJob \n";
80-
}
81-
if ($userId === null) {
82-
$this->userManager->callForSeenUsers(function (IUser $user) use ($inBackground) {
83-
$this->rescanUserPhotos($user->getUID(), $inBackground);
84-
});
85-
} else {
86-
$user = $this->userManager->get($userId);
87-
if ($user !== null) {
88-
$this->rescanUserPhotos($userId, $inBackground);
89-
}
90-
}
91-
return 0;
92-
}
71+
/**
72+
* @param InputInterface $input
73+
* @param OutputInterface $output
74+
* @return int
75+
*/
76+
protected function execute(InputInterface $input, OutputInterface $output): int {
77+
if ($this->encryptionManager->isEnabled()) {
78+
$output->writeln('Encryption is enabled. Aborted.');
79+
return 1;
80+
}
81+
$this->output = $output;
82+
$userId = $input->getArgument('user_id');
83+
$pathToScan = $input->getArgument('path');
84+
$inBackground = !($input->getOption('now') ?? true);
85+
if ($inBackground) {
86+
echo "Extracting coordinates from photo is performed in a BackgroundJob \n";
87+
}
88+
if ($userId === null) {
89+
$this->userManager->callForSeenUsers(function (IUser $user, string $pathToScan) use ($inBackground) {
90+
$this->rescanUserPhotos($user->getUID(), $inBackground, $pathToScan);
91+
});
92+
} else {
93+
$user = $this->userManager->get($userId);
94+
if ($user !== null) {
95+
$this->rescanUserPhotos($userId, $inBackground, $pathToScan);
96+
}
97+
}
98+
return 0;
99+
}
93100

94-
/**
95-
* @param string $userId
96-
* @param bool $inBackground
97-
* @return void
98-
* @throws \OCP\PreConditionNotMetException
99-
*/
100-
private function rescanUserPhotos(string $userId, bool $inBackground = true) {
101-
echo '======== User '.$userId.' ========'."\n";
102-
$c = 1;
103-
foreach ($this->photofilesService->rescan($userId, $inBackground) as $path) {
104-
echo '['.$c.'] Photo "'.$path.'" added'."\n";
105-
$c++;
106-
}
107-
$this->config->setUserValue($userId, 'maps', 'installScanDone', 'yes');
108-
}
101+
/**
102+
* @param string $userId
103+
* @param bool $inBackground
104+
* @param string $pathToScan
105+
* @return void
106+
* @throws \OCP\PreConditionNotMetException
107+
*/
108+
private function rescanUserPhotos(string $userId, bool $inBackground = true, string $pathToScan = null) {
109+
echo '======== User ' . $userId . ' ========' . "\n";
110+
$c = 1;
111+
foreach ($this->photofilesService->rescan($userId, $inBackground, $pathToScan) as $path) {
112+
echo '[' . $c . '] Photo "' . $path . '" added' . "\n";
113+
$c++;
114+
}
115+
if ($pathToScan === null) {
116+
$this->config->setUserValue($userId, 'maps', 'installScanDone', 'yes');
117+
}
118+
}
109119
}

lib/Service/PhotofilesService.php

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use Psr\Log\LoggerInterface;
3232

3333
require_once __DIR__ . '/../../vendor/autoload.php';
34+
3435
use lsolesen\pel\PelDataWindow;
3536
use lsolesen\pel\PelEntryAscii;
3637
use lsolesen\pel\PelEntryRational;
@@ -71,11 +72,16 @@ public function __construct(
7172
$this->backgroundJobCache = $this->cacheFactory->createDistributed('maps:background-jobs');
7273
}
7374

74-
public function rescan($userId, $inBackground = true) {
75+
public function rescan($userId, $inBackground = true, $pathToScan = null) {
7576
$this->photosCache->clear($userId);
7677
$userFolder = $this->root->getUserFolder($userId);
77-
$photos = $this->gatherPhotoFiles($userFolder, true);
78-
$this->photoMapper->deleteAll($userId);
78+
if ($pathToScan === null) {
79+
$folder = $userFolder;
80+
$this->photoMapper->deleteAll($userId);
81+
} else {
82+
$folder = $userFolder->get($pathToScan);
83+
}
84+
$photos = $this->gatherPhotoFiles($folder, true);
7985
foreach ($photos as $photo) {
8086
if ($inBackground) {
8187
$this->addPhoto($photo, $userId);
@@ -404,7 +410,7 @@ private function gatherPhotoFiles($folder, $recursive) {
404410
}
405411
try {
406412
$notes = array_merge($notes, $this->gatherPhotoFiles($node, $recursive));
407-
} catch (\OCP\Files\StorageNotAvailableException|\Exception $e) {
413+
} catch (\OCP\Files\StorageNotAvailableException | \Exception $e) {
408414
$msg = 'WARNING: Could not access ' . $node->getName();
409415
echo($msg . "\n");
410416
$this->logger->error($msg);
@@ -442,12 +448,12 @@ private function getExif($file) : ?ExifGeoData {
442448
$exif_geo_data->validate(true);
443449
} catch (ExifDataInvalidException $e) {
444450
$exif_geo_data = null;
445-
$this->logger->notice($e->getMessage(), ['code' => $e->getCode(),'path' => $path]);
451+
$this->logger->notice($e->getMessage(), ['code' => $e->getCode(), 'path' => $path]);
446452
} catch (ExifDataNoLocationException $e) {
447-
$this->logger->notice($e->getMessage(), ['code' => $e->getCode(),'path' => $path]);
453+
$this->logger->notice($e->getMessage(), ['code' => $e->getCode(), 'path' => $path]);
448454
} catch (\Throwable $f) {
449455
$exif_geo_data = null;
450-
$this->logger->error($f->getMessage(), ['code' => $f->getCode(),'path' => $path]);
456+
$this->logger->error($f->getMessage(), ['code' => $f->getCode(), 'path' => $path]);
451457
}
452458
return $exif_geo_data;
453459
}
@@ -519,19 +525,25 @@ private function setGeolocation($pelSubIfdGps, $latitudeDegreeDecimal, $longitud
519525
= $this->degreeDecimalToDegreeMinuteSecond(abs($longitudeDegreeDecimal));
520526

521527
$pelSubIfdGps->addEntry(new PelEntryAscii(
522-
PelTag::GPS_LATITUDE_REF, $latitudeRef));
528+
PelTag::GPS_LATITUDE_REF,
529+
$latitudeRef
530+
));
523531
$pelSubIfdGps->addEntry(new PelEntryRational(
524532
PelTag::GPS_LATITUDE,
525533
[$latitudeDegreeMinuteSecond['degree'], 1],
526534
[$latitudeDegreeMinuteSecond['minute'], 1],
527-
[round($latitudeDegreeMinuteSecond['second'] * 1000), 1000]));
535+
[round($latitudeDegreeMinuteSecond['second'] * 1000), 1000]
536+
));
528537
$pelSubIfdGps->addEntry(new PelEntryAscii(
529-
PelTag::GPS_LONGITUDE_REF, $longitudeRef));
538+
PelTag::GPS_LONGITUDE_REF,
539+
$longitudeRef
540+
));
530541
$pelSubIfdGps->addEntry(new PelEntryRational(
531542
PelTag::GPS_LONGITUDE,
532543
[$longitudeDegreeMinuteSecond['degree'], 1],
533544
[$longitudeDegreeMinuteSecond['minute'], 1],
534-
[round($longitudeDegreeMinuteSecond['second'] * 1000), 1000]));
545+
[round($longitudeDegreeMinuteSecond['second'] * 1000), 1000]
546+
));
535547
}
536548

537549
private function degreeDecimalToDegreeMinuteSecond($degreeDecimal) {
@@ -542,5 +554,4 @@ private function degreeDecimalToDegreeMinuteSecond($degreeDecimal) {
542554
$second = $remainder * 60;
543555
return ['degree' => $degree, 'minute' => $minute, 'second' => $second];
544556
}
545-
546557
}

0 commit comments

Comments
 (0)