Complex classes like View often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use View, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
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 |
||
85 | |||
86 | /** |
||
87 | * Get breadcrumb title. |
||
88 | * |
||
89 | * @return string |
||
90 | */ |
||
91 | public function getBreadcrumbTitle(): string |
||
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 |
||
190 | |||
191 | /** |
||
192 | * Get preprocess tpl name. |
||
193 | * |
||
194 | * @return string |
||
195 | */ |
||
196 | protected function preProcessTplName(): string |
||
200 | |||
201 | /** |
||
202 | * Get process tpl name. |
||
203 | * |
||
204 | * @return string |
||
205 | */ |
||
206 | protected function processTplName(): string |
||
210 | |||
211 | /** {@inheritdoc} */ |
||
212 | protected function postProcessTplName(): string |
||
216 | |||
217 | /** {@inheritdoc} */ |
||
218 | public function postProcess(): void |
||
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() |
||
300 | |||
301 | /** {@inheritdoc} */ |
||
302 | public function postProcessAjax() |
||
305 | |||
306 | /** {@inheritdoc} */ |
||
307 | public function preProcessAjax() |
||
310 | |||
311 | /** |
||
312 | * Get module name from request. |
||
313 | * |
||
314 | * @return string |
||
315 | */ |
||
316 | protected function getModuleNameFromRequest(): string |
||
323 | |||
324 | /** |
||
325 | * Load js config. |
||
326 | * |
||
327 | * @param \App\Request $request |
||
328 | */ |
||
329 | public function loadJsConfig(\App\Request $request): void |
||
341 | |||
342 | /** |
||
343 | * Get the list of user quick menu links. |
||
344 | * |
||
345 | * @return array |
||
346 | */ |
||
347 | protected function getUserQuickMenuLinks(): array |
||
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.