| Total Complexity | 59 |
| Total Lines | 396 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
Complex classes like TypoScriptTemplateObjectBrowserModuleFunctionController 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 TypoScriptTemplateObjectBrowserModuleFunctionController, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 37 | class TypoScriptTemplateObjectBrowserModuleFunctionController |
||
| 38 | { |
||
| 39 | /** |
||
| 40 | * @var TypoScriptTemplateModuleController |
||
| 41 | */ |
||
| 42 | protected $pObj; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * The currently selected sys_template record |
||
| 46 | * @var array|null |
||
| 47 | */ |
||
| 48 | protected $templateRow; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @var ExtendedTemplateService |
||
| 52 | */ |
||
| 53 | protected $templateService; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var int GET/POST var 'id' |
||
| 57 | */ |
||
| 58 | protected $id; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @var ServerRequestInterface |
||
| 62 | */ |
||
| 63 | protected $request; |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Init, called from parent object |
||
| 67 | * |
||
| 68 | * @param TypoScriptTemplateModuleController $pObj |
||
| 69 | * @param ServerRequestInterface $request |
||
| 70 | */ |
||
| 71 | public function init($pObj, ServerRequestInterface $request) |
||
| 72 | { |
||
| 73 | $this->pObj = $pObj; |
||
| 74 | $this->request = $request; |
||
| 75 | |||
| 76 | // Setting MOD_MENU items as we need them for logging: |
||
| 77 | $this->pObj->MOD_MENU = array_merge($this->pObj->MOD_MENU, $this->modMenu()); |
||
| 78 | $this->pObj->modMenu_dontValidateList .= ',ts_browser_toplevel_setup,ts_browser_toplevel_const,ts_browser_TLKeys_setup,ts_browser_TLKeys_const'; |
||
| 79 | $this->pObj->modMenu_setDefaultList .= ',ts_browser_showComments'; |
||
| 80 | $this->id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0); |
||
| 81 | } |
||
| 82 | |||
| 83 | /** |
||
| 84 | * Mod menu |
||
| 85 | * |
||
| 86 | * @return array |
||
| 87 | */ |
||
| 88 | protected function modMenu() |
||
| 130 | } |
||
| 131 | |||
| 132 | /** |
||
| 133 | * Initialize editor |
||
| 134 | * |
||
| 135 | * Initializes the module. Done in this function because we may need to re-initialize if data is submitted! |
||
| 136 | * |
||
| 137 | * @param int $pageId |
||
| 138 | * @param int $template_uid |
||
| 139 | * @return bool |
||
| 140 | */ |
||
| 141 | protected function initialize_editor($pageId, $template_uid = 0) |
||
| 155 | } |
||
| 156 | |||
| 157 | /** |
||
| 158 | * Main, called from parent object |
||
| 159 | * |
||
| 160 | * @return string |
||
| 161 | */ |
||
| 162 | public function main() |
||
| 163 | { |
||
| 164 | $lang = $this->getLanguageService(); |
||
| 165 | $POST = $this->request->getParsedBody(); |
||
| 166 | // Checking for more than one template an if, set a menu... |
||
| 167 | $manyTemplatesMenu = $this->pObj->templateMenu($this->request); |
||
| 168 | $template_uid = 0; |
||
| 169 | if ($manyTemplatesMenu) { |
||
| 170 | $template_uid = $this->pObj->MOD_SETTINGS['templatesOnPage']; |
||
| 171 | } |
||
| 172 | $bType = $this->pObj->MOD_SETTINGS['ts_browser_type']; |
||
| 173 | $existTemplate = $this->initialize_editor($this->id, $template_uid); |
||
| 174 | // initialize |
||
| 175 | $assigns = []; |
||
| 176 | $assigns['existTemplate'] = $existTemplate; |
||
| 177 | $assigns['tsBrowserType'] = $this->pObj->MOD_SETTINGS['ts_browser_type']; |
||
| 178 | if ($existTemplate) { |
||
| 179 | $assigns['templateRecord'] = $this->templateRow; |
||
| 180 | $assigns['linkWrapTemplateTitle'] = $this->pObj->linkWrapTemplateTitle($this->templateRow['title'], ($bType === 'setup' ? 'config' : 'constants')); |
||
| 181 | $assigns['manyTemplatesMenu'] = $manyTemplatesMenu; |
||
| 182 | |||
| 183 | if (($POST['add_property'] ?? false) || ($POST['update_value'] ?? false) || ($POST['clear_object'] ?? false)) { |
||
| 184 | // add property |
||
| 185 | $line = ''; |
||
| 186 | if (is_array($POST['data'])) { |
||
| 187 | $name = key($POST['data']); |
||
| 188 | if (($POST['data'][$name]['name'] ?? null) !== '') { |
||
| 189 | // Workaround for this special case: User adds a key and submits by pressing the return key. The form however will use "add_property" which is the name of the first submit button in this form. |
||
| 190 | unset($POST['update_value']); |
||
| 191 | $POST['add_property'] = 'Add'; |
||
| 192 | } |
||
| 193 | if ($POST['add_property'] ?? false) { |
||
| 194 | $property = trim($POST['data'][$name]['name']); |
||
| 195 | if (preg_replace('/[^a-zA-Z0-9_\\.]*/', '', $property) != $property) { |
||
| 196 | $badPropertyMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noSpaces') . $lang->getLL('nothingUpdated'), $lang->getLL('badProperty'), FlashMessage::ERROR); |
||
| 197 | $this->addFlashMessage($badPropertyMessage); |
||
| 198 | } else { |
||
| 199 | $pline = $name . '.' . $property . ' = ' . trim($POST['data'][$name]['propertyValue']); |
||
| 200 | $propertyAddedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('propertyAdded')); |
||
| 201 | $this->addFlashMessage($propertyAddedMessage); |
||
| 202 | $line .= LF . $pline; |
||
| 203 | } |
||
| 204 | } elseif ($POST['update_value'] ?? false) { |
||
| 205 | $pline = $name . ' = ' . trim($POST['data'][$name]['value']); |
||
| 206 | $updatedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('valueUpdated')); |
||
| 207 | $this->addFlashMessage($updatedMessage); |
||
| 208 | $line .= LF . $pline; |
||
| 209 | } elseif ($POST['clear_object'] ?? false) { |
||
| 210 | if ($POST['data'][$name]['clearValue'] ?? false) { |
||
| 211 | $pline = $name . ' >'; |
||
| 212 | $objectClearedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('objectCleared')); |
||
| 213 | $this->addFlashMessage($objectClearedMessage); |
||
| 214 | $line .= LF . $pline; |
||
| 215 | } |
||
| 216 | } |
||
| 217 | } |
||
| 218 | if ($line) { |
||
| 219 | $saveId = ($this->templateRow['_ORIG_uid'] ?? false) ?: $this->templateRow['uid'] ?? 0; |
||
| 220 | // Set the data to be saved |
||
| 221 | $recData = []; |
||
| 222 | $field = $bType === 'setup' ? 'config' : 'constants'; |
||
| 223 | $recData['sys_template'][$saveId][$field] = $this->templateRow[$field] . $line; |
||
| 224 | // Create new tce-object |
||
| 225 | $tce = GeneralUtility::makeInstance(DataHandler::class); |
||
| 226 | // Initialize |
||
| 227 | $tce->start($recData, []); |
||
| 228 | // Saved the stuff |
||
| 229 | $tce->process_datamap(); |
||
| 230 | // re-read the template ... |
||
| 231 | $this->initialize_editor($this->id, $template_uid); |
||
| 232 | } |
||
| 233 | } |
||
| 234 | } |
||
| 235 | $tsbr = $this->request->getQueryParams()['tsbr'] ?? null; |
||
| 236 | $update = 0; |
||
| 237 | if (is_array($tsbr)) { |
||
| 238 | // If any plus-signs were clicked, it's registered. |
||
| 239 | $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType] = $this->templateService->ext_depthKeys($tsbr, $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType] ?? []); |
||
| 240 | $update = 1; |
||
| 241 | } |
||
| 242 | if ($POST['Submit'] ?? false) { |
||
| 243 | // If any POST-vars are send, update the condition array |
||
| 244 | $this->pObj->MOD_SETTINGS['tsbrowser_conditions'] = $POST['conditions']; |
||
| 245 | $update = 1; |
||
| 246 | } |
||
| 247 | if ($update) { |
||
| 248 | $this->getBackendUserAuthentication()->pushModuleData('web_ts', $this->pObj->MOD_SETTINGS); |
||
| 249 | } |
||
| 250 | $this->templateService->matchAlternative = $this->pObj->MOD_SETTINGS['tsbrowser_conditions'] ?? []; |
||
| 251 | $this->templateService->matchAlternative[] = 'dummydummydummydummydummydummydummydummydummydummydummy'; |
||
| 252 | // This is just here to make sure that at least one element is in the array so that the tsparser actually uses this array to match. |
||
| 253 | $this->templateService->constantMode = $this->pObj->MOD_SETTINGS['ts_browser_const']; |
||
| 254 | // "sObj" is set by ExtendedTemplateService to edit single keys |
||
| 255 | $sObj = $this->request->getParsedBody()['sObj'] ?? $this->request->getQueryParams()['sObj'] ?? null; |
||
| 256 | if (!empty($sObj) && $this->templateService->constantMode) { |
||
| 257 | $this->templateService->constantMode = 'untouched'; |
||
| 258 | } |
||
| 259 | $this->templateService->regexMode = $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'] ?? ''; |
||
| 260 | $this->templateService->linkObjects = true; |
||
| 261 | $this->templateService->ext_regLinenumbers = true; |
||
| 262 | $this->templateService->ext_regComments = $this->pObj->MOD_SETTINGS['ts_browser_showComments']; |
||
| 263 | $this->templateService->bType = $bType; |
||
| 264 | $this->templateService->generateConfig(); |
||
| 265 | if ($bType === 'setup') { |
||
| 266 | $theSetup = $this->templateService->setup; |
||
| 267 | } else { |
||
| 268 | $theSetup = $this->templateService->setup_constants; |
||
| 269 | } |
||
| 270 | // EDIT A VALUE: |
||
| 271 | $assigns['typoScriptPath'] = $sObj; |
||
| 272 | if (!empty($sObj)) { |
||
| 273 | [$theSetup, $theSetupValue] = $this->templateService->ext_getSetup($theSetup, $sObj); |
||
| 274 | $assigns['theSetupValue'] = $theSetupValue; |
||
| 275 | if ($existTemplate === false) { |
||
| 276 | $noTemplateMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noCurrentTemplate'), $lang->getLL('edit'), FlashMessage::ERROR); |
||
| 277 | $this->addFlashMessage($noTemplateMessage); |
||
| 278 | } |
||
| 279 | // Links: |
||
| 280 | $urlParameters = [ |
||
| 281 | 'id' => $this->id |
||
| 282 | ]; |
||
| 283 | /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */ |
||
| 284 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
| 285 | $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters); |
||
| 286 | $assigns['moduleUrl'] = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters); |
||
| 287 | $assigns['isNotInTopLevelKeyList'] = !isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$sObj]); |
||
| 288 | $assigns['hasProperties'] = !empty($theSetup); |
||
| 289 | if ($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$sObj] ?? false) { |
||
| 290 | $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($sObj) . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0'; |
||
| 291 | } else { |
||
| 292 | if (!empty($theSetup)) { |
||
| 293 | $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($sObj) . ']=1&SET[ts_browser_toplevel_' . $bType . ']=' . rawurlencode($sObj); |
||
| 294 | } |
||
| 295 | } |
||
| 296 | } else { |
||
| 297 | $this->templateService->tsbrowser_depthKeys = $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType] ?? null; |
||
| 298 | if ($this->request->getParsedBody()['search_field'] ?? false) { |
||
| 299 | // If any POST-vars are send, update the condition array |
||
| 300 | $searchString = $this->request->getParsedBody()['search_field']; |
||
| 301 | try { |
||
| 302 | $this->templateService->tsbrowser_depthKeys = |
||
| 303 | $this->templateService->ext_getSearchKeys( |
||
| 304 | $theSetup, |
||
| 305 | '', |
||
| 306 | $searchString, |
||
| 307 | [] |
||
| 308 | ); |
||
| 309 | } catch (Exception $e) { |
||
| 310 | $this->addFlashMessage( |
||
| 311 | GeneralUtility::makeInstance(FlashMessage::class, sprintf($lang->getLL('error.' . $e->getCode()), $searchString), '', FlashMessage::ERROR) |
||
| 312 | ); |
||
| 313 | } |
||
| 314 | } |
||
| 315 | $assigns['hasTsBrowserTypes'] = is_array($this->pObj->MOD_MENU['ts_browser_type'] ?? false) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1; |
||
| 316 | if (is_array($this->pObj->MOD_MENU['ts_browser_type']) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1) { |
||
| 317 | $assigns['browserTypeDropdownMenu'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_type]', $bType, $this->pObj->MOD_MENU['ts_browser_type']); |
||
| 318 | } |
||
| 319 | $assigns['hasTopLevelInObjectList'] = is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType] ?? false) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1; |
||
| 320 | if (is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1) { |
||
| 321 | $assigns['objectListDropdownMenu'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_toplevel_' . $bType . ']', $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType], $this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]); |
||
| 322 | } |
||
| 323 | |||
| 324 | $assigns['regexSearchCheckbox'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_regexsearch]', $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'] ?? false, '', '', 'id="checkTs_browser_regexsearch"'); |
||
| 325 | $assigns['postSearchField'] = $POST['search_field'] ?? null; |
||
| 326 | $theKey = $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType] ?? ''; |
||
| 327 | if (!$theKey || !str_replace('-', '', $theKey)) { |
||
| 328 | $theKey = ''; |
||
| 329 | } |
||
| 330 | [$theSetup, $theSetupValue] = $this->templateService->ext_getSetup($theSetup, $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType] ?? ''); |
||
| 331 | $tree = $this->templateService->ext_getObjTree($theSetup, $theKey, '', '', $theSetupValue, $this->pObj->MOD_SETTINGS['ts_browser_alphaSort'] ?? ''); |
||
| 332 | $tree = $this->templateService->substituteCMarkers($tree); |
||
| 333 | $urlParameters = [ |
||
| 334 | 'id' => $this->id |
||
| 335 | ]; |
||
| 336 | /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */ |
||
| 337 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
| 338 | $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters); |
||
| 339 | // Parser Errors: |
||
| 340 | $pEkey = $bType === 'setup' ? 'config' : 'constants'; |
||
| 341 | $assigns['hasParseErrors'] = !empty($this->templateService->parserErrors[$pEkey]); |
||
| 342 | if (!empty($this->templateService->parserErrors[$pEkey])) { |
||
| 343 | $assigns['showErrorDetailsUri'] = $aHref . '&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TemplateAnalyzerModuleFunctionController&highlightType=' . $bType . '&highlightLine='; |
||
| 344 | $assigns['parseErrors'] = $this->templateService->parserErrors[$pEkey]; |
||
| 345 | } |
||
| 346 | |||
| 347 | if (isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$theKey])) { |
||
| 348 | $assigns['moduleUrlRemoveFromObjectList'] = $aHref . '&addKey[' . $theKey . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0'; |
||
| 349 | } |
||
| 350 | |||
| 351 | $assigns['hasKeySelected'] = $theKey !== ''; |
||
| 352 | |||
| 353 | if ($theKey) { |
||
| 354 | $assigns['treeLabel'] = $theKey; |
||
| 355 | } else { |
||
| 356 | $assigns['rootLLKey'] = $bType === 'setup' ? 'setupRoot' : 'constantRoot'; |
||
| 357 | } |
||
| 358 | $assigns['tsTree'] = $tree; |
||
| 359 | |||
| 360 | // second row options |
||
| 361 | $assigns['isSetupAndCropLinesDisabled'] = $bType === 'setup'; |
||
| 362 | $assigns['checkBoxShowComments'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_showComments]', $this->pObj->MOD_SETTINGS['ts_browser_showComments'] ?? '', '', '', 'id="checkTs_browser_showComments"'); |
||
| 363 | $assigns['checkBoxAlphaSort'] = BackendUtility::getFuncCheck($this->id, 'SET[ts_browser_alphaSort]', $this->pObj->MOD_SETTINGS['ts_browser_alphaSort'] ?? '', '', '', 'id="checkTs_browser_alphaSort"'); |
||
| 364 | if ($bType === 'setup') { |
||
| 365 | $assigns['dropdownDisplayConstants'] = BackendUtility::getDropdownMenu($this->id, 'SET[ts_browser_const]', $this->pObj->MOD_SETTINGS['ts_browser_const'] ?? '', $this->pObj->MOD_MENU['ts_browser_const']); |
||
| 366 | } |
||
| 367 | |||
| 368 | // Conditions: |
||
| 369 | $assigns['hasConditions'] = is_array($this->templateService->sections) && !empty($this->templateService->sections); |
||
| 370 | $activeConditions = 0; |
||
| 371 | if (is_array($this->templateService->sections) && !empty($this->templateService->sections)) { |
||
| 372 | $tsConditions = []; |
||
| 373 | foreach ($this->templateService->sections as $key => $val) { |
||
| 374 | $isSet = (bool)($this->pObj->MOD_SETTINGS['tsbrowser_conditions'][$key] ?? false); |
||
| 375 | if ($isSet) { |
||
| 376 | $activeConditions++; |
||
| 377 | } |
||
| 378 | |||
| 379 | $tsConditions[] = [ |
||
| 380 | 'key' => $key, |
||
| 381 | 'value' => $val, |
||
| 382 | 'label' => $this->templateService->substituteCMarkers(htmlspecialchars($val)), |
||
| 383 | 'isSet' => $isSet |
||
| 384 | ]; |
||
| 385 | } |
||
| 386 | $assigns['tsConditions'] = $tsConditions; |
||
| 387 | } |
||
| 388 | $assigns['activeConditions'] = $activeConditions; |
||
| 389 | // Ending section displayoptions |
||
| 390 | } |
||
| 391 | $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip'); |
||
| 392 | $view = GeneralUtility::makeInstance(StandaloneView::class); |
||
| 393 | $view->setTemplatePathAndFilename('EXT:tstemplate/Resources/Private/Templates/TemplateObjectBrowserModuleFunction.html'); |
||
| 394 | $view->assignMultiple($assigns); |
||
| 395 | |||
| 396 | return $view->render(); |
||
| 397 | } |
||
| 398 | |||
| 399 | /** |
||
| 400 | * Add flash message to queue |
||
| 401 | * |
||
| 402 | * @param FlashMessage $flashMessage |
||
| 403 | */ |
||
| 404 | protected function addFlashMessage(FlashMessage $flashMessage) |
||
| 405 | { |
||
| 406 | $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); |
||
| 407 | $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); |
||
| 408 | $defaultFlashMessageQueue->enqueue($flashMessage); |
||
| 409 | } |
||
| 410 | |||
| 411 | /** |
||
| 412 | * @return LanguageService |
||
| 413 | */ |
||
| 414 | protected function getLanguageService(): LanguageService |
||
| 417 | } |
||
| 418 | |||
| 419 | /** |
||
| 420 | * @return BackendUserAuthentication |
||
| 421 | */ |
||
| 422 | protected function getBackendUserAuthentication(): BackendUserAuthentication |
||
| 425 | } |
||
| 426 | |||
| 427 | /** |
||
| 428 | * @return PageRenderer |
||
| 429 | */ |
||
| 430 | protected function getPageRenderer(): PageRenderer |
||
| 433 | } |
||
| 434 | } |
||
| 435 |