Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 65
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
FileSearchProvider
0.00% covered (danger)
0.00%
0 / 65
0.00% covered (danger)
0.00%
0 / 7
210
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getOrder
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 search
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 formatResult
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 1
20
 formatSubline
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare(strict_types=1);
4
5/**
6 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
7 * SPDX-License-Identifier: AGPL-3.0-or-later
8 */
9
10namespace OCA\Libresign\Search;
11
12use OCA\Libresign\AppInfo\Application;
13use OCA\Libresign\Db\File;
14use OCA\Libresign\Db\SignRequestMapper;
15use OCP\App\IAppManager;
16use OCP\Files\IMimeTypeDetector;
17use OCP\Files\IRootFolder;
18use OCP\IL10N;
19use OCP\IURLGenerator;
20use OCP\IUser;
21use OCP\Search\IProvider;
22use OCP\Search\ISearchQuery;
23use OCP\Search\SearchResult;
24use OCP\Search\SearchResultEntry;
25
26class FileSearchProvider implements IProvider {
27    public function __construct(
28        private IL10N $l10n,
29        private IURLGenerator $urlGenerator,
30        private IRootFolder $rootFolder,
31        private IAppManager $appManager,
32        private IMimeTypeDetector $mimeTypeDetector,
33        private SignRequestMapper $fileMapper,
34    ) {
35    }
36
37    #[\Override]
38    public function getId(): string {
39        return 'libresign_files';
40    }
41
42    #[\Override]
43    public function getName(): string {
44        // TRANSLATORS Nextcloud unified search provider name for finding LibreSign documents.
45        return $this->l10n->t('LibreSign documents');
46    }
47
48    #[\Override]
49    public function getOrder(string $route, array $routeParameters): int {
50        if (str_starts_with($route, Application::APP_ID . '.')) {
51            return 0;
52        }
53        return 10;
54    }
55
56    #[\Override]
57    public function search(IUser $user, ISearchQuery $query): SearchResult {
58        if (!$this->appManager->isEnabledForUser(Application::APP_ID, $user)) {
59            // TRANSLATORS Nextcloud unified search provider name for finding LibreSign documents.
60            return SearchResult::complete($this->l10n->t('LibreSign documents'), []);
61        }
62
63        $term = $query->getTerm();
64        $limit = $query->getLimit();
65        $offset = $query->getCursor();
66
67        try {
68            $files = $this->fileMapper->getFilesToSearchProvider($user, $term, $limit, (int)$offset);
69        } catch (\Exception) {
70            // TRANSLATORS Nextcloud unified search provider name for finding LibreSign documents.
71            return SearchResult::complete($this->l10n->t('LibreSign documents'), []);
72        }
73
74        $results = array_map(fn (File $file) => $this->formatResult($file, $user), $files);
75
76        return SearchResult::paginated(
77            // TRANSLATORS Nextcloud unified search provider name for finding LibreSign documents.
78            $this->l10n->t('LibreSign documents'),
79            $results,
80            $offset + $limit
81        );
82    }
83
84    private function formatResult(File $file, IUser $user): SearchResultEntry {
85        $userFolder = $this->rootFolder->getUserFolder($file->getUserId());
86        $thumbnailUrl = '';
87        $subline = '';
88        $icon = '';
89        $path = '';
90
91        try {
92            $nodes = $userFolder->getById($file->getNodeId());
93            if (!empty($nodes)) {
94                $node = array_shift($nodes);
95
96                $icon = $this->mimeTypeDetector->mimeTypeIcon($node->getMimetype());
97
98                $thumbnailUrl = $this->urlGenerator->linkToRouteAbsolute(
99                    'ocs.libresign.File.getThumbnailByFileId',
100                    [
101                        'apiVersion' => 'v1',
102                        'x' => 32,
103                        'y' => 32,
104                        'fileId' => $file->getId()
105                    ]
106                );
107
108                $path = $userFolder->getRelativePath($node->getPath());
109                $subline = $this->formatSubline($path);
110            }
111        } catch (\Exception) {
112        }
113
114        if ($file->getUserId() === $user->getUID()) {
115            $link = $this->urlGenerator->linkToRouteAbsolute(
116                'libresign.page.indexFPath',
117                ['path' => 'filelist/sign']
118            );
119            $link .= '?uuid=' . urlencode($file->getUuid());
120        } else {
121            $link = $this->urlGenerator->linkToRouteAbsolute(
122                'libresign.page.indexFPath',
123                ['path' => 'validation/' . $file->getUuid()]
124            );
125        }
126
127        $searchResultEntry = new SearchResultEntry(
128            $thumbnailUrl,
129            $file->getName(),
130            $subline,
131            $link,
132            $icon,
133        );
134
135        $searchResultEntry->addAttribute('fileId', (string)$file->getNodeId());
136        $searchResultEntry->addAttribute('path', $path);
137
138        return $searchResultEntry;
139    }
140
141    private function formatSubline(string $path): string {
142        if (strrpos($path, '/') > 0) {
143            $path = ltrim(dirname($path), '/');
144            // TRANSLATORS This string indicates the location of a file in a given path.
145            return $this->l10n->t('in %s', [$path]);
146        } else {
147            return '';
148        }
149    }
150
151}