Hero placeholder fieldname: vitec_hero_bgimage (content block prefix)

The vitec/herosection content block has prefixFields - the real column
and sys_file_reference fieldname is vitec_hero_bgimage; the JSON merely
strips the prefix. The first apply wrote the 20 references with the bare
name, so they existed but never rendered (no herosection anywhere had an
image, so there was no working example to catch it against).

- BuildProductOverviews: attach/backfill/skip-check now use
  vitec_hero_bgimage
- new migration fix_overview_hero_refs.php: renames the existing 20
  references in place (no re-attach) and sets the counter column

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
orascheandClaude Fable 5 committed 2026-11-03 18:42:06 +01:00
1 parent 77661bf0b6
commit 8e173b1a85
2 files changed
+117 -4

No files matched your search

+111
View File
@@ -0,0 +1,111 @@
<?php
/**
* fix_overview_hero_refs.php (2026-11-03)
*
* Repariert die Hero-Platzhalter-Referenzen der 20 Produkt-Übersichtsseiten:
* vitec:build-product-overviews --apply hatte die sys_file_reference-Zeilen
* mit fieldname 'hero_bgimage' angelegt - der Content-Block vitec/herosection
* hat aber prefixFields, die echte Spalte/der echte Fieldname ist
* 'vitec_hero_bgimage' (das JSON streift den Praefix nur ab). Ergebnis:
* Referenzen existieren, rendern aber nicht.
*
* Dieses Skript biegt die vorhandenen Referenzen um (fieldname-Update) und
* setzt das Zaehlfeld tt_content.vitec_hero_bgimage - KEIN Neuanlegen.
*
* php migrations/fix_overview_hero_refs.php # INSPECT (default)
* php migrations/fix_overview_hero_refs.php --apply # schreibt
*/
declare(strict_types=1);
$apply = in_array('--apply', $argv, true);
$settings = require __DIR__ . '/../config/system/settings.php';
$db = $settings['DB']['Connections']['Default'];
$pdo = new PDO(
sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4', $db['host'], $db['dbname']),
$db['user'],
$db['password'],
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
echo $apply ? "APPLY\n\n" : "INSPECT - nichts wird geschrieben (--apply zum Schreiben)\n\n";
// Zielspalte muss existieren, sonst stimmt die Diagnose nicht
$col = (int)$pdo->query(
"SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'tt_content' AND COLUMN_NAME = 'vitec_hero_bgimage'"
)->fetchColumn();
echo 'tt_content.vitec_hero_bgimage vorhanden: ' . ($col > 0 ? 'ja' : 'NEIN') . "\n";
if ($col === 0) {
echo "ABBRUCH: Zielspalte fehlt - Feldname im Content Block pruefen.\n";
exit(1);
}
// die falsch benannten Referenzen, nur an vitec_herosection-Elementen
$refs = $pdo->query(
"SELECT r.uid AS ref_uid, r.uid_foreign AS content_uid, r.uid_local AS file_uid,
c.pid, c.CType, f.identifier
FROM sys_file_reference r
JOIN tt_content c ON c.uid = r.uid_foreign
LEFT JOIN sys_file f ON f.uid = r.uid_local
WHERE r.deleted = 0 AND r.tablenames = 'tt_content' AND r.fieldname = 'hero_bgimage'
AND c.deleted = 0 AND c.CType = 'vitec_herosection'
ORDER BY c.pid"
)->fetchAll(PDO::FETCH_ASSOC);
echo count($refs) . " Referenz(en) mit fieldname 'hero_bgimage' an vitec_herosection:\n";
foreach ($refs as $ref) {
printf(
" ref #%d -> content #%d (pid %d) file %s\n",
$ref['ref_uid'],
$ref['content_uid'],
$ref['pid'],
(string)$ref['identifier']
);
}
// Sicherheitsnetz: Elemente, die BEIDE Varianten tragen (sollte es nicht geben)
$both = $pdo->query(
"SELECT uid_foreign FROM sys_file_reference
WHERE deleted = 0 AND tablenames = 'tt_content' AND fieldname = 'vitec_hero_bgimage'
AND uid_foreign IN (SELECT uid_foreign FROM sys_file_reference
WHERE deleted = 0 AND tablenames = 'tt_content' AND fieldname = 'hero_bgimage')"
)->fetchAll(PDO::FETCH_COLUMN);
if ($both !== []) {
echo "ACHTUNG: Elemente mit korrekter UND falscher Referenz: " . implode(', ', $both) . " - die falschen wuerden geloescht statt umbenannt.\n";
}
if (!$apply) {
echo "\nINSPECT-Ende.\n";
exit(0);
}
$renamed = 0;
$deleted = 0;
foreach ($refs as $ref) {
if (in_array((string)$ref['content_uid'], array_map('strval', $both), true)) {
$pdo->prepare('UPDATE sys_file_reference SET deleted = 1, tstamp = ? WHERE uid = ?')
->execute([time(), (int)$ref['ref_uid']]);
$deleted++;
continue;
}
$pdo->prepare("UPDATE sys_file_reference SET fieldname = 'vitec_hero_bgimage', tstamp = ? WHERE uid = ?")
->execute([time(), (int)$ref['ref_uid']]);
$renamed++;
}
// Zaehlfeld pro betroffenem Element nachziehen
$contentUids = array_values(array_unique(array_map(static fn(array $r): int => (int)$r['content_uid'], $refs)));
foreach ($contentUids as $uid) {
$count = (int)$pdo->query(
"SELECT COUNT(*) FROM sys_file_reference
WHERE deleted = 0 AND tablenames = 'tt_content' AND fieldname = 'vitec_hero_bgimage' AND uid_foreign = " . $uid
)->fetchColumn();
$pdo->prepare('UPDATE tt_content SET vitec_hero_bgimage = ?, tstamp = ? WHERE uid = ?')
->execute([$count, time(), $uid]);
}
printf("\nFertig: %d Referenz(en) umbenannt, %d geloescht, %d Zaehlfeld(er) gesetzt.\n", $renamed, $deleted, count($contentUids));
echo "Danach: vendor/bin/typo3 cache:flush\n";
@@ -397,7 +397,9 @@ final class BuildProductOverviewsCommand extends Command
'uid_local' => GeneralUtility::makeInstance(StorageRepository::class)
->getDefaultStorage()->getFile($placeholder)->getUid(),
];
$this->datamap['tt_content'][$heroId]['hero_bgimage'] = $refId;
// content block vitec/herosection has prefixFields - the real
// column/fieldname is vitec_hero_bgimage (JSON strips the prefix)
$this->datamap['tt_content'][$heroId]['vitec_hero_bgimage'] = $refId;
$this->report[] = ' hero: attach ' . $placeholder;
} else {
$this->report[] = ' hero: would attach ' . $placeholder;
@@ -462,7 +464,7 @@ final class BuildProductOverviewsCommand extends Command
return;
}
$existing = (int)$pool->getConnectionForTable('sys_file_reference')->fetchOne(
"SELECT COUNT(*) FROM sys_file_reference WHERE deleted = 0 AND tablenames = 'tt_content' AND fieldname = 'hero_bgimage' AND uid_foreign = ?",
"SELECT COUNT(*) FROM sys_file_reference WHERE deleted = 0 AND tablenames = 'tt_content' AND fieldname = 'vitec_hero_bgimage' AND uid_foreign = ?",
[$heroUid]
);
if ($existing > 0) {
@@ -485,9 +487,9 @@ final class BuildProductOverviewsCommand extends Command
->getDefaultStorage()->getFile($placeholder)->getUid(),
'tablenames' => 'tt_content',
'uid_foreign' => $heroUid,
'fieldname' => 'hero_bgimage',
'fieldname' => 'vitec_hero_bgimage',
];
$this->datamap['tt_content'][$heroUid]['hero_bgimage'] = 1;
$this->datamap['tt_content'][$heroUid]['vitec_hero_bgimage'] = 1;
$this->report[] = ' hero #' . $heroUid . ': attach ' . $placeholder;
}