TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
FormManagerController.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Form\Controller;
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 
18 use Symfony\Component\Yaml\Yaml;
31 use TYPO3\CMS\Form\Exception as FormException;
34 
41 {
42 
48  protected $defaultViewObjectName = BackendTemplateView::class;
49 
57  public function initializeReferencesAction()
58  {
59  $this->defaultViewObjectName = JsonView::class;
60  }
61 
68  public function indexAction()
69  {
70  $this->registerDocheaderButtons();
71  $this->view->getModuleTemplate()->setModuleName($this->request->getPluginName() . '_' . $this->request->getControllerName());
72  $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue());
73 
74  $this->view->assign('forms', $this->getAvailableFormDefinitions());
75  $this->view->assign('stylesheets', $this->resolveResourcePaths($this->formSettings['formManager']['stylesheets']));
76  $this->view->assign('dynamicRequireJsModules', $this->formSettings['formManager']['dynamicRequireJsModules']);
77  $this->view->assign('formManagerAppInitialData', $this->getFormManagerAppInitialData());
78  if (!empty($this->formSettings['formManager']['javaScriptTranslationFile'])) {
79  $this->getPageRenderer()->addInlineLanguageLabelFile($this->formSettings['formManager']['javaScriptTranslationFile']);
80  }
81  }
82 
94  public function createAction(string $formName, string $templatePath, string $prototypeName, string $savePath): string
95  {
96  if (!$this->isValidTemplatePath($prototypeName, $templatePath)) {
97  throw new FormException(sprintf('The template path "%s" is not allowed', $templatePath), 1329233410);
98  }
99  if (empty($formName)) {
100  throw new FormException(sprintf('No form name', $templatePath), 1472312204);
101  }
102 
103  $templatePath = GeneralUtility::getFileAbsFileName($templatePath);
104  $form = Yaml::parse(file_get_contents($templatePath));
105  $form['label'] = $formName;
106  $form['identifier'] = $this->formPersistenceManager->getUniqueIdentifier($this->convertFormNameToIdentifier($formName));
107  $form['prototypeName'] = $prototypeName;
108 
109  $formPersistenceIdentifier = $this->formPersistenceManager->getUniquePersistenceIdentifier($form['identifier'], $savePath);
110  $this->formPersistenceManager->save($formPersistenceIdentifier, $form);
111 
112  return $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor');
113  }
114 
124  public function duplicateAction(string $formName, string $formPersistenceIdentifier, string $savePath): string
125  {
126  $formToDuplicate = $this->formPersistenceManager->load($formPersistenceIdentifier);
127  $formToDuplicate['label'] = $formName;
128  $formToDuplicate['identifier'] = $this->formPersistenceManager->getUniqueIdentifier($this->convertFormNameToIdentifier($formName));
129 
130  $formPersistenceIdentifier = $this->formPersistenceManager->getUniquePersistenceIdentifier($formToDuplicate['identifier'], $savePath);
131  $this->formPersistenceManager->save($formPersistenceIdentifier, $formToDuplicate);
132 
133  return $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor');
134  }
135 
143  public function referencesAction(string $formPersistenceIdentifier)
144  {
145  $this->view->assign('references', $this->getProcessedReferencesRows($formPersistenceIdentifier));
146  $this->view->assign('formPersistenceIdentifier', $formPersistenceIdentifier);
147  // referencesAction uses the extbase JsonView::class.
148  // That's why we have to set the view variables in this way.
149  $this->view->setVariablesToRender([
150  'references',
151  'formPersistenceIdentifier'
152  ]);
153  }
154 
163  public function deleteAction(string $formPersistenceIdentifier)
164  {
165  if (
166  empty($this->getReferences($formPersistenceIdentifier))
167  && strpos($formPersistenceIdentifier, 'EXT:') === false
168  ) {
169  $this->formPersistenceManager->delete($formPersistenceIdentifier);
170  } else {
171  $this->addFlashMessage(
172  TranslationService::getInstance()->translate(
173  $this->formSettings['formManager']['controller']['deleteAction']['errorMessage'],
174  [$formPersistenceIdentifier],
175  $this->formSettings['formManager']['translationFile'],
176  null,
177  $this->formSettings['formManager']['controller']['deleteAction']['errorMessage']
178  ),
179  TranslationService::getInstance()->translate(
180  $this->formSettings['formManager']['controller']['deleteAction']['errorTitle'],
181  null,
182  $this->formSettings['formManager']['translationFile'],
183  null,
184  $this->formSettings['formManager']['controller']['deleteAction']['errorTitle']
185  ),
187  true
188  );
189  }
190  $this->redirect('index');
191  }
192 
203  protected function getAccessibleFormStorageFolders(): array
204  {
205  $preparedAccessibleFormStorageFolders = [];
206  foreach ($this->formPersistenceManager->getAccessibleFormStorageFolders() as $identifier => $folder) {
207  $preparedAccessibleFormStorageFolders[] = [
208  'label' => $folder->getName(),
209  'value' => $identifier
210  ];
211  }
212  return $preparedAccessibleFormStorageFolders;
213  }
214 
221  protected function getFormManagerAppInitialData(): string
222  {
223  $formManagerAppInitialData = [
224  'selectablePrototypesConfiguration' => $this->formSettings['formManager']['selectablePrototypesConfiguration'],
225  'accessibleFormStorageFolders' => $this->getAccessibleFormStorageFolders(),
226  'endpoints' => [
227  'create' => $this->controllerContext->getUriBuilder()->uriFor('create'),
228  'duplicate' => $this->controllerContext->getUriBuilder()->uriFor('duplicate'),
229  'delete' => $this->controllerContext->getUriBuilder()->uriFor('delete'),
230  'references' => $this->controllerContext->getUriBuilder()->uriFor('references')
231  ],
232  ];
233 
234  $formManagerAppInitialData = ArrayUtility::reIndexNumericArrayKeysRecursive($formManagerAppInitialData);
235  $formManagerAppInitialData = TranslationService::getInstance()->translateValuesRecursive(
236  $formManagerAppInitialData,
237  $this->formSettings['formManager']['translationFile']
238  );
239  return json_encode($formManagerAppInitialData);
240  }
241 
247  protected function getAvailableFormDefinitions(): array
248  {
249  $availableFormDefinitions = [];
250  foreach ($this->formPersistenceManager->listForms() as $formDefinition) {
251  $referenceCount = count($this->getReferences($formDefinition['persistenceIdentifier']));
252  $formDefinition['referenceCount'] = $referenceCount;
253  $availableFormDefinitions[] = $formDefinition;
254  }
255  return $availableFormDefinitions;
256  }
257 
266  protected function getProcessedReferencesRows(string $persistenceIdentifier): array
267  {
268  if (empty($persistenceIdentifier)) {
269  throw new \InvalidArgumentException('$persistenceIdentifier must not be empty.', 1477071939);
270  }
271 
272  $references = [];
273  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
274 
275  $referenceRows = $this->getReferences($persistenceIdentifier);
276  foreach ($referenceRows as &$referenceRow) {
277  $record = $this->getRecord($referenceRow['tablename'], $referenceRow['recuid']);
278  if (!$record) {
279  continue;
280  }
281  $pageRecord = $this->getRecord('pages', $record['pid']);
282  $urlParameters = [
283  'edit' => [
284  $referenceRow['tablename'] => [
285  $referenceRow['recuid'] => 'edit'
286  ]
287  ],
288  'returnUrl' => $this->getModuleUrl('web_FormFormbuilder')
289  ];
290 
291  $references[] = [
292  'recordPageTitle' => is_array($pageRecord) ? $this->getRecordTitle('pages', $pageRecord) : '',
293  'recordTitle' => $this->getRecordTitle($referenceRow['tablename'], $record, true),
294  'recordIcon' => $iconFactory->getIconForRecord($referenceRow['tablename'], $record, Icon::SIZE_SMALL)->render(),
295  'recordUid' => $referenceRow['recuid'],
296  'recordEditUrl' => $this->getModuleUrl('record_edit', $urlParameters),
297  ];
298  }
299  return $references;
300  }
301 
310  protected function getReferences(string $persistenceIdentifier): array
311  {
312  if (empty($persistenceIdentifier)) {
313  throw new \InvalidArgumentException('$persistenceIdentifier must not be empty.', 1472238493);
314  }
315 
316  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
317  $referenceRows = $queryBuilder
318  ->select('*')
319  ->from('sys_refindex')
320  ->where(
321  $queryBuilder->expr()->eq('deleted', 0),
322  $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier', \PDO::PARAM_STR)),
323  $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($persistenceIdentifier, \PDO::PARAM_STR)),
324  $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter('tt_content', \PDO::PARAM_STR))
325  )
326  ->execute()
327  ->fetchAll();
328  return $referenceRows;
329  }
330 
342  protected function isValidTemplatePath(string $prototypeName, string $templatePath): bool
343  {
344  $isValid = false;
345  foreach ($this->formSettings['formManager']['selectablePrototypesConfiguration'] as $prototypesConfiguration) {
346  if ($prototypesConfiguration['identifier'] !== $prototypeName) {
347  continue;
348  }
349  foreach ($prototypesConfiguration['newFormTemplates'] as $templatesConfiguration) {
350  if ($templatesConfiguration['templatePath'] !== $templatePath) {
351  continue;
352  }
353  $isValid = true;
354  break;
355  }
356  }
357 
358  $templatePath = GeneralUtility::getFileAbsFileName($templatePath);
359  if (!is_file($templatePath)) {
360  $isValid = false;
361  }
362 
363  return $isValid;
364  }
365 
371  protected function registerDocheaderButtons()
372  {
374  $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
375  $currentRequest = $this->request;
376  $moduleName = $currentRequest->getPluginName();
377  $getVars = $this->request->getArguments();
378 
379  $mayMakeShortcut = $this->getBackendUser()->mayMakeShortcut();
380  if ($mayMakeShortcut) {
381  $extensionName = $currentRequest->getControllerExtensionName();
382  if (count($getVars) === 0) {
383  $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName);
384  $getVars = ['id', 'M', $modulePrefix];
385  }
386 
387  $shortcutButton = $buttonBar->makeShortcutButton()
388  ->setModuleName($moduleName)
389  ->setDisplayName($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:module.shortcut_name'))
390  ->setGetVariables($getVars);
391  $buttonBar->addButton($shortcutButton);
392  }
393 
394  if (isset($getVars['action']) && $getVars['action'] !== 'index') {
395  $backButton = $buttonBar->makeLinkButton()
396  ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:back'))
397  ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL))
398  ->setHref($this->getModuleUrl($moduleName));
399  $buttonBar->addButton($backButton);
400  } else {
401  $addFormButton = $buttonBar->makeLinkButton()
402  ->setDataAttributes(['identifier' => 'newForm'])
403  ->setHref('#')
404  ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.create_new_form'))
405  ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-document-new', Icon::SIZE_SMALL));
406  $buttonBar->addButton($addFormButton, ButtonBar::BUTTON_POSITION_LEFT);
407  }
408  }
409 
416  protected function convertFormNameToIdentifier(string $formName): string
417  {
418  $formIdentifier = preg_replace('/[^a-zA-Z0-9-_]/', '', $formName);
419  $formIdentifier = lcfirst($formIdentifier);
420  return $formIdentifier;
421  }
422 
430  protected function getRecord(string $table, int $uid)
431  {
432  return BackendUtility::getRecord($table, $uid);
433  }
434 
443  protected function getRecordTitle(string $table, array $row, bool $prep = false): string
444  {
445  return BackendUtility::getRecordTitle($table, $row, $prep);
446  }
447 
455  protected function getModuleUrl(string $moduleName, array $urlParameters = []): string
456  {
457  return BackendUtility::getModuleUrl($moduleName, $urlParameters);
458  }
459 
466  {
467  return $GLOBALS['BE_USER'];
468  }
469 
475  protected function getLanguageService(): LanguageService
476  {
477  return $GLOBALS['LANG'];
478  }
479 
485  protected function getPageRenderer(): PageRenderer
486  {
487  return GeneralUtility::makeInstance(PageRenderer::class);
488  }
489 }
getProcessedReferencesRows(string $persistenceIdentifier)
getModuleUrl(string $moduleName, array $urlParameters=[])
isValidTemplatePath(string $prototypeName, string $templatePath)
redirect($actionName, $controllerName=null, $extensionName=null, array $arguments=null, $pageUid=null, $delay=0, $statusCode=303)
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
referencesAction(string $formPersistenceIdentifier)
static getRecord($table, $uid, $fields= '*', $where= '', $useDeleteClause=true)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
addFlashMessage($messageBody, $messageTitle= '', $severity=\TYPO3\CMS\Core\Messaging\AbstractMessage::OK, $storeInSession=true)
createAction(string $formName, string $templatePath, string $prototypeName, string $savePath)
static getFileAbsFileName($filename, $_=null, $_2=null)
duplicateAction(string $formName, string $formPersistenceIdentifier, string $savePath)
getRecordTitle(string $table, array $row, bool $prep=false)