Skip to content
This repository was archived by the owner on Oct 13, 2025. It is now read-only.

Commit 1e0cfe2

Browse files
authored
V0.3.6 dev (#170)
* v0.3.6 preparation. Added initial state for admin settings * Fix initial state override * v0.3.6 updates, added option to delete group files except the largest one
1 parent 0a7f3f3 commit 1e0cfe2

File tree

16 files changed

+401
-180
lines changed

16 files changed

+401
-180
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [0.3.6 - 2023-06-19]
6+
7+
[`cloud_py_api`](https://github.com/cloud-py-api/cloud_py_api) is **required** to be installed
8+
(or updated) and enabled first.
9+
10+
### Added
11+
12+
- Nextcloud Hub 5 (27) support
13+
- Option to delete all duplicates in group except the largest one
14+
15+
### Updated
16+
17+
- Updated packages
18+
- Updated l10n
19+
520
## [0.3.5 - 2023-03-23]
621

722
[`cloud_py_api`](https://github.com/cloud-py-api/cloud_py_api) is **required** to be installed

README.md

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,3 @@ Starting from 0.2.0 version MediaDC is only included in Nextcloud v25 and higher
3535
* [Andrey Borysenko](https://github.com/andrey18106)
3636
* [Alexander Piskun](https://github.com/bigcat88)
3737

38-
## Support
39-
40-
You can support us in several ways:
41-
42-
- ⭐ Star our work (it really motivates)
43-
- ❗ Create an Issue or feature request (bring to us an excellent idea)
44-
- 💁 Resolve some Issue or create a Pull Request (contribute to this project)
45-
- 🪙 Donate with any amount with one of the links below (fund this project)
46-
47-
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate?hosted_button_id=H5PLJJMWLDNJQ)
48-
[![Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/cloud_py_api/donate)

appinfo/info.xml

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,9 @@ This app allows to find duplicate or similar 📸📹 photos and videos
1818
* **Save your time and cloud space** The title says all...
1919
2020
Quick start guide and further information in our [Wiki](https://github.com/cloud-py-api/mediadc/wiki).
21-
22-
### Support
23-
24-
You can support us in several ways:
25-
26-
- ⭐ Star our work (it really motivates)
27-
- ❗ Create an Issue or feature request (bring to us an excellent idea)
28-
- 💁 Resolve some Issue or create a Pull Request (contribute to this project)
29-
- 🪙 Donate with any amount with one of the links below (fund this project)
30-
31-
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate?hosted_button_id=H5PLJJMWLDNJQ)
32-
[![Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/cloud_py_api/donate)
3321
]]>
3422
</description>
35-
<version>0.3.5</version>
23+
<version>0.3.6</version>
3624
<licence>agpl</licence>
3725
<author mail="[email protected]" homepage="https://github.com/andrey18106">Andrey Borysenko</author>
3826
<author mail="[email protected]" homepage="https://github.com/bigcat88">Alexander Piskun</author>
@@ -56,7 +44,7 @@ You can support us in several ways:
5644
<screenshot>https://raw.githubusercontent.com/cloud-py-api/mediadc/main/screenshots/mediadc_filesplugin.png</screenshot>
5745
<dependencies>
5846
<php min-version="7.4" min-int-size="64" />
59-
<nextcloud min-version="25" max-version="26" />
47+
<nextcloud min-version="25" max-version="28" />
6048
</dependencies>
6149
<background-jobs>
6250
<job>OCA\MediaDC\BackgroundJob\CollectorCleanupJob</job>

appinfo/routes.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363

6464
// BATCH ACTIONS API
6565
['name' => 'collector#removeTaskDetailGroups', 'url' => '/api/v1/tasks/{taskId}/details/remove', 'verb' => 'POST'],
66+
['name' => 'collector#deleteTaskDetailGroupsFiles', 'url' => '/api/v1/tasks/{taskId}/details/delete', 'verb' => 'POST'],
6667
['name' => 'collector#removeTaskDetailFiles', 'url' => '/api/v1/tasks/{taskId}/files/{groupId}/remove', 'verb' => 'POST'],
6768
['name' => 'collector#deleteTaskDetailFiles', 'url' => '/api/v1/tasks/{taskId}/files/{groupId}/delete', 'verb' => 'POST'],
6869
]

css/style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @copyright Copyright (c) 2022 Andrey Borysenko <[email protected]>
33
*
4-
* @copyright opyright (c) 2022 Alexander Piskun <[email protected]>
4+
* @copyright Copyright (c) 2022 Alexander Piskun <[email protected]>
55
*
66
* @author 2022 Andrey Borysenko <[email protected]>
77
*

lib/Controller/CollectorController.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
namespace OCA\MediaDC\Controller;
3030

31+
use Exception;
3132
use OCP\IRequest;
3233
use OCP\AppFramework\Controller;
3334
use OCP\AppFramework\Http;
@@ -201,15 +202,17 @@ public function getTaskInfo(int $taskId): JSONResponse {
201202
* @param int $taskId target task id
202203
* @param string $format export file format (xml, json)
203204
*
204-
* @return DataDownloadResponse
205+
* @throws Exception
206+
* @return DataDownloadResponse|null
205207
*/
206-
public function getTaskResultsExport(int $taskId, string $format): DataDownloadResponse {
208+
public function getTaskResultsExport(int $taskId, string $format): ?DataDownloadResponse {
207209
if (in_array($format, ['xml', 'json'])) {
208210
$export = $this->service->exportTaskResults(intval($taskId), $format);
209211
if ($export) {
210212
return new DataDownloadResponse($export['data'], $export['filename'], $export['contentType']);
211213
}
212214
}
215+
throw new Exception('Bad request. Requested export format is not supported.');
213216
}
214217

215218
/**
@@ -330,6 +333,18 @@ public function removeTaskDetailGroups(int $taskId, array $groupIds): JSONRespon
330333
}
331334
}
332335

336+
/**
337+
* @NoAdminRequired
338+
* @NoCSRFRequired
339+
*/
340+
public function deleteTaskDetailGroupsFiles(int $taskId, array $groupIds): JSONResponse {
341+
if ($taskId && $groupIds) {
342+
return new JSONResponse($this->service->deleteTaskDetailGroupsFiles($taskId, $groupIds), Http::STATUS_OK);
343+
} else {
344+
return new JSONResponse(['success' => false], Http::STATUS_OK);
345+
}
346+
}
347+
333348
/**
334349
* @NoAdminRequired
335350
* @NoCSRFRequired

lib/Db/CollectorTaskDetailMapper.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,22 @@ public function findAllByGroupId(int $taskId, int $groupId): array {
115115
}, $qb->executeQuery()->fetchAll());
116116
}
117117

118+
public function findAllByGroupIdSize(int $taskId, int $groupId): array {
119+
$qb = $this->db->getQueryBuilder();
120+
$qb->select(
121+
'mdc_t_d.fileid',
122+
)
123+
->from($this->tableName, 'mdc_t_d')
124+
->innerJoin('mdc_t_d', 'filecache', 'f', $qb->expr()->eq('mdc_t_d.fileid', 'f.fileid'))
125+
->where($qb->expr()->eq('mdc_t_d.task_id', $qb->createNamedParameter($taskId, IQueryBuilder::PARAM_INT)))
126+
->andWhere($qb->expr()->eq('mdc_t_d.group_id', $qb->createNamedParameter($groupId, IQueryBuilder::PARAM_INT)))
127+
->orderBy('mdc_t_d.group_id', 'ASC')
128+
->addOrderBy('f.size', 'DESC');
129+
return array_map(function ($row) {
130+
return intval($row['fileid']);
131+
}, $qb->executeQuery()->fetchAll());
132+
}
133+
118134
/**
119135
* @param int $taskId
120136
* @param int $limit

lib/Service/CollectorService.php

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
namespace OCA\MediaDC\Service;
3030

3131
use DOMDocument;
32+
use OCA\Files_Sharing\SharedStorage;
3233
use OCP\Files\File;
3334
use OCP\Files\Node;
3435
use OCP\Files\Folder;
@@ -768,7 +769,7 @@ public function deleteTaskDetailFile($taskId, $groupId, $fileid, $removeIfOneLef
768769
} catch (NotPermittedException | NotFoundException $e) {
769770
return [
770771
'success' => false,
771-
'not_permited' => $e instanceof NotPermittedException,
772+
'not_permitted' => $e instanceof NotPermittedException,
772773
'not_found' => $e instanceof NotFoundException,
773774
];
774775
}
@@ -780,7 +781,7 @@ public function deleteTaskDetailFile($taskId, $groupId, $fileid, $removeIfOneLef
780781
}
781782

782783
/**
783-
* Remove ColectorTaskDetail groups with deleting coresponding files
784+
* Remove CollectorTaskDetail groups with deleting corresponding files
784785
*
785786
* @param int $taskId
786787
* @param array $groupIds
@@ -801,7 +802,45 @@ public function removeTaskDetailGroups(int $taskId, array $groupIds) {
801802
}
802803

803804
/**
804-
* Delete ColectorTaskDetail groups with deleting coresponding files
805+
* Delete all CollectorTaskDetail group files except one largest
806+
*
807+
* @param int $taskId
808+
* @param array $groupIds
809+
*
810+
* @return array
811+
*/
812+
public function deleteTaskDetailGroupsFiles(int $taskId, array $groupIds) {
813+
$result = [];
814+
foreach ($groupIds as $groupId) {
815+
$groupFiles = $this->tasksDetailsMapper->findAllByGroupIdSize($taskId, $groupId);
816+
$largestFileId = array_splice($groupFiles, 0, 1)[0];
817+
$this->tasksDetailsMapper->deleteGroupFiles($taskId, $groupId, [$largestFileId]);
818+
$this->markResolvedPhoto($largestFileId, true);
819+
$this->markResolvedVideo($largestFileId, true);
820+
$collectorTask = null;
821+
foreach ($groupFiles as $fileId) {
822+
$deleteFileResult = $this->deleteTaskDetailFile($taskId, $groupId, $fileId, false);
823+
if ($deleteFileResult['success']) {
824+
$collectorTask = $deleteFileResult['task'];
825+
$fileIdIndex = array_search($fileId, $groupFiles);
826+
if ($fileIdIndex !== false) {
827+
array_splice($groupFiles, $fileIdIndex, 1)[0];
828+
}
829+
}
830+
}
831+
if (count($groupFiles) === 0) {
832+
$result[] = intval($groupId);
833+
}
834+
}
835+
return [
836+
'success' => count($result) === count($groupIds),
837+
'removedGroupIds' => $result,
838+
'task' => $collectorTask,
839+
];
840+
}
841+
842+
/**
843+
* Delete CollectorTaskDetail groups with deleting corresponding files
805844
*
806845
* @param int $taskId
807846
* @param int $groupId
@@ -813,7 +852,7 @@ public function deleteTaskDetailFiles(int $taskId, int $groupId, array $fileIds)
813852
$result = [];
814853
$errors = [
815854
'locked' => [],
816-
'not_permited' => [],
855+
'not_permitted' => [],
817856
'not_found' => [],
818857
];
819858
$groupFiles = $this->tasksDetailsMapper->findAllByGroupId($taskId, $groupId);
@@ -828,8 +867,8 @@ public function deleteTaskDetailFiles(int $taskId, int $groupId, array $fileIds)
828867
if (isset($deleteFileResult['locked']) && $deleteFileResult['locked']) {
829868
array_push($errors['locked'], $fileId);
830869
}
831-
if (isset($deleteFileResult['not_permited']) && $deleteFileResult['not_permited']) {
832-
array_push($errors['not_permited'], $fileId);
870+
if (isset($deleteFileResult['not_permitted']) && $deleteFileResult['not_permitted']) {
871+
array_push($errors['not_permitted'], $fileId);
833872
}
834873
if (isset($deleteFileResult['not_found']) && $deleteFileResult['not_found']) {
835874
array_push($errors['not_found'], $fileId);
@@ -855,7 +894,7 @@ public function deleteTaskDetailFiles(int $taskId, int $groupId, array $fileIds)
855894
}
856895

857896
/**
858-
* Remove ColectorTaskDetail groups with deleting coresponding files
897+
* Remove CollectorTaskDetail groups with deleting corresponding files
859898
*
860899
* @param int $taskId
861900
* @param int $groupId

lib/Settings/AdminSettings.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,33 @@
2929
namespace OCA\MediaDC\Settings;
3030

3131
use OCA\MediaDC\AppInfo\Application;
32+
use OCA\MediaDC\Db\SettingMapper;
3233
use OCP\AppFramework\Http\TemplateResponse;
34+
use OCP\AppFramework\Services\IInitialState;
3335
use OCP\Settings\ISettings;
3436

3537
class AdminSettings implements ISettings {
36-
public function __construct() {
38+
/** @var SettingMapper */
39+
private $settingMapper;
40+
41+
/** @var IInitialState */
42+
private $initialState;
43+
44+
public function __construct(
45+
IInitialState $initialState,
46+
SettingMapper $settingMapper
47+
) {
48+
$this->settingMapper = $settingMapper;
49+
$this->initialState = $initialState;
3750
}
3851

3952
/**
4053
* @return TemplateResponse
4154
*/
4255
public function getForm() {
56+
$settings = $this->settingMapper->findAll();
57+
$this->initialState->provideInitialState('settings', $settings);
58+
4359
return new TemplateResponse(Application::APP_ID, 'admin');
4460
}
4561

0 commit comments

Comments
 (0)