‪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 
22 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
27 
29 {
35  protected ‪$allowedFields = [];
36 
42  protected ‪$allowedLanguages = [];
43 
49  protected ‪$explicitAllowFields = [];
50 
54  protected ‪$queryBuilder;
55 
60  public function ‪__construct(array $searchFields, QueryBuilder ‪$queryBuilder)
61  {
62  $this->allowedFields = $this->‪getAllowedFieldsForCurrentUser($searchFields);
63  $this->allowedLanguages = $this->‪getAllowedLanguagesForCurrentUser();
64  foreach ($searchFields as $table => ‪$fields) {
65  if ($table !== 'pages' && (‪$GLOBALS['TCA'][$table]['ctrl']['type'] ?? false)) {
66  $type = ‪$GLOBALS['TCA'][$table]['ctrl']['type'];
67  $fieldConfig = ‪$GLOBALS['TCA'][$table]['columns'][$type]['config'];
68  // Check for items
69  if ($fieldConfig['type'] === 'select'
70  && is_array($fieldConfig['items'] ?? false)
71  && isset($fieldConfig['authMode'])
72  ) {
73  $this->explicitAllowFields[$table][$type] = $this->‪getExplicitAllowTypesForCurrentUser(
74  $table,
75  $type
76  );
77  }
78  }
79  }
80  $this->queryBuilder = ‪$queryBuilder;
81  }
82 
86  protected function ‪getAllowedLanguagesForCurrentUser(): array
87  {
88  // Comma-separated list of allowed languages, e.g. "0,1". If empty, user has access to all languages.
89  ‪$allowedLanguages = trim(‪$GLOBALS['BE_USER']->groupData['allowed_languages'] ?? '');
90  if (‪$allowedLanguages === '') {
91  return [];
92  }
93 
95  }
96 
103  protected function ‪getExplicitAllowTypesForCurrentUser(string $table, string $typeField): array
104  {
105  $allowDenyFieldTypes = [];
106  $fieldConfig = ‪$GLOBALS['TCA'][$table]['columns'][$typeField]['config'];
107  foreach ($fieldConfig['items'] as $iVal) {
108  $itemIdentifier = (string)$iVal['value'];
109  if ($itemIdentifier === '--div--') {
110  continue;
111  }
112  if (‪$GLOBALS['BE_USER']->checkAuthMode($table, $typeField, $itemIdentifier)) {
113  $allowDenyFieldTypes[] = $itemIdentifier;
114  }
115  }
116  return $allowDenyFieldTypes;
117  }
118 
126  protected function ‪getAllowedFieldsForCurrentUser(array $searchFields = []): array
127  {
128  if (!$searchFields) {
129  return [];
130  }
131 
132  ‪$allowedFields = [];
133 
134  foreach ($searchFields as $table => $fieldList) {
135  if (!‪$GLOBALS['BE_USER']->isAdmin() && !‪$GLOBALS['BE_USER']->check('tables_modify', $table)) {
136  // table not allowed
137  continue;
138  }
139  foreach ($fieldList as $field) {
140  $isExcludeField = ‪$GLOBALS['TCA'][$table]['columns'][$field]['exclude'] ?? false;
141  if (!‪$GLOBALS['BE_USER']->isAdmin()
142  && $isExcludeField
143  && !‪$GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $field)) {
144  continue;
145  }
146  ‪$allowedFields[$table][$field] = true;
147  }
148  }
149  return ‪$allowedFields;
150  }
151 
152  public function ‪buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder): CompositeExpression
153  {
154  $constraints = [];
155 
156  if ($this->allowedFields) {
157  $constraints = [
158  $expressionBuilder->or(
159  // broken link is in page and page is editable
160  $expressionBuilder->and(
161  $expressionBuilder->eq(
162  'tx_linkvalidator_link.table_name',
163  $this->queryBuilder->quote('pages')
164  ),
166  ),
167  // OR broken link is in content and content is editable
168  $expressionBuilder->and(
169  $expressionBuilder->neq(
170  'tx_linkvalidator_link.table_name',
171  $this->queryBuilder->quote('pages')
172  ),
174  )
175  ),
176  ];
177 
178  // check if fields are editable
179  $additionalWhere = [];
180  foreach ($this->allowedFields as $table => ‪$fields) {
181  foreach (‪$fields as $field => $value) {
182  $additionalWhere[] = $expressionBuilder->and(
183  $expressionBuilder->eq(
184  'tx_linkvalidator_link.table_name',
185  $this->queryBuilder->quote((string)$table)
186  ),
187  $expressionBuilder->eq(
188  'tx_linkvalidator_link.field',
189  $this->queryBuilder->quote((string)$field)
190  )
191  );
192  }
193  }
194  if ($additionalWhere) {
195  $constraints[] = $expressionBuilder->or(...$additionalWhere);
196  }
197  } else {
198  // add a constraint that will always return zero records because there are NO allowed fields
199  $constraints[] = $expressionBuilder->isNull('tx_linkvalidator_link.table_name');
200  }
201 
202  foreach ($this->explicitAllowFields as $table => $field) {
203  $additionalWhere = [];
204  $additionalWhere[] = $expressionBuilder->and(
205  $expressionBuilder->eq(
206  'tx_linkvalidator_link.table_name',
207  $this->queryBuilder->quote((string)$table)
208  ),
209  $expressionBuilder->in(
210  'tx_linkvalidator_link.element_type',
211  $this->queryBuilder->quoteArrayBasedValueListToStringList(array_unique(current($field) ?: []))
212  )
213  );
214  $additionalWhere[] = $expressionBuilder->neq(
215  'tx_linkvalidator_link.table_name',
216  $this->queryBuilder->quote((string)$table)
217  );
218  $constraints[] = $expressionBuilder->or(...$additionalWhere);
219  }
220 
221  if ($this->allowedLanguages) {
222  $additionalWhere = [];
223  foreach ($this->allowedLanguages as $langId) {
224  $additionalWhere[] = $expressionBuilder->or(
225  $expressionBuilder->eq(
226  'tx_linkvalidator_link.language',
227  $this->queryBuilder->quote((string)$langId)
228  ),
229  $expressionBuilder->eq(
230  'tx_linkvalidator_link.language',
231  $this->queryBuilder->quote('-1')
232  )
233  );
234  }
235  $constraints[] = $expressionBuilder->or(...$additionalWhere);
236  }
237  // If allowed languages is empty: all languages are allowed, so no constraint in this case
238 
239  return $expressionBuilder->and(...$constraints);
240  }
241 }
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\in
‪in(string $fieldName, $value)
Definition: ExpressionBuilder.php:227
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\getAllowedFieldsForCurrentUser
‪getAllowedFieldsForCurrentUser(array $searchFields=[])
Definition: EditableRestriction.php:122
‪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:99
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionInterface
Definition: QueryRestrictionInterface.php:27
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\or
‪or(CompositeExpression|\Doctrine\DBAL\Query\Expression\CompositeExpression|string|null ... $expressions)
Definition: ExpressionBuilder.php:59
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\eq
‪eq(string $fieldName, $value)
Definition: ExpressionBuilder.php:84
‪$fields
‪$fields
Definition: pages.php:5
‪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:155
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\$allowedLanguages
‪array $allowedLanguages
Definition: EditableRestriction.php:40
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\buildExpression
‪buildExpression(array $queriedTables, ExpressionBuilder $expressionBuilder)
Definition: EditableRestriction.php:148
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction
Definition: EditableRestriction.php:29
‪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\Database\Query\Expression\ExpressionBuilder\and
‪and(CompositeExpression|\Doctrine\DBAL\Query\Expression\CompositeExpression|string|null ... $expressions,)
Definition: ExpressionBuilder.php:50
‪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:50
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\getAllowedLanguagesForCurrentUser
‪getAllowedLanguagesForCurrentUser()
Definition: EditableRestriction.php:82
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\__construct
‪__construct(array $searchFields, QueryBuilder $queryBuilder)
Definition: EditableRestriction.php:56
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static list< int > intExplode(string $delimiter, string $string, bool $removeEmptyValues=false)
Definition: GeneralUtility.php:756
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\$allowedFields
‪array $allowedFields
Definition: EditableRestriction.php:34
‪TYPO3\CMS\Linkvalidator\QueryRestrictions\EditableRestriction\$explicitAllowFields
‪array $explicitAllowFields
Definition: EditableRestriction.php:46
‪TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder\neq
‪neq(string $fieldName, $value)
Definition: ExpressionBuilder.php:101