1<?php 2 3/* 4 * This file is part of the TYPO3 CMS project. 5 * 6 * It is free software; you can redistribute it and/or modify it under 7 * the terms of the GNU General Public License, either version 2 8 * of the License, or any later version. 9 * 10 * For the full copyright and license information, please read the 11 * LICENSE.txt file that was distributed with this source code. 12 * 13 * The TYPO3 project - inspiring people to share! 14 */ 15 16namespace TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching; 17 18use TYPO3\CMS\Backend\Utility\BackendUtility; 19use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher; 20use TYPO3\CMS\Core\Context\Context; 21use TYPO3\CMS\Core\Utility\GeneralUtility; 22 23/** 24 * Matching TypoScript conditions for backend disposal. 25 * 26 * Used with the TypoScript parser. 27 * Matches browserinfo, IP numbers for use with templates 28 */ 29class ConditionMatcher extends AbstractConditionMatcher 30{ 31 /** 32 * @var Context 33 */ 34 protected $context; 35 36 public function __construct(Context $context = null, int $pageId = null, array $rootLine = null) 37 { 38 $this->context = $context ?? GeneralUtility::makeInstance(Context::class); 39 $this->pageId = $pageId ?? $this->determinePageId(); 40 if ($rootLine === null) { 41 $rootLine = BackendUtility::BEgetRootLine($this->pageId, '', true); 42 ksort($rootLine); 43 } 44 $this->rootline = $rootLine; 45 $this->initializeExpressionLanguageResolver(); 46 } 47 48 protected function updateExpressionLanguageVariables(): void 49 { 50 $treeLevel = $this->rootline ? count($this->rootline) - 1 : 0; 51 $tree = new \stdClass(); 52 $tree->level = $treeLevel; 53 $tree->rootLine = $this->rootline; 54 $tree->rootLineIds = array_column($this->rootline, 'uid'); 55 $tree->rootLineParentIds = array_slice(array_column($this->rootline, 'pid'), 2); 56 57 $backendUserAspect = $this->context->getAspect('backend.user'); 58 $backend = new \stdClass(); 59 $backend->user = new \stdClass(); 60 $backend->user->isAdmin = $backendUserAspect->get('isAdmin'); 61 $backend->user->isLoggedIn = $backendUserAspect->get('isLoggedIn'); 62 $backend->user->userId = $backendUserAspect->get('id'); 63 $backend->user->userGroupList = implode(',', $backendUserAspect->get('groupIds')); 64 65 $workspaceAspect = $this->context->getAspect('workspace'); 66 $workspace = new \stdClass(); 67 $workspace->workspaceId = $workspaceAspect->get('id'); 68 $workspace->isLive = $workspaceAspect->get('isLive'); 69 $workspace->isOffline = $workspaceAspect->get('isOffline'); 70 71 $this->expressionLanguageResolverVariables = [ 72 'tree' => $tree, 73 'backend' => $backend, 74 'workspace' => $workspace, 75 'page' => BackendUtility::getRecord('pages', $this->pageId ?? $this->determinePageId()) ?: [], 76 ]; 77 } 78 79 /** 80 * Tries to determine the ID of the page currently processed. 81 * When User/Group TS-Config is parsed when no specific page is handled 82 * (i.e. in the Extension Manager, etc.) this function will return "0", so that 83 * the accordant conditions (e.g. PIDinRootline) will return "FALSE" 84 * 85 * @return int The determined page id or otherwise 0 86 */ 87 private function determinePageId(): int 88 { 89 $pageId = 0; 90 $editStatement = GeneralUtility::_GP('edit'); 91 $commandStatement = GeneralUtility::_GP('cmd'); 92 // Determine id from module that was called with an id: 93 if ($id = (int)GeneralUtility::_GP('id')) { 94 $pageId = $id; 95 } elseif (is_array($editStatement)) { 96 $table = key($editStatement); 97 $uidAndAction = current($editStatement); 98 $uid = key($uidAndAction); 99 $action = current($uidAndAction); 100 if ($action === 'edit') { 101 $pageId = $this->getPageIdByRecord($table, $uid); 102 } elseif ($action === 'new') { 103 $pageId = $this->getPageIdByRecord($table, $uid, true); 104 } 105 } elseif (is_array($commandStatement)) { 106 $table = key($commandStatement); 107 $uidActionAndTarget = current($commandStatement); 108 $uid = (int)key($uidActionAndTarget); 109 $actionAndTarget = current($uidActionAndTarget); 110 $action = key($actionAndTarget); 111 $target = current($actionAndTarget); 112 if ($action === 'delete') { 113 $pageId = $this->getPageIdByRecord($table, $uid); 114 } elseif ($action === 'copy' || $action === 'move') { 115 $pageId = $this->getPageIdByRecord($table, (int)($target['target'] ?? $target), true); 116 } 117 } 118 return $pageId; 119 } 120 121 /** 122 * Gets the page id by a record. 123 * 124 * @param string $table Name of the table 125 * @param int $id Id of the accordant record 126 * @param bool $ignoreTable Whether to ignore the page, if TRUE a positive 127 * @return int Id of the page the record is persisted on 128 */ 129 private function getPageIdByRecord($table, $id, $ignoreTable = false): int 130 { 131 $pageId = 0; 132 $id = (int)$id; 133 if ($table && $id) { 134 if (($ignoreTable || $table === 'pages') && $id >= 0) { 135 $pageId = $id; 136 } else { 137 $record = BackendUtility::getRecordWSOL($table, abs($id), '*', '', false); 138 $pageId = (int)$record['pid']; 139 } 140 } 141 return $pageId; 142 } 143} 144