Files
orascheandClaude Fable 5 e2d4367d7a Products run: missing records, asset re-run, audit page, category pages
- new vitec:create-missing-products: MGW Diamond TOUGH, MGW Pico TOUGH,
  MGW Pico+ TOUGH and X-View Integrated Displays as visible records
  (teaser drafts, pid and sys_category assignments copied from the
  sibling product; titles equal the Dropbox folder names so the image
  importer matches immediately). IQS4 stays out - its delivery folder
  is empty, question to Joe
- asset re-run via vitec:import-product-images after re-staging the
  Dropbox delivery (the misfiled Diamond-OG banner corrected into the
  OG inbox folder again): new photos for 95-Series, Avedia chassis,
  SFF PRISM and the new TOUGH/X-View records
- new migrations/build_product_audit.php: generates the internal
  product-asset audit at /product-audit/ (same basic auth, same-origin
  thumbnails) - one row per record with thumbnail, detail link, badges
  for hero/photos/texts/resources/datasheets/solutions, flags, stats
  and client-side filters; re-run any time
- new vitec:import-product-category-pages: builds the nine
  /products/<category> pages (frontend layout 9, hero/main/preFooter)
  from the agency "Product Category Pages" workbooks - intro
  paragraphs, Why-VITEC / product / solution cards, the comparison
  rows as ONE text element with a plain table (no comparison CType
  exists; FE styles it), prefooter banner to /contact, full page
  properties, page sorting per sitemap 3.1-3.9; the empty shells #455
  and #457 are reused. Product card links resolve record-first (exact
  title, stripped parenthesis, family alias, unique slug prefix);
  ProductFamilyAliases gains ten category-level family labels. Solution
  cards tolerate US/UK spelling (center/centre, visualization/
  visualisation). Applied and verified live (nine routes, links,
  tables, meta)
- known gaps reported, queued for Joe: IQS4, Media Players (93/94),
  Chassis Systems, Express Backplanes, Accessories & Cables, PCIe
  Encoders, VMS Plugins & Integrations; the Vision family card awaits
  a flagship decision

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 13:31:03 +01:00

70 lines
2.7 KiB
PHP

<?php
declare(strict_types=1);
namespace Evomedien\Vitec\Import;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Joe's solution/market workbooks fill the product slots with FAMILY labels
* ("VSN Platforms", "End Points", "OG Platform"), not record titles. One
* card renders one product record, so every family maps to its
* representative product here - an editorial mapping (Olli, 2026-10-19),
* deliberately versioned next to the importers that read the workbooks
* instead of hidden in database state. Both workbook importers consult it
* AFTER their exact title match, so a real record title always wins.
*
* Keys are normalised like the importers' norm(): lowercase, '+' -> plus,
* everything non-alphanumeric stripped. Values are product slugs - stable
* across environments, unlike uids.
*/
final class ProductFamilyAliases
{
private const MAP = [
'vsnplatforms' => 'vsn-v3',
'visionsc' => 'visionsc-uhd2',
'visionio' => 'visionio-sd14',
'wallcontrol' => 'aetria-wallcontrol',
'imagegraphics' => 'image-4k',
'xseries' => 'fx4',
'endpoints' => 'avedia-end-points',
'mgwproductfamily' => 'mgw-ace-encoder',
'diamondip' => 'diamond-ip-og-ip-to-ip-encoder',
'ogplatform' => 'mgw-diamond-og-sdi-composite-blade-encoder',
'capturecards' => 'visionav-hd',
// category-page workbooks (2026-10-27): family cards on
// /products/<category> resolve to their flagship record
'rfgateways' => '45-series-rf-gateways',
'ipgateways' => 'channellink',
'prismtranscoder' => 'prism-1ru-rack-mount-transcoder',
'mgwace' => 'mgw-ace-encoder',
'imagegraphicscards' => 'image-4k',
'avedia' => 'avedia-platform-iptv-signage-cmsserver',
'vsn' => 'vsn-v3',
'visionlc' => 'visionlc-hd',
'videowallmanagementsoftware' => 'wall-control-10',
'vitecog' => 'mgw-diamond-og-sdi-composite-blade-encoder',
];
/**
* @return array<string,mixed>|null the aliased product row, or null when
* the label is no known family
*/
public static function resolve(string $normalisedLabel): ?array
{
$slug = self::MAP[$normalisedLabel] ?? null;
if ($slug === null) {
return null;
}
$row = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable('tx_vitec_domain_model_product')
->fetchAssociative(
'SELECT * FROM tx_vitec_domain_model_product WHERE deleted = 0 AND slug = ?',
[$slug]
);
return $row ?: null;
}
}