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 : // Entry Queryable functions:
119 : ///
120 : /// * Include Reference
121 : /// When you fetch an entry of a content type that has a reference field,
122 : /// by default, the content of the referred entry is not fetched.
123 : /// It only fetches the UID of the referred entry, along with the content of
124 : /// the specified entry.
125 : ///
126 : /// If you wish to fetch the content of the entry that is included in
127 : /// the reference field, you need to use the include[] parameter,
128 : /// and specify the UID of the reference field as value.
129 : /// This informs Contentstack that the request also includes
130 : /// fetching the entry used in the specified reference field.
131 : /// Add a constraint that requires a particular reference key details.
132 : /// [includeReference] provides three options, none, only and except
133 : /// i.e accepts list of fieldUid
134 : /// [referenceFieldUid] Key who has reference to some other class object.
135 : /// Array of the only reference keys to be included in response.
136 : ///
137 : /// {Example 1}: Reference type None
138 : ///
139 : /// ```dart
140 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
141 : /// final query = stack.contentType('contentTypeUid').entry().query();
142 : /// query.includeReference("referenceFieldUid",
143 : /// IncludeReference.none(fieldUidList: null));
144 : /// await entry.fetch();
145 : /// ```
146 : ///
147 : /// {Example 2}: Reference type only
148 : ///
149 : /// ```dart
150 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
151 : /// final query = stack.contentType('contentTypeUid').entry().query();
152 : /// final fieldUid = list of string type;
153 : /// query.includeReference("referenceFieldUid",
154 : /// IncludeReference.only(fieldUidList: fieldUid));
155 : /// ```
156 : ///
157 : /// {Example 3}: Reference type except
158 : ///
159 : /// ```dart
160 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
161 : /// final query = stack.contentType('contentTypeUid').entry().query();
162 : /// query.includeReference("referenceFieldUid",
163 : /// IncludeReference.except(fieldUidList: fieldUid));
164 : /// ```
165 : ///
166 : void includeReference(String referenceFieldUid,
167 : {include.Include includeReferenceField}) {
168 1 : if (referenceFieldUid != null && referenceFieldUid.isNotEmpty) {
169 2 : final List referenceArray = [];
170 : if (includeReferenceField != null) {
171 1 : includeReferenceField.when(none: (fieldUid) {
172 1 : referenceArray.add(referenceFieldUid);
173 1 : if (fieldUid.fieldUidList != null &&
174 2 : fieldUid.fieldUidList.isNotEmpty) {
175 2 : for (final item in fieldUid.fieldUidList) {
176 : referenceArray.add(item);
177 2 : }
178 : }
179 1 : queryParameter['include[]'] = referenceArray.toString();
180 : }, only: (fieldUid) {
181 1 : final Map<String, dynamic> referenceOnlyParam = <String, dynamic>{};
182 1 : if (fieldUid.fieldUidList != null &&
183 1 : fieldUid.fieldUidList.isNotEmpty) {
184 2 : for (final item in fieldUid.fieldUidList) {
185 2 : referenceArray.add(item);
186 : }
187 2 : }
188 : referenceOnlyParam[referenceFieldUid] = referenceArray;
189 : //_include(referenceFieldUid);
190 : includeReference(referenceFieldUid);
191 : queryParameter['only'] = referenceOnlyParam.toString();
192 : }, except: (fieldUid) {
193 : final Map<String, dynamic> referenceOnlyParam = <String, dynamic>{};
194 : if (fieldUid.fieldUidList != null &&
195 : fieldUid.fieldUidList.isNotEmpty) {
196 : for (final item in fieldUid.fieldUidList) {
197 : referenceArray.add(item);
198 : }
199 : }
200 : referenceOnlyParam[referenceFieldUid] = referenceArray;
201 : //_include(referenceFieldUid);
202 : includeReference(referenceFieldUid);
203 : queryParameter['except'] = referenceOnlyParam.toString();
204 : });
205 : } else {
206 : queryParameter['include[]'] = referenceFieldUid;
207 1 : }
208 2 : }
209 : }
210 :
211 : /// This method also includes the content type
212 : /// UIDs of the referenced entries returned in the response
213 : /// return [Query] so you can chain this call
214 : ///
215 : /// Example:
216 : ///
217 : /// ```dart
218 : /// final stack = contentstack.Stack('apiKey, 'deliveryKey, 'environment);
219 : /// final query = stack.contentType('contentTypeUid').entry().query();
220 : /// query.includeReferenceContentTypeUID();
221 : /// ```
222 : ///
223 : void includeReferenceContentTypeUID() {
224 : queryParameter['include_reference_content_type_uid'] = 'true';
225 : }
226 :
227 : ///
228 : /// [locale] is code of the language of which the
229 1 : /// entries needs to be included.
230 1 : /// Only the entries published in this locale will be fetched.
231 1 : ///
232 2 : /// Example:
233 1 : ///
234 : /// ```dart
235 3 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
236 : /// final query = stack.contentType("contentTypeUid").entry().query();
237 : /// query.locale('en-eu');
238 : /// ```
239 : ///
240 : void locale(String locale) {
241 : queryParameter['locale'] = locale;
242 : }
243 :
244 : /////////////////////////////////////////////////
245 : //-------------[Entry Queryable]---------------//
246 : /////////////////////////////////////////////////
247 :
248 : /// Specifies an array of only keys in BASE object
249 : /// that would be included in the response.
250 : /// [fieldUid] Array of the only reference keys to be included in response.
251 : /// [Query] object, so you can chain this call.
252 : ///
253 1 : /// Example:
254 1 : ///
255 1 : /// ```dart
256 2 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
257 1 : /// final query = stack.contentType("contentTypeUid").entry().query();
258 : /// fieldUid is String type of List
259 3 : /// query.only(fieldUid);
260 : /// ```
261 : ///
262 : void only(List<String> fieldUid) {
263 : if (fieldUid != null && fieldUid.isNotEmpty) {
264 : final List<String> referenceArray = [];
265 : for (final item in fieldUid) {
266 : referenceArray.add(item);
267 : }
268 : queryParameter['only[BASE][]'] = referenceArray.toString();
269 : }
270 : }
271 :
272 : ///
273 : /// * AND Operator
274 : /// Get entries that satisfy all the conditions provided in the '$and' query.
275 : ///
276 : /// * OR Operator
277 : /// Get all entries that satisfy at least one of the given conditions provided
278 : /// in the '$or' query.
279 : ///
280 : /// * {Example}: operator OR
281 : ///
282 : /// ```dart
283 : /// final stackInstance1 = Credential.stack();
284 : /// final queryBase1 = stackInstance1.contentType('room').entry().query();
285 : /// queryBase1.where('title', QueryOperation.equals(value: 'Room 13'));
286 : /// ```
287 : /// ```dart
288 : /// final stackInstance2 = Credential.stack();
289 : /// final queryBase2 = stackInstance2.contentType('room').entry().query();
290 : /// queryBase2.where('attendee', QueryOperation.equals(value: 20));
291 : /// ```
292 : /// ```dart
293 : /// final List<contentstack.Query> listOfQuery = [queryBase1, queryBase2];
294 : /// query.operator(QueryOperator.or(queryObjects: listOfQuery));
295 : /// await query.find().then((response){
296 : /// print(response.toString());
297 : /// }).catchError((onError){
298 : /// print(onError);
299 : /// });
300 : /// ```
301 : ///
302 : /// * {Example}: And Operator:
303 : ///
304 : /// ```dart
305 : /// final stackInstance1 = Credential.stack();
306 : /// final queryBase1 = stackInstance1.contentType('room').entry().query();
307 : /// queryBase1.where('title', QueryOperation.equals(value: 'Room 13'));
308 : /// ```
309 : ///
310 1 : /// ```dart
311 : /// final stackInstance2 = Credential.stack();
312 1 : /// final queryBase2 = stackInstance2.contentType('room').entry().query();
313 1 : /// queryBase2.where('attendee', QueryOperation.equals(value: 20));
314 : /// ```
315 2 : /// ```dart
316 1 : /// final List<contentstack.Query> listOfQuery = [queryBase1, queryBase2];
317 1 : /// query.operator(QueryOperator.and(queryObjects: listOfQuery));
318 2 : /// await query.find().then((response){
319 2 : /// print(response.toString());
320 1 : /// }).catchError((onError){
321 : /// print(onError);
322 : /// });
323 3 : /// ```
324 1 : ///
325 1 : void operator(QueryOperator operator) {
326 1 : operator.when(and: (and) {
327 2 : final List<Query> queryList =
328 2 : and.queryObjects; //and.queryObjects is list of Query Objects
329 1 : if (queryList.isNotEmpty) {
330 : final emptyList = [];
331 : for (final item in queryList) {
332 1 : emptyList.add(item.parameter);
333 : }
334 1 : parameter['\$and'] = emptyList;
335 3 : }
336 1 : }, or: (or) {
337 1 : final List<Query> queryList =
338 1 : or.queryObjects; //and.queryObjects is list of Query Objects
339 2 : if (queryList.isNotEmpty) {
340 2 : final emptyList = [];
341 1 : for (final item in queryList) {
342 : emptyList.add(item.parameter);
343 : }
344 1 : parameter['\$or'] = emptyList;
345 : }
346 1 : });
347 3 : }
348 :
349 : ///
350 2 : /// Remove header key
351 : /// [key] custom header key
352 : ///
353 : /// Example:
354 : ///
355 : /// ```dart
356 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
357 : /// final query = stack.contentType('content_type_uid').entry().query();
358 : /// query.removeHeader('key');
359 : /// ```
360 : ///
361 : void removeHeader(String key) {
362 : if (_client.stackHeaders.containsKey(key)) {
363 : _client.stackHeaders.remove(key);
364 : }
365 : }
366 :
367 1 : ///
368 2 : /// To set headers for Built.io Contentstack rest calls.
369 2 : /// Scope is limited to this object and followed classes.
370 : /// [key] header name.
371 : /// [value] header value against given header name.
372 : ///
373 : /// Example:
374 : ///
375 : /// ```dart
376 : /// final stack = contentstack.Stack('apiKey','deliveryToken','environment');
377 : /// final query = stack.contentType('content_type_uid').entry().query();
378 : /// query.setHeader('key', 'value');
379 : /// ```
380 : ///
381 : void setHeader(String key, String value) {
382 : if (key.isNotEmpty && value.isNotEmpty) {
383 : _client.stackHeaders[key] = value;
384 1 : }
385 2 : }
386 :
387 : ///
388 : /// * Reference Search Equals:
389 : /// Get entries having values based on referenced fields.
390 : /// This query retrieves all entries that satisfy the query
391 : /// conditions made on referenced fields.
392 : ///
393 : /// * Reference Search Not-equals:
394 : /// Get entries having values based on referenced fields.
395 : /// This query works the opposite of $in_query and retrieves
396 : /// all entries that does not satisfy query conditions
397 : /// made on referenced fields.
398 : ///
399 : /// * [referenceUid] is Reference field
400 : /// * [reference] It accepts Enum type
401 : /// QueryReference.include() OR QueryReference.NotInclude()
402 1 : /// and it accepts instance of Query
403 2 : /// Example:
404 3 : ///
405 : /// ```dart
406 : /// final query = stack.contentType('room').entry().query();
407 : /// query.referenceSearch('fieldUid', QueryReference.include(query: query));
408 : /// await query.find().then((response){
409 : /// print(response);
410 : /// });
411 : /// ```
412 : ///
413 : void whereReference(String referenceUid, QueryReference reference) {
414 : if (referenceUid != null && referenceUid.isNotEmpty) {
415 : reference.when(include: (queryInstance) {
416 : parameter[referenceUid] = {'\$in_query': queryInstance.query.parameter};
417 : }, notInclude: (queryInstance) {
418 : parameter[referenceUid] = {
419 : '\$nin_query': queryInstance.query.parameter
420 0 : };
421 0 : });
422 : }
423 : }
424 : }
|