‪TYPO3CMS  10.4
FormSlugAjaxController.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 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
28 
35 {
36 
64  public function ‪suggestAction(ServerRequestInterface $request): ResponseInterface
65  {
66  $this->‪checkRequest($request);
67 
68  $queryParameters = $request->getParsedBody() ?? [];
69  $values = $queryParameters['values'];
70  $mode = $queryParameters['mode'];
71  $tableName = (string)($queryParameters['tableName'] ?? '');
72  $pid = (int)$queryParameters['pageId'];
73  $parentPageId = (int)$queryParameters['parentPageId'];
74  $recordId = (int)$queryParameters['recordId'];
75  $languageId = (int)$queryParameters['language'];
76  $fieldName = $queryParameters['fieldName'];
77 
78  $fieldConfig = ‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'] ?? [];
79  $row = (array)‪BackendUtility::getRecord($tableName, $recordId);
80  $recordType = ‪BackendUtility::getTCAtypeValue($tableName, $row);
81  $columnsOverridesConfigOfField = ‪$GLOBALS['TCA'][$tableName]['types'][$recordType]['columnsOverrides'][$fieldName]['config'] ?? null;
82  if ($columnsOverridesConfigOfField) {
83  ‪ArrayUtility::mergeRecursiveWithOverrule($fieldConfig, $columnsOverridesConfigOfField);
84  }
85  if (empty($fieldConfig)) {
86  throw new \RuntimeException(
87  'No valid field configuration for table ' . $tableName . ' field name ' . $fieldName . ' found.',
88  1535379534
89  );
90  }
91 
92  $evalInfo = !empty($fieldConfig['eval']) ? ‪GeneralUtility::trimExplode(',', $fieldConfig['eval'], true) : [];
93  $hasToBeUniqueInDb = in_array('unique', $evalInfo, true);
94  $hasToBeUniqueInSite = in_array('uniqueInSite', $evalInfo, true);
95  $hasToBeUniqueInPid = in_array('uniqueInPid', $evalInfo, true);
96 
97  $hasConflict = false;
98 
99  $recordData = $values;
100  if (!isset($recordData['uid'])) {
101  $recordData['uid'] = $recordId;
102  }
103  $recordData['pid'] = $pid;
104  if (!empty(‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
105  $recordData[‪$GLOBALS['TCA'][$tableName]['ctrl']['languageField']] = $languageId;
106  }
107  if ($tableName === 'pages' && empty($recordData['is_siteroot'])) {
108  $recordData['is_siteroot'] = $row['is_siteroot'];
109  }
110 
111  $slug = GeneralUtility::makeInstance(SlugHelper::class, $tableName, $fieldName, $fieldConfig);
112  if ($mode === 'auto') {
113  // New page - Feed incoming values to generator
114  $proposal = $slug->generate($recordData, $pid);
115  } elseif ($mode === 'recreate') {
116  $proposal = $slug->generate($recordData, $parentPageId);
117  } elseif ($mode === 'manual') {
118  // Existing record - Fetch full record and only validate against the new "slug" field.
119  $proposal = $slug->sanitize($values['manual']);
120  } else {
121  throw new \RuntimeException('mode must be either "auto", "recreate" or "manual"', 1535835666);
122  }
123 
124  $state = ‪RecordStateFactory::forName($tableName)
125  ->fromArray($recordData, $pid, $recordId);
126  if ($hasToBeUniqueInDb && !$slug->isUniqueInTable($proposal, $state)) {
127  $hasConflict = true;
128  $proposal = $slug->buildSlugForUniqueInTable($proposal, $state);
129  }
130  if ($hasToBeUniqueInSite && !$slug->isUniqueInSite($proposal, $state)) {
131  $hasConflict = true;
132  $proposal = $slug->buildSlugForUniqueInSite($proposal, $state);
133  }
134  if ($hasToBeUniqueInPid && !$slug->isUniqueInPid($proposal, $state)) {
135  $hasConflict = true;
136  $proposal = $slug->buildSlugForUniqueInPid($proposal, $state);
137  }
138 
139  return new ‪JsonResponse([
140  'hasConflicts' => $hasConflict,
141  'manual' => $values['manual'] ?? '',
142  'proposal' => $proposal,
143  ]);
144  }
145 
151  protected function ‪checkRequest(ServerRequestInterface $request): bool
152  {
153  $queryParameters = $request->getParsedBody() ?? [];
154  $expectedHash = GeneralUtility::hmac(
155  implode(
156  '',
157  [
158  $queryParameters['tableName'],
159  $queryParameters['pageId'],
160  $queryParameters['recordId'],
161  $queryParameters['language'],
162  $queryParameters['fieldName'],
163  $queryParameters['command'],
164  $queryParameters['parentPageId'],
165  ]
166  ),
167  __CLASS__
168  );
169  if (!hash_equals($expectedHash, $queryParameters['signature'])) {
170  throw new \InvalidArgumentException(
171  'HMAC could not be verified',
172  1535137045
173  );
174  }
175  return true;
176  }
177 }
‪TYPO3\CMS\Backend\Controller\FormSlugAjaxController\suggestAction
‪ResponseInterface suggestAction(ServerRequestInterface $request)
Definition: FormSlugAjaxController.php:64
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory
Definition: RecordStateFactory.php:26
‪TYPO3\CMS\Core\DataHandling\SlugHelper
Definition: SlugHelper.php:42
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪TYPO3\CMS\Core\Http\JsonResponse
Definition: JsonResponse.php:26
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Controller\AbstractFormEngineAjaxController
Definition: AbstractFormEngineAjaxController.php:34
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Backend\Controller
Definition: AbstractFormEngineAjaxController.php:18
‪TYPO3\CMS\Backend\Controller\FormSlugAjaxController
Definition: FormSlugAjaxController.php:35
‪TYPO3\CMS\Backend\Controller\FormSlugAjaxController\checkRequest
‪bool checkRequest(ServerRequestInterface $request)
Definition: FormSlugAjaxController.php:151
‪TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory\forName
‪static static forName(string $name)
Definition: RecordStateFactory.php:35
‪TYPO3\CMS\Backend\Utility\BackendUtility\getTCAtypeValue
‪static string getTCAtypeValue($table, $row)
Definition: BackendUtility.php:636