Total Complexity | 42 |
Total Lines | 385 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like PermissionController 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.
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 PermissionController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
34 | class PermissionController extends ActionController |
||
35 | { |
||
36 | /** |
||
37 | * @var string prefix for session |
||
38 | */ |
||
39 | const SESSION_PREFIX = 'tx_Beuser_'; |
||
40 | |||
41 | /** |
||
42 | * @var int the current page id |
||
43 | */ |
||
44 | protected $id; |
||
45 | |||
46 | /** |
||
47 | * @var string |
||
48 | */ |
||
49 | protected $returnUrl = ''; |
||
50 | |||
51 | /** |
||
52 | * @var int |
||
53 | */ |
||
54 | protected $depth; |
||
55 | |||
56 | /** |
||
57 | * Number of levels to enable recursive settings for |
||
58 | * |
||
59 | * @var int |
||
60 | */ |
||
61 | protected $getLevels = 10; |
||
62 | |||
63 | /** |
||
64 | * @var array |
||
65 | */ |
||
66 | protected $pageInfo = []; |
||
67 | |||
68 | /** |
||
69 | * Backend Template Container |
||
70 | * |
||
71 | * @var string |
||
72 | */ |
||
73 | protected $defaultViewObjectName = BackendTemplateView::class; |
||
74 | |||
75 | /** |
||
76 | * BackendTemplateContainer |
||
77 | * |
||
78 | * @var BackendTemplateView |
||
79 | */ |
||
80 | protected $view; |
||
81 | |||
82 | /** |
||
83 | * Initialize action |
||
84 | */ |
||
85 | protected function initializeAction() |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * Initializes view |
||
116 | * |
||
117 | * @param ViewInterface $view The view to be initialized |
||
118 | */ |
||
119 | protected function initializeView(ViewInterface $view) |
||
132 | } |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Registers the Icons into the docheader |
||
137 | * |
||
138 | * @throws \InvalidArgumentException |
||
139 | */ |
||
140 | protected function registerDocHeaderButtons() |
||
141 | { |
||
142 | /** @var ButtonBar $buttonBar */ |
||
143 | $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar(); |
||
144 | $currentRequest = $this->request; |
||
145 | $moduleName = $currentRequest->getPluginName(); |
||
146 | $lang = $this->getLanguageService(); |
||
147 | |||
148 | if ($currentRequest->getControllerActionName() === 'edit') { |
||
149 | // CLOSE button: |
||
150 | if (!empty($this->returnUrl)) { |
||
151 | $closeButton = $buttonBar->makeLinkButton() |
||
152 | ->setHref($this->returnUrl) |
||
153 | ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc')) |
||
154 | ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon( |
||
155 | 'actions-close', |
||
156 | Icon::SIZE_SMALL |
||
157 | )); |
||
158 | $buttonBar->addButton($closeButton); |
||
159 | } |
||
160 | |||
161 | // SAVE button: |
||
162 | $saveButton = $buttonBar->makeInputButton() |
||
163 | ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveCloseDoc')) |
||
164 | ->setName('tx_beuser_system_beusertxpermission[submit]') |
||
165 | ->setValue('Save') |
||
166 | ->setForm('PermissionControllerEdit') |
||
167 | ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon( |
||
168 | 'actions-document-save', |
||
169 | Icon::SIZE_SMALL |
||
170 | )) |
||
171 | ->setShowLabelText(true); |
||
172 | |||
173 | $buttonBar->addButton($saveButton); |
||
174 | } |
||
175 | |||
176 | $shortcutButton = $buttonBar->makeShortcutButton() |
||
177 | ->setModuleName($moduleName) |
||
178 | ->setDisplayName($this->getShortcutTitle()) |
||
179 | ->setArguments([ |
||
180 | 'route' => GeneralUtility::_GP('route'), |
||
181 | 'id' => (int)$this->id, |
||
182 | ]); |
||
183 | $buttonBar->addButton($shortcutButton); |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Index action |
||
188 | */ |
||
189 | public function indexAction() |
||
190 | { |
||
191 | if (!$this->id) { |
||
192 | $this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0]; |
||
193 | } |
||
194 | |||
195 | if ($this->getBackendUser()->workspace != 0) { |
||
196 | // Adding section with the permission setting matrix: |
||
197 | $this->addFlashMessage( |
||
198 | LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser') ?? '', |
||
199 | LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser') ?? '', |
||
200 | FlashMessage::WARNING |
||
201 | ); |
||
202 | } |
||
203 | |||
204 | // depth options |
||
205 | $depthOptions = []; |
||
206 | $url = $this->uriBuilder->reset()->setArguments([ |
||
207 | 'action' => 'index', |
||
208 | 'depth' => '${value}', |
||
209 | 'id' => $this->id |
||
210 | ])->buildBackendUri(); |
||
211 | foreach ([1, 2, 3, 4, 10] as $depthLevel) { |
||
212 | $levelLabel = $depthLevel === 1 ? 'level' : 'levels'; |
||
213 | $depthOptions[$depthLevel] = $depthLevel . ' ' . LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:' . $levelLabel, 'beuser'); |
||
214 | } |
||
215 | $this->view->assign('currentId', $this->id); |
||
216 | $this->view->assign('depthBaseUrl', $url); |
||
217 | $this->view->assign('depth', $this->depth); |
||
218 | $this->view->assign('depthOptions', $depthOptions); |
||
219 | |||
220 | $beUserArray = BackendUtility::getUserNames(); |
||
221 | $this->view->assign('beUsers', $beUserArray); |
||
222 | $beGroupArray = BackendUtility::getGroupNames(); |
||
223 | $this->view->assign('beGroups', $beGroupArray); |
||
224 | |||
225 | /** @var PageTreeView $tree */ |
||
226 | $tree = GeneralUtility::makeInstance(PageTreeView::class); |
||
227 | $tree->init(); |
||
228 | $tree->addField('perms_user', true); |
||
229 | $tree->addField('perms_group', true); |
||
230 | $tree->addField('perms_everybody', true); |
||
231 | $tree->addField('perms_userid', true); |
||
232 | $tree->addField('perms_groupid', true); |
||
233 | $tree->addField('hidden'); |
||
234 | $tree->addField('fe_group'); |
||
235 | $tree->addField('starttime'); |
||
236 | $tree->addField('endtime'); |
||
237 | $tree->addField('editlock'); |
||
238 | |||
239 | // Create the tree from $this->id |
||
240 | if ($this->id) { |
||
241 | $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getIcon($this->pageInfo)]; |
||
242 | } else { |
||
243 | $tree->tree[] = ['row' => $this->pageInfo, 'HTML' => $tree->getRootIcon($this->pageInfo)]; |
||
244 | } |
||
245 | $tree->getTree($this->id, $this->depth); |
||
246 | $this->view->assign('viewTree', $tree->tree); |
||
247 | |||
248 | // CSH for permissions setting |
||
249 | $this->view->assign('cshItem', BackendUtility::cshItem('xMOD_csh_corebe', 'perm_module', '', '<span class="btn btn-default btn-sm">|</span>')); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Edit action |
||
254 | */ |
||
255 | public function editAction() |
||
256 | { |
||
257 | $this->view->assign('id', $this->id); |
||
258 | $this->view->assign('depth', $this->depth); |
||
259 | |||
260 | if (!$this->id) { |
||
261 | $this->pageInfo = ['title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'uid' => 0, 'pid' => 0]; |
||
262 | } |
||
263 | if ($this->getBackendUser()->workspace != 0) { |
||
264 | // Adding FlashMessage with the permission setting matrix: |
||
265 | $this->addFlashMessage( |
||
266 | LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser') ?? '', |
||
267 | LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser') ?? '', |
||
268 | FlashMessage::WARNING |
||
269 | ); |
||
270 | } |
||
271 | // Get user names and group names |
||
272 | $beGroupArray = BackendUtility::getGroupNames(); |
||
273 | $beUserArray = BackendUtility::getUserNames(); |
||
274 | |||
275 | // Owner selector |
||
276 | $beUserDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')]; |
||
277 | foreach ($beUserArray as $uid => &$row) { |
||
278 | $beUserDataArray[$uid] = $row['username']; |
||
279 | } |
||
280 | $beUserDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser'); |
||
281 | $this->view->assign('currentBeUser', $this->pageInfo['perms_userid']); |
||
282 | $this->view->assign('beUserData', $beUserDataArray); |
||
283 | |||
284 | // Group selector |
||
285 | $beGroupDataArray = [0 => LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectNone', 'beuser')]; |
||
286 | foreach ($beGroupArray as $uid => $row) { |
||
287 | $beGroupDataArray[$uid] = $row['title']; |
||
288 | } |
||
289 | $beGroupDataArray[-1] = LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:selectUnchanged', 'beuser'); |
||
290 | $this->view->assign('currentBeGroup', $this->pageInfo['perms_groupid']); |
||
291 | $this->view->assign('beGroupData', $beGroupDataArray); |
||
292 | $this->view->assign('pageInfo', $this->pageInfo); |
||
293 | $this->view->assign('returnUrl', $this->returnUrl); |
||
294 | $this->view->assign('recursiveSelectOptions', $this->getRecursiveSelectOptions()); |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * Update action |
||
299 | * |
||
300 | * @param array $data |
||
301 | * @param array $mirror |
||
302 | */ |
||
303 | protected function updateAction(array $data, array $mirror) |
||
304 | { |
||
305 | $dataHandlerInput = []; |
||
306 | // Prepare the input data for data handler |
||
307 | if (!empty($data['pages'])) { |
||
308 | foreach ($data['pages'] as $pageUid => $properties) { |
||
309 | // if the owner and group field shouldn't be touched, unset the option |
||
310 | if ((int)$properties['perms_userid'] === -1) { |
||
311 | unset($properties['perms_userid']); |
||
312 | } |
||
313 | if ((int)$properties['perms_groupid'] === -1) { |
||
314 | unset($properties['perms_groupid']); |
||
315 | } |
||
316 | $dataHandlerInput[$pageUid] = $properties; |
||
317 | if (!empty($mirror['pages'][$pageUid])) { |
||
318 | $mirrorPages = GeneralUtility::intExplode(',', $mirror['pages'][$pageUid]); |
||
319 | foreach ($mirrorPages as $mirrorPageUid) { |
||
320 | $dataHandlerInput[$mirrorPageUid] = $properties; |
||
321 | } |
||
322 | } |
||
323 | } |
||
324 | } |
||
325 | |||
326 | $dataHandler = GeneralUtility::makeInstance(DataHandler::class); |
||
327 | $dataHandler->start( |
||
328 | [ |
||
329 | 'pages' => $dataHandlerInput |
||
330 | ], |
||
331 | [] |
||
332 | ); |
||
333 | $dataHandler->process_datamap(); |
||
334 | |||
335 | $this->redirectToUri($this->returnUrl); |
||
336 | } |
||
337 | |||
338 | /** |
||
339 | * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication |
||
340 | */ |
||
341 | protected function getBackendUser() |
||
342 | { |
||
343 | return $GLOBALS['BE_USER']; |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Finding tree and offer setting of values recursively. |
||
348 | * |
||
349 | * @return array |
||
350 | */ |
||
351 | protected function getRecursiveSelectOptions() |
||
387 | } |
||
388 | |||
389 | /** |
||
390 | * Check if page record exists and set pageInfo |
||
391 | */ |
||
392 | protected function setPageInfo(): void |
||
393 | { |
||
394 | $this->pageInfo = BackendUtility::readPageAccess(BackendUtility::getRecord('pages', $this->id) ? $this->id : 0, ' 1=1'); |
||
395 | } |
||
396 | |||
397 | /** |
||
398 | * Returns LanguageService |
||
399 | * |
||
400 | * @return \TYPO3\CMS\Core\Localization\LanguageService |
||
401 | */ |
||
402 | protected function getLanguageService() |
||
403 | { |
||
404 | return $GLOBALS['LANG']; |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * Returns the shortcut title for the current page |
||
409 | * |
||
410 | * @return string |
||
411 | */ |
||
412 | protected function getShortcutTitle(): string |
||
419 | ); |
||
420 | } |
||
421 | } |
||
422 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.