Completed
Push — master ( a913c9...a9d925 )
by
unknown
42:40 queued 10s
created
core/Controller/UnifiedSearchController.php 1 patch
Indentation   +135 added lines, -135 removed lines patch added patch discarded remove patch
@@ -35,139 +35,139 @@
 block discarded – undo
35 35
  * @psalm-import-type CoreUnifiedSearchResult from ResponseDefinitions
36 36
  */
37 37
 class UnifiedSearchController extends OCSController {
38
-	public function __construct(
39
-		IRequest $request,
40
-		private IUserSession $userSession,
41
-		private SearchComposer $composer,
42
-		private IRouter $router,
43
-		private IURLGenerator $urlGenerator,
44
-		private IL10N $l10n,
45
-		private IAppConfig $appConfig,
46
-	) {
47
-		parent::__construct('core', $request);
48
-	}
49
-
50
-	/**
51
-	 * Get the providers for unified search
52
-	 *
53
-	 * @param string $from the url the user is currently at
54
-	 * @return DataResponse<Http::STATUS_OK, list<CoreUnifiedSearchProvider>, array{}>
55
-	 *
56
-	 * 200: Providers returned
57
-	 */
58
-	#[NoAdminRequired]
59
-	#[NoCSRFRequired]
60
-	#[ApiRoute(verb: 'GET', url: '/providers', root: '/search')]
61
-	public function getProviders(string $from = ''): DataResponse {
62
-		[$route, $parameters] = $this->getRouteInformation($from);
63
-
64
-		$result = $this->composer->getProviders($route, $parameters);
65
-		$response = new DataResponse($result);
66
-		$response->setETag(md5(json_encode($result)));
67
-		return $response;
68
-	}
69
-
70
-	/**
71
-	 * Launch a search for a specific search provider.
72
-	 *
73
-	 * Additional filters are available for each provider.
74
-	 * Send a request to /providers endpoint to list providers with their available filters.
75
-	 *
76
-	 * @param string $providerId ID of the provider
77
-	 * @param string $term Term to search
78
-	 * @param int|null $sortOrder Order of entries
79
-	 * @param int|null $limit Maximum amount of entries (capped by configurable unified-search.max-results-per-request, default: 25)
80
-	 * @param int|string|null $cursor Offset for searching
81
-	 * @param string $from The current user URL
82
-	 *
83
-	 * @return DataResponse<Http::STATUS_OK, CoreUnifiedSearchResult, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, string, array{}>
84
-	 *
85
-	 * 200: Search entries returned
86
-	 * 400: Searching is not possible
87
-	 */
88
-	#[NoAdminRequired]
89
-	#[NoCSRFRequired]
90
-	#[ApiRoute(verb: 'GET', url: '/providers/{providerId}/search', root: '/search')]
91
-	public function search(
92
-		string $providerId,
93
-		// Unused parameter for OpenAPI spec generator
94
-		string $term = '',
95
-		?int $sortOrder = null,
96
-		?int $limit = null,
97
-		$cursor = null,
98
-		string $from = '',
99
-	): DataResponse {
100
-		[$route, $routeParameters] = $this->getRouteInformation($from);
101
-
102
-		$limit ??= SearchQuery::LIMIT_DEFAULT;
103
-		$maxLimit = $this->appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST);
104
-		$limit = max(1, min($limit, $maxLimit));
105
-
106
-		try {
107
-			$filters = $this->composer->buildFilterList($providerId, $this->request->getParams());
108
-		} catch (UnsupportedFilter|InvalidArgumentException $e) {
109
-			return new DataResponse($e->getMessage(), Http::STATUS_BAD_REQUEST);
110
-		}
111
-
112
-		if ($filters->count() === 0) {
113
-			return new DataResponse($this->l10n->t('No valid filters provided'), Http::STATUS_BAD_REQUEST);
114
-		}
115
-
116
-		return new DataResponse(
117
-			$this->composer->search(
118
-				$this->userSession->getUser(),
119
-				$providerId,
120
-				new SearchQuery(
121
-					$filters,
122
-					$sortOrder ?? ISearchQuery::SORT_DATE_DESC,
123
-					$limit,
124
-					$cursor,
125
-					$route,
126
-					$routeParameters
127
-				)
128
-			)->jsonSerialize()
129
-		);
130
-	}
131
-
132
-	protected function getRouteInformation(string $url): array {
133
-		$routeStr = '';
134
-		$parameters = [];
135
-
136
-		if ($url !== '') {
137
-			$urlParts = parse_url($url);
138
-			$urlPath = $urlParts['path'];
139
-
140
-			// Optionally strip webroot from URL. Required for route matching on setups
141
-			// with Nextcloud in a webserver subfolder (webroot).
142
-			$webroot = $this->urlGenerator->getWebroot();
143
-			if ($webroot !== '' && substr($urlPath, 0, strlen($webroot)) === $webroot) {
144
-				$urlPath = substr($urlPath, strlen($webroot));
145
-			}
146
-
147
-			try {
148
-				$parameters = $this->router->findMatchingRoute($urlPath);
149
-
150
-				// contacts.PageController.index => contacts.Page.index
151
-				$route = $parameters['caller'];
152
-				if (substr($route[1], -10) === 'Controller') {
153
-					$route[1] = substr($route[1], 0, -10);
154
-				}
155
-				$routeStr = implode('.', $route);
156
-
157
-				// cleanup
158
-				unset($parameters['_route'], $parameters['action'], $parameters['caller']);
159
-			} catch (ResourceNotFoundException $exception) {
160
-			}
161
-
162
-			if (isset($urlParts['query'])) {
163
-				parse_str($urlParts['query'], $queryParameters);
164
-				$parameters = array_merge($parameters, $queryParameters);
165
-			}
166
-		}
167
-
168
-		return [
169
-			$routeStr,
170
-			$parameters,
171
-		];
172
-	}
38
+    public function __construct(
39
+        IRequest $request,
40
+        private IUserSession $userSession,
41
+        private SearchComposer $composer,
42
+        private IRouter $router,
43
+        private IURLGenerator $urlGenerator,
44
+        private IL10N $l10n,
45
+        private IAppConfig $appConfig,
46
+    ) {
47
+        parent::__construct('core', $request);
48
+    }
49
+
50
+    /**
51
+     * Get the providers for unified search
52
+     *
53
+     * @param string $from the url the user is currently at
54
+     * @return DataResponse<Http::STATUS_OK, list<CoreUnifiedSearchProvider>, array{}>
55
+     *
56
+     * 200: Providers returned
57
+     */
58
+    #[NoAdminRequired]
59
+    #[NoCSRFRequired]
60
+    #[ApiRoute(verb: 'GET', url: '/providers', root: '/search')]
61
+    public function getProviders(string $from = ''): DataResponse {
62
+        [$route, $parameters] = $this->getRouteInformation($from);
63
+
64
+        $result = $this->composer->getProviders($route, $parameters);
65
+        $response = new DataResponse($result);
66
+        $response->setETag(md5(json_encode($result)));
67
+        return $response;
68
+    }
69
+
70
+    /**
71
+     * Launch a search for a specific search provider.
72
+     *
73
+     * Additional filters are available for each provider.
74
+     * Send a request to /providers endpoint to list providers with their available filters.
75
+     *
76
+     * @param string $providerId ID of the provider
77
+     * @param string $term Term to search
78
+     * @param int|null $sortOrder Order of entries
79
+     * @param int|null $limit Maximum amount of entries (capped by configurable unified-search.max-results-per-request, default: 25)
80
+     * @param int|string|null $cursor Offset for searching
81
+     * @param string $from The current user URL
82
+     *
83
+     * @return DataResponse<Http::STATUS_OK, CoreUnifiedSearchResult, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, string, array{}>
84
+     *
85
+     * 200: Search entries returned
86
+     * 400: Searching is not possible
87
+     */
88
+    #[NoAdminRequired]
89
+    #[NoCSRFRequired]
90
+    #[ApiRoute(verb: 'GET', url: '/providers/{providerId}/search', root: '/search')]
91
+    public function search(
92
+        string $providerId,
93
+        // Unused parameter for OpenAPI spec generator
94
+        string $term = '',
95
+        ?int $sortOrder = null,
96
+        ?int $limit = null,
97
+        $cursor = null,
98
+        string $from = '',
99
+    ): DataResponse {
100
+        [$route, $routeParameters] = $this->getRouteInformation($from);
101
+
102
+        $limit ??= SearchQuery::LIMIT_DEFAULT;
103
+        $maxLimit = $this->appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST);
104
+        $limit = max(1, min($limit, $maxLimit));
105
+
106
+        try {
107
+            $filters = $this->composer->buildFilterList($providerId, $this->request->getParams());
108
+        } catch (UnsupportedFilter|InvalidArgumentException $e) {
109
+            return new DataResponse($e->getMessage(), Http::STATUS_BAD_REQUEST);
110
+        }
111
+
112
+        if ($filters->count() === 0) {
113
+            return new DataResponse($this->l10n->t('No valid filters provided'), Http::STATUS_BAD_REQUEST);
114
+        }
115
+
116
+        return new DataResponse(
117
+            $this->composer->search(
118
+                $this->userSession->getUser(),
119
+                $providerId,
120
+                new SearchQuery(
121
+                    $filters,
122
+                    $sortOrder ?? ISearchQuery::SORT_DATE_DESC,
123
+                    $limit,
124
+                    $cursor,
125
+                    $route,
126
+                    $routeParameters
127
+                )
128
+            )->jsonSerialize()
129
+        );
130
+    }
131
+
132
+    protected function getRouteInformation(string $url): array {
133
+        $routeStr = '';
134
+        $parameters = [];
135
+
136
+        if ($url !== '') {
137
+            $urlParts = parse_url($url);
138
+            $urlPath = $urlParts['path'];
139
+
140
+            // Optionally strip webroot from URL. Required for route matching on setups
141
+            // with Nextcloud in a webserver subfolder (webroot).
142
+            $webroot = $this->urlGenerator->getWebroot();
143
+            if ($webroot !== '' && substr($urlPath, 0, strlen($webroot)) === $webroot) {
144
+                $urlPath = substr($urlPath, strlen($webroot));
145
+            }
146
+
147
+            try {
148
+                $parameters = $this->router->findMatchingRoute($urlPath);
149
+
150
+                // contacts.PageController.index => contacts.Page.index
151
+                $route = $parameters['caller'];
152
+                if (substr($route[1], -10) === 'Controller') {
153
+                    $route[1] = substr($route[1], 0, -10);
154
+                }
155
+                $routeStr = implode('.', $route);
156
+
157
+                // cleanup
158
+                unset($parameters['_route'], $parameters['action'], $parameters['caller']);
159
+            } catch (ResourceNotFoundException $exception) {
160
+            }
161
+
162
+            if (isset($urlParts['query'])) {
163
+                parse_str($urlParts['query'], $queryParameters);
164
+                $parameters = array_merge($parameters, $queryParameters);
165
+            }
166
+        }
167
+
168
+        return [
169
+            $routeStr,
170
+            $parameters,
171
+        ];
172
+    }
173 173
 }
Please login to merge, or discard this patch.
core/AppInfo/ConfigLexicon.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -20,89 +20,89 @@
 block discarded – undo
20 20
  * Please Add & Manage your Config Keys in that file and keep the Lexicon up to date!
21 21
  */
22 22
 class ConfigLexicon implements ILexicon {
23
-	public const SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES = 'shareapi_allow_federation_on_public_shares';
24
-	public const SHARE_CUSTOM_TOKEN = 'shareapi_allow_custom_tokens';
25
-	public const SHARE_LINK_PASSWORD_DEFAULT = 'shareapi_enable_link_password_by_default';
26
-	public const SHARE_LINK_PASSWORD_ENFORCED = 'shareapi_enforce_links_password';
27
-	public const SHARE_LINK_EXPIRE_DATE_DEFAULT = 'shareapi_default_expire_date';
28
-	public const SHARE_LINK_EXPIRE_DATE_ENFORCED = 'shareapi_enforce_expire_date';
29
-	public const USER_LANGUAGE = 'lang';
30
-	public const OCM_DISCOVERY_ENABLED = 'ocm_discovery_enabled';
31
-	public const OCM_INVITE_ACCEPT_DIALOG = 'ocm_invite_accept_dialog';
23
+    public const SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES = 'shareapi_allow_federation_on_public_shares';
24
+    public const SHARE_CUSTOM_TOKEN = 'shareapi_allow_custom_tokens';
25
+    public const SHARE_LINK_PASSWORD_DEFAULT = 'shareapi_enable_link_password_by_default';
26
+    public const SHARE_LINK_PASSWORD_ENFORCED = 'shareapi_enforce_links_password';
27
+    public const SHARE_LINK_EXPIRE_DATE_DEFAULT = 'shareapi_default_expire_date';
28
+    public const SHARE_LINK_EXPIRE_DATE_ENFORCED = 'shareapi_enforce_expire_date';
29
+    public const USER_LANGUAGE = 'lang';
30
+    public const OCM_DISCOVERY_ENABLED = 'ocm_discovery_enabled';
31
+    public const OCM_INVITE_ACCEPT_DIALOG = 'ocm_invite_accept_dialog';
32 32
 
33
-	public const USER_LOCALE = 'locale';
34
-	public const USER_TIMEZONE = 'timezone';
33
+    public const USER_LOCALE = 'locale';
34
+    public const USER_TIMEZONE = 'timezone';
35 35
 
36
-	public const UNIFIED_SEARCH_MIN_SEARCH_LENGTH = 'unified_search_min_search_length';
37
-	public const UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST = 'unified_search_max_results_per_request';
36
+    public const UNIFIED_SEARCH_MIN_SEARCH_LENGTH = 'unified_search_min_search_length';
37
+    public const UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST = 'unified_search_max_results_per_request';
38 38
 
39
-	public const LASTCRON_TIMESTAMP = 'lastcron';
39
+    public const LASTCRON_TIMESTAMP = 'lastcron';
40 40
 
41
-	public function getStrictness(): Strictness {
42
-		return Strictness::IGNORE;
43
-	}
41
+    public function getStrictness(): Strictness {
42
+        return Strictness::IGNORE;
43
+    }
44 44
 
45
-	public function getAppConfigs(): array {
46
-		return [
47
-			new Entry(
48
-				key: self::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES,
49
-				type: ValueType::BOOL,
50
-				defaultRaw: true,
51
-				definition: 'adds share permission to public shares to allow adding them to your Nextcloud (federation)',
52
-				lazy: true,
53
-			),
54
-			new Entry(
55
-				key: self::SHARE_CUSTOM_TOKEN,
56
-				type: ValueType::BOOL,
57
-				defaultRaw: fn (Preset $p): bool => match ($p) {
58
-					Preset::FAMILY, Preset::PRIVATE => true,
59
-					default => false,
60
-				},
61
-				definition: 'Allow users to customize share URL',
62
-				lazy: true,
63
-				note: 'Shares with guessable tokens may be accessed easily. Shares with custom tokens will continue to be accessible after this setting has been disabled.',
64
-			),
65
-			new Entry(self::SHARE_LINK_PASSWORD_DEFAULT, ValueType::BOOL, false, 'Ask for a password when sharing document by default'),
66
-			new Entry(
67
-				key: self::SHARE_LINK_PASSWORD_ENFORCED,
68
-				type: ValueType::BOOL,
69
-				defaultRaw: fn (Preset $p): bool => match ($p) {
70
-					Preset::SCHOOL, Preset::UNIVERSITY, Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
71
-					default => false,
72
-				},
73
-				definition: 'Enforce password protection for shared documents'
74
-			),
75
-			new Entry(
76
-				key: self::SHARE_LINK_EXPIRE_DATE_DEFAULT,
77
-				type: ValueType::BOOL,
78
-				defaultRaw: fn (Preset $p): bool => match ($p) {
79
-					Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
80
-					default => false,
81
-				},
82
-				definition: 'Default expiration date for shares via link or mail'
83
-			),
84
-			new Entry(
85
-				key: self::SHARE_LINK_EXPIRE_DATE_ENFORCED,
86
-				type: ValueType::BOOL,
87
-				defaultRaw: fn (Preset $p): bool => match ($p) {
88
-					Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
89
-					default => false,
90
-				},
91
-				definition: 'Enforce expiration date for shares via link or mail'
92
-			),
93
-			new Entry(self::LASTCRON_TIMESTAMP, ValueType::INT, 0, 'timestamp of last cron execution'),
94
-			new Entry(self::OCM_DISCOVERY_ENABLED, ValueType::BOOL, true, 'enable/disable OCM', lazy: true),
95
-			new Entry(self::OCM_INVITE_ACCEPT_DIALOG, ValueType::STRING, '', 'route to local invite accept dialog', lazy: true, note: 'set as empty string to disable feature'),
96
-			new Entry(self::UNIFIED_SEARCH_MIN_SEARCH_LENGTH, ValueType::INT, 1, 'Minimum search length to trigger the request', lazy: false, rename: 'unified-search.min-search-length'),
97
-			new Entry(self::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST, ValueType::INT, 25, 'Maximum results returned per search request', lazy: false, rename: 'unified-search.max-results-per-request'),
98
-		];
99
-	}
45
+    public function getAppConfigs(): array {
46
+        return [
47
+            new Entry(
48
+                key: self::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES,
49
+                type: ValueType::BOOL,
50
+                defaultRaw: true,
51
+                definition: 'adds share permission to public shares to allow adding them to your Nextcloud (federation)',
52
+                lazy: true,
53
+            ),
54
+            new Entry(
55
+                key: self::SHARE_CUSTOM_TOKEN,
56
+                type: ValueType::BOOL,
57
+                defaultRaw: fn (Preset $p): bool => match ($p) {
58
+                    Preset::FAMILY, Preset::PRIVATE => true,
59
+                    default => false,
60
+                },
61
+                definition: 'Allow users to customize share URL',
62
+                lazy: true,
63
+                note: 'Shares with guessable tokens may be accessed easily. Shares with custom tokens will continue to be accessible after this setting has been disabled.',
64
+            ),
65
+            new Entry(self::SHARE_LINK_PASSWORD_DEFAULT, ValueType::BOOL, false, 'Ask for a password when sharing document by default'),
66
+            new Entry(
67
+                key: self::SHARE_LINK_PASSWORD_ENFORCED,
68
+                type: ValueType::BOOL,
69
+                defaultRaw: fn (Preset $p): bool => match ($p) {
70
+                    Preset::SCHOOL, Preset::UNIVERSITY, Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
71
+                    default => false,
72
+                },
73
+                definition: 'Enforce password protection for shared documents'
74
+            ),
75
+            new Entry(
76
+                key: self::SHARE_LINK_EXPIRE_DATE_DEFAULT,
77
+                type: ValueType::BOOL,
78
+                defaultRaw: fn (Preset $p): bool => match ($p) {
79
+                    Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
80
+                    default => false,
81
+                },
82
+                definition: 'Default expiration date for shares via link or mail'
83
+            ),
84
+            new Entry(
85
+                key: self::SHARE_LINK_EXPIRE_DATE_ENFORCED,
86
+                type: ValueType::BOOL,
87
+                defaultRaw: fn (Preset $p): bool => match ($p) {
88
+                    Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
89
+                    default => false,
90
+                },
91
+                definition: 'Enforce expiration date for shares via link or mail'
92
+            ),
93
+            new Entry(self::LASTCRON_TIMESTAMP, ValueType::INT, 0, 'timestamp of last cron execution'),
94
+            new Entry(self::OCM_DISCOVERY_ENABLED, ValueType::BOOL, true, 'enable/disable OCM', lazy: true),
95
+            new Entry(self::OCM_INVITE_ACCEPT_DIALOG, ValueType::STRING, '', 'route to local invite accept dialog', lazy: true, note: 'set as empty string to disable feature'),
96
+            new Entry(self::UNIFIED_SEARCH_MIN_SEARCH_LENGTH, ValueType::INT, 1, 'Minimum search length to trigger the request', lazy: false, rename: 'unified-search.min-search-length'),
97
+            new Entry(self::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST, ValueType::INT, 25, 'Maximum results returned per search request', lazy: false, rename: 'unified-search.max-results-per-request'),
98
+        ];
99
+    }
100 100
 
101
-	public function getUserConfigs(): array {
102
-		return [
103
-			new Entry(self::USER_LANGUAGE, ValueType::STRING, definition: 'language'),
104
-			new Entry(self::USER_LOCALE, ValueType::STRING, definition: 'locale'),
105
-			new Entry(self::USER_TIMEZONE, ValueType::STRING, definition: 'timezone'),
106
-		];
107
-	}
101
+    public function getUserConfigs(): array {
102
+        return [
103
+            new Entry(self::USER_LANGUAGE, ValueType::STRING, definition: 'language'),
104
+            new Entry(self::USER_LOCALE, ValueType::STRING, definition: 'locale'),
105
+            new Entry(self::USER_TIMEZONE, ValueType::STRING, definition: 'timezone'),
106
+        ];
107
+    }
108 108
 }
Please login to merge, or discard this patch.