1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
// ------------------------------------------------------------------------- |
4
|
|
|
// OVIDENTIA http://www.ovidentia.org |
5
|
|
|
// Ovidentia is free software; you can redistribute it and/or modify |
6
|
|
|
// it under the terms of the GNU General Public License as published by |
7
|
|
|
// the Free Software Foundation; either version 2, or (at your option) |
8
|
|
|
// any later version. |
9
|
|
|
// |
10
|
|
|
// This program is distributed in the hope that it will be useful, but |
11
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of |
12
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
13
|
|
|
// See the GNU General Public License for more details. |
14
|
|
|
// |
15
|
|
|
// You should have received a copy of the GNU General Public License |
16
|
|
|
// along with this program; if not, write to the Free Software |
17
|
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
18
|
|
|
// USA. |
19
|
|
|
// ------------------------------------------------------------------------- |
20
|
|
|
/** |
21
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL) |
22
|
|
|
* @copyright Copyright (c) 2022 by SI4YOU ({@link https://www.siforyou.com}) |
23
|
|
|
*/ |
24
|
|
|
namespace Capwelton\LibApp\Ctrl; |
25
|
|
|
|
26
|
|
|
use Capwelton\Widgets\Widgets\Helpers\WidgetAction; |
|
|
|
|
27
|
|
|
use Capwelton\Widgets\Widgets\Interfaces\WidgetDisplayableInterface; |
|
|
|
|
28
|
|
|
use Capwelton\Widgets\Widgets\Layout\WidgetFlexLayout; |
|
|
|
|
29
|
|
|
use Capwelton\Widgets\Widgets\Page\WidgetBabPage; |
|
|
|
|
30
|
|
|
use Capwelton\Widgets\Widgets\Page\WidgetPage; |
|
|
|
|
31
|
|
|
use Capwelton\LibApp\AppObjectInterface; |
32
|
|
|
use Capwelton\LibApp\Exceptions\AppUnknownActionException; |
33
|
|
|
use Capwelton\LibApp\Exceptions\AppException; |
34
|
|
|
use Capwelton\LibApp\AppObject; |
35
|
|
|
use Capwelton\LibApp\Exceptions\AppAccessException; |
36
|
|
|
use Capwelton\LibApp\Exceptions\AppSaveException; |
37
|
|
|
use Capwelton\LibApp\Exceptions\AppDeletedRecordException; |
38
|
|
|
use Capwelton\LibApp\Exceptions\AppNotFoundException; |
39
|
|
|
use Capwelton\LibApp\Func_App; |
40
|
|
|
use Capwelton\LibApp\AppComponent; |
41
|
|
|
use Capwelton\LibOrm\Exceptions\ORMException; |
|
|
|
|
42
|
|
|
require_once $GLOBALS['babInstallPath'] . 'utilit/controller.class.php'; |
43
|
|
|
require_once $GLOBALS['babInstallPath'] . 'utilit/json.php'; |
44
|
|
|
|
45
|
|
|
require_once dirname(__FILE__) . '/../functions.php'; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @method self proxy() |
49
|
|
|
*/ |
50
|
|
|
class AppController extends \bab_Controller implements AppObjectInterface |
51
|
|
|
{ |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @var Func_App |
55
|
|
|
*/ |
56
|
|
|
protected $app = null; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var string[] |
60
|
|
|
*/ |
61
|
|
|
protected $reloadSelectors = array(); |
62
|
|
|
|
63
|
|
|
protected $toasts = array(); |
64
|
|
|
|
65
|
|
|
protected $keepDialogOpened = false; |
66
|
|
|
|
67
|
|
|
private $SSERecordSet; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @param string $reloadSelector |
71
|
|
|
* @param boolean $withSSE |
72
|
|
|
* If true, the reloadSelector will be added in the SSE payload |
73
|
|
|
* @param mixed $for |
74
|
|
|
* The user id or a list of users id. If null, current user will be used |
75
|
|
|
*/ |
76
|
|
|
public function addReloadSelector($reloadSelector, $withSSE = false, $for = null) |
77
|
|
|
{ |
78
|
|
|
$this->reloadSelectors[$reloadSelector] = $reloadSelector; |
79
|
|
|
if($withSSE){ |
80
|
|
|
$sseRecordSet = $this->getSSERecordSet(); |
81
|
|
|
$sseRecordSet->newReloadSelector($reloadSelector, $for); |
82
|
|
|
} |
83
|
|
|
return $this; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @return string[] |
88
|
|
|
*/ |
89
|
|
|
public function getReloadSelectors() |
90
|
|
|
{ |
91
|
|
|
return $this->reloadSelectors; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
public function getSSERecordSet() |
95
|
|
|
{ |
96
|
|
|
if(isset($this->SSERecordSet)){ |
97
|
|
|
return $this->SSERecordSet; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$App = $this->App(); |
101
|
|
|
$this->SSERecordSet = $App->SSESet(); |
102
|
|
|
return $this->SSERecordSet; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
public function keepDialogOpened($keepDialogOpened = true) |
106
|
|
|
{ |
107
|
|
|
$this->keepDialogOpened = $keepDialogOpened; |
108
|
|
|
return $this; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Can be used in a controller to check if the current request was made by ajax. |
113
|
|
|
* |
114
|
|
|
* @var bool |
115
|
|
|
*/ |
116
|
|
|
protected $isAjaxRequest = null; |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Name of method to use to create action |
120
|
|
|
* |
121
|
|
|
* @var string |
122
|
|
|
*/ |
123
|
|
|
public $createActionMethod = 'createActionForTg'; |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @param Func_App $app |
127
|
|
|
*/ |
128
|
|
|
public function __construct(Func_App $app = null) |
129
|
|
|
{ |
130
|
|
|
$this->setApp($app); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* @param string $name |
135
|
|
|
* @param mixed $arguments |
136
|
|
|
* @return mixed |
137
|
|
|
*/ |
138
|
|
|
public function __call($name, $arguments = array()) |
139
|
|
|
{ |
140
|
|
|
$component = $this->App()->getComponentByName($name); |
141
|
|
|
if($component){ |
142
|
|
|
return call_user_func_array(array( |
143
|
|
|
$component, |
144
|
|
|
'controller' |
145
|
|
|
), $arguments); |
146
|
|
|
} |
147
|
|
|
throw new AppException(sprintf($this->App()->translate('Unknown action %s'), $name)); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* {@inheritdoc} |
152
|
|
|
* @see AppObject::setApp() |
153
|
|
|
*/ |
154
|
|
|
public function setApp(Func_App $app = null) |
155
|
|
|
{ |
156
|
|
|
$this->app = $app; |
157
|
|
|
return $this; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* {@inheritdoc} |
162
|
|
|
* @see AppObject::App() |
163
|
|
|
*/ |
164
|
|
|
public function App() |
165
|
|
|
{ |
166
|
|
|
return $this->app; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* @return string |
171
|
|
|
*/ |
172
|
|
|
protected function getControllerTg() |
173
|
|
|
{ |
174
|
|
|
return $this->App()->controllerTg; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Can be used in a controller to check if the current request was made by ajax. |
179
|
|
|
* |
180
|
|
|
* @return bool |
181
|
|
|
*/ |
182
|
|
|
public function isAjaxRequest() |
183
|
|
|
{ |
184
|
|
|
if(! isset($this->isAjaxRequest)){ |
185
|
|
|
$this->isAjaxRequest = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'); |
186
|
|
|
} |
187
|
|
|
return $this->isAjaxRequest; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* Ensures that the user is logged in. |
192
|
|
|
* Tries to use the appropriate authentication type depending on the situation. |
193
|
|
|
*/ |
194
|
|
|
public function requireCredential($message = null) |
195
|
|
|
{ |
196
|
|
|
if($this->isAjaxRequest()){ |
197
|
|
|
$authType = 'Basic'; |
198
|
|
|
} |
199
|
|
|
else{ |
200
|
|
|
$authType = ''; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
if(! isset($message)){ |
204
|
|
|
$message = $this->App()->translate('You must be logged in to access this page.'); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
bab_requireCredential($message, $authType); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Returns an instance of the specific controller class. |
212
|
|
|
* If $proxy is true, a proxy to this controller is returned instead. |
213
|
|
|
* |
214
|
|
|
* @deprecated use $App->ControllerProxy() instead |
215
|
|
|
* @param string $classname |
216
|
|
|
* @param bool $proxy |
217
|
|
|
* @return AppController |
218
|
|
|
*/ |
219
|
|
|
public static function getInstance($classname, $proxy = true) |
220
|
|
|
{ |
221
|
|
|
|
222
|
|
|
// If the app object was not specified (through the setApp() method) |
223
|
|
|
// we try to select one according to the classname prefix. |
224
|
|
|
list ($prefix) = explode('_', __CLASS__); |
225
|
|
|
$functionalityName = ucwords($prefix); |
226
|
|
|
/** @var Func_App */ |
227
|
|
|
$App = @\bab_functionality::get('App/' . $functionalityName); |
228
|
|
|
|
229
|
|
|
if(!$App){ |
|
|
|
|
230
|
|
|
throw new AppException('Faild to autodetect functionality App/' . $functionalityName . ', the getInstance method is deprecated, use $App->ControllerProxy() instead'); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
$controller = $App->ControllerProxy($classname, $proxy); |
|
|
|
|
234
|
|
|
|
235
|
|
|
return $controller; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* Dynamically creates a proxy class for this controller with all public, non-final and non-static functions |
240
|
|
|
* overriden so that they return an action (WidgetAction) corresponding to each of them. |
241
|
|
|
* |
242
|
|
|
* @param string $classname |
243
|
|
|
* @return AppController |
244
|
|
|
*/ |
245
|
|
|
static function getProxyInstance(Func_App $App, $classname) |
|
|
|
|
246
|
|
|
{ |
247
|
|
|
$class = new \ReflectionClass($classname); |
248
|
|
|
$proxyClassname = $class->getShortName() . self::PROXY_CLASS_SUFFIX; |
249
|
|
|
$finalProxyClassname = $class->getNamespaceName()."\\".$proxyClassname; |
250
|
|
|
if(! class_exists($finalProxyClassname)){ |
251
|
|
|
$classStr = ""; |
252
|
|
|
if($class->getNamespaceName() != ""){ |
253
|
|
|
$classStr .= " namespace ".$class->getNamespaceName()."; "; |
254
|
|
|
} |
255
|
|
|
$classStr .= 'class ' . $proxyClassname . ' extends ' . $class->getShortName() . ' {' . "\n"; |
256
|
|
|
$methods = $class->getMethods(); |
257
|
|
|
|
258
|
|
|
$classStr .= ' public function __construct($App) { |
259
|
|
|
$this->setApp($App); |
260
|
|
|
}' . "\n"; |
261
|
|
|
|
262
|
|
|
foreach ($methods as $method){ |
263
|
|
|
if($method->name === '__construct' || ! $method->isPublic() || $method->isStatic() || $method->isFinal() || $method->name === 'setApp' || $method->name === 'App' || $method->name === 'setCrm' || $method->name === 'Crm'){ |
264
|
|
|
continue; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
$classStr .= ' public function ' . $method->name . '('; |
268
|
|
|
$parameters = $method->getParameters(); |
269
|
|
|
$parametersStr = array(); |
270
|
|
|
foreach ($parameters as $parameter){ |
271
|
|
|
|
272
|
|
|
if($parameter->isDefaultValueAvailable()){ |
273
|
|
|
$parametersStr[] = '$' . $parameter->name . ' = ' . var_export($parameter->getDefaultValue(), true); |
274
|
|
|
} |
275
|
|
|
else{ |
276
|
|
|
$parametersStr[] = '$' . $parameter->name; |
277
|
|
|
} |
278
|
|
|
} |
279
|
|
|
$classStr .= implode(', ', $parametersStr); |
280
|
|
|
$classStr .= ') {' . "\n"; |
281
|
|
|
$classStr .= ' $args = func_get_args();' . "\n"; |
282
|
|
|
$classStr .= ' return $this->getMethodAction(__FUNCTION__, $args);' . "\n"; |
283
|
|
|
$classStr .= ' }' . "\n"; |
284
|
|
|
} |
285
|
|
|
$classStr .= '}' . "\n"; |
286
|
|
|
// We define the proxy class |
287
|
|
|
eval($classStr); |
|
|
|
|
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
$proxy = new $finalProxyClassname($App); |
291
|
|
|
|
292
|
|
|
// $proxy = bab_getInstance($proxyClassname); |
293
|
|
|
return $proxy; |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* @return self |
298
|
|
|
*/ |
299
|
|
|
public function proxy() |
300
|
|
|
{ |
301
|
|
|
return self::getProxyInstance($this->App(), get_class($this)); |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Get proxy class with action from the new addon controller |
306
|
|
|
* |
307
|
|
|
* @return self |
308
|
|
|
*/ |
309
|
|
|
protected function quickProxy() |
310
|
|
|
{ |
311
|
|
|
$proxy = $this->proxy(); |
312
|
|
|
$proxy->createActionMethod = 'createActionForAddon'; |
313
|
|
|
return $proxy; |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* {@inheritdoc} |
318
|
|
|
* @see \bab_Controller::getObjectName() |
319
|
|
|
*/ |
320
|
|
|
protected function getObjectName($classname) |
321
|
|
|
{ |
322
|
|
|
list ($objectname) = explode('Controller', $classname); |
323
|
|
|
if($this->App()->getComponentByName($objectname)){ |
324
|
|
|
return strtolower($objectname); |
325
|
|
|
} |
326
|
|
|
list (, $objectname) = explode('Ctrl', $classname); |
327
|
|
|
return strtolower($objectname); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Returns the action object corresponding to the current object method $methodName |
332
|
|
|
* with the parameters $args. |
333
|
|
|
* |
334
|
|
|
* @param string $methodName |
335
|
|
|
* @param array $args |
336
|
|
|
* @return WidgetAction Or null on error. |
337
|
|
|
*/ |
338
|
|
|
protected function getMethodAction($methodName, $args) |
339
|
|
|
{ |
340
|
|
|
$fullClassName = substr(get_class($this), 0, - strlen(self::PROXY_CLASS_SUFFIX)); |
341
|
|
|
$className = join('', array_slice(explode('\\', $fullClassName), - 1)); |
342
|
|
|
|
343
|
|
|
$reflector = new \ReflectionClass(get_class($this)); |
344
|
|
|
$parent = $reflector->getParentClass(); |
345
|
|
|
if($parent){ |
|
|
|
|
346
|
|
|
$parentMethod = $parent->getMethod('__construct'); |
347
|
|
|
$docComment = $parentMethod->getDocComment(); |
348
|
|
|
if(strpos($docComment, '@isComponentController') !== false){ |
349
|
|
|
$fullClassName = $parent->getName(); |
350
|
|
|
} |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
$rc = new \ReflectionClass($fullClassName); |
354
|
|
|
|
355
|
|
|
if(! $rc->hasMethod($methodName)){ |
356
|
|
|
throw new \bab_InvalidActionException($fullClassName . '::' . $methodName); |
357
|
|
|
} |
358
|
|
|
$method = new \ReflectionMethod($fullClassName, $methodName); |
359
|
|
|
|
360
|
|
|
$objectName = $this->getObjectName($className); |
361
|
|
|
|
362
|
|
|
$parameters = $method->getParameters(); |
363
|
|
|
$actionParams = array(); |
364
|
|
|
$argNumber = 0; |
365
|
|
|
foreach ($parameters as $parameter){ |
366
|
|
|
$parameterName = $parameter->getName(); |
367
|
|
|
if(isset($args[$argNumber])){ |
368
|
|
|
$actionParams[$parameterName] = $args[$argNumber]; |
369
|
|
|
} |
370
|
|
|
elseif($parameter->isDefaultValueAvailable()){ |
371
|
|
|
$actionParams[$parameterName] = $parameter->getDefaultValue(); |
372
|
|
|
} |
373
|
|
|
else{ |
374
|
|
|
$actionParams[$parameterName] = null; |
375
|
|
|
} |
376
|
|
|
$argNumber ++; |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
$action = new WidgetAction(); |
380
|
|
|
|
381
|
|
|
$action->setMethod($this->getControllerTg(), $objectName . '.' . $methodName, $actionParams); |
382
|
|
|
|
383
|
|
|
$docComment = $method->getDocComment(); |
384
|
|
|
if(strpos($docComment, '@ajax') !== false){ |
385
|
|
|
$action->setAjax(true); |
386
|
|
|
} |
387
|
|
|
if(strpos($docComment, '@requireSaveMethod') !== false && method_exists($action, 'setRequireSaveMethod')){ |
388
|
|
|
$action->setRequireSaveMethod(true); |
389
|
|
|
} |
390
|
|
|
if(strpos($docComment, '@requireDeleteMethod') !== false && method_exists($action, 'setRequireDeleteMethod')){ |
391
|
|
|
$action->setRequireDeleteMethod(true); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
return $action; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
/** |
398
|
|
|
* @return WidgetAction |
399
|
|
|
*/ |
400
|
|
|
protected function createActionForTg($idx, $actionParams) |
401
|
|
|
{ |
402
|
|
|
$action = new WidgetAction(); |
403
|
|
|
|
404
|
|
|
$action->setMethod($this->App()->controllerTg, $idx, $actionParams); |
405
|
|
|
|
406
|
|
|
return $action; |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
/** |
410
|
|
|
* @return WidgetAction |
411
|
|
|
*/ |
412
|
|
|
protected function createActionForAddon($idx, $actionParams) |
413
|
|
|
{ |
414
|
|
|
$App = $this->App(); |
415
|
|
|
$action = new WidgetAction(); |
416
|
|
|
|
417
|
|
|
$action->setParameters($actionParams); |
418
|
|
|
|
419
|
|
|
list (, , $file) = explode('/', $App->controllerTg); |
420
|
|
|
|
421
|
|
|
$action->setParameter('addon', $App->getAddonName() . '.' . $file); |
422
|
|
|
$action->setParameter('idx', $idx); |
423
|
|
|
|
424
|
|
|
return $action; |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* Tries to dispatch the action to the correct sub-controller. |
429
|
|
|
* |
430
|
|
|
* @param WidgetAction $action |
431
|
|
|
* @return mixed |
432
|
|
|
*/ |
433
|
|
|
final public function execute(WidgetAction $action) |
434
|
|
|
{ |
435
|
|
|
$this->app->setCurrentComponent(null); |
436
|
|
|
|
437
|
|
|
$method = $action->getMethod(); |
438
|
|
|
|
439
|
|
|
if(! isset($method) || '' === $method){ |
440
|
|
|
return false; |
441
|
|
|
} |
442
|
|
|
|
443
|
|
|
list ($objectName,) = explode('.', $method); |
444
|
|
|
|
445
|
|
|
if(! method_exists($this, $objectName)){ |
446
|
|
|
/* @var $component AppComponent */ |
447
|
|
|
$component = $this->app->getComponentByName($objectName); |
448
|
|
|
if($component){ |
|
|
|
|
449
|
|
|
$this->app->setCurrentComponent($component); |
450
|
|
|
$objectController = $component->controller(false); |
451
|
|
|
} |
452
|
|
|
else{ |
453
|
|
|
header('HTTP/1.0 400 Bad Request'); |
454
|
|
|
throw new AppUnknownActionException($action); |
455
|
|
|
} |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
if(! isset($component)){ |
459
|
|
|
$objectController = $this->{$objectName}(false); |
460
|
|
|
if(! ($objectController instanceof AppController)){ |
461
|
|
|
return false; |
462
|
|
|
} |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
try{ |
466
|
|
|
$returnedValue = $objectController->execAction($action); |
|
|
|
|
467
|
|
|
} |
468
|
|
|
catch (AppAccessException $e){ |
469
|
|
|
|
470
|
|
|
if(! bab_isUserLogged() && $e->requireCredential){ |
471
|
|
|
bab_requireCredential($e->getMessage()); |
472
|
|
|
} |
473
|
|
|
else{ |
474
|
|
|
if($this->isAjaxRequest()){ |
475
|
|
|
|
476
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden', true, 403); |
477
|
|
|
|
478
|
|
|
die(bab_json_encode(array( |
479
|
|
|
'exception' => 'app_AccessException', |
480
|
|
|
'message' => bab_convertStringFromDatabase($e->getMessage(), 'UTF-8'), |
481
|
|
|
'errorMessage' => bab_convertStringFromDatabase($e->getMessage(), 'UTF-8') |
482
|
|
|
))); |
483
|
|
|
} |
484
|
|
|
$this->accessPage($e); |
485
|
|
|
} |
486
|
|
|
} |
487
|
|
|
catch (AppSaveException $e){ |
488
|
|
|
|
489
|
|
|
if($this->isAjaxRequest()){ |
490
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden', true, 403); |
491
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
492
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
493
|
|
|
header('Content-type: application/json'); |
494
|
|
|
|
495
|
|
|
die(bab_json_encode(array( |
496
|
|
|
'exception' => 'app_SaveException', |
497
|
|
|
'message' => bab_convertStringFromDatabase($e->getMessage(), 'UTF-8'), |
498
|
|
|
'errorMessage' => bab_convertStringFromDatabase($e->getMessage(), 'UTF-8') |
499
|
|
|
))); |
500
|
|
|
} |
501
|
|
|
} |
502
|
|
|
catch (AppDeletedRecordException $e){ |
503
|
|
|
$this->deletedItemPage($action, $e); |
504
|
|
|
} |
505
|
|
|
catch (AppNotFoundException $e){ |
506
|
|
|
$this->notFoundPage($action, $e); |
507
|
|
|
} |
508
|
|
|
catch (ORMException $e){ |
509
|
|
|
$this->errorPage($e); |
510
|
|
|
} |
511
|
|
|
catch (\Exception $e){ |
512
|
|
|
$this->unexpectedErrorPage($e); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
$W = bab_Widgets(); |
516
|
|
|
|
517
|
|
|
if($returnedValue instanceof WidgetDisplayableInterface){ |
518
|
|
|
|
519
|
|
|
if($returnedValue instanceof WidgetBabPage && ! $this->isAjaxRequest()){ |
520
|
|
|
|
521
|
|
|
// If the action returned a page, we display it. |
522
|
|
|
$returnedValue->displayHtml(); |
523
|
|
|
} |
524
|
|
|
else{ |
525
|
|
|
|
526
|
|
|
$htmlCanvas = $W->HtmlCanvas(); |
527
|
|
|
if(self::$acceptJson){ |
528
|
|
|
$itemId = $returnedValue->getId(); |
529
|
|
|
$returnArray = array( |
530
|
|
|
$itemId => $returnedValue->display($htmlCanvas) |
531
|
|
|
); |
532
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
533
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
534
|
|
|
header('Content-type: application/json'); |
535
|
|
|
die(bab_json_encode($returnArray)); |
536
|
|
|
} |
537
|
|
|
else{ |
538
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
539
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
540
|
|
|
header('Content-type: text/html'); |
541
|
|
|
if($returnedValue instanceof WidgetPage && method_exists($returnedValue, 'getPageTitle')){ |
542
|
|
|
$pageTitle = $returnedValue->getPageTitle(); |
543
|
|
|
|
544
|
|
|
if(method_exists($htmlCanvas, 'sendPageTitle')){ |
545
|
|
|
$htmlCanvas->sendPageTitle($pageTitle); |
546
|
|
|
} |
547
|
|
|
else{ |
548
|
|
|
header('X-Cto-PageTitle: ' . $pageTitle); |
549
|
|
|
} |
550
|
|
|
} |
551
|
|
|
$html = $returnedValue->display($htmlCanvas); |
552
|
|
|
die($html); |
|
|
|
|
553
|
|
|
} |
554
|
|
|
} |
555
|
|
|
} |
556
|
|
|
elseif(is_array($returnedValue)){ |
557
|
|
|
|
558
|
|
|
$htmlCanvas = $W->HtmlCanvas(); |
559
|
|
|
$returnedArray = array(); |
560
|
|
|
foreach ($returnedValue as $key => &$item){ |
561
|
|
|
if($item instanceof WidgetDisplayableInterface){ |
562
|
|
|
$returnedArray[$item->getId()] = $item->display($htmlCanvas); |
563
|
|
|
} |
564
|
|
|
else{ |
565
|
|
|
$returnedArray[$key] = $item; |
566
|
|
|
} |
567
|
|
|
} |
568
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
569
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
570
|
|
|
header('Content-type: application/json'); |
571
|
|
|
die(bab_convertStringFromDatabase(bab_json_encode($returnedArray), \bab_charset::UTF_8)); |
572
|
|
|
} |
573
|
|
|
elseif(true === $returnedValue || is_string($returnedValue)){ |
574
|
|
|
|
575
|
|
|
if($this->isAjaxRequest()){ |
576
|
|
|
$body = bab_getBody(); |
577
|
|
|
$json = array(); |
578
|
|
|
$json['messages'] = array(); |
579
|
|
|
$toasts = isset($body->messages['toasts']) ? $body->messages['toasts'] : array(); |
580
|
|
|
unset($body->messages['toasts']); |
581
|
|
|
$messages = $body->messages; |
582
|
|
|
$errors = $body->errors; |
583
|
|
|
foreach ($messages as $message){ |
584
|
|
|
$json['messages'][] = array( |
585
|
|
|
'level' => 'info', |
586
|
|
|
'content' => $message, |
587
|
|
|
'time' => 4000 |
588
|
|
|
); |
589
|
|
|
} |
590
|
|
|
foreach ($errors as $message){ |
591
|
|
|
$json['messages'][] = array( |
592
|
|
|
'level' => 'danger', |
593
|
|
|
'content' => $message |
594
|
|
|
); |
595
|
|
|
} |
596
|
|
|
$json['toasts'] = $toasts; |
597
|
|
|
if($objectController->getReloadSelectors()){ |
598
|
|
|
$json['reloadSelector'] = implode(',', $objectController->getReloadSelectors()); |
599
|
|
|
} |
600
|
|
|
if($objectController->keepDialogOpened){ |
601
|
|
|
$json['keepDialogOpened'] = true; |
602
|
|
|
} |
603
|
|
|
echo bab_json_encode($json); |
604
|
|
|
die(); |
|
|
|
|
605
|
|
|
} |
606
|
|
|
} |
607
|
|
|
|
608
|
|
|
return $returnedValue; |
609
|
|
|
} |
610
|
|
|
|
611
|
|
|
protected function deletedItemPage(WidgetAction $action, AppDeletedRecordException $e) |
612
|
|
|
{ |
613
|
|
|
if($this->isAjaxRequest()){ |
614
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden', true, 403); |
615
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
616
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
617
|
|
|
header('Content-type: application/json'); |
618
|
|
|
|
619
|
|
|
die(app_json_encode( |
|
|
|
|
620
|
|
|
array( |
621
|
|
|
'exception' => 'app_SaveException', |
622
|
|
|
'message' => bab_convertStringFromDatabase($e->getMessage(), 'UTF-8'), |
623
|
|
|
'errorMessage' => bab_convertStringFromDatabase($e->getMessage(), 'UTF-8') |
624
|
|
|
))); |
625
|
|
|
} |
626
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404); |
627
|
|
|
|
628
|
|
|
$App = app_App(); |
629
|
|
|
$W = bab_Widgets(); |
630
|
|
|
|
631
|
|
|
$page = $App->Ui()->ErrorPage(); |
632
|
|
|
$page->addClass(\Func_Icons::ICON_LEFT_16); |
633
|
|
|
|
634
|
|
|
$page->addItem($content = $W->FlexItems() |
|
|
|
|
635
|
|
|
->setSizePolicy('app-error-page-content') |
636
|
|
|
->setJustifyContent(WidgetFlexLayout::FLEX_JUSTIFY_CONTENT_SPACE_AROUND) |
637
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)); |
638
|
|
|
|
639
|
|
|
// TRANSLATORS: %s can be task, contact, organization ... |
640
|
|
|
$content->addItem($W->FlexItems($W->Label('') |
641
|
|
|
->setIcon(\Func_Icons::PLACES_USER_TRASH) |
642
|
|
|
->setIconFormat(48, 'left'), $section = $W->FlexItems() |
643
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)) |
644
|
|
|
->addClass('widget-50pc alert alert-warning') |
645
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)); |
646
|
|
|
$section->addItems($W->Title($App->translate('Error'), 1), $W->Title(sprintf($App->translate('This %s has been deleted'), $e->getObjectTitle()))); |
647
|
|
|
|
648
|
|
|
if($e instanceof AppDeletedRecordException){ |
|
|
|
|
649
|
|
|
$section->addItems($e->getDeletedBy(), $e->getDeletedOn()); |
650
|
|
|
} |
651
|
|
|
|
652
|
|
|
$page->displayHtml(); |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
protected function notFoundPage(WidgetAction $action, AppNotFoundException $e) |
656
|
|
|
{ |
657
|
|
|
if($this->isAjaxRequest()){ |
658
|
|
|
$message = sprintf(app_translate('This %s does not exists'), $e->getObjectTitle() . ' (' . $e->getId() . ')'); |
659
|
|
|
$json = array( |
660
|
|
|
'messages' => array( |
661
|
|
|
array( |
662
|
|
|
'level' => 'danger', |
663
|
|
|
'content' => $message |
664
|
|
|
) |
665
|
|
|
) |
666
|
|
|
); |
667
|
|
|
echo bab_json_encode($json); |
668
|
|
|
die(); |
|
|
|
|
669
|
|
|
} |
670
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404); |
671
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
672
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
673
|
|
|
|
674
|
|
|
$App = app_App(); |
675
|
|
|
$W = bab_Widgets(); |
676
|
|
|
|
677
|
|
|
$page = $App->Ui()->ErrorPage(); |
678
|
|
|
$page->addClass(\Func_Icons::ICON_LEFT_16); |
679
|
|
|
|
680
|
|
|
$page->addItem($content = $W->FlexItems() |
681
|
|
|
->setSizePolicy('app-error-page-content') |
682
|
|
|
->setJustifyContent(WidgetFlexLayout::FLEX_JUSTIFY_CONTENT_SPACE_AROUND) |
683
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)); |
684
|
|
|
|
685
|
|
|
// TRANSLATORS: %s can be task, contact, organization ... |
686
|
|
|
$content->addItem($W->FlexItems($W->Label('') |
687
|
|
|
->setIcon(\Func_Icons::STATUS_DIALOG_QUESTION) |
688
|
|
|
->setIconFormat(48, 'left'), $section = $W->FlexItems() |
689
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)) |
690
|
|
|
->addClass('widget-50pc alert alert-warning') |
691
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)); |
692
|
|
|
$section->addItems($W->Title($App->translate('Error'), 1), $W->Title(sprintf($App->translate('This %s does not exists'), $e->getObjectTitle()))); |
693
|
|
|
|
694
|
|
|
$page->displayHtml(); |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
protected function unexpectedErrorPage(\Exception $e) |
698
|
|
|
{ |
699
|
|
|
if($this->isAjaxRequest()){ |
700
|
|
|
$message = sprintf(app_translate('An unexpected error occured') . ':' . '%s', $e->getMessage()); |
701
|
|
|
$json = array( |
702
|
|
|
'messages' => array( |
703
|
|
|
array( |
704
|
|
|
'level' => 'danger', |
705
|
|
|
'content' => $message |
706
|
|
|
) |
707
|
|
|
) |
708
|
|
|
); |
709
|
|
|
echo bab_json_encode($json); |
710
|
|
|
die(); |
|
|
|
|
711
|
|
|
} |
712
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal server error', true, 500); |
713
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
714
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
715
|
|
|
|
716
|
|
|
$App = app_App(); |
717
|
|
|
$W = bab_Widgets(); |
718
|
|
|
|
719
|
|
|
$page = $App->Ui()->ErrorPage(); |
720
|
|
|
$page->addClass(\Func_Icons::ICON_LEFT_16); |
721
|
|
|
|
722
|
|
|
$page->addItem($content = $W->FlexItems() |
723
|
|
|
->setSizePolicy('app-error-page-content') |
724
|
|
|
->setJustifyContent(WidgetFlexLayout::FLEX_JUSTIFY_CONTENT_SPACE_AROUND) |
725
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)); |
726
|
|
|
|
727
|
|
|
// TRANSLATORS: %s can be task, contact, organization ... |
728
|
|
|
$content->addItem($contentBox = $W->FlexItems($W->FlexItems($W->Label('') |
729
|
|
|
->setIcon(\Func_Icons::STATUS_DIALOG_WARNING) |
730
|
|
|
->setIconFormat(48, 'left'), $section = $W->FlexItems() |
731
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)) |
732
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)) |
733
|
|
|
->addClass('widget-50pc alert alert-danger') |
734
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)); |
735
|
|
|
|
736
|
|
|
$logCode = '#' . hrtime(true); |
|
|
|
|
737
|
|
|
$message = addcslashes($e->getMessage(), "\000..\037\177..\377\\"); |
738
|
|
|
$trace = addcslashes($e->getTraceAsString(), "\000..\037\177..\377\\"); |
739
|
|
|
|
740
|
|
|
error_log(sprintf('Error %s : %s', $logCode, $message) . PHP_EOL . $trace); |
741
|
|
|
|
742
|
|
|
$section->addItems($W->Title($App->translate('Error'), 1), $W->Title($App->translate('An unexpected error occured')), $W->Label(sprintf($App->translate('It has been logged with the following error code : %s'), $logCode))); |
743
|
|
|
|
744
|
|
|
if(bab_isUserAdministrator()){ |
745
|
|
|
$contentBox->addItem($W->Section('Stack trace', $stackTraceBox = $W->FlexItems($W->Label($message) |
746
|
|
|
->addClass('widget-description')) |
747
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)) |
748
|
|
|
->setFoldable(true, true)); |
749
|
|
|
$traces = explode("\n", $e->getTraceAsString()); |
750
|
|
|
foreach ($traces as $trace){ |
751
|
|
|
$stackTraceBox->addItem($W->Label($trace)); |
752
|
|
|
} |
753
|
|
|
} |
754
|
|
|
else{ |
755
|
|
|
$section->addItem($W->Label($App->translate('Please contact the administrator'))); |
756
|
|
|
} |
757
|
|
|
|
758
|
|
|
$page->displayHtml(); |
759
|
|
|
} |
760
|
|
|
|
761
|
|
|
protected function errorPage(\Exception $e) |
762
|
|
|
{ |
763
|
|
|
if($this->isAjaxRequest()){ |
764
|
|
|
$message = sprintf(app_translate('An unexpected error occured') . ':' . '%s', $e->getMessage()); |
765
|
|
|
$json = array( |
766
|
|
|
'messages' => array( |
767
|
|
|
array( |
768
|
|
|
'level' => 'danger', |
769
|
|
|
'content' => $message |
770
|
|
|
) |
771
|
|
|
) |
772
|
|
|
); |
773
|
|
|
echo bab_json_encode($json); |
774
|
|
|
die(); |
|
|
|
|
775
|
|
|
} |
776
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal server error', true, 500); |
777
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
778
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
779
|
|
|
|
780
|
|
|
$App = app_App(); |
781
|
|
|
$W = bab_Widgets(); |
782
|
|
|
|
783
|
|
|
$page = $App->Ui()->ErrorPage(); |
784
|
|
|
$page->addClass(\Func_Icons::ICON_LEFT_16); |
785
|
|
|
|
786
|
|
|
$page->addItem($content = $W->FlexItems() |
787
|
|
|
->setSizePolicy('app-error-page-content') |
788
|
|
|
->setJustifyContent(WidgetFlexLayout::FLEX_JUSTIFY_CONTENT_SPACE_AROUND) |
789
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)); |
790
|
|
|
|
791
|
|
|
// TRANSLATORS: %s can be task, contact, organization ... |
792
|
|
|
$content->addItem($contentBox = $W->FlexItems($W->FlexItems($W->Label('') |
793
|
|
|
->setIcon(\Func_Icons::STATUS_DIALOG_WARNING) |
794
|
|
|
->setIconFormat(48, 'left'), $section = $W->FlexItems() |
795
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)) |
796
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)) |
797
|
|
|
->addClass('widget-50pc alert alert-danger') |
798
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)); |
799
|
|
|
|
800
|
|
|
$logCode = '#' . hrtime(true); |
|
|
|
|
801
|
|
|
$message = addcslashes($e->getMessage(), "\000..\037\177..\377\\"); |
802
|
|
|
$trace = addcslashes($e->getTraceAsString(), "\000..\037\177..\377\\"); |
803
|
|
|
|
804
|
|
|
error_log(sprintf('Error %s : %s', $logCode, $message) . PHP_EOL . $trace); |
805
|
|
|
|
806
|
|
|
$section->addItems($W->Title($App->translate('Error'), 1), $W->Title($App->translate('An unexpected error occured')), $W->Label(sprintf($App->translate('It has been logged with the following error code : %s'), $logCode))); |
807
|
|
|
|
808
|
|
|
if(bab_isUserAdministrator()){ |
809
|
|
|
$contentBox->addItem($W->Section('Stack trace', $stackTraceBox = $W->FlexItems($W->Label($message) |
810
|
|
|
->addClass('widget-description')) |
811
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)) |
812
|
|
|
->setFoldable(true, true)); |
813
|
|
|
$traces = explode("\n", $e->getTraceAsString()); |
814
|
|
|
foreach ($traces as $trace){ |
815
|
|
|
$stackTraceBox->addItem($W->Label($trace)); |
816
|
|
|
} |
817
|
|
|
} |
818
|
|
|
else{ |
819
|
|
|
$section->addItem($W->Label($App->translate('Please contact the administrator'))); |
820
|
|
|
} |
821
|
|
|
|
822
|
|
|
$page->displayHtml(); |
823
|
|
|
} |
824
|
|
|
|
825
|
|
|
protected function accessPage(\Exception $e) |
826
|
|
|
{ |
827
|
|
|
if($this->isAjaxRequest()){ |
828
|
|
|
$message = $e->getMessage(); |
829
|
|
|
$json = array( |
830
|
|
|
'messages' => array( |
831
|
|
|
array( |
832
|
|
|
'level' => 'danger', |
833
|
|
|
'content' => $message |
834
|
|
|
) |
835
|
|
|
) |
836
|
|
|
); |
837
|
|
|
echo bab_json_encode($json); |
838
|
|
|
die(); |
|
|
|
|
839
|
|
|
} |
840
|
|
|
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden', true, 403); |
841
|
|
|
header('Cache-Control: no-cache, must-revalidate'); |
842
|
|
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); |
843
|
|
|
|
844
|
|
|
$App = app_App(); |
845
|
|
|
$W = bab_Widgets(); |
846
|
|
|
|
847
|
|
|
$page = $App->Ui()->ErrorPage(); |
848
|
|
|
$page->addClass(\Func_Icons::ICON_LEFT_16); |
849
|
|
|
|
850
|
|
|
$page->addItem($content = $W->FlexItems() |
851
|
|
|
->setSizePolicy('app-error-page-content') |
852
|
|
|
->setJustifyContent(WidgetFlexLayout::FLEX_JUSTIFY_CONTENT_SPACE_AROUND) |
853
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)); |
854
|
|
|
|
855
|
|
|
// TRANSLATORS: %s can be task, contact, organization ... |
856
|
|
|
$content->addItem($W->FlexItems($W->FlexItems($W->Label('') |
857
|
|
|
->setIcon(\Func_Icons_Awesome::WEBAPP_UNLOCK_ALT) |
|
|
|
|
858
|
|
|
->setIconFormat(48, 'left'), $section = $W->FlexItems() |
859
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)) |
860
|
|
|
->setAlignItems(WidgetFlexLayout::FLEX_ALIGN_ITEMS_CENTER)) |
861
|
|
|
->addClass('widget-50pc alert alert-danger') |
862
|
|
|
->setDirection(WidgetFlexLayout::FLEX_DIRECTION_COL)); |
863
|
|
|
|
864
|
|
|
$section->addItems($W->Title($App->translate('Error'), 1), $W->Label($e->getMessage())); |
865
|
|
|
|
866
|
|
|
$page->displayHtml(); |
867
|
|
|
} |
868
|
|
|
|
869
|
|
|
/** |
870
|
|
|
* Method to call before saving |
871
|
|
|
* |
872
|
|
|
* @since 1.0.22 |
873
|
|
|
* @return self |
874
|
|
|
*/ |
875
|
|
|
public function requireSaveMethod() |
876
|
|
|
{ |
877
|
|
|
if('GET' === $_SERVER['REQUEST_METHOD']){ |
878
|
|
|
throw new AppException('Method not allowed'); |
879
|
|
|
} |
880
|
|
|
|
881
|
|
|
return $this; |
882
|
|
|
} |
883
|
|
|
|
884
|
|
|
/** |
885
|
|
|
* Method to call before deleting |
886
|
|
|
* |
887
|
|
|
* @since 1.0.22 |
888
|
|
|
* @return self |
889
|
|
|
*/ |
890
|
|
|
public function requireDeleteMethod() |
891
|
|
|
{ |
892
|
|
|
if('GET' === $_SERVER['REQUEST_METHOD']){ |
893
|
|
|
throw new AppException('Method not allowed'); |
894
|
|
|
} |
895
|
|
|
|
896
|
|
|
return $this; |
897
|
|
|
} |
898
|
|
|
|
899
|
|
|
/** |
900
|
|
|
* Similar to the addMessage method, addToast allows for more customization |
901
|
|
|
* |
902
|
|
|
* @param string $message |
903
|
|
|
* The message displayed in the toast. Can be HTML or string |
904
|
|
|
* @param string $title |
905
|
|
|
* The title of the toast. |
906
|
|
|
* @param string $type |
907
|
|
|
* Choose between 'text', 'log', 'success', 'warn', 'error', 'info'. Other values will result in a 'info' type |
908
|
|
|
* @param string $position |
909
|
|
|
* The position on the screen of the toast. Can be 'tl', 'tm', 'tr', 'ml', 'mm', 'mr', 'bl', 'bm' or 'br' (first letter is for 'Top', 'Middle', or 'Bottom', second one is for 'Left', 'Middle', 'Right') |
910
|
|
|
* @param int $duration |
911
|
|
|
* The duration in milliseconds the toast will be shown |
912
|
|
|
* @return self |
913
|
|
|
*/ |
914
|
|
|
public function addToast($message, $title = '', $type = 'success', $position = 'tr', $duration = 8000) |
915
|
|
|
{ |
916
|
|
|
$toast = array( |
917
|
|
|
'title' => $title, |
918
|
|
|
'message' => $message, |
919
|
|
|
'type' => $type, |
920
|
|
|
'duration' => $duration, |
921
|
|
|
'position' => $position |
922
|
|
|
); |
923
|
|
|
$babBody = bab_getBody(); |
924
|
|
|
if(! isset($babBody->messages['toasts'])){ |
925
|
|
|
$babBody->messages['toasts'] = array(); |
926
|
|
|
} |
927
|
|
|
$babBody->messages['toasts'][] = $toast; |
928
|
|
|
return $this; |
929
|
|
|
} |
930
|
|
|
|
931
|
|
|
public function getToasts() |
932
|
|
|
{ |
933
|
|
|
return $this->toasts; |
934
|
|
|
} |
935
|
|
|
|
936
|
|
|
/** |
937
|
|
|
* Custom fields |
938
|
|
|
* |
939
|
|
|
* @return AppCtrlCustomField |
940
|
|
|
*/ |
941
|
|
|
public function CustomField($proxy = true) |
942
|
|
|
{ |
943
|
|
|
return $this->App()->ControllerProxy('Capwelton\LibApp\Ctrl\AppCtrlCustomField', $proxy); |
944
|
|
|
} |
945
|
|
|
|
946
|
|
|
/** |
947
|
|
|
* Custom sections |
948
|
|
|
* |
949
|
|
|
* @return AppCtrlCustomSection |
950
|
|
|
*/ |
951
|
|
|
public function CustomSection($proxy = true) |
952
|
|
|
{ |
953
|
|
|
return $this->App()->ControllerProxy('Capwelton\LibApp\Ctrl\AppCtrlCustomSection', $proxy); |
954
|
|
|
} |
955
|
|
|
|
956
|
|
|
/** |
957
|
|
|
* Custom containers |
958
|
|
|
* |
959
|
|
|
* @return AppCtrlCustomContainer |
960
|
|
|
*/ |
961
|
|
|
public function CustomContainer($proxy = true) |
962
|
|
|
{ |
963
|
|
|
return $this->App()->ControllerProxy('Capwelton\LibApp\Ctrl\AppCtrlCustomContainer', $proxy); |
964
|
|
|
} |
965
|
|
|
|
966
|
|
|
/** |
967
|
|
|
* Notification |
968
|
|
|
* |
969
|
|
|
* @return AppCtrlNotification |
970
|
|
|
*/ |
971
|
|
|
public function Notification($proxy = true) |
972
|
|
|
{ |
973
|
|
|
return $this->App()->ControllerProxy('Capwelton\LibApp\Ctrl\AppCtrlNotification', $proxy); |
974
|
|
|
} |
975
|
|
|
|
976
|
|
|
/** |
977
|
|
|
* SSE |
978
|
|
|
* |
979
|
|
|
* @return AppCtrlSSE |
980
|
|
|
*/ |
981
|
|
|
public function SSE($proxy = true) |
982
|
|
|
{ |
983
|
|
|
return $this->App()->ControllerProxy('Capwelton\LibApp\Ctrl\AppCtrlSSE', $proxy); |
984
|
|
|
} |
985
|
|
|
|
986
|
|
|
/** |
987
|
|
|
* Addon configuration |
988
|
|
|
* |
989
|
|
|
* @return AppCtrlAddonConfiguration |
990
|
|
|
*/ |
991
|
|
|
public function AddonConfiguration($proxy = true) |
992
|
|
|
{ |
993
|
|
|
return $this->App()->ControllerProxy('Capwelton\LibApp\Ctrl\AppCtrlAddonConfiguration', $proxy); |
994
|
|
|
} |
995
|
|
|
|
996
|
|
|
/** |
997
|
|
|
* Addon configuration |
998
|
|
|
* |
999
|
|
|
* @return AppCtrlConfiguration |
1000
|
|
|
*/ |
1001
|
|
|
public function Configuration($proxy = true) |
1002
|
|
|
{ |
1003
|
|
|
return $this->App()->ControllerProxy('Capwelton\LibApp\Ctrl\AppCtrlConfiguration', $proxy); |
1004
|
|
|
} |
1005
|
|
|
|
1006
|
|
|
public function accessDenied() |
1007
|
|
|
{ |
1008
|
|
|
$App = $this->App(); |
1009
|
|
|
$page = $this->accessPage(new AppAccessException($App->translate('Access denied'))); |
|
|
|
|
1010
|
|
|
return $page; |
1011
|
|
|
} |
1012
|
|
|
} |
1013
|
|
|
|
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths