‪TYPO3CMS  11.5
SiteLanguageContainer.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 
25 
32 {
33  private const ‪FOREIGN_TABLE = 'site_language';
34  private const ‪FOREIGN_FIELD = 'languageId';
35 
36  protected array ‪$inlineData;
38 
44  protected ‪$defaultFieldInformation = [
45  'tcaDescription' => [
46  'renderType' => 'tcaDescription',
47  ],
48  ];
49 
57  {
58  parent::__construct(‪$nodeFactory, ‪$data);
59  $this->inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
60  }
61 
62  public function ‪render(): array
63  {
64  $this->inlineData = $this->data['inlineData'];
65 
66  $this->inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
67 
68  $row = $this->data['databaseRow'];
69  $parameterArray = $this->data['parameterArray'];
70  $config = $parameterArray['fieldConf']['config'];
71  $resultArray = $this->‪initializeResultArray();
72 
73  // Add the current inline job to the structure stack
74  $this->inlineStackProcessor->pushStableStructureItem([
75  'table' => $this->data['tableName'],
76  'uid' => $row['uid'],
77  'field' => $this->data['fieldName'],
78  'config' => $config,
79  ]);
80 
81  // Hand over original returnUrl to SiteInlineAjaxController. Needed if opening for instance a
82  // nested element in a new view to then go back to the original returnUrl and not the url of
83  // the site inline ajax controller.
84  $config['originalReturnUrl'] = $this->data['returnUrl'];
85 
86  // e.g. data[site][1][languages]
87  $nameForm = $this->inlineStackProcessor->getCurrentStructureFormPrefix();
88  // e.g. data-0-site-1-languages
89  $nameObject = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
90  // e.g. array('table' => 'site', 'uid' => '1', 'field' => 'languages', 'config' => array())
91  $top = $this->inlineStackProcessor->getStructureLevel(0);
92 
93  $this->inlineData['config'][$nameObject] = [
94  'table' => ‪self::FOREIGN_TABLE,
95  ];
96 
97  $configJson = (string)json_encode($config);
98  $this->inlineData['config'][$nameObject . '-' . ‪self::FOREIGN_TABLE] = [
99  'min' => $config['minitems'],
100  'max' => $config['maxitems'],
101  'sortable' => false,
102  'top' => [
103  'table' => $top['table'],
104  'uid' => $top['uid'],
105  ],
106  'context' => [
107  'config' => $configJson,
108  'hmac' => GeneralUtility::hmac($configJson, 'InlineContext'),
109  ],
110  ];
111  $this->inlineData['nested'][$nameObject] = $this->data['tabAndInlineStack'];
112 
113  $uniqueIds = [];
114  foreach ($parameterArray['fieldConf']['children'] as $children) {
115  $value = (int)($children['databaseRow'][self::FOREIGN_FIELD]['0'] ?? 0);
116  if (isset($children['databaseRow']['uid'])) {
117  $uniqueIds[$children['databaseRow']['uid']] = $value;
118  }
119  }
120 
121  $uniquePossibleRecords = $config['uniquePossibleRecords'] ?? [];
122  $possibleRecordsUidToTitle = [];
123  foreach ($uniquePossibleRecords as $possibleRecord) {
124  $possibleRecordsUidToTitle[$possibleRecord[1]] = $possibleRecord[0];
125  }
126  $this->inlineData['unique'][$nameObject . '-' . ‪self::FOREIGN_TABLE] = [
127  // Usually "max" would the the number of possible records. However, since
128  // we also allow new languages to be created, we just use the maxitems value.
129  'max' => $config['maxitems'],
130  // "used" must be a string array
131  'used' => array_map('strval', $uniqueIds),
132  'table' => ‪self::FOREIGN_TABLE,
133  'elTable' => ‪self::FOREIGN_TABLE,
134  'field' => ‪self::FOREIGN_FIELD,
135  'possible' => $possibleRecordsUidToTitle,
136  ];
137 
138  $resultArray['inlineData'] = ‪$this->inlineData;
139 
140  $fieldInformationResult = $this->‪renderFieldInformation();
141  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
142  $selectorOptions = $childRecordUids = $childHtml = [];
143 
144  foreach ($config['uniquePossibleRecords'] ?? [] as $record) {
145  // Do not add the PHP_INT_MAX placeholder or already configured languages
146  if ($record[1] !== PHP_INT_MAX && !in_array($record[1], $uniqueIds, true)) {
147  $selectorOptions[] = ['value' => (string)$record[1], 'label' => (string)$record[0]];
148  }
149  }
150 
151  foreach ($this->data['parameterArray']['fieldConf']['children'] as $children) {
152  $children['inlineParentUid'] = $row['uid'];
153  $children['inlineFirstPid'] = $this->data['inlineFirstPid'];
154  $children['inlineParentConfig'] = $config;
155  $children['inlineData'] = ‪$this->inlineData;
156  $children['inlineStructure'] = $this->inlineStackProcessor->getStructure();
157  $children['inlineExpandCollapseStateArray'] = $this->data['inlineExpandCollapseStateArray'];
158  $children['renderType'] = 'inlineRecordContainer';
159  $childResult = $this->nodeFactory->create($children)->render();
160  $childHtml[] = $childResult['html'];
161  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $childResult, false);
162  if (isset($children['databaseRow']['uid'])) {
163  $childRecordUids[] = $children['databaseRow']['uid'];
164  }
165  }
166 
167  $view = GeneralUtility::makeInstance(StandaloneView::class);
168  $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
169  'EXT:backend/Resources/Private/Templates/SiteLanguageContainer.html'
170  ));
171  $view->assignMultiple([
172  'nameObject' => $nameObject,
173  'nameForm' => $nameForm,
174  'formGroupAttributes' => GeneralUtility::implodeAttributes([
175  'class' => 'form-group',
176  'id' => $nameObject,
177  'data-uid' => (string)$row['uid'],
178  'data-local-table' => (string)$top['table'],
179  'data-local-field' => (string)$top['field'],
180  'data-foreign-table' => self::FOREIGN_TABLE,
181  'data-object-group' => $nameObject . '-' . self::FOREIGN_TABLE,
182  'data-form-field' => $nameForm,
183  'data-appearance' => (string)json_encode($config['appearance'] ?? ''),
184  ], true),
185  'fieldInformation' => $fieldInformationResult['html'],
186  'selectorConfigutation' => [
187  'identifier' => $nameObject . '-' . self::FOREIGN_TABLE . '_selector',
188  'size' => $config['size'] ?? 4,
189  'options' => $selectorOptions,
190  ],
191  'inlineRecords' => [
192  'identifier' => $nameObject . '_records',
193  'title' => trim($parameterArray['fieldConf']['label'] ?? ''),
194  'records' => implode(PHP_EOL, $childHtml),
195  ],
196  'childRecordUids' => implode(',', $childRecordUids),
197  'validationRules' => $this->‪getValidationDataAsJsonString([
198  'type' => 'inline',
199  'minitems' => $config['minitems'] ?? null,
200  'maxitems' => $config['maxitems'] ?? null,
201  ]),
202  ]);
203 
204  $resultArray['html'] = $view->render();
205  $resultArray['requireJsModules'][] = ‪JavaScriptModuleInstruction::forRequireJS('TYPO3/CMS/Backend/FormEngine/Container/SiteLanguageContainer');
206 
207  return $resultArray;
208  }
209 }
‪TYPO3\CMS\Backend\Form\AbstractNode\mergeChildReturnIntoExistingResult
‪array mergeChildReturnIntoExistingResult(array $existing, array $childReturn, bool $mergeHtml=true)
Definition: AbstractNode.php:120
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer\FOREIGN_TABLE
‪const FOREIGN_TABLE
Definition: SiteLanguageContainer.php:33
‪TYPO3\CMS\Backend\Form\AbstractNode\initializeResultArray
‪array initializeResultArray()
Definition: AbstractNode.php:91
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer\$inlineData
‪array $inlineData
Definition: SiteLanguageContainer.php:36
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer\render
‪render()
Definition: SiteLanguageContainer.php:61
‪TYPO3\CMS\Backend\Form\AbstractNode\$nodeFactory
‪NodeFactory $nodeFactory
Definition: AbstractNode.php:36
‪TYPO3\CMS\Backend\Form\Container
Definition: AbstractContainer.php:16
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer\$inlineStackProcessor
‪InlineStackProcessor $inlineStackProcessor
Definition: SiteLanguageContainer.php:37
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction
Definition: JavaScriptModuleInstruction.php:23
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction\forRequireJS
‪static self forRequireJS(string $name, string $exportName=null)
Definition: JavaScriptModuleInstruction.php:49
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer\$defaultFieldInformation
‪array $defaultFieldInformation
Definition: SiteLanguageContainer.php:43
‪TYPO3\CMS\Backend\Form\AbstractNode\getValidationDataAsJsonString
‪string getValidationDataAsJsonString(array $config)
Definition: AbstractNode.php:156
‪TYPO3\CMS\Backend\Form\AbstractNode\$data
‪array $data
Definition: AbstractNode.php:43
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer
Definition: AbstractContainer.php:28
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer
Definition: SiteLanguageContainer.php:32
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer\__construct
‪__construct(NodeFactory $nodeFactory, array $data)
Definition: SiteLanguageContainer.php:55
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\renderFieldInformation
‪array renderFieldInformation()
Definition: AbstractContainer.php:34
‪TYPO3\CMS\Backend\Form\Container\SiteLanguageContainer\FOREIGN_FIELD
‪const FOREIGN_FIELD
Definition: SiteLanguageContainer.php:34
‪TYPO3\CMS\Backend\Form\NodeFactory
Definition: NodeFactory.php:37
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:31
‪TYPO3\CMS\Backend\Form\InlineStackProcessor
Definition: InlineStackProcessor.php:30
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50