forked from cutelyst/cutelyst
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontext.h
574 lines (504 loc) · 18.6 KB
/
context.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
/*
* Copyright (C) 2013-2018 Daniel Nicoletti <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CUTELYST_CONTEXT_H
#define CUTELYST_CONTEXT_H
#include <QtCore/QObject>
#include <QtCore/QVariant>
#include <QtCore/QUrl>
#include <QtCore/QStringList>
#include <QtCore/QStack>
#include <Cutelyst/request.h>
#include <Cutelyst/cutelyst_global.h>
namespace Cutelyst {
class Action;
class Application;
class Component;
class Engine;
class Response;
class Dispatcher;
class Controller;
class View;
class Stats;
class Plugin;
class ContextPrivate;
/*! \class Context context.h Cutelyst/Context
* @brief The %Cutelyst %Context
*
* This is the context class that glues Request and Response plus
* some helper methods.
*/
class CUTELYST_LIBRARY Context : public QObject
{
Q_OBJECT
Q_PROPERTY(Action* action READ action CONSTANT)
Q_PROPERTY(QString actionName READ actionName CONSTANT)
Q_PROPERTY(QString ns READ ns CONSTANT)
Q_PROPERTY(QString namespace READ ns CONSTANT)
Q_PROPERTY(Request *req READ request CONSTANT)
Q_PROPERTY(Request *request READ request CONSTANT)
Q_PROPERTY(Controller *controller READ controller CONSTANT)
Q_PROPERTY(QString controllerName READ controllerName CONSTANT)
Q_PROPERTY(QVariantMap config READ config CONSTANT)
Q_PROPERTY(bool state READ state CONSTANT)
public:
/*!
* Constructs a new DUMMY Context object that is child of Application
* This currently is experimental to allow non network events (such as database notification)
* to be able to use our infrastructure
*/
Context(Application *app);
virtual ~Context();
/*!
* Returns true if an error was set.
*/
bool error() const;
/*!
* Sets an error string and try to stop
*/
void error(const QString &error);
/*!
* Returns a list of errors that were defined
*/
QStringList errors() const;
/**
* Contains the return value of the last executed action.
*/
bool state() const;
/*!
* Sets the state of the current executed action, setting to false
* will make the dispatcher skip non processed actions.
*/
void setState(bool state);
/**
* Returns the engine instance. See Cutelyst::Engine
*/
Engine *engine() const;
/**
* Returns the application instance. See Cutelyst::Application
*/
Application *app() const;
/**
* Returns the current Cutelyst::Response object, see there for details.
*/
Response *response() const;
/**
* Returns the current Cutelyst::Response object, see there for details.
*/
Response *res() const;
/**
* Returns a pointer to the current action
*/
Action *action() const;
/**
* Returns the private name of the current action
*/
QString actionName() const;
/**
* Returns the namespace of the current action.
* i.e. the URI prefix corresponding to the controller
* of the current action. For example:
* // a class named FooBar which inherits Controller
* c->ns(); // returns 'foo/bar'
*/
QString ns() const;
/**
* Returns the current Request object containing
* information about the client request Request
*/
Request *request() const;
/**
* Short for request()
*/
Request *req() const;
/**
* Returns the dispatcher instance. See Cutelyst::Dispatcher
*/
Dispatcher *dispatcher() const;
/**
* The current controller name
*/
QString controllerName() const;
/**
* Returns the current controller
*/
Controller *controller() const;
/**
* Returns the controller by name, or nullptr
* if the controller is not found
*/
Controller *controller(const QString &name) const;
/**
* Returns the view with name name or nullptr if not found
*/
View *view(const QString &name = QString()) const;
/**
* Returns the view set to be used
* for rendering this request, if one
* is set by setView() or nullptr if none was set
*/
View *customView() const;
/**
* Defines the view to be used to render
* the request, it must be previously
* be registered by Cutelyst::Application.
*
* Action classes like RenderView will use
* this value to overwrite their settings.
*
* Returns true if a view with the given
* name was found
*/
bool setCustomView(const QString &name);
/**
* You can set hash keys by passing arguments,
* that will be united with the stash,
* which may be used to store data and pass it between
* components during a request.
*
* The stash is automatically sent to the view.
* The stash is cleared at the end of a request;
* it cannot be used for persistent storage
* (for this you must use a session; see Cutelyst::Plugin::Session
* for a complete system integrated with Cutelyst).
*
* \code{.cpp}
* c->stash({
* {"foo", 10},
* {"bar", QStringLiteral("my stash value")}
* });
* \endcode
*/
inline void stash(const QVariantHash &unite);
/**
* Returns a QVariantHash reference to the stash,
* which may be used to store data and pass it between
* components during a request.
*
* The stash is automatically sent to the view.
* The stash is cleared at the end of a request;
* it cannot be used for persistent storage
* (for this you must use a session; see Cutelyst::Plugin::Session
* for a complete system integrated with Cutelyst).
*/
QVariantHash &stash();
/**
* A convenient method to retrieve a single value from the stash
*/
QVariant stash(const QString &key) const;
/**
* A convenient method to retrieve a single value with a default value from the stash
*/
QVariant stash(const QString &key, const QVariant &defaultValue) const;
/**
* Removes the item with the key from the stash and returns the value associated with it.
* If the item does not exist in the stash, the function simply returns a default-constructed value.
* If you don't use the return value, stashRemove() is more efficient.
*/
QVariant stashTake(const QString &key);
/**
* Removes the item that has the key from the stash.
* Returns true if any item was removed removed.
*/
bool stashRemove(const QString &key);
/**
* A convenient method to set a single value to the stash
*/
void setStash(const QString &key, const QVariant &value);
/**
* A convenient method to set a single ParamsMultiMap to the stash
*/
void setStash(const QString &key, const ParamsMultiMap &map);
/**
* Returns the internal execution stack (actions that are currently executing).
*/
QStack<Component *> stack() const;
/**
* Constructs an absolute QUrl object based on the application root, the
* provided path, and the additional arguments and query parameters provided.
* When used as a string, provides a textual URI.
*
* The first argument is taken as a public URI path relative
* c->ns (if it doesn't begin with a forward slash) or
* relative to the application root (if it does). It is then merged with
* c->request()->base() any \p args are appended as additional path
* components; and any queryValues> are appended as "?foo=bar" parameters.
*/
QUrl uriFor(const QString &path = QString(),
const QStringList &args = QStringList(),
const ParamsMultiMap &queryValues = ParamsMultiMap()) const;
/**
* Constructs an absolute QUrl object based on the application root, the
* provided path, and the additional arguments and query parameters provided.
* When used as a string, provides a textual URI.
*
* The first argument is taken as a public URI path relative
* c->ns (if it doesn't begin with a forward slash) or
* relative to the application root (if it does). It is then merged with
* c->request()->base() and any queryValues> are appended as "?foo=bar" parameters.
*/
inline QUrl uriFor(const QString &path,
const ParamsMultiMap &queryValues) const;
/**
* Constructs an absolute QUrl object based on the application root, the
* provided path, and the additional arguments and query parameters provided.
* When used as a string, provides a textual URI.
*
* If no arguments are provided, the URI for the current action is returned.
* To return the current action and also provide \p args, use
* c->uriFor(c->action(), args).
*/
QUrl uriFor(Action *action,
const QStringList &captures = QStringList(),
const QStringList &args = QStringList(),
const ParamsMultiMap &queryValues = ParamsMultiMap()) const;
/**
* Constructs an absolute QUrl object based on the application root, the
* provided path, and the additional arguments and query parameters provided.
* When used as a string, provides a textual URI.
*/
inline QUrl uriFor(Action *action,
const ParamsMultiMap &queryValues) const;
/**
* A private path to the Cutelyst action you want to create a URI for.
*
* This is a shortcut for calling c->dispatcher()->getActionByPath(path)
* and passing the resulting action and the remaining arguments to c->uri_for.
*
* Note that although the path looks like a URI that dispatches to the wanted action,
* it is not a URI, but an internal path to that action.
*
* For example, if the action looks like:
* \code{.h}
* class Users : public Cutelyst::Controller
* {
* public:
* C_ATTR(lst, :Path(the-list))
* void lst(Context *c);
* };
* \endcode
*
* You can use:
* c->uriForAction('/users/lst');
* and it will create the URI /users/the-list.
*/
QUrl uriForAction(const QString &path,
const QStringList &captures = QStringList(),
const QStringList &args = QStringList(),
const ParamsMultiMap &queryValues = ParamsMultiMap()) const;
/**
* A convenience method for the uriForAction() without the arguments parameter
*/
inline QUrl uriForAction(const QString &path,
const ParamsMultiMap &queryValues) const;
/**
* Returns true if the last executed Action requested
* that the processing be escaped.
*/
bool detached() const;
/**
* The same as forward(action)
*
* When called with no arguments it escapes the processing chain entirely.
*/
void detach(Action *action = nullptr);
/**
* Detaches the processing chain telling the Engine that
* the request is not finished yet.
*
* It's often useful to call async API's, while convenient the use of QEventLoop
* will only work for the first request or lead to a crash due stacking of calls.
*
* This method, tells the Engine that this request is not finished yet, making
* it return to the event loop to process other requests or the task that was
* created prior to calling this.
*
* Once done call attachAsync() in order to process the remaining of the action chain.
*/
void detachAsync();
/*!
* \brief attachAsync
*
* Reattaches to the remaining actions
*/
void attachAsync();
/**
* This is one way of calling another action (method) in the same or
* a different controller. You can also use directly call another method
* to the same or a different controller.
*
* The main difference is that 'forward' uses some of the Cutelyst request
* cycle overhead, including debugging, which may be useful to you. On the
* other hand, there are some complications to using 'forward', restrictions
* on values returned from 'forward', and it may not handle errors as you prefer.
* Whether you use 'forward' or not is up to you; it is not considered superior to
* the other ways to call a method.
*
* forward calls Component::execute.
*
* Keep in mind that the End() method used is that of the caller action.
* So a c->detach() inside a forwarded action would run the End() method from
* the original action requested.
*/
bool forward(Component *component);
/**
* This is one way of calling another action (method) in the same or
* a different controller. You can also use directly call another method
* to the same or a different controller.
*
* The main difference is that 'forward' uses some of the Cutelyst request
* cycle overhead, including debugging, which may be useful to you. On the
* other hand, there are some complications to using 'forward', restrictions
* on values returned from 'forward', and it may not handle errors as you prefer.
* Whether you use 'forward' or not is up to you; it is not considered superior to
* the other ways to call a method.
*
* forward calls another action, by its private name.
*
* Keep in mind that the End() method used is that of the caller action.
* So a c->detach() inside a forwarded action would run the End() method from
* the original action requested.
*/
bool forward(const QString &action);
/**
* Gets an action in a given namespace.
*/
Action *getAction(const QString &action, const QString &ns = QString()) const;
/**
* Gets all actions of a given name in a namespace and all parent namespaces.
*/
QVector<Action *> getActions(const QString &action, const QString &ns = QString()) const;
/**
* Returns all registered plugins
*/
QVector<Plugin *> plugins() const;
/*!
* Returns the registered plugin that casts to the template type \p T
*/
template <typename T>
T plugin()
{
const auto pluginsConst = plugins();
for (Plugin *plugin : pluginsConst) {
auto p = qobject_cast<T>(plugin);
if (p) {
return p;
}
}
return nullptr;
}
/**
* Execute an action. Errors are available via error().
*/
bool execute(Component *code);
/**
* Returns the current locale to be used when processing Views
* or translating user messages.
*
* If not explicity set by setLocale it will use the QLocale::setDefault(),
* or QLocale::system() if not set.
*/
QLocale locale() const;
/**
* Defines the current locale to be used when processing Views
* or translating user messages.
*
* Setting a locale on a web application can be done in many ways,
* so it's up to the developer to decide which one to use.
*
* For example it's possible to try to guess the user locale with
* the request header Accept-Language, and or use the chained dispatcher to first
* match the locale as in "example.com/pt-br/some_action", and or store
* the locale into a cookie or session.
*
* Be sure to set it as soon as possible so that all content can be properly localized.
*/
void setLocale(const QLocale &locale);
/**
* Returns a configuration value for key with an optional default value
*/
QVariant config(const QString &key, const QVariant &defaultValue = QVariant()) const;
/**
* Returns a configuration mapping for all configuration read
*/
QVariantMap config() const;
/**
* Translates the \a sourceText for the given \a context into the language defined by locale().
*
* See Application::addTranslator() for information about installation of translators. Internally
* this function will use QTranslator::translate().
*
* \code{.cpp}
* void MyController::index(Context *c)
* {
* c->res()->setBody(c->translate("MyController", "You are on the index page."));
* }
* \endcode
*/
QString translate(const char *context, const char *sourceText, const char *disambiguation = nullptr, int n = -1) const;
/*!
* This method is deprecated and no longer works, creating local event loops
* leads to crashes.
*
* This creates a local event loop that requires next() to be called \p count times.
*
* If wait() was already called and didn't return it will increase the counter of
* the unfinished wait().
*
* Returns true when the event loop finishes and false if the call only increased
* the event loop counter.
*/
Q_DECL_DEPRECATED bool wait(uint count = 1);
public Q_SLOTS:
/*!
* This method is deprecated and no longer works, creating local event loops
* leads to crashes.
*
* Decreases the local event loop counter created by wait() eventually
* quitting it's execution if 0 is reached.
*
* If you set force to true it will quit the loop immediately
* regardless of it's counter.
*/
void next(bool force = false);
protected:
/*!
* Constructs a new Context object using private implementation.
*/
Context(ContextPrivate *priv);
void finalize();
friend class Application;
friend class Action;
friend class DispatchType;
friend class Plugin;
friend class Engine;
friend class Controller;
ContextPrivate *d_ptr;
private:
Q_DECLARE_PRIVATE(Context)
};
inline void Context::stash(const QVariantHash &unite)
{ stash().unite(unite); }
inline QUrl Context::uriFor(const QString &path, const ParamsMultiMap &queryValues) const
{ return uriFor(path, QStringList(), queryValues); }
inline QUrl Context::uriFor(Action *action, const ParamsMultiMap &queryValues) const
{ return uriFor(action, QStringList(), QStringList(), queryValues); }
inline QUrl Context::uriForAction(const QString &path, const ParamsMultiMap &queryValues) const
{ return uriForAction(path, QStringList(), QStringList(), queryValues); }
}
Q_DECLARE_METATYPE(Cutelyst::Context *)
#endif // CUTELYST_CONTEXT_H