Vorschaubild beim Teilen, robots.txt als Bot-Steuerung
Das Feld "Vorschaubild beim Teilen" gab es seit dem SEO-Paket, ausgegeben wurde es nie: keine mit KantSites gebaute Seite hatte ein og:image. Es wird jetzt aufgeloest - erst das gesetzte Vorschaubild, sonst das Beitragsbild - als absolute Adresse bis 1600 px, dazu og:site_name, og:locale, og:image:alt und twitter:card (klein ohne Bild, gross mit). Dasselbe Bild steht im strukturierten Datensatz eines Beitrags; Archive haben jetzt ebenfalls Open-Graph-Angaben. Eigene robots.txt-Zeilen: 200 statt 30, und Leerzeilen bleiben als Trenner erhalten - Regeln je Bot (welche KI-Crawler lesen duerfen) brauchen Bloecke, nicht einen Klumpen. Behoben: die Symbolerzeugung suchte feste Breiten statt der Varianten, die das Bild wirklich hat - ein 192 px grosses Zeichen, also der haeufigste Fall, scheiterte damit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f2ef2a4901
commit
35d8270afd
10 files changed
+137
-10
No files matched your search
@@ -5,6 +5,7 @@ namespace App\Controller;
|
||||
use App\Content\Consent;
|
||||
use App\Content\CustomCode;
|
||||
use App\Content\FormRepository;
|
||||
use App\Content\MediaLibrary;
|
||||
use App\Content\MenuRepository;
|
||||
use App\Content\PageRepository;
|
||||
use App\Content\PartialRepository;
|
||||
@@ -20,7 +21,7 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
final class PageController extends AbstractController
|
||||
{
|
||||
public function __construct(private PageRepository $pages, private MenuRepository $menus, private PostRepository $posts, private FormRepository $forms, private RedirectRepository $redirects, private SiteSettings $settings, private PartialRepository $partials, private CustomCode $code, private Consent $consent, private Theme $theme, private StyleCompiler $styles, private string $secret, private string $siteOrigin)
|
||||
public function __construct(private PageRepository $pages, private MenuRepository $menus, private PostRepository $posts, private FormRepository $forms, private RedirectRepository $redirects, private SiteSettings $settings, private PartialRepository $partials, private CustomCode $code, private Consent $consent, private Theme $theme, private StyleCompiler $styles, private MediaLibrary $media, private string $secret, private string $siteOrigin)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,6 +82,7 @@ final class PageController extends AbstractController
|
||||
'pageScript' => [] === $this->code->scriptsOf($page['document']) ? null : '/assets/seite/'.$page['id'].'.js',
|
||||
'forms' => $this->formStates($page, $request->query->getString('gesendet')),
|
||||
'breadcrumbs' => $this->breadcrumbs($page),
|
||||
'socialImage' => $this->socialImage($page),
|
||||
'structuredData' => $this->structuredData($page),
|
||||
'areas' => $areas,
|
||||
'sections' => $sections,
|
||||
@@ -197,6 +199,32 @@ final class PageController extends AbstractController
|
||||
*
|
||||
* @return list<array>
|
||||
*/
|
||||
/**
|
||||
* Das Bild, das beim Teilen erscheint - und im strukturierten Datensatz.
|
||||
*
|
||||
* Zuerst das eigens gesetzte Vorschaubild, sonst bei einem Beitrag sein Beitragsbild. Dieses
|
||||
* Feld gab es schon, ausgegeben wurde es nie: eine Einstellung, die speichert und nichts tut.
|
||||
* Die Adresse muss absolut sein, weil sie in fremden Diensten landet, und die Variante nicht
|
||||
* die größte - 1600 px reichen jedem Vorschaubild, 2400 kostet nur Ladezeit beim Teilen.
|
||||
*
|
||||
* @return array{url: string, alt: string}|null
|
||||
*/
|
||||
private function socialImage(array $page): ?array
|
||||
{
|
||||
$id = (string) ($page['og_media_id'] ?? '') ?: (string) ($page['featured_media_id'] ?? '');
|
||||
if ('' === $id) {
|
||||
return null;
|
||||
}
|
||||
$item = $this->media->find($id);
|
||||
if (null === $item || [] === $item['variants']) {
|
||||
return null;
|
||||
}
|
||||
$passend = array_filter($item['variants'], static fn (array $variant): bool => $variant['width'] <= 1600);
|
||||
$variant = end($passend) ?: $item['variants'][0];
|
||||
|
||||
return ['url' => rtrim($this->siteOrigin, '/').$variant['src'], 'alt' => (string) ($item['alt'] ?? '')];
|
||||
}
|
||||
|
||||
private function structuredData(array $page): array
|
||||
{
|
||||
$origin = rtrim($this->siteOrigin, '/');
|
||||
@@ -222,6 +250,10 @@ final class PageController extends AbstractController
|
||||
if (null !== ($page['author'] ?? null) && '' !== $page['author']) {
|
||||
$article['author'] = ['@type' => 'Person', 'name' => $page['author']];
|
||||
}
|
||||
$bild = $this->socialImage($page);
|
||||
if (null !== $bild) {
|
||||
$article['image'] = $bild['url'];
|
||||
}
|
||||
$blocks[] = $article;
|
||||
}
|
||||
$trail = $this->breadcrumbs($page);
|
||||
|
||||
Reference in new issue
Block a user