PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC] ); // ---- data ------------------------------------------------------------------- $products = $pdo->query( "SELECT uid, title, slug, teaser, subtitle, description, description2, highlights, capabilities, applications, resources, resources_layout, hidden, legacy, supportproduct, subproduct, hideonwebsite, hideonproducts, showdatapath FROM tx_vitec_domain_model_product WHERE deleted = 0 ORDER BY LOWER(title), uid" )->fetchAll(); // FAL references per product and fieldname, with file identifiers $fileRefs = $pdo->query( "SELECT r.uid_foreign, r.fieldname, f.identifier, f.name FROM sys_file_reference r JOIN sys_file f ON f.uid = r.uid_local WHERE r.deleted = 0 AND r.hidden = 0 AND r.tablenames = 'tx_vitec_domain_model_product' AND r.fieldname IN ('heroimage','productimage','ogimage','videofile') ORDER BY r.uid_foreign, r.fieldname, r.sorting_foreign" )->fetchAll(); $files = []; foreach ($fileRefs as $r) { $files[(int)$r['uid_foreign']][$r['fieldname']][] = ['url' => '/fileadmin' . $r['identifier'], 'name' => (string)$r['name']]; } // inline resource cards $resourceRows = $pdo->query( 'SELECT * FROM tx_vitec_product_resource WHERE deleted = 0 AND hidden = 0 ORDER BY product, sorting' )->fetchAll(); $resources = []; foreach ($resourceRows as $r) { $resources[(int)$r['product']][] = $r; } // MM: datasheets (download records) and solutions, in MM order $datasheets = []; foreach ($pdo->query( 'SELECT mm.uid_local AS product, d.title FROM tx_vitec_product_datasheet_mm mm JOIN tx_vitec_domain_model_download d ON d.uid = mm.uid_foreign AND d.deleted = 0 ORDER BY mm.uid_local, mm.sorting' )->fetchAll() as $r) { $datasheets[(int)$r['product']][] = (string)$r['title']; } $solutions = []; foreach ($pdo->query( 'SELECT mm.uid_local AS product, s.title FROM tx_vitec_product_solution_mm mm JOIN tx_vitec_domain_model_solution s ON s.uid = mm.uid_foreign AND s.deleted = 0 ORDER BY mm.uid_local, mm.sorting' )->fetchAll() as $r) { $solutions[(int)$r['product']][] = (string)$r['title']; } // inline feature cards (Why choose ...?) + their icon references $features = []; foreach ($pdo->query( 'SELECT uid, product, title, cardtext FROM tx_vitec_product_feature WHERE deleted = 0 AND hidden = 0 ORDER BY product, sorting, uid' )->fetchAll() as $r) { $features[(int)$r['product']][] = $r; } $featureIcons = []; foreach ($pdo->query( "SELECT r.uid_foreign, f.identifier, f.name FROM sys_file_reference r JOIN sys_file f ON f.uid = r.uid_local WHERE r.deleted = 0 AND r.hidden = 0 AND r.tablenames = 'tx_vitec_product_feature' AND r.fieldname = 'icon' ORDER BY r.uid_foreign, r.sorting_foreign" )->fetchAll() as $r) { $featureIcons[(int)$r['uid_foreign']] ??= ['url' => '/fileadmin' . $r['identifier'], 'name' => (string)$r['name']]; } // ---- helpers ------------------------------------------------------------------ function h(string $v): string { return htmlspecialchars($v, ENT_QUOTES | ENT_HTML5); } /** check/cross cell; a count > 1 is shown next to the check */ function cell(bool $ok, int $count = 0): string { if (!$ok) { return '✗'; } return '✓' . ($count > 1 ? '' . $count . '' : '') . ''; } function filled(?string $v): bool { return trim(strip_tags((string)$v)) !== ''; } /** labeled block in the detail pane; HTML of RTE fields is rendered */ function textBlock(string $label, ?string $value): string { if (!filled($value)) { return ''; } return '
' . h($label) . '
' . $value . '
'; } /** @param array $images */ function imageBlock(string $label, array $images): string { if ($images === []) { return ''; } $out = '
' . h($label) . ' (' . count($images) . ')
'; foreach ($images as $img) { $out .= '' . '' . h($img['name']) . ''; } return $out . '
'; } /** * Feature cards with their icon thumbnails (click to enlarge). * * @param array> $items * @param array $featureIcons */ function featuresBlock(array $items, array $featureIcons): string { if ($items === []) { return ''; } $withIcon = 0; $cards = ''; foreach ($items as $it) { $icon = $featureIcons[(int)$it['uid']] ?? null; if ($icon !== null) { $withIcon++; } $cards .= '
' . ($icon !== null ? '' . '' . h($icon['name']) . '' : '✗') . '
' . h((string)$it['title']) . '
' . '
' . h((string)$it['cardtext']) . '
'; } return '
Features (' . count($items) . ' cards, ' . $withIcon . ' icons)
' . '
' . $cards . '
'; } /** @param string[] $items */ function listBlock(string $label, array $items): string { if ($items === []) { return ''; } return '
' . h($label) . ' (' . count($items) . ')
  • ' . implode('
  • ', array_map('h', $items)) . '
'; } // ---- columns ------------------------------------------------------------------ $columns = ['Hero', 'Photos', 'Video', 'Teaser', 'Subtitle', 'Description', 'Descr. 2', 'Highlights', 'Capabilities', 'Applications', 'Features', 'Resources', 'Datasheets', 'Solutions']; $filledPerColumn = array_fill_keys($columns, 0); $rowsHtml = ''; foreach ($products as $p) { $uid = (int)$p['uid']; $f = $files[$uid] ?? []; $res = $resources[$uid] ?? []; $ds = $datasheets[$uid] ?? []; $sol = $solutions[$uid] ?? []; $feat = $features[$uid] ?? []; $featIconCount = count(array_filter($feat, static fn(array $it): bool => isset($featureIcons[(int)$it['uid']]))); $checks = [ 'Hero' => [count($f['heroimage'] ?? []), true], 'Photos' => [count($f['productimage'] ?? []), true], 'Video' => [count($f['videofile'] ?? []), true], 'Teaser' => [filled($p['teaser']) ? 1 : 0, false], 'Subtitle' => [filled($p['subtitle']) ? 1 : 0, false], 'Description' => [filled($p['description']) ? 1 : 0, false], 'Descr. 2' => [filled($p['description2']) ? 1 : 0, false], 'Highlights' => [filled($p['highlights']) ? 1 : 0, false], 'Capabilities' => [filled($p['capabilities']) ? 1 : 0, false], 'Applications' => [filled($p['applications']) ? 1 : 0, false], 'Features' => [count($feat), true], 'Resources' => [count($res), true], 'Datasheets' => [count($ds), true], 'Solutions' => [count($sol), true], ]; $cells = ''; foreach ($columns as $column) { [$count, $showCount] = $checks[$column]; $filledPerColumn[$column] += $count > 0 ? 1 : 0; if ($column === 'Features' && $count > 0) { // cards + how many of them carry an icon $cells .= '✓' . $count . '·' . $featIconCount . 'i'; continue; } $cells .= cell($count > 0, $showCount ? $count : 0); } $flags = []; foreach (['hidden' => 'hidden', 'legacy' => 'legacy', 'supportproduct' => 'support', 'subproduct' => 'sub', 'hideonwebsite' => 'hideWeb', 'hideonproducts' => 'hideList', 'showdatapath' => 'datapath'] as $col => $label) { if ((int)$p[$col] === 1) { $flags[] = $label; } } // detail pane: every content of the record $resourceLines = []; foreach ($res as $r) { $parts = []; foreach (['title', 'header', 'label', 'kind', 'link'] as $key) { if (isset($r[$key]) && trim((string)$r[$key]) !== '') { $parts[] = (string)$r[$key]; } } $resourceLines[] = $parts === [] ? ('#' . $r['uid']) : implode(' · ', $parts); } $detail = 'Open Product ↗' . '
' . '/product/' . h(trim((string)$p['slug'], '/')) . '' . ' · uid ' . $uid . ' · resources_layout: ' . h((string)$p['resources_layout']) . ($flags !== [] ? ' · Flags: ' . h(implode(', ', $flags)) : '') . '
' . imageBlock('Hero Image', $f['heroimage'] ?? []) . imageBlock('Product Images', $f['productimage'] ?? []) . imageBlock('OG Image', $f['ogimage'] ?? []) . listBlock('Video Files', array_map(static fn(array $v): string => $v['name'] . ' (' . $v['url'] . ')', $f['videofile'] ?? [])) . textBlock('Teaser', (string)$p['teaser']) . textBlock('Subtitle', (string)$p['subtitle']) . textBlock('Description', (string)$p['description']) . textBlock('Description 2', (string)$p['description2']) . textBlock('Highlights', (string)$p['highlights']) . textBlock('Capabilities', (string)$p['capabilities']) . textBlock('Applications', (string)$p['applications']) . featuresBlock($feat, $featureIcons) . listBlock('Resources', $resourceLines) . listBlock('Datasheets', $ds) . listBlock('Solutions', $sol); $rowsHtml .= '' . '▸' . h((string)$p['title']) . ($flags !== [] ? ' ' . h(implode(' ', $flags)) . '' : '') . '' . $cells . '' . "\n" . '
' . $detail . '
' . "\n"; } $headCells = 'Product (' . count($products) . ') ▲'; foreach ($columns as $column) { $headCells .= '' . h($column) . '' . $filledPerColumn[$column] . ''; } // ---- page --------------------------------------------------------------------- ?> VITEC Product Content Check

VITEC Product Content Check

products · as of · click a row for details