Add business type, location and logo to the structured data

Three optional settings extend LocalBusiness: a subtype from a fixed list, coordinates as a pair, and a logo from the media library. Without them the output stays as it was, and stored settings need no migration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5.5 committed 2026-11-09 08:02:38 +01:00
1 parent d75c295f59
commit f2c04b311f
7 files changed
+188 -2

No files matched your search

+47
View File
@@ -4450,6 +4450,53 @@ display: flex', '#b1{display:flex;color:red}'];
self::assertSame(['Baden-Baden', 'Rastatt', 'Karlsruhe', 'Offenburg'], $data['areaServed']);
}
public function testBusinessTypeLocationAndLogoReachTheStructuredData(): void
{
$this->pages->publish('page-1', $this->pages->saveDraft('page-1', DemoContent::pages()['home'], 0), 1);
$basis = ['country' => 'DE', 'homePath' => 'home', 'legalName' => 'Luximmo UG', 'street' => 'Hauptstraße 169', 'city' => 'Gaggenau', 'localBusiness' => '1'];
$daten = function (): array {
preg_match('#<script type="application/ld\+json">(.*?)</script>#s', $this->request('/')->getContent(), $match);
return json_decode(html_entity_decode($match[1], ENT_QUOTES), true);
};
// Ohne Angaben bleibt alles, wie es war: bestehende Websites ändern sich nicht.
$this->site->save($basis);
$vorher = $daten();
self::assertSame('LocalBusiness', $vorher['@type']);
self::assertArrayNotHasKey('geo', $vorher);
self::assertArrayNotHasKey('logo', $vorher);
$mediaId = bin2hex(random_bytes(16));
$this->db->insert('media', ['id' => $mediaId, 'title' => 'Logo', 'alt' => '', 'variants' => json_encode([['src' => '/media/'.$mediaId.'/480', 'width' => 480, 'height' => 420], ['src' => '/media/'.$mediaId.'/640', 'width' => 640, 'height' => 561]], JSON_THROW_ON_ERROR), 'archived' => 0, 'version' => 1, 'created_at' => '2026-11-09 00:00:00']);
$eingabe = [...$basis, 'businessType' => 'RealEstateAgent', 'latitude' => '48,79381', 'longitude' => '8.33237', 'organisationLogoMediaId' => $mediaId];
$this->site->save($eingabe);
$nachher = $daten();
self::assertSame('RealEstateAgent', $nachher['@type']);
self::assertSame(['@type' => 'GeoCoordinates', 'latitude' => 48.79381, 'longitude' => 8.33237], $nachher['geo']);
self::assertStringEndsWith('/media/'.$mediaId.'/640', $nachher['logo']);
// Erneutes Speichern der geladenen Werte verliert nichts.
$this->site->save([...$this->site->load(), 'sameAs' => '']);
self::assertSame($nachher, $daten());
// Ohne „lokal“ gibt es weder Unterart noch Standort; das Logo gilt für jede Organisation.
$this->site->save([...$eingabe, 'localBusiness' => '']);
$organisation = $daten();
self::assertSame('Organization', $organisation['@type']);
self::assertArrayNotHasKey('geo', $organisation);
self::assertArrayHasKey('logo', $organisation);
foreach ([['businessType' => 'Geheimdienst'], ['latitude' => '91', 'longitude' => '8'], ['latitude' => 'abc', 'longitude' => '8'], ['latitude' => '48.1'], ['organisationLogoMediaId' => str_repeat('a', 32)]] as $falsch) {
try {
$this->site->save([...$basis, ...$falsch]);
self::fail('Ungültige Angabe angenommen: '.json_encode($falsch));
} catch (InvalidPage) {
$this->addToAssertionCount(1);
}
}
}
public function testReSavingLoadedSettingsKeepsHoursAndServiceArea(): void
{
$this->site->save(['country' => 'DE', 'homePath' => 'home', 'hours' => ['Monday' => ['opens' => '07:30', 'closes' => '17:00']], 'areaServed' => 'Bühl