‪TYPO3CMS  ‪main
EditableRestriction.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
23 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
28 
30 {
36  protected ‪$allowedFields = [];
37 
43  protected ‪$allowedLanguages = [];
44 
50  protected ‪$explicitAllowFields = [];
51 
55  protected ‪$queryBuilder;
56 
61  public function ‪__construct(array $searchFields, QueryBuilder ‪$queryBuilder)
62  {
63  $this->allowedFields = $this->‪getAllowedFieldsForCurrentUser($searchFields);
64  $this->allowedLanguages = $this->‪getAllowedLanguagesForCurrentUser();
65  foreach ($searchFields as $table => ‪$fields) {
66  if ($table !== 'pages' && (‪$GLOBALS['TCA'][$table]['ctrl']['type'] ?? false)) {
67  $type = ‪$GLOBALS['TCA'][$table]['ctrl']['type'];
68  $fieldConfig = ‪$GLOBALS['TCA'][$table]['columns'][$type]['config'];
69  // Check for items
70  if ($fieldConfig['type'] === 'select'
71  && is_array($fieldConfig['items'] ?? false)
72  && isset($fieldConfig['authMode'])
73  ) {
74  $this->explicitAllowFields[$table][$type] = $this->‪getExplicitAllowTypesForCurrentUser(
75  $table,
76  $type
77  );
78  }
79  }
80  }
81  $this->queryBuilder = ‪$queryBuilder;
82  }
83 
87  protected function ‪getAllowedLanguagesForCurrentUser(): array
88  {
89  // Comma-separated list of allowed languages, e.g. "0,1". If empty, user has access to all languages.
90  ‪$allowedLanguages = trim(‪$GLOBALS['BE_USER']->groupData['allowed_languages'] ?? '');
91  if (‪$allowedLanguages === '') {
92  return [];
93  }
94 
95  return GeneralUtility::intExplode(',', ‪$allowedLanguages);
96  }
97 
104  protected function ‪getExplicitAllowTypesForCurrentUser(string $table, string $typeField): array
105  {
106  $allowDenyFieldTypes = [];
107  $fieldConfig = ‪$GLOBALS['TCA'][$table]['columns'][$typeField]['config'];
108  foreach ($fieldConfig['items'] as $iVal) {
109  $itemIdentifier = (string)$iVal['value'];
110  if ($itemIdentifier === '--div--') {
111  continue;
112  }
113  if (‪$GLOBALS['BE_USER']->checkAuthMode($table, $typeField, $itemIdentifier)) {
114  $allowDenyFieldTypes[] = $itemIdentifier;
115  }
116  }
117  return $allowDenyFieldTypes;
118  }
119 
127  protected function ‪getAllowedFieldsForCurrentUser(array $searchFields = []): array
128  {
129  if (!$searchFields) {
130  return [];
131  }
132 
133  ‪$allowedFields = [];
134 
135  foreach ($searchFields as $table => $fieldList) {
136  if (!‪$GLOBALS['BE_USER']->isAdmin() && !‪$GLOBALS['BE_USER']->check('tables_modify', $table)) {
137  // table not allowed
138  continue;
139  }
140  foreach ($fieldList as $field) {
141  $isExcludeField = ‪$GLOBALS['TCA'][$table]['columns'][$field]['exclude'] ?? false;
142  if (!‪$GLOBALS['BE_USER']->isAdmin()
143  && $isExcludeField
144  && !‪$GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $field)) {
145  continue;
146  }
147  ‪$allowedFields[$table][$field] = true;
148  }
149  }
150  return ‪$allowedFields;
151  }
152 
153  public function ‪buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
154  {
155  $constraints = [];
156 
157  if ($this->allowedFields) {
158  $constraints = [
159  $expressionBuilder->or(
160  // broken link is in page and page is editable
161  $expressionBuilder->and(
162  $expressionBuilder->eq(
163  'tx_linkvalidator_link.table_name',
164  $this->queryBuilder->quote('pages')
165  ),
167  ),
168  // OR broken link is in content and content is editable
169  $expressionBuilder->and(
170  $expressionBuilder->neq(
171  'tx_linkvalidator_link.table_name',
172  $this->queryBuilder->quote('pages')
173  ),
175  )
176  ),
177  ];
178 
179  // check if fields are editable
180  $additionalWhere = [];
181  foreach ($this->allowedFields as $table => ‪$fields) {
182  foreach (‪$fields as $field => $value) {
183  $additionalWhere[] = $expressionBuilder->and(
184  $expressionBuilder->eq(
185  'tx_linkvalidator_link.table_name',
186  $this->queryBuilder->quote($table)
187  ),
188  $expressionBuilder->eq(
189  'tx_linkvalidator_link.field',
190  $this->queryBuilder->quote($field)
191  )
192  );
193  }
194  }
195  if ($additionalWhere) {
196  $constraints[] = $expressionBuilder->or(...$additionalWhere);
197  }
198  } else {
199  // add a constraint that will always return zero records because there are NO allowed fields
200  $constraints[] = $expressionBuilder->isNull('tx_linkvalidator_link.table_name');
201  }
202 
203  foreach ($this->explicitAllowFields as $table => $field) {
204  $additionalWhere = [];
205  $additionalWhere[] = $expressionBuilder->and(
206  $expressionBuilder->eq(
207  'tx_linkvalidator_link.table_name',
208  $this->queryBuilder->quote($table)
209  ),
210  $expressionBuilder->in(
211  'tx_linkvalidator_link.element_type',
212  $this->queryBuilder->quoteArrayBasedValueListToStringList(array_unique(current($field) ?: []))
213  )
214  );
215  $additionalWhere[] = $expressionBuilder->neq(
216  'tx_linkvalidator_link.table_name',
217  $this->queryBuilder->quote($table)
218  );
219  $constraints[] = $expressionBuilder->or(...$additionalWhere);
220  }
221 
222  if ($this->allowedLanguages) {
223  $additionalWhere = [];
224  foreach ($this->allowedLanguages as $langId) {
225  $additionalWhere[] = $expressionBuilder->or(
226  $expressionBuilder->eq(
227  'tx_linkvalidator_link.language',
228  $this->queryBuilder->quote($langId, ‪Connection::PARAM_INT)
229  ),
230  $expressionBuilder->eq(
231  'tx_linkvalidator_link.language',
232  $this->queryBuilder->quote(-1, ‪Connection::PARAM_INT)
233  )
234  );
235  }
236  $constraints[] = $expressionBuilder->or(...$additionalWhere);
237  }
238  // If allowed languages is empty: all languages are allowed, so no constraint in this case
239 
240  return $expressionBuilder->and(...$constraints);
241  }
242 }
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\in
‪in(string $fieldName, $value)
Definition: ExpressionBuilder.php:233
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\getAllowedFieldsForCurrentUser
‪getAllowedFieldsForCurrentUser(array $searchFields=[])
Definition: EditableRestriction.php:123
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:50
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder
Definition: ExpressionBuilder.php:40
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\getExplicitAllowTypesForCurrentUser
‪string[] getExplicitAllowTypesForCurrentUser(string $table, string $typeField)
Definition: EditableRestriction.php:100
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionInterface
Definition: QueryRestrictionInterface.php:27
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\eq
‪eq(string $fieldName, $value)
Definition: ExpressionBuilder.php:100
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\or
‪or(CompositeExpression|string|null ... $expressions)
Definition: ExpressionBuilder.php:77
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\and
‪and(CompositeExpression|string|null ... $expressions)
Definition: ExpressionBuilder.php:69
‪TYPO3\CMS\Linkvalidator\QueryRestrictions
Definition: EditableRestriction.php:18
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression
Definition: CompositeExpression.php:27
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\isNull
‪isNull(string $fieldName)
Definition: ExpressionBuilder.php:171
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\$allowedLanguages
‪array $allowedLanguages
Definition: EditableRestriction.php:41
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\buildExpression
‪buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder)
Definition: EditableRestriction.php:149
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction
Definition: EditableRestriction.php:30
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:39
‪TYPO3\CMS\Core\Type\Bitmask\Permission\CONTENT_EDIT
‪const CONTENT_EDIT
Definition: Permission.php:55
‪TYPO3\CMS\Core\Database\Query\QueryHelper\stripLogicalOperatorPrefix
‪static string stripLogicalOperatorPrefix(string $constraint)
Definition: QueryHelper.php:171
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_EDIT
‪const PAGE_EDIT
Definition: Permission.php:40
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\$queryBuilder
‪QueryBuilder $queryBuilder
Definition: EditableRestriction.php:51
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\getAllowedLanguagesForCurrentUser
‪getAllowedLanguagesForCurrentUser()
Definition: EditableRestriction.php:83
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\__construct
‪__construct(array $searchFields, QueryBuilder $queryBuilder)
Definition: EditableRestriction.php:57
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\$allowedFields
‪array $allowedFields
Definition: EditableRestriction.php:35
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\$explicitAllowFields
‪array $explicitAllowFields
Definition: EditableRestriction.php:47
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\neq
‪neq(string $fieldName, $value)
Definition: ExpressionBuilder.php:117