Batch of 2026-10-28/29 plus 2026-11-03: - NEW vitec:import-datapath-stories: 22 story packages from the agency dump (docx + Links/ assets) as usecase records with content, quotes, images, customer logos, download cards; --repair-quotes normalizes attribution lines; asset backfill for existing stories - /products grid incident repaired (fix_products_grid, fix_graphics_grid, check_grid_page): containers unhidden, 46 duplicate cards soft-deleted, section order restored; BuildProductPortfolio and ImportProductCategoryPages now GUARD against re-runs on pages that already carry vitec_cols_% containers - ' double-encoding fixed: render-pipeline importers write literal apostrophes (ENT_NOQUOTES), fix_double_entities literalizes existing rows - ticket quick wins (ticket_quickwins_20261028), broadcast market page cleanup, AttachCardImages market-card handling, SubmarketWorkbook META REPAIR, story content/video fixes (fix_story_*) - ProvideProductCatalog: transitional v1 fields removed (categories uid/link, legacyGroupFields, item products teaser) - pure v2 shape (ticket 0024-FE); search renderer keeps its teaser - BuildProductOverviews: heroes get the numbered placeholder background (placeholders/pages/<uid>-01.png, wide grey fallback) - backfill on existing pages with empty hero_bgimage, attached at creation for new pages; existing references always win (ticket 0026-FE); 40 placeholder PNGs shipped to fileadmin (not tracked) - AttachPageMedia: --depth=3 with sysfolders as pass-through parents for the overview pages' -08 menu tiles - NEW migrations/fec_isolation_test.sh: two-user live test proving fe_comment ticket isolation (backend verified tight, cross-user sighting traced to the FE page-JSON cache, ticket 0027-BE) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
82 lines
3.1 KiB
PHP
82 lines
3.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Ticket 0014-FE Punkt 2: doppelt kodierte HTML-Entities in tt_content
|
|
* (z. B. "VITEC&apos;s" im JSON). Ursache: die Produkt-Importer
|
|
* escapten mit ENT_QUOTES|ENT_HTML5 (' -> '), die RTE-Persistenz
|
|
* escapte das & erneut. Die Importer schreiben seit 2026-10-28 literal
|
|
* (ENT_NOQUOTES); dieses Skript repariert den Bestand um EINE
|
|
* Escaping-Stufe: &apos; -> ' usw.
|
|
*
|
|
* Plain PDO (Muster migrations/check_bg.php).
|
|
*
|
|
* Usage: php migrations/fix_double_entities.php (Scan/Report)
|
|
* php migrations/fix_double_entities.php --apply
|
|
*/
|
|
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', '1');
|
|
|
|
// Stufe 1: doppelt kodierte Entities um eine Stufe reduzieren.
|
|
// Stufe 2 (Befund 2026-10-28: Scan fand KEINE Doubles in der DB - die DB
|
|
// traegt ' EINFACH kodiert, erst die Render-Pipeline escapet das &
|
|
// erneut): Apostroph-Entities literal machen, dann kann nichts mehr doppeln.
|
|
const PATTERNS = ['&apos;', '&quot;', '&#039;', '&amp;', '&nbsp;', ''', '''];
|
|
const REPLACEMENTS = [''', '"', ''', '&', ' ', "'", "'"];
|
|
|
|
$apply = in_array('--apply', $argv, true);
|
|
|
|
$root = null;
|
|
$dir = __DIR__;
|
|
for ($i = 0; $i < 5; $i++) {
|
|
if (is_file($dir . '/config/system/settings.php')) {
|
|
$root = $dir;
|
|
break;
|
|
}
|
|
$dir = dirname($dir);
|
|
}
|
|
if ($root === null) {
|
|
exit("Could not locate project root above " . __DIR__ . "\n");
|
|
}
|
|
$settings = require $root . '/config/system/settings.php';
|
|
$db = $settings['DB']['Connections']['Default'];
|
|
$pdo = new PDO(
|
|
sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $db['host'] ?? 'localhost', $db['port'] ?? 3306, $db['dbname'] ?? ''),
|
|
$db['user'] ?? '',
|
|
$db['password'] ?? '',
|
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
|
|
);
|
|
|
|
echo ($apply ? 'APPLY' : 'SCAN') . "\n";
|
|
|
|
$like = implode(' OR ', array_map(static fn(string $p): string => "bodytext LIKE '%" . $p . "%'", PATTERNS));
|
|
$rows = $pdo->query(
|
|
"SELECT c.uid, c.pid, p.slug, c.CType, c.bodytext FROM tt_content c
|
|
LEFT JOIN pages p ON p.uid = c.pid
|
|
WHERE c.deleted = 0 AND ($like) ORDER BY p.slug, c.uid"
|
|
)->fetchAll();
|
|
|
|
$fixed = 0;
|
|
foreach ($rows as $row) {
|
|
$new = str_replace(PATTERNS, REPLACEMENTS, (string)$row['bodytext']);
|
|
$hits = [];
|
|
foreach (PATTERNS as $pattern) {
|
|
$n = substr_count((string)$row['bodytext'], $pattern);
|
|
if ($n > 0) {
|
|
$hits[] = $pattern . 'x' . $n;
|
|
}
|
|
}
|
|
printf("#%-6d %-28s %-45s %s\n", $row['uid'], $row['CType'], (string)$row['slug'], implode(' ', $hits));
|
|
if ($apply) {
|
|
$pdo->prepare('UPDATE tt_content SET bodytext = ?, tstamp = UNIX_TIMESTAMP() WHERE uid = ?')
|
|
->execute([$new, (int)$row['uid']]);
|
|
$fixed++;
|
|
}
|
|
}
|
|
echo "\n" . count($rows) . " Element(e) betroffen" . ($apply ? ", $fixed repariert. Danach: vendor/bin/typo3 cache:flush" : ". Mit --apply reparieren.") . "\n";
|
|
if (!$apply && $rows !== []) {
|
|
echo "HINWEIS: Ersetzt wird genau EINE Escaping-Stufe (&apos; -> ' usw.).\n";
|
|
}
|