Files
VITEC-website/migrations/ticket_quickwins_20261028.php
orascheandClaude Fable 5 77661bf0b6 Datapath stories, grid repairs, menu v2 pure, hero placeholders, fec test
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>
2026-11-03 18:29:56 +01:00

148 lines
6.0 KiB
PHP

<?php
declare(strict_types=1);
/**
* Zwei Quick Wins aus Arnes Tickets (2026-10-28):
*
* A) 0012-FE Punkt 2: die Karte "Request access" auf /support (uid 11489)
* soll auf /support/login-to-helpdesk#form-helpdesk zeigen (Anker auf
* das HelpDesk-Formular; Schema form-<formKey>).
*
* B) 0009-FE Punkt 7: vitec_ctabanner auf Market-/Solution-Seiten haben
* Labels ("Contact our team" / "Request a demo"), aber keine Links.
* Leere primary_cta mit Contact-Label -> /contact, leere secondary_cta
* mit Demo-Label -> /contact/request-a-demo (als t3://page?uid=...).
* Gefuellte Links werden NIE angefasst.
*
* Plain PDO (Muster migrations/check_bg.php).
*
* Usage: php migrations/ticket_quickwins_20261028.php (inspect)
* php migrations/ticket_quickwins_20261028.php --apply
*/
error_reporting(E_ALL);
ini_set('display_errors', '1');
const REQUEST_ACCESS_UID = 11489;
const ANCHOR = 'form-helpdesk';
$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]
);
echo ($apply ? 'APPLY' : 'INSPECT') . "\n";
function pageUidBySlug(PDO $pdo, string $slug): int
{
$stmt = $pdo->prepare('SELECT uid FROM pages WHERE deleted = 0 AND slug = ? AND sys_language_uid IN (0,-1)');
$stmt->execute([$slug]);
return (int)$stmt->fetchColumn();
}
// --- A) Request-access-Karte -> Anker ---------------------------------------
echo "\n--- A) Request access -> #" . ANCHOR . " ---\n";
$stmt = $pdo->prepare('SELECT uid, header, vitec_primary_cta FROM tt_content WHERE deleted = 0 AND uid = ?');
$stmt->execute([REQUEST_ACCESS_UID]);
$card = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$card) {
echo "Karte #" . REQUEST_ACCESS_UID . " nicht gefunden - uebersprungen.\n";
} elseif (stripos((string)$card['header'], 'request access') === false) {
echo "Karte #" . REQUEST_ACCESS_UID . " heisst \"" . $card['header'] . "\" (erwartet: Request access) - NICHT angefasst.\n";
} else {
$cta = (string)$card['vitec_primary_cta'];
if (str_contains($cta, '#' . ANCHOR)) {
echo "Karte #" . REQUEST_ACCESS_UID . ": Anker bereits gesetzt ($cta) - nichts zu tun.\n";
} elseif ($cta === '') {
echo "Karte #" . REQUEST_ACCESS_UID . ": primary_cta ist LEER - erst klaeren, nicht angefasst.\n";
} else {
$new = $cta . '#' . ANCHOR;
echo "Karte #" . REQUEST_ACCESS_UID . " (\"" . $card['header'] . "\"): \"$cta\" -> \"$new\"\n";
if ($apply) {
$pdo->prepare('UPDATE tt_content SET vitec_primary_cta = ?, tstamp = UNIX_TIMESTAMP() WHERE uid = ?')
->execute([$new, REQUEST_ACCESS_UID]);
echo " geschrieben.\n";
}
}
}
// --- B) CTA-Banner-Defaults auf Market-/Solution-Seiten ----------------------
echo "\n--- B) ctabanner-Links auf /markets + /solutions ---\n";
$contactUid = pageUidBySlug($pdo, '/contact');
$demoUid = pageUidBySlug($pdo, '/contact/request-a-demo');
$solutionsUid = pageUidBySlug($pdo, '/solutions');
if ($contactUid === 0 || $demoUid === 0 || $solutionsUid === 0) {
exit("Zielseiten nicht aufloesbar (/contact=#$contactUid, request-a-demo=#$demoUid, /solutions=#$solutionsUid) - Abbruch.\n");
}
echo "Ziele: /contact=#$contactUid, request-a-demo=#$demoUid, /solutions=#$solutionsUid\n";
$rows = $pdo->query(
"SELECT c.uid, p.slug, c.vitec_primary_cta, c.vitec_primary_cta_label,
c.vitec_secondary_cta, c.vitec_secondary_cta_label
FROM tt_content c JOIN pages p ON p.uid = c.pid AND p.deleted = 0
WHERE c.deleted = 0 AND c.CType = 'vitec_ctabanner'
AND (p.slug = '/markets' OR p.slug LIKE '/markets/%' OR p.slug = '/solutions' OR p.slug LIKE '/solutions/%')
ORDER BY p.slug"
)->fetchAll(PDO::FETCH_ASSOC);
$setPrimary = 0;
$setSecondary = 0;
foreach ($rows as $row) {
$actions = [];
$pLabel = (string)$row['vitec_primary_cta_label'];
$sLabel = (string)$row['vitec_secondary_cta_label'];
// Sub-Solution-Variante: "Contact our team" / "Request a demo";
// Market-Variante (Fund 28.10.): "Talk to our team" / "Explore solutions"
if ((string)$row['vitec_primary_cta'] === '' && (stripos($pLabel, 'contact') !== false || stripos($pLabel, 'talk') !== false)) {
$actions['vitec_primary_cta'] = 't3://page?uid=' . $contactUid;
$setPrimary++;
}
if ((string)$row['vitec_secondary_cta'] === '') {
if (stripos($sLabel, 'demo') !== false) {
$actions['vitec_secondary_cta'] = 't3://page?uid=' . $demoUid;
$setSecondary++;
} elseif (stripos($sLabel, 'solution') !== false) {
$actions['vitec_secondary_cta'] = 't3://page?uid=' . $solutionsUid;
$setSecondary++;
}
}
if ($actions === []) {
continue;
}
echo "#" . $row['uid'] . " " . $row['slug'] . ": " . implode(', ', array_map(
static fn(string $field, string $value): string => $field . ' = ' . $value,
array_keys($actions), $actions
)) . "\n";
if ($apply) {
$set = implode(', ', array_map(static fn(string $f): string => "$f = ?", array_keys($actions)));
$pdo->prepare("UPDATE tt_content SET $set, tstamp = UNIX_TIMESTAMP() WHERE uid = ?")
->execute([...array_values($actions), (int)$row['uid']]);
}
}
echo "\n" . count($rows) . " Banner geprueft · $setPrimary primary + $setSecondary secondary " . ($apply ? 'gesetzt' : 'zu setzen') . ".\n";
if (!$apply) {
echo "Inspect only - mit --apply schreiben.\n";
} else {
echo "Danach: vendor/bin/typo3 cache:flush\n";
}