- new project-neutral extension evo_megamenu_json (Evomedien): a Megamenu plugin holding entries, columns, items, teaser cards and a featured slot as nested records; presentation settings travel with the payload so the front end reads behaviour instead of hard-coding it; published as page.10.fields.megaMenu, driven by the site settings megamenu.contentUid and megamenu.storagePid - vitec:seed-megamenu fills one element from the live structure: 5 entries, 26 columns, 95 items, 4 story cards; items without a page yet are flagged pending so the front end falls back to the column link - vitec:debug-sets prints the resolved site set order - read-only diagnostics: check_megamenu_schema.php, check_typoscript_templates.php - docs: schema updates run via extension:setup (database:updateschema no longer exists in v14), and a JSON Accept header activates headless-mixed, which strips every set-added page field
85 lines
3.1 KiB
PHP
85 lines
3.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Evomedien\Vitec\Command;
|
|
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use TYPO3\CMS\Core\Site\SiteFinder;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
|
|
/**
|
|
* Diagnostic: prints the site sets in the order TYPO3 actually resolves them.
|
|
*
|
|
* Set order decides who wins: friendsoftypo3/headless resets the whole `page`
|
|
* object (`page < lib.headlessPage`), so every set that adds page-level
|
|
* fields has to load AFTER it. When headless ends up last, those fields
|
|
* vanish without any error - which is exactly the failure this command was
|
|
* written for (2026-09-11).
|
|
*
|
|
* vendor/bin/typo3 vitec:debug-sets
|
|
*/
|
|
#[AsCommand(
|
|
name: 'vitec:debug-sets',
|
|
description: 'Print the resolved site set order (diagnoses page-level TypoScript being reset)'
|
|
)]
|
|
final class DebugSetsCommand extends Command
|
|
{
|
|
protected function configure(): void
|
|
{
|
|
$this->addOption('site', null, InputOption::VALUE_REQUIRED, 'Site identifier', 'vitec');
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$identifier = (string)$input->getOption('site');
|
|
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByIdentifier($identifier);
|
|
|
|
if (!method_exists($site, 'getSets')) {
|
|
$output->writeln('<error>This TYPO3 version does not expose Site::getSets().</error>');
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
$sets = $site->getSets();
|
|
$output->writeln(sprintf('Site "%s": %d sets, in load order', $identifier, count($sets)));
|
|
|
|
$position = 0;
|
|
$headlessAt = null;
|
|
$vitecAt = null;
|
|
foreach ($sets as $set) {
|
|
$position++;
|
|
$name = is_object($set) && property_exists($set, 'name') ? (string)$set->name : (string)$set;
|
|
if ($name === 'friendsoftypo3/headless') {
|
|
$headlessAt = $position;
|
|
}
|
|
if ($name === 'evomedien/vitecset') {
|
|
$vitecAt = $position;
|
|
}
|
|
$mark = in_array($name, ['friendsoftypo3/headless', 'evomedien/vitecset'], true) ? ' <-- ' : ' ';
|
|
$output->writeln(sprintf('%2d.%s%s', $position, $mark, $name));
|
|
}
|
|
|
|
$output->writeln('');
|
|
if ($headlessAt === null || $vitecAt === null) {
|
|
$output->writeln('<comment>headless or vitecset is not in the resolved list at all.</comment>');
|
|
return Command::SUCCESS;
|
|
}
|
|
if ($headlessAt > $vitecAt) {
|
|
$output->writeln(sprintf(
|
|
'<error>PROBLEM: headless loads at %d, AFTER vitecset at %d - it resets `page` and drops the page-level fields.</error>',
|
|
$headlessAt, $vitecAt
|
|
));
|
|
} else {
|
|
$output->writeln(sprintf(
|
|
'<info>Order is fine: headless at %d, vitecset at %d.</info>',
|
|
$headlessAt, $vitecAt
|
|
));
|
|
}
|
|
return Command::SUCCESS;
|
|
}
|
|
}
|