1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Controller class for views. |
4
|
|
|
* |
5
|
|
|
* @package Controller |
6
|
|
|
* |
7
|
|
|
* @copyright YetiForce Sp. z o.o. |
8
|
|
|
* @license YetiForce Public License 3.0 (licenses/LicenseEN.txt or yetiforce.com) |
9
|
|
|
* @author Tomasz Kur <[email protected]> |
10
|
|
|
* @author Mariusz Krzaczkowski <[email protected]> |
11
|
|
|
* @author Radosław Skrzypczak <[email protected]> |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace App\Controller; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Controller class for views. |
18
|
|
|
*/ |
19
|
|
|
abstract class View extends Base |
|
|
|
|
20
|
|
|
{ |
21
|
|
|
/** @var \App\Viewer Viewer object. */ |
22
|
|
|
protected $viewer; |
23
|
|
|
|
24
|
|
|
/** {@inheritdoc} */ |
25
|
|
|
public function __construct(\App\Request $request) |
26
|
|
|
{ |
27
|
|
|
parent::__construct($request); |
28
|
|
|
$this->loadJsConfig($request); |
29
|
|
|
$this->viewer = new \App\Viewer(); |
30
|
|
|
$this->viewer->assign('MODULE_NAME', $this->getModuleNameFromRequest($this->request)); |
|
|
|
|
31
|
|
|
$this->viewer->assign('VIEW', $this->request->getByType('view', \App\Purifier::ALNUM)); |
32
|
|
|
$this->viewer->assign('NONCE', \App\Session::get('CSP_TOKEN')); |
33
|
|
|
$this->viewer->assign('LANGUAGE', \App\Language::getLanguage()); |
34
|
|
|
$this->viewer->assign('LANG', \App\Language::getShortLanguageName()); |
35
|
|
|
$this->viewer->assign('USER', \App\User::getUser()); |
36
|
|
|
$this->viewer->assign('ACTION_NAME', $this->request->getAction()); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Check permission. |
41
|
|
|
* |
42
|
|
|
* @throws \App\Exceptions\NoPermitted |
43
|
|
|
* |
44
|
|
|
* @return void |
45
|
|
|
*/ |
46
|
|
|
public function checkPermission(): void |
47
|
|
|
{ |
48
|
|
|
$this->getModuleNameFromRequest($this->request); |
|
|
|
|
49
|
|
|
if (!\App\User::getUser()->isPermitted($this->moduleName)) { |
50
|
|
|
throw new \App\Exceptions\AppException('ERR_MODULE_PERMISSION_DENIED'); |
51
|
|
|
} |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** {@inheritdoc} */ |
55
|
|
|
public function preProcess($display = true): void |
56
|
|
|
{ |
57
|
|
|
if ($this->loginRequired()) { |
58
|
|
|
$this->viewer->assign('MENU', \YF\Modules\Base\Model\Menu::getInstance($this->viewer->getTemplateVars('MODULE_NAME'))->getMenu()); |
59
|
|
|
} |
60
|
|
|
$this->viewer->assign('PAGE_TITLE', (\Conf\Config::$siteName ?: \App\Language::translate('LBL_CUSTOMER_PORTAL')) . ' ' . $this->getPageTitle()); |
61
|
|
|
$this->viewer->assign('CSS_FILE', $this->getHeaderCss()); |
62
|
|
|
$this->viewer->assign('USER_QUICK_MENU', $this->getUserQuickMenuLinks()); |
63
|
|
|
if ($display) { |
64
|
|
|
$this->preProcessDisplay(); |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Get page title. |
70
|
|
|
* |
71
|
|
|
* @return string |
72
|
|
|
*/ |
73
|
|
|
public function getPageTitle(): string |
74
|
|
|
{ |
75
|
|
|
$title = \App\Language::translateModule($this->moduleName); |
76
|
|
|
$pageTitle = $this->getBreadcrumbTitle(); |
77
|
|
|
if (isset($this->pageTitle)) { |
78
|
|
|
$pageTitle = \App\Language::translate($this->pageTitle); |
|
|
|
|
79
|
|
|
} |
80
|
|
|
if ($pageTitle) { |
81
|
|
|
$title .= ' - ' . $pageTitle; |
82
|
|
|
} |
83
|
|
|
return $title; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Get breadcrumb title. |
88
|
|
|
* |
89
|
|
|
* @return string |
90
|
|
|
*/ |
91
|
|
|
public function getBreadcrumbTitle(): string |
92
|
|
|
{ |
93
|
|
|
if (!empty($this->pageTitle)) { |
94
|
|
|
return $this->pageTitle; |
95
|
|
|
} |
96
|
|
|
return ''; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* Convert scripts path. |
101
|
|
|
* |
102
|
|
|
* @param array $files |
103
|
|
|
* @param string $fileExtension |
104
|
|
|
* |
105
|
|
|
* @return array |
106
|
|
|
*/ |
107
|
|
|
public function convertScripts(array $files, string $fileExtension): array |
108
|
|
|
{ |
109
|
|
|
$scriptsInstances = []; |
110
|
|
|
foreach ($files as $file) { |
111
|
|
|
[$fileName, $isOptional] = array_pad($file, 2, false); |
|
|
|
|
112
|
|
|
$path = ROOT_DIRECTORY . "/public_html/$fileName"; |
113
|
|
|
$script = new \App\Script(); |
114
|
|
|
$script->set('type', $fileExtension); |
115
|
|
|
$minFilePath = str_replace('.' . $fileExtension, '.min.' . $fileExtension, $fileName); |
116
|
|
|
if (\App\Config::$minScripts && file_exists(ROOT_DIRECTORY . "/public_html/$minFilePath")) { |
117
|
|
|
$scriptsInstances[] = $script->set('src', PUBLIC_DIRECTORY . $minFilePath . self::getTime($path)); |
118
|
|
|
} elseif (file_exists($path)) { |
119
|
|
|
$scriptsInstances[] = $script->set('src', PUBLIC_DIRECTORY . $fileName . self::getTime($path)); |
120
|
|
|
} elseif (!$isOptional) { |
121
|
|
|
\App\Log::warning('File not found: ' . $path); |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
return $scriptsInstances; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Gets file modification time. |
129
|
|
|
* |
130
|
|
|
* @param string $path |
131
|
|
|
* |
132
|
|
|
* @return string |
133
|
|
|
*/ |
134
|
|
|
public static function getTime(string $path): string |
135
|
|
|
{ |
136
|
|
|
$url = ''; |
137
|
|
|
if ($fs = filemtime($path)) { |
138
|
|
|
$url = '?s=' . $fs; |
139
|
|
|
} |
140
|
|
|
return $url; |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Retrieves css styles that need to loaded in the page. |
145
|
|
|
* |
146
|
|
|
* @return \App\Script[] |
147
|
|
|
*/ |
148
|
|
|
public function getHeaderCss(): array |
149
|
|
|
{ |
150
|
|
|
return $this->convertScripts([ |
151
|
|
|
['libraries/@fortawesome/fontawesome-free/css/all.css'], |
152
|
|
|
['libraries/@mdi/font/css/materialdesignicons.css'], |
153
|
|
|
['libraries/chosen-js/chosen.css'], |
154
|
|
|
['libraries/bootstrap-chosen/bootstrap-chosen.css'], |
155
|
|
|
['libraries/jQuery-Validation-Engine/css/validationEngine.jquery.css'], |
156
|
|
|
['libraries/select2/dist/css/select2.css'], |
157
|
|
|
['libraries/datatables.net-bs4/css/dataTables.bootstrap4.css'], |
158
|
|
|
['libraries/datatables.net-responsive-bs4/css/responsive.bootstrap4.css'], |
159
|
|
|
['libraries/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css'], |
160
|
|
|
['libraries/bootstrap-daterangepicker/daterangepicker.css'], |
161
|
|
|
['libraries/clockpicker/dist/bootstrap4-clockpicker.css'], |
162
|
|
|
['libraries/jstree-bootstrap-theme/dist/themes/proton/style.css'], |
163
|
|
|
['libraries/jstree/dist/themes/default/style.css'], |
164
|
|
|
['libraries/@pnotify/core/dist/PNotify.css'], |
165
|
|
|
['libraries/@pnotify/confirm/dist/PNotifyConfirm.css'], |
166
|
|
|
['libraries/@pnotify/bootstrap4/dist/PNotifyBootstrap4.css'], |
167
|
|
|
['libraries/@pnotify/mobile/dist/PNotifyMobile.css'], |
168
|
|
|
['libraries/@pnotify/desktop/dist/PNotifyDesktop.css'], |
169
|
|
|
['libraries/jquery-ui-dist/jquery-ui.css'], |
170
|
|
|
['layouts/resources/icons/additionalIcons.css'], |
171
|
|
|
['layouts/resources/icons/yfm.css'], |
172
|
|
|
['layouts/resources/icons/yfi.css'], |
173
|
|
|
['layouts/' . \App\Viewer::getLayoutName() . '/skins/basic/Main.css'], |
174
|
|
|
], 'css'); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Pre process display. |
179
|
|
|
* |
180
|
|
|
* @return void |
181
|
|
|
*/ |
182
|
|
|
protected function preProcessDisplay(): void |
183
|
|
|
{ |
184
|
|
|
if (\App\Session::has('systemError')) { |
185
|
|
|
$this->viewer->assign('ERRORS', \App\Session::get('systemError')); |
186
|
|
|
\App\Session::unset('systemError'); |
187
|
|
|
} |
188
|
|
|
$this->viewer->view($this->preProcessTplName(), $this->moduleName); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Get preprocess tpl name. |
193
|
|
|
* |
194
|
|
|
* @return string |
195
|
|
|
*/ |
196
|
|
|
protected function preProcessTplName(): string |
197
|
|
|
{ |
198
|
|
|
return 'Header.tpl'; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Get process tpl name. |
203
|
|
|
* |
204
|
|
|
* @return string |
205
|
|
|
*/ |
206
|
|
|
protected function processTplName(): string |
207
|
|
|
{ |
208
|
|
|
return $this->request->getAction() . '/Index.tpl'; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** {@inheritdoc} */ |
212
|
|
|
protected function postProcessTplName(): string |
213
|
|
|
{ |
214
|
|
|
return 'Footer.tpl'; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** {@inheritdoc} */ |
218
|
|
|
public function postProcess(): void |
219
|
|
|
{ |
220
|
|
|
if (null === $this->viewer->getTemplateVars('SHOW_FOOTER_BAR')) { |
221
|
|
|
$this->viewer->assign('SHOW_FOOTER_BAR', true); |
222
|
|
|
} |
223
|
|
|
$this->viewer->assign('JS_FILE', $this->getFooterScripts()); |
224
|
|
|
if (\App\Config::$debugApi && \App\Session::has('debugApi') && \App\Session::get('debugApi')) { |
225
|
|
|
$this->viewer->assign('DEBUG_API', \App\Session::get('debugApi')); |
226
|
|
|
$this->viewer->view('DebugApi.tpl', $this->moduleName); |
227
|
|
|
\App\Session::set('debugApi', false); |
228
|
|
|
} |
229
|
|
|
$this->viewer->view($this->postProcessTplName(), $this->moduleName); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Scripts. |
234
|
|
|
* |
235
|
|
|
* @param bool $loadForModule |
236
|
|
|
* |
237
|
|
|
* @return \App\Script[] |
238
|
|
|
*/ |
239
|
|
|
public function getFooterScripts(bool $loadForModule = true): array |
240
|
|
|
{ |
241
|
|
|
$action = $this->request->getAction(); |
242
|
|
|
$languageHandlerShortName = \App\Language::getShortLanguageName(); |
243
|
|
|
$fileName = ["libraries/jQuery-Validation-Engine/js/languages/jquery.validationEngine-$languageHandlerShortName.js"]; |
244
|
|
|
if (!file_exists(PUBLIC_DIRECTORY . $fileName[0])) { |
245
|
|
|
$fileName = ['libraries/jQuery-Validation-Engine/js/languages/jquery.validationEngine-en.js']; |
246
|
|
|
} |
247
|
|
|
$files = [ |
248
|
|
|
['libraries/jquery/dist/jquery.js'], |
249
|
|
|
['libraries/jquery.class.js/jquery.class.js'], |
250
|
|
|
['libraries/block-ui/jquery.blockUI.js'], |
251
|
|
|
['libraries/@pnotify/core/dist/PNotify.js'], |
252
|
|
|
['libraries/@pnotify/mobile/dist/PNotifyMobile.js'], |
253
|
|
|
['libraries/@pnotify/desktop/dist/PNotifyDesktop.js'], |
254
|
|
|
['libraries/@pnotify/confirm/dist/PNotifyConfirm.js'], |
255
|
|
|
['libraries/@pnotify/bootstrap4/dist/PNotifyBootstrap4.js'], |
256
|
|
|
['libraries/@pnotify/font-awesome5/dist/PNotifyFontAwesome5.js'], |
257
|
|
|
['libraries/jquery-ui-dist/jquery-ui.js'], |
258
|
|
|
['libraries/popper.js/dist/umd/popper.js'], |
259
|
|
|
['vendor/ckeditor/ckeditor/ckeditor.js'], |
260
|
|
|
['vendor/ckeditor/ckeditor/adapters/jquery.js'], |
261
|
|
|
['libraries/bootstrap/dist/js/bootstrap.js'], |
262
|
|
|
['libraries/bootstrap-datepicker/dist/js/bootstrap-datepicker.js'], |
263
|
|
|
['libraries/bootstrap-daterangepicker/daterangepicker.js'], |
264
|
|
|
['libraries/bootbox/dist/bootbox.min.js'], |
265
|
|
|
['libraries/chosen-js/chosen.jquery.js'], |
266
|
|
|
['libraries/select2/dist/js/select2.full.js'], |
267
|
|
|
['libraries/moment/min/moment.min.js'], |
268
|
|
|
['libraries/inputmask/dist/jquery.inputmask.js'], |
269
|
|
|
['libraries/datatables.net/js/jquery.dataTables.js'], |
270
|
|
|
['libraries/datatables.net-bs4/js/dataTables.bootstrap4.js'], |
271
|
|
|
['libraries/datatables.net-responsive/js/dataTables.responsive.js'], |
272
|
|
|
['libraries/datatables.net-responsive-bs4/js/responsive.bootstrap4.js'], |
273
|
|
|
['libraries/jQuery-Validation-Engine/js/jquery.validationEngine.js'], |
274
|
|
|
$fileName, |
275
|
|
|
['libraries/jstree/dist/jstree.js'], |
276
|
|
|
['libraries/clockpicker/dist/bootstrap4-clockpicker.js'], |
277
|
|
|
['layouts/resources/validator/BaseValidator.js'], |
278
|
|
|
['layouts/resources/validator/FieldValidator.js'], |
279
|
|
|
['layouts/resources/helper.js'], |
280
|
|
|
['layouts/resources/Field.js'], |
281
|
|
|
['layouts/resources/Connector.js'], |
282
|
|
|
['layouts/resources/app.js'], |
283
|
|
|
['layouts/resources/Fields.js'], |
284
|
|
|
['layouts/resources/ProgressIndicator.js'], |
285
|
|
|
['layouts/' . \App\Viewer::getLayoutName() . '/modules/Base/resources/Header.js'], |
286
|
|
|
['layouts/' . \App\Viewer::getLayoutName() . "/modules/Base/resources/{$action}.js"], |
287
|
|
|
]; |
288
|
|
|
if ($loadForModule) { |
289
|
|
|
$moduleName = $this->getModuleNameFromRequest(); |
290
|
|
|
$files[] = ['layouts/' . \App\Viewer::getLayoutName() . "/modules/{$moduleName}/resources/{$action}.js", true]; |
291
|
|
|
} |
292
|
|
|
return $this->convertScripts($files, 'js'); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** {@inheritdoc} */ |
296
|
|
|
public function validateRequest() |
297
|
|
|
{ |
298
|
|
|
$this->request->validateReadAccess(); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** {@inheritdoc} */ |
302
|
|
|
public function postProcessAjax() |
303
|
|
|
{ |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** {@inheritdoc} */ |
307
|
|
|
public function preProcessAjax() |
308
|
|
|
{ |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* Get module name from request. |
313
|
|
|
* |
314
|
|
|
* @return string |
315
|
|
|
*/ |
316
|
|
|
protected function getModuleNameFromRequest(): string |
317
|
|
|
{ |
318
|
|
|
if (empty($this->moduleName)) { |
319
|
|
|
$this->moduleName = $this->request->getModule(); |
320
|
|
|
} |
321
|
|
|
return $this->moduleName; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Load js config. |
326
|
|
|
* |
327
|
|
|
* @param \App\Request $request |
328
|
|
|
*/ |
329
|
|
|
public function loadJsConfig(\App\Request $request): void |
330
|
|
|
{ |
331
|
|
|
$jsEnv = [ |
332
|
|
|
'siteUrl' => \App\Utils::getPublicUrl('', true), |
333
|
|
|
'langPrefix' => \App\Language::getLanguage(), |
334
|
|
|
'langKey' => \App\Language::getShortLanguageName(), |
335
|
|
|
'parentModule' => $request->getByType('parent', 2), |
336
|
|
|
]; |
337
|
|
|
foreach ($jsEnv as $key => $value) { |
338
|
|
|
\App\Config::setJsEnv($key, $value); |
339
|
|
|
} |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* Get the list of user quick menu links. |
344
|
|
|
* |
345
|
|
|
* @return array |
346
|
|
|
*/ |
347
|
|
|
protected function getUserQuickMenuLinks(): array |
348
|
|
|
{ |
349
|
|
|
$user = \App\User::getUser(); |
350
|
|
|
$links = [ |
351
|
|
|
[ |
352
|
|
|
'label' => 'LBL_CHANGE_PASSWORD', |
353
|
|
|
'moduleName' => 'Users', |
354
|
|
|
'data' => ['url' => 'index.php?module=Users&view=PasswordChangeModal'], |
355
|
|
|
'icon' => 'yfi yfi-change-passowrd', |
356
|
|
|
'class' => 'text-decoration-none u-fs-sm text-secondary js-show-modal d-block', |
357
|
|
|
'btnClass' => ' ', |
358
|
|
|
'href' => '#', |
359
|
|
|
'showLabel' => true, |
360
|
|
|
], |
361
|
|
|
[ |
362
|
|
|
'label' => 'BTN_YOUR_ACCOUNT_ACCESS_HISTORY', |
363
|
|
|
'moduleName' => 'Users', |
364
|
|
|
'data' => ['url' => 'index.php?module=Users&view=AccessActivityHistoryModal'], |
365
|
|
|
'icon' => 'yfi yfi-login-history', |
366
|
|
|
'class' => 'text-decoration-none u-fs-sm text-secondary js-show-modal d-block', |
367
|
|
|
'btnClass' => ' ', |
368
|
|
|
'href' => '#', |
369
|
|
|
'showLabel' => true, |
370
|
|
|
], |
371
|
|
|
]; |
372
|
|
|
if ('PLL_PASSWORD_2FA' === $user->get('login_method') && !$user->isEmpty('authy_methods')) { |
373
|
|
|
$links[] = [ |
374
|
|
|
'label' => 'BTN_2FA_TOTP_QR_CODE', |
375
|
|
|
'moduleName' => 'Users', |
376
|
|
|
'data' => ['url' => 'index.php?module=Users&view=TwoFactorAuthenticationModal'], |
377
|
|
|
'icon' => 'fas fa-key', |
378
|
|
|
'class' => 'text-decoration-none u-fs-sm text-secondary js-show-modal d-block', |
379
|
|
|
'btnClass' => ' ', |
380
|
|
|
'href' => '#', |
381
|
|
|
'showLabel' => true, |
382
|
|
|
]; |
383
|
|
|
} |
384
|
|
|
return $links; |
385
|
|
|
} |
386
|
|
|
} |
387
|
|
|
|
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.