예제 #1
0
 /**
  * Adds localizations or synchronizes the locations of all child records.
  * Handle AJAX calls to localize all records of a parent, localize a single record or to synchronize with the original language parent.
  *
  * @param ServerRequestInterface $request the incoming request
  * @param ResponseInterface $response the empty response
  * @return ResponseInterface the filled response
  */
 public function synchronizeLocalizeAction(ServerRequestInterface $request, ResponseInterface $response)
 {
     $ajaxArguments = isset($request->getParsedBody()['ajax']) ? $request->getParsedBody()['ajax'] : $request->getQueryParams()['ajax'];
     $domObjectId = $ajaxArguments[0];
     $type = $ajaxArguments[1];
     /** @var InlineStackProcessor $inlineStackProcessor */
     $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
     // Parse the DOM identifier (string), add the levels to the structure stack (array), load the TCA config:
     $inlineStackProcessor->initializeByParsingDomObjectIdString($domObjectId);
     $inlineStackProcessor->injectAjaxConfiguration($ajaxArguments['context']);
     $inlineFirstPid = $this->getInlineFirstPidFromDomObjectId($domObjectId);
     $jsonArray = false;
     if ($type === 'localize' || $type === 'synchronize' || MathUtility::canBeInterpretedAsInteger($type)) {
         // Parent, this table embeds the child table
         $parent = $inlineStackProcessor->getStructureLevel(-1);
         $parentFieldName = $parent['field'];
         // Child, a record from this table should be rendered
         $child = $inlineStackProcessor->getUnstableStructure();
         $formDataCompilerInputForParent = ['vanillaUid' => (int) $parent['uid'], 'command' => 'edit', 'tableName' => $parent['table'], 'databaseRow' => ['uid' => (int) $parent['uid']], 'inlineFirstPid' => $inlineFirstPid, 'columnsToProcess' => [$parentFieldName], 'inlineStructure' => $inlineStackProcessor->getStructure(), 'inlineCompileExistingChildren' => false];
         /** @var TcaDatabaseRecord $formDataGroup */
         $formDataGroup = GeneralUtility::makeInstance(InlineParentRecord::class);
         /** @var FormDataCompiler $formDataCompiler */
         $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
         $parentData = $formDataCompiler->compile($formDataCompilerInputForParent);
         $parentConfig = $parentData['processedTca']['columns'][$parentFieldName]['config'];
         $oldItemList = $parentData['databaseRow'][$parentFieldName];
         $cmd = array();
         $cmd[$parent['table']][$parent['uid']]['inlineLocalizeSynchronize'] = $parent['field'] . ',' . $type;
         /** @var $tce DataHandler */
         $tce = GeneralUtility::makeInstance(DataHandler::class);
         $tce->stripslashes_values = false;
         $tce->start(array(), $cmd);
         $tce->process_cmdmap();
         $newItemList = $tce->registerDBList[$parent['table']][$parent['uid']][$parentFieldName];
         $jsonArray = array('data' => '', 'stylesheetFiles' => [], 'scriptCall' => []);
         $nameObject = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($inlineFirstPid);
         $nameObjectForeignTable = $nameObject . '-' . $child['table'];
         $oldItems = FormEngineUtility::getInlineRelatedRecordsUidArray($oldItemList);
         $newItems = FormEngineUtility::getInlineRelatedRecordsUidArray($newItemList);
         // Set the items that should be removed in the forms view:
         $removedItems = array_diff($oldItems, $newItems);
         foreach ($removedItems as $childUid) {
             $jsonArray['scriptCall'][] = 'inline.deleteRecord(' . GeneralUtility::quoteJSvalue($nameObjectForeignTable . '-' . $childUid) . ', {forceDirectRemoval: true});';
         }
         $localizedItems = array_diff($newItems, $oldItems);
         foreach ($localizedItems as $childUid) {
             $childData = $this->compileChild($parentData, $parentFieldName, (int) $childUid);
             $childData['inlineParentUid'] = (int) $parent['uid'];
             // @todo: needed?
             $childData['inlineStructure'] = $inlineStackProcessor->getStructure();
             // @todo: needed?
             $childData['inlineExpandCollapseStateArray'] = $parentData['inlineExpandCollapseStateArray'];
             $childData['renderType'] = 'inlineRecordContainer';
             $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
             $childResult = $nodeFactory->create($childData)->render();
             $jsonArray = $this->mergeChildResultIntoJsonResult($jsonArray, $childResult);
             // Get the name of the field used as foreign selector (if any):
             $foreignSelector = isset($parentConfig['foreign_selector']) && $parentConfig['foreign_selector'] ? $parentConfig['foreign_selector'] : false;
             $selectedValue = $foreignSelector ? GeneralUtility::quoteJSvalue($childData['databaseRow'][$foreignSelector]) : 'null';
             if (is_array($selectedValue)) {
                 $selectedValue = $selectedValue[0];
             }
             $jsonArray['scriptCall'][] = 'inline.memorizeAddRecord(' . GeneralUtility::quoteJSvalue($nameObjectForeignTable) . ', ' . GeneralUtility::quoteJSvalue($childUid) . ', null, ' . $selectedValue . ');';
             // Remove possible virtual records in the form which showed that a child records could be localized:
             $transOrigPointerFieldName = $GLOBALS['TCA'][$childData['table']]['ctrl']['transOrigPointerField'];
             if (isset($childData['databaseRow'][$transOrigPointerFieldName]) && $childData['databaseRow'][$transOrigPointerFieldName]) {
                 $transOrigPointerField = $childData['databaseRow'][$transOrigPointerFieldName];
                 if (is_array($transOrigPointerField)) {
                     $transOrigPointerField = $transOrigPointerField[0];
                 }
                 $jsonArray['scriptCall'][] = 'inline.fadeAndRemove(' . GeneralUtility::quoteJSvalue($nameObjectForeignTable . '-' . $transOrigPointerField . '_div') . ');';
             }
             if (!empty($childResult['html'])) {
                 array_unshift($jsonArray['scriptCall'], 'inline.domAddNewRecord(\'bottom\', ' . GeneralUtility::quoteJSvalue($nameObject . '_records') . ', ' . GeneralUtility::quoteJSvalue($nameObjectForeignTable) . ', json.data);');
             }
         }
     }
     $response->getBody()->write(json_encode($jsonArray));
     return $response;
 }
 /**
  * Gets the related records of the embedding item, this could be 1:n, m:n.
  *
  * @param string $table The table name of the record
  * @param string $itemList The list of related child records
  * @return array The records related to the parent item
  */
 protected function getRelatedRecordsArray($table, $itemList)
 {
     $records = array();
     $itemArray = FormEngineUtility::getInlineRelatedRecordsUidArray($itemList);
     // Perform modification of the selected items array:
     foreach ($itemArray as $uid) {
         // Get the records for this uid using \TYPO3\CMS\Backend\Form\DataPreprocessor
         if ($record = $this->getRecord($table, $uid)) {
             $records[$uid] = $record;
         }
     }
     return $records;
 }
예제 #3
0
 /**
  * Handle AJAX calls to localize all records of a parent, localize a single record or to synchronize with the original language parent.
  *
  * @param string $type Defines the type 'localize' or 'synchronize' (string) or a single uid to be localized (int)
  * @param int $inlineFirstPid Inline first pid
  * @return array An array to be used for JSON
  */
 protected function renderInlineSynchronizeLocalizeRecords($type, $inlineFirstPid)
 {
     $jsonArray = FALSE;
     if (GeneralUtility::inList('localize,synchronize', $type) || MathUtility::canBeInterpretedAsInteger($type)) {
         $inlineRelatedRecordResolver = GeneralUtility::makeInstance(InlineRelatedRecordResolver::class);
         // The parent level:
         $parent = $this->inlineStackProcessor->getStructureLevel(-1);
         $current = $this->inlineStackProcessor->getUnstableStructure();
         $parentRecord = $inlineRelatedRecordResolver->getRecord($parent['table'], $parent['uid']);
         $cmd = array();
         $cmd[$parent['table']][$parent['uid']]['inlineLocalizeSynchronize'] = $parent['field'] . ',' . $type;
         /** @var $tce \TYPO3\CMS\Core\DataHandling\DataHandler */
         $tce = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
         $tce->stripslashes_values = FALSE;
         $tce->start(array(), $cmd);
         $tce->process_cmdmap();
         $oldItemList = $parentRecord[$parent['field']];
         $newItemList = $tce->registerDBList[$parent['table']][$parent['uid']][$parent['field']];
         $jsonArray = array('scriptCall' => array());
         $nameObject = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($inlineFirstPid);
         $nameObjectForeignTable = $nameObject . '-' . $current['table'];
         // Get the name of the field pointing to the original record:
         $transOrigPointerField = $GLOBALS['TCA'][$current['table']]['ctrl']['transOrigPointerField'];
         // Get the name of the field used as foreign selector (if any):
         $foreignSelector = isset($parent['config']['foreign_selector']) && $parent['config']['foreign_selector'] ? $parent['config']['foreign_selector'] : FALSE;
         // Convert lists to array with uids of child records:
         $oldItems = FormEngineUtility::getInlineRelatedRecordsUidArray($oldItemList);
         $newItems = FormEngineUtility::getInlineRelatedRecordsUidArray($newItemList);
         // Determine the items that were localized or localized:
         $removedItems = array_diff($oldItems, $newItems);
         $localizedItems = array_diff($newItems, $oldItems);
         // Set the items that should be removed in the forms view:
         foreach ($removedItems as $item) {
             $jsonArray['scriptCall'][] = 'inline.deleteRecord(' . GeneralUtility::quoteJSvalue($nameObjectForeignTable . '-' . $item) . ', {forceDirectRemoval: true});';
         }
         // Set the items that should be added in the forms view:
         $html = '';
         $resultArray = NULL;
         // @todo: This should be another container ...
         foreach ($localizedItems as $item) {
             $row = $inlineRelatedRecordResolver->getRecord($current['table'], $item);
             $selectedValue = $foreignSelector ? GeneralUtility::quoteJSvalue($row[$foreignSelector]) : 'null';
             $options = $this->getConfigurationOptionsForChildElements();
             $options['databaseRow'] = array('uid' => $parent['uid']);
             $options['inlineFirstPid'] = $inlineFirstPid;
             $options['inlineRelatedRecordToRender'] = $row;
             $options['inlineRelatedRecordConfig'] = $parent['config'];
             $options['inlineStructure'] = $this->inlineStackProcessor->getStructure();
             $options['isAjaxContext'] = TRUE;
             $options['renderType'] = 'inlineRecordContainer';
             $childArray = $this->nodeFactory->create($options)->render();
             $html .= $childArray['html'];
             $childArray['html'] = '';
             // @todo: Obsolete if a container and copied from AbstractContainer for now
             if ($resultArray === NULL) {
                 $resultArray = $childArray;
             } else {
                 if (!empty($childArray['extJSCODE'])) {
                     $resultArray['extJSCODE'] .= LF . $childArray['extJSCODE'];
                 }
                 foreach ($childArray['additionalJavaScriptPost'] as $value) {
                     $resultArray['additionalJavaScriptPost'][] = $value;
                 }
                 foreach ($childArray['additionalJavaScriptSubmit'] as $value) {
                     $resultArray['additionalJavaScriptSubmit'][] = $value;
                 }
                 if (!empty($childArray['inlineData'])) {
                     $resultArrayInlineData = $resultArray['inlineData'];
                     $childInlineData = $childArray['inlineData'];
                     ArrayUtility::mergeRecursiveWithOverrule($resultArrayInlineData, $childInlineData);
                     $resultArray['inlineData'] = $resultArrayInlineData;
                 }
             }
             $jsonArray['scriptCall'][] = 'inline.memorizeAddRecord(' . GeneralUtility::quoteJSvalue($nameObjectForeignTable) . ', ' . GeneralUtility::quoteJSvalue($item) . ', null, ' . $selectedValue . ');';
             // Remove possible virtual records in the form which showed that a child records could be localized:
             if (isset($row[$transOrigPointerField]) && $row[$transOrigPointerField]) {
                 $jsonArray['scriptCall'][] = 'inline.fadeAndRemove(' . GeneralUtility::quoteJSvalue($nameObjectForeignTable . '-' . $row[$transOrigPointerField] . '_div') . ');';
             }
         }
         if (!empty($html)) {
             $jsonArray['data'] = $html;
             array_unshift($jsonArray['scriptCall'], 'inline.domAddNewRecord(\'bottom\', ' . GeneralUtility::quoteJSvalue($nameObject . '_records') . ', ' . GeneralUtility::quoteJSvalue($nameObjectForeignTable) . ', json.data);');
         }
         $this->mergeResult($resultArray);
         $jsonArray = $this->getInlineAjaxCommonScriptCalls($jsonArray, $parent['config'], $inlineFirstPid);
     }
     return $jsonArray;
 }