Line data Source code
1 : import 'dart:async';
2 : import 'dart:convert';
3 :
4 : import 'package:contentstack/client.dart';
5 : import 'package:contentstack/src/base_query.dart';
6 : import 'package:contentstack/src/enums/include.dart' as include;
7 : import 'package:contentstack/src/enums/operator.dart';
8 : import 'package:contentstack/src/enums/reference.dart';
9 :
10 : /// Contentstack provides certain queries that you
11 : /// can use to fetch filtered results.
12 : /// You can use queries for Entries and Assets API requests.
13 : /// Learn more about [Query](https://www.contentstack.com/docs/developers/apis/content-delivery-api/#queries)
14 : class Query extends BaseQuery {
15 : final HttpClient _client;
16 : final String _contentTypeUid;
17 : String _path;
18 1 :
19 5 : Query([this._client, this._contentTypeUid]) {
20 1 : queryParameter['environment'] = _client.stackHeaders['environment'];
21 5 : _path =
22 : '/${_client.stack.apiVersion}/content_types/$_contentTypeUid/entries';
23 : }
24 1 :
25 3 : ///
26 2 : /// This method adds key and value to an Entry.
27 3 : /// [key] The key as string which needs to be added to an Entry
28 1 : /// [value] The value as string which needs to be added to an Entry
29 : /// [Query] object, so you can chain this call.
30 1 : ///
31 : /// Example:
32 : ///
33 1 : /// ```dart
34 1 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
35 6 : /// final query = stack.contentType('contentTypeUid').entry().query();
36 2 : /// entry.addParam(key, value);
37 : /// ```
38 : ///
39 : void addParam(String key, String value) {
40 : if (key != null && value != null && key.isNotEmpty && value.isNotEmpty) {
41 : queryParameter[key] = value.toString();
42 : }
43 : }
44 :
45 : ///
46 : /// Specifies list of field uids that would be excluded from the response.
47 : /// [fieldUid] field uid which get excluded from the response.
48 : /// [Query] object, so you can chain this call.
49 : ///
50 : /// Example:
51 : ///
52 : /// ```dart
53 1 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
54 2 : /// final query = stack.contentType("contentTypeUid").entry().query();
55 3 : /// fieldUid is String type of List
56 : /// query.except(fieldUid);
57 : /// ```
58 : ///
59 : void except(List<String> fieldUid) {
60 : if (fieldUid != null && fieldUid.isNotEmpty) {
61 : final List referenceArray = [];
62 : for (final item in fieldUid) {
63 : referenceArray.add(item);
64 : }
65 : queryParameter['except[BASE][]'] = referenceArray.toString();
66 : }
67 : }
68 :
69 : Future<T> find<T, K>() async {
70 : getQueryUrl();
71 1 : final uri = Uri.https(_client.stack.endpoint, _path, queryParameter);
72 3 : return _client.sendRequest<T, K>(uri);
73 3 : }
74 :
75 : Map getQueryUrl() {
76 : if (parameter != null && parameter.isNotEmpty) {
77 : final stringify = json.encode(parameter);
78 : queryParameter['query'] = stringify.toString();
79 : return queryParameter;
80 : }
81 : return queryParameter;
82 : }
83 :
84 : ///
85 : /// Include Content Type of all returned objects along with objects
86 : /// themselves. return, [Query] so you can chain this call.
87 : ///
88 : /// Example:
89 : ///
90 : /// ```dart
91 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
92 : /// final query = stack.contentType('contentTypeUid').entry().query();
93 : /// query.includeContentType();
94 : /// ```
95 : ///
96 : void includeContentType() {
97 : queryParameter['include_content_type'] = 'true';
98 : queryParameter['include_global_field_schema'] = 'true';
99 : }
100 :
101 : ///
102 : /// Retrieve the published content of the fallback locale if an entry is not
103 1 : /// localized in specified locale.
104 1 : ///
105 2 : /// Example
106 5 : ///
107 1 : /// ```dart
108 3 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
109 2 : /// final query = stack.contentType('contentTypeUid').entry().query();
110 : /// entry.includeFallback()
111 : /// ```
112 : ///
113 : void includeFallback() {
114 : queryParameter['include_fallback'] = true.toString();
115 : }
116 :
117 : ///
118 : /// includeEmbeddedItems instance of Query
119 : /// Include Embedded Objects (Entries and Assets) along with entry/entries details
120 : ///
121 : /// [Example for Entry class]
122 : /// ```
123 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
124 : /// final query = stack.contentType('contentTypeUid').entry().query();
125 : /// query = query.includeEmbeddedItems()
126 : /// ```
127 : ///
128 : void includeEmbeddedItems() {
129 : queryParameter['include_embedded_items[]'] = 'BASE';
130 : }
131 :
132 : //
133 : // Entry Queryable functions:
134 : ///
135 : /// * Include Reference
136 : /// When you fetch an entry of a content type that has a reference field,
137 : /// by default, the content of the referred entry is not fetched.
138 : /// It only fetches the UID of the referred entry, along with the content of
139 : /// the specified entry.
140 : ///
141 : /// If you wish to fetch the content of the entry that is included in
142 : /// the reference field, you need to use the include[] parameter,
143 : /// and specify the UID of the reference field as value.
144 : /// This informs Contentstack that the request also includes
145 : /// fetching the entry used in the specified reference field.
146 : /// Add a constraint that requires a particular reference key details.
147 : /// [includeReference] provides three options, none, only and except
148 : /// i.e accepts list of fieldUid
149 : /// [referenceFieldUid] Key who has reference to some other class object.
150 : /// Array of the only reference keys to be included in response.
151 : ///
152 : /// {Example 1}: Reference type None
153 : ///
154 : /// ```dart
155 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
156 : /// final query = stack.contentType('contentTypeUid').entry().query();
157 : /// query.includeReference("referenceFieldUid",
158 : /// IncludeReference.none(fieldUidList: null));
159 : /// await entry.fetch();
160 : /// ```
161 : ///
162 : /// {Example 2}: Reference type only
163 : ///
164 : /// ```dart
165 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
166 : /// final query = stack.contentType('contentTypeUid').entry().query();
167 : /// final fieldUid = list of string type;
168 1 : /// query.includeReference("referenceFieldUid",
169 2 : /// IncludeReference.only(fieldUidList: fieldUid));
170 : /// ```
171 1 : ///
172 1 : /// {Example 3}: Reference type except
173 1 : ///
174 2 : /// ```dart
175 2 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
176 : /// final query = stack.contentType('contentTypeUid').entry().query();
177 2 : /// query.includeReference("referenceFieldUid",
178 : /// IncludeReference.except(fieldUidList: fieldUid));
179 1 : /// ```
180 : ///
181 1 : void includeReference(String referenceFieldUid,
182 1 : {include.Include includeReferenceField}) {
183 1 : if (referenceFieldUid != null && referenceFieldUid.isNotEmpty) {
184 2 : final List referenceArray = [];
185 2 : if (includeReferenceField != null) {
186 : includeReferenceField.when(none: (fieldUid) {
187 2 : referenceArray.add(referenceFieldUid);
188 : if (fieldUid.fieldUidList != null &&
189 : fieldUid.fieldUidList.isNotEmpty) {
190 : for (final item in fieldUid.fieldUidList) {
191 : referenceArray.add(item);
192 : }
193 : }
194 : queryParameter['include[]'] = referenceArray.toString();
195 : }, only: (fieldUid) {
196 : final Map<String, dynamic> referenceOnlyParam = <String, dynamic>{};
197 : if (fieldUid.fieldUidList != null &&
198 : fieldUid.fieldUidList.isNotEmpty) {
199 : for (final item in fieldUid.fieldUidList) {
200 : referenceArray.add(item);
201 : }
202 : }
203 : referenceOnlyParam[referenceFieldUid] = referenceArray;
204 : //_include(referenceFieldUid);
205 : includeReference(referenceFieldUid);
206 : queryParameter['only'] = referenceOnlyParam.toString();
207 1 : }, except: (fieldUid) {
208 2 : final Map<String, dynamic> referenceOnlyParam = <String, dynamic>{};
209 : if (fieldUid.fieldUidList != null &&
210 : fieldUid.fieldUidList.isNotEmpty) {
211 : for (final item in fieldUid.fieldUidList) {
212 : referenceArray.add(item);
213 : }
214 : }
215 : referenceOnlyParam[referenceFieldUid] = referenceArray;
216 : //_include(referenceFieldUid);
217 : includeReference(referenceFieldUid);
218 : queryParameter['except'] = referenceOnlyParam.toString();
219 : });
220 : } else {
221 : queryParameter['include[]'] = referenceFieldUid;
222 : }
223 : }
224 : }
225 :
226 : /// This method also includes the content type
227 : /// UIDs of the referenced entries returned in the response
228 : /// return [Query] so you can chain this call
229 1 : ///
230 1 : /// Example:
231 1 : ///
232 2 : /// ```dart
233 1 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
234 : /// final query = stack.contentType('contentTypeUid').entry().query();
235 3 : /// query.includeReferenceContentTypeUID();
236 : /// ```
237 : ///
238 : void includeReferenceContentTypeUID() {
239 : queryParameter['include_reference_content_type_uid'] = 'true';
240 : }
241 :
242 : ///
243 : /// [locale] is code of the language of which the
244 : /// entries needs to be included.
245 : /// Only the entries published in this locale will be fetched.
246 : ///
247 : /// Example:
248 : ///
249 : /// ```dart
250 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
251 : /// final query = stack.contentType("contentTypeUid").entry().query();
252 : /// query.locale('en-eu');
253 1 : /// ```
254 1 : ///
255 1 : void locale(String locale) {
256 2 : queryParameter['locale'] = locale;
257 1 : }
258 :
259 3 : /////////////////////////////////////////////////
260 : //-------------[Entry Queryable]---------------//
261 : /////////////////////////////////////////////////
262 :
263 : /// Specifies an array of only keys in BASE object
264 : /// that would be included in the response.
265 : /// [fieldUid] Array of the only reference keys to be included in response.
266 : /// [Query] object, so you can chain this call.
267 : ///
268 : /// Example:
269 : ///
270 : /// ```dart
271 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
272 : /// final query = stack.contentType("contentTypeUid").entry().query();
273 : /// fieldUid is String type of List
274 : /// query.only(fieldUid);
275 : /// ```
276 : ///
277 : void only(List<String> fieldUid) {
278 : if (fieldUid != null && fieldUid.isNotEmpty) {
279 : final List<String> referenceArray = [];
280 : for (final item in fieldUid) {
281 : referenceArray.add(item);
282 : }
283 : queryParameter['only[BASE][]'] = referenceArray.toString();
284 : }
285 : }
286 :
287 : ///
288 : /// * AND Operator
289 : /// Get entries that satisfy all the conditions provided in the '$and' query.
290 : ///
291 : /// * OR Operator
292 : /// Get all entries that satisfy at least one of the given conditions provided
293 : /// in the '$or' query.
294 : ///
295 : /// * {Example}: operator OR
296 : ///
297 : /// ```dart
298 : /// final stackInstance1 = Credential.stack();
299 : /// final queryBase1 = stackInstance1.contentType('room').entry().query();
300 : /// queryBase1.where('title', QueryOperation.equals(value: 'Room 13'));
301 : /// ```
302 : /// ```dart
303 : /// final stackInstance2 = Credential.stack();
304 : /// final queryBase2 = stackInstance2.contentType('room').entry().query();
305 : /// queryBase2.where('attendee', QueryOperation.equals(value: 20));
306 : /// ```
307 : /// ```dart
308 : /// final List<contentstack.Query> listOfQuery = [queryBase1, queryBase2];
309 : /// query.operator(QueryOperator.or(queryObjects: listOfQuery));
310 1 : /// await query.find().then((response){
311 : /// print(response.toString());
312 1 : /// }).catchError((onError){
313 1 : /// print(onError);
314 : /// });
315 2 : /// ```
316 1 : ///
317 1 : /// * {Example}: And Operator:
318 2 : ///
319 2 : /// ```dart
320 1 : /// final stackInstance1 = Credential.stack();
321 : /// final queryBase1 = stackInstance1.contentType('room').entry().query();
322 : /// queryBase1.where('title', QueryOperation.equals(value: 'Room 13'));
323 3 : /// ```
324 1 : ///
325 1 : /// ```dart
326 1 : /// final stackInstance2 = Credential.stack();
327 2 : /// final queryBase2 = stackInstance2.contentType('room').entry().query();
328 2 : /// queryBase2.where('attendee', QueryOperation.equals(value: 20));
329 1 : /// ```
330 : /// ```dart
331 : /// final List<contentstack.Query> listOfQuery = [queryBase1, queryBase2];
332 1 : /// query.operator(QueryOperator.and(queryObjects: listOfQuery));
333 : /// await query.find().then((response){
334 1 : /// print(response.toString());
335 3 : /// }).catchError((onError){
336 1 : /// print(onError);
337 1 : /// });
338 1 : /// ```
339 2 : ///
340 2 : void operator(QueryOperator operator) {
341 1 : operator.when(and: (and) {
342 : final List<Query> queryList =
343 : and.queryObjects; //and.queryObjects is list of Query Objects
344 1 : if (queryList.isNotEmpty) {
345 : final emptyList = [];
346 1 : for (final item in queryList) {
347 3 : emptyList.add(item.parameter);
348 : }
349 : parameter['\$and'] = emptyList;
350 2 : }
351 : }, or: (or) {
352 : final List<Query> queryList =
353 : or.queryObjects; //and.queryObjects is list of Query Objects
354 : if (queryList.isNotEmpty) {
355 : final emptyList = [];
356 : for (final item in queryList) {
357 : emptyList.add(item.parameter);
358 : }
359 : parameter['\$or'] = emptyList;
360 : }
361 : });
362 : }
363 :
364 : ///
365 : /// Remove header key
366 : /// [key] custom header key
367 1 : ///
368 2 : /// Example:
369 2 : ///
370 : /// ```dart
371 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
372 : /// final query = stack.contentType('content_type_uid').entry().query();
373 : /// query.removeHeader('key');
374 : /// ```
375 : ///
376 : void removeHeader(String key) {
377 : if (_client.stackHeaders.containsKey(key)) {
378 : _client.stackHeaders.remove(key);
379 : }
380 : }
381 :
382 : ///
383 : /// To set headers for Built.io Contentstack rest calls.
384 1 : /// Scope is limited to this object and followed classes.
385 2 : /// [key] header name.
386 : /// [value] header value against given header name.
387 : ///
388 : /// Example:
389 : ///
390 : /// ```dart
391 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
392 : /// final query = stack.contentType('content_type_uid').entry().query();
393 : /// query.setHeader('key', 'value');
394 : /// ```
395 : ///
396 : void setHeader(String key, String value) {
397 : if (key.isNotEmpty && value.isNotEmpty) {
398 : _client.stackHeaders[key] = value;
399 : }
400 : }
401 :
402 1 : ///
403 2 : /// * Reference Search Equals:
404 3 : /// Get entries having values based on referenced fields.
405 : /// This query retrieves all entries that satisfy the query
406 : /// conditions made on referenced fields.
407 : ///
408 : /// * Reference Search Not-equals:
409 : /// Get entries having values based on referenced fields.
410 : /// This query works the opposite of $in_query and retrieves
411 : /// all entries that does not satisfy query conditions
412 : /// made on referenced fields.
413 : ///
414 : /// * [referenceUid] is Reference field
415 : /// * [reference] It accepts Enum type
416 : /// QueryReference.include() OR QueryReference.NotInclude()
417 : /// and it accepts instance of Query
418 : /// Example:
419 : ///
420 0 : /// ```dart
421 0 : /// final query = stack.contentType('room').entry().query();
422 : /// query.referenceSearch('fieldUid', QueryReference.include(query: query));
423 : /// await query.find().then((response){
424 : /// print(response);
425 : /// });
426 : /// ```
427 : ///
428 : void whereReference(String referenceUid, QueryReference reference) {
429 : if (referenceUid != null && referenceUid.isNotEmpty) {
430 : reference.when(include: (queryInstance) {
431 : parameter[referenceUid] = {'\$in_query': queryInstance.query.parameter};
432 : }, notInclude: (queryInstance) {
433 : parameter[referenceUid] = {
434 : '\$nin_query': queryInstance.query.parameter
435 : };
436 : });
437 : }
438 : }
439 : }
|