[FEATURE] Custom TypoScript-conditions also in backend
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Configuration / TypoScript / ConditionMatching / ConditionMatcher.php
1 <?php
2 namespace TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Controller\EditDocumentController;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19 use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * Matching TypoScript conditions for backend disposal.
24 *
25 * Used with the TypoScript parser.
26 * Matches browserinfo, IPnumbers for use with templates
27 *
28 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
29 */
30 class ConditionMatcher extends AbstractConditionMatcher {
31
32 /**
33 * Constructor for this class
34 */
35 public function __construct() {}
36
37 /**
38 * Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]"
39 *
40 * @param string $string The condition to match against its criterias.
41 * @return bool Whether the condition matched
42 * @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::parse()
43 */
44 protected function evaluateCondition($string) {
45 list($key, $value) = GeneralUtility::trimExplode('=', $string, FALSE, 2);
46 $result = parent::evaluateConditionCommon($key, $value);
47 if (is_bool($result)) {
48 return $result;
49 } else {
50 switch ($key) {
51 case 'usergroup':
52 $groupList = $this->getGroupList();
53 $values = GeneralUtility::trimExplode(',', $value, TRUE);
54 foreach ($values as $test) {
55 if ($test === '*' || GeneralUtility::inList($groupList, $test)) {
56 return TRUE;
57 }
58 }
59 break;
60 case 'adminUser':
61 if ($this->isUserLoggedIn()) {
62 return !((bool)$value xor $this->isAdminUser());
63 }
64 break;
65 case 'treeLevel':
66 $values = GeneralUtility::trimExplode(',', $value, TRUE);
67 $treeLevel = count($this->rootline) - 1;
68 // If a new page is being edited or saved the treeLevel is higher by one:
69 if ($this->isNewPageWithPageId($this->pageId)) {
70 $treeLevel++;
71 }
72 foreach ($values as $test) {
73 if ($test == $treeLevel) {
74 return TRUE;
75 }
76 }
77 break;
78 case 'PIDupinRootline':
79 case 'PIDinRootline':
80 $values = GeneralUtility::trimExplode(',', $value, TRUE);
81 if ($key == 'PIDinRootline' || !in_array($this->pageId, $values) || $this->isNewPageWithPageId($this->pageId)) {
82 foreach ($values as $test) {
83 foreach ($this->rootline as $rl_dat) {
84 if ($rl_dat['uid'] == $test) {
85 return TRUE;
86 }
87 }
88 }
89 }
90 break;
91 default:
92 $conditionResult = parent::evaluateCustomDefinedCondition($string);
93 if ($conditionResult !== NULL) {
94 return $conditionResult;
95 }
96 }
97 }
98 return FALSE;
99 }
100
101 /**
102 * Returns GP / ENV vars
103 *
104 * @param string $var Identifier
105 * @return mixed The value of the variable pointed to or NULL if variable did not exist
106 * @access private
107 */
108 protected function getVariable($var) {
109 $vars = explode(':', $var, 2);
110 return parent::getVariableCommon($vars);
111 }
112
113 /**
114 * Get the usergroup list of the current user.
115 *
116 * @return string The usergroup list of the current user
117 */
118 protected function getGroupList() {
119 return $this->getBackendUserAuthentication()->groupList;
120 }
121
122 /**
123 * Tries to determine the ID of the page currently processed.
124 * When User/Group TS-Config is parsed when no specific page is handled
125 * (i.e. in the Extension Manager, etc.) this function will return "0", so that
126 * the accordant conditions (e.g. PIDinRootline) will return "FALSE"
127 *
128 * @return int The determined page id or otherwise 0
129 */
130 protected function determinePageId() {
131 $pageId = 0;
132 $editStatement = GeneralUtility::_GP('edit');
133 $commandStatement = GeneralUtility::_GP('cmd');
134 // Determine id from module that was called with an id:
135 if ($id = (int)GeneralUtility::_GP('id')) {
136 $pageId = $id;
137 } elseif (is_array($editStatement)) {
138 list($table, $uidAndAction) = each($editStatement);
139 list($uid, $action) = each($uidAndAction);
140 if ($action === 'edit') {
141 $pageId = $this->getPageIdByRecord($table, $uid);
142 } elseif ($action === 'new') {
143 $pageId = $this->getPageIdByRecord($table, $uid, TRUE);
144 }
145 } elseif (is_array($commandStatement)) {
146 list($table, $uidActionAndTarget) = each($commandStatement);
147 list($uid, $actionAndTarget) = each($uidActionAndTarget);
148 list($action, $target) = each($actionAndTarget);
149 if ($action === 'delete') {
150 $pageId = $this->getPageIdByRecord($table, $uid);
151 } elseif ($action === 'copy' || $action === 'move') {
152 $pageId = $this->getPageIdByRecord($table, $target, TRUE);
153 }
154 }
155 return $pageId;
156 }
157
158 /**
159 * Gets the properties for the current page.
160 *
161 * @return array The properties for the current page.
162 */
163 protected function getPage() {
164 $pageId = isset($this->pageId) ? $this->pageId : $this->determinePageId();
165 return BackendUtility::getRecord('pages', $pageId);
166 }
167
168 /**
169 * Gets the page id by a record.
170 *
171 * @param string $table Name of the table
172 * @param int $id Id of the accordant record
173 * @param bool $ignoreTable Whether to ignore the page, if TRUE a positive
174 * @return int Id of the page the record is persisted on
175 */
176 protected function getPageIdByRecord($table, $id, $ignoreTable = FALSE) {
177 $pageId = 0;
178 $id = (int)$id;
179 if ($table && $id) {
180 if (($ignoreTable || $table === 'pages') && $id >= 0) {
181 $pageId = $id;
182 } else {
183 $record = BackendUtility::getRecordWSOL($table, abs($id), '*', '', FALSE);
184 $pageId = $record['pid'];
185 }
186 }
187 return $pageId;
188 }
189
190 /**
191 * Determine if record of table 'pages' with the given $pid is currently created in TCEforms.
192 * This information is required for conditions in BE for PIDupinRootline.
193 *
194 * @param int $pageId The pid the check for as parent page
195 * @return bool TRUE if the is currently a new page record being edited with $pid as uid of the parent page
196 */
197 protected function isNewPageWithPageId($pageId) {
198 if (isset($GLOBALS['SOBE']) && $GLOBALS['SOBE'] instanceof EditDocumentController) {
199 $pageId = (int)$pageId;
200 $elementsData = $GLOBALS['SOBE']->elementsData;
201 $data = $GLOBALS['SOBE']->data;
202 // If saving a new page record:
203 if (is_array($data) && isset($data['pages']) && is_array($data['pages'])) {
204 foreach ($data['pages'] as $uid => $fields) {
205 if (strpos($uid, 'NEW') === 0 && $fields['pid'] == $pageId) {
206 return TRUE;
207 }
208 }
209 }
210 // If editing a new page record (not saved yet):
211 if (is_array($elementsData)) {
212 foreach ($elementsData as $element) {
213 if ($element['cmd'] === 'new' && $element['table'] === 'pages') {
214 if ($element['pid'] < 0) {
215 $pageRecord = BackendUtility::getRecord('pages', abs($element['pid']), 'pid');
216 $element['pid'] = $pageRecord['pid'];
217 }
218 if ($element['pid'] == $pageId) {
219 return TRUE;
220 }
221 }
222 }
223 }
224 }
225 return FALSE;
226 }
227
228 /**
229 * Determines the rootline for the current page.
230 *
231 * @return array The rootline for the current page.
232 */
233 protected function determineRootline() {
234 $pageId = isset($this->pageId) ? $this->pageId : $this->determinePageId();
235 return BackendUtility::BEgetRootLine($pageId, '', TRUE);
236 }
237
238 /**
239 * Get the id of the current user.
240 *
241 * @return int The id of the current user
242 */
243 protected function getUserId() {
244 return $this->getBackendUserAuthentication()->user['uid'];
245 }
246
247 /**
248 * Determines if a user is logged in.
249 *
250 * @return bool Determines if a user is logged in
251 */
252 protected function isUserLoggedIn() {
253 return (bool)$this->getBackendUserAuthentication()->user['uid'];
254 }
255
256 /**
257 * Determines whether the current user is admin.
258 *
259 * @return bool Whether the current user is admin
260 */
261 protected function isAdminUser() {
262 return $this->getBackendUserAuthentication()->isAdmin();
263 }
264
265 /**
266 * Set/write a log message.
267 *
268 * @param string $message The log message to set/write
269 * @return void
270 */
271 protected function log($message) {
272 if (is_object($this->getBackendUserAuthentication())) {
273 $this->getBackendUserAuthentication()->writelog(3, 0, 1, 0, $message, array());
274 }
275 }
276
277 /**
278 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
279 */
280 protected function getBackendUserAuthentication() {
281 return $GLOBALS['BE_USER'];
282 }
283
284 }