Skip to content

Commit b00475f

Browse files
committed
Make data handler generic and working on localization
1 parent 563219c commit b00475f

1 file changed

Lines changed: 106 additions & 26 deletions

File tree

Classes/Hooks/DataHandlerHook.php

Lines changed: 106 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Hoogi91\Spreadsheets\Hooks;
66

7+
use Hoogi91\Spreadsheets\Domain\ValueObject\DsnValueObject;
78
use TYPO3\CMS\Backend\Utility\BackendUtility;
89
use TYPO3\CMS\Core\Database\ConnectionPool;
910
use TYPO3\CMS\Core\DataHandling\DataHandler;
@@ -17,10 +18,38 @@ class DataHandlerHook
1718
*/
1819
private array $records = [];
1920

21+
/**
22+
* @var array<string, array<string, array<string, array<string>>>>
23+
*/
24+
private array $activationTypes = [];
25+
2026
public function __construct(
2127
private readonly FileRepository $fileRepository,
2228
private readonly ConnectionPool $connectionPool
2329
) {
30+
foreach ($GLOBALS['TCA'] as $table => $tca) {
31+
$table = (string)$table;
32+
foreach ($tca['columns'] ?? [] as $column => $conf) {
33+
if (
34+
isset($conf['config']['renderType'], $conf['config']['uploadField'])
35+
&& $conf['config']['renderType'] === 'spreadsheetInput'
36+
) {
37+
$this->activationTypes[$table]['*'][(string)$conf['config']['uploadField']][] = $column;
38+
}
39+
}
40+
41+
foreach ($GLOBALS['TCA'][$table]['types'] as $CType => $type) {
42+
$CType = (string)$CType;
43+
foreach ($type['columnsOverrides'] as $column => $conf) {
44+
if (
45+
isset($conf['config']['renderType'], $conf['config']['uploadField'])
46+
&& $conf['config']['renderType'] === 'spreadsheetInput'
47+
) {
48+
$this->activationTypes[$table][$CType][(string)$conf['config']['uploadField']][] = $column;
49+
}
50+
}
51+
}
52+
}
2453
}
2554

2655
/**
@@ -37,56 +66,107 @@ public function processDatamap_afterDatabaseOperations( // @codingStandardsIgnor
3766
array $fieldArray,
3867
DataHandler $dataHandler
3968
): void {
40-
// skip processing for unknown uid, wrong table, status or not updated assets
69+
// skip processing for not found uid or irrelevant status
4170
$uid = $dataHandler->substNEWwithIDs[$id] ?? (is_int($id) ? $id : null);
42-
if (
43-
$uid === null
44-
|| $table !== 'tt_content'
45-
|| !array_key_exists('tx_spreadsheets_assets', $fieldArray)
46-
|| !in_array($status, ['new', 'update'], true)
47-
) {
71+
if ($uid === null || !is_string($table) || !in_array($status, ['new', 'update'], true)) {
4872
return;
4973
}
5074

51-
// skip if not spreadsheet table or bodytext is already filled
52-
$CType = $fieldArray['CType'] ?? $this->getBackendRecordField($uid, 'CType');
53-
if (!in_array($CType, ['spreadsheets_table', 'spreadsheets_tabs'], true)) {
75+
// ignore if handler should not process for table and/or CType
76+
$CType = $fieldArray['CType'] ?? $this->getBackendRecordField($uid, $table, 'CType');
77+
if (!isset($this->activationTypes[$table]['*']) && !isset($this->activationTypes[$table][$CType])) {
5478
return;
5579
}
5680

57-
// truncate bodytext after update if assets have been removed
58-
if ($fieldArray['tx_spreadsheets_assets'] === 0) {
59-
if ($status === 'update') {
60-
$this->connectionPool
61-
->getConnectionForTable('tt_content')
62-
->update('tt_content', ['bodytext' => ''], ['uid' => $uid]);
81+
$activationConfig = $this->activationTypes[$table][$CType] ?? $this->activationTypes[$table]['*'];
82+
foreach ($activationConfig as $uploadField => $renderFields) {
83+
// truncate render fields after update if assets have been removed
84+
if ($fieldArray[$uploadField] === 0) {
85+
if ($status === 'update') {
86+
$this->connectionPool
87+
->getConnectionForTable($table)
88+
->update($table, array_fill_keys($renderFields, ''), ['uid' => $uid]);
89+
}
90+
91+
continue;
6392
}
6493

65-
return;
94+
// if upload fields was filled we get it's relations and start to update all render fields if required
95+
/** @var array<FileReference> $relations */
96+
$relations = $this->fileRepository->findByRelation($table, $uploadField, $uid);
97+
foreach ($renderFields as $renderField) {
98+
$this->setSpreadsheetValue($uid, $table, $status, $renderField, $relations);
99+
}
66100
}
101+
}
67102

68-
/** @var array<FileReference> $relations */
69-
$relations = $this->fileRepository->findByRelation('tt_content', 'tx_spreadsheets_assets', $uid);
103+
/**
104+
* @param int $uid UID of chart record
105+
* @param string $table Table to update
106+
* @param string $status Status of current record update
107+
* @param string $field Field to update spreadsheet value
108+
* @param array<FileReference> $relations File relations found
109+
*
110+
*/
111+
private function setSpreadsheetValue(
112+
int $uid,
113+
string $table,
114+
string $status,
115+
string $field,
116+
array $relations
117+
): void {
70118
if (empty($relations)) {
71119
return;
72120
}
73121

74-
// update bodytext to default file selection
75-
if (empty($this->getBackendRecordField($uid, 'bodytext')) === true) {
122+
// if backend record field is currently empty we pre-select with first relation
123+
$fieldValue = $this->getBackendRecordField($uid, $table, $field);
124+
if (empty($fieldValue) === true) {
76125
$this->connectionPool
77-
->getConnectionForTable('tt_content')
78-
->update('tt_content', ['bodytext' => 'spreadsheet://' . $relations[0]->getUid()], ['uid' => $uid]);
126+
->getConnectionForTable($table)
127+
->update($table, [$field => 'spreadsheet://' . $relations[0]->getUid()], ['uid' => $uid]);
128+
} elseif ($status === 'new' && is_string($fieldValue)) {
129+
$dsn = $this->getTranslatedSpreadsheetDsn(
130+
DsnValueObject::createFromDSN($fieldValue),
131+
$relations
132+
);
133+
if ($dsn !== null) {
134+
$this->connectionPool
135+
->getConnectionForTable($table)
136+
->update($table, [$field => $dsn], ['uid' => $uid]);
137+
}
138+
}
139+
}
140+
141+
/**
142+
* @param DsnValueObject $dsn Original DSN
143+
* @param array<FileReference> $references File relations found
144+
*
145+
*/
146+
private function getTranslatedSpreadsheetDsn(DsnValueObject $dsn, array $references): ?string
147+
{
148+
foreach ($references as $reference) {
149+
if ($reference->getReferenceProperty('l10n_parent') === $dsn->getFileReference()) {
150+
return str_replace(
151+
'spreadsheet://' . $dsn->getFileReference(),
152+
'spreadsheet://' . $reference->getUid(),
153+
$dsn->getDsn()
154+
);
155+
}
79156
}
157+
158+
return null;
80159
}
81160

82161
/**
83-
* @param int $uid UID of tt_content record
162+
* @param int $uid UID of record
163+
* @param string $table Table to get record from
84164
* @param string $field Field to extract
85165
*/
86-
private function getBackendRecordField(int $uid, string $field): mixed
166+
private function getBackendRecordField(int $uid, string $table, string $field): mixed
87167
{
88168
if (!isset($this->records[$uid])) {
89-
$this->records[$uid] = BackendUtility::getRecord('tt_content', $uid); // @codeCoverageIgnore
169+
$this->records[$uid] = BackendUtility::getRecord($table, $uid); // @codeCoverageIgnore
90170
}
91171

92172
return $this->records[$uid][$field] ?? null;

0 commit comments

Comments
 (0)