181 lines
4.7 KiB
PHP
181 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
abstract class StructuredData
|
|
{
|
|
/**
|
|
* @param array<int, array<string, mixed>> $graph
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected static function wrap(array $graph): array
|
|
{
|
|
return [
|
|
'@context' => 'https://schema.org',
|
|
'@graph' => array_values($graph),
|
|
];
|
|
}
|
|
|
|
protected static function siteUrl(): string
|
|
{
|
|
return url('/');
|
|
}
|
|
|
|
protected static function siteName(): string
|
|
{
|
|
return (string) setting('site_name', config('app.name'));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected static function websiteNode(?string $searchUrlTemplate = null): array
|
|
{
|
|
$siteUrl = static::siteUrl();
|
|
$siteName = static::siteName();
|
|
|
|
$node = [
|
|
'@type' => 'WebSite',
|
|
'@id' => $siteUrl . '#website',
|
|
'url' => $siteUrl,
|
|
'name' => $siteName,
|
|
'inLanguage' => app()->getLocale(),
|
|
'publisher' => ['@id' => $siteUrl . '#organization'],
|
|
];
|
|
|
|
if ($searchUrlTemplate) {
|
|
$node['potentialAction'] = [
|
|
'@type' => 'SearchAction',
|
|
'target' => [
|
|
'@type' => 'EntryPoint',
|
|
'urlTemplate' => $searchUrlTemplate,
|
|
],
|
|
'query-input' => 'required name=search_term_string',
|
|
];
|
|
}
|
|
|
|
return $node;
|
|
}
|
|
|
|
protected static function organizationNode(): array
|
|
{
|
|
$siteUrl = static::siteUrl();
|
|
$siteName = static::siteName();
|
|
|
|
$node = [
|
|
'@type' => 'Organization',
|
|
'@id' => $siteUrl . '#organization',
|
|
'name' => $siteName,
|
|
'url' => $siteUrl,
|
|
];
|
|
|
|
$logo = setting('site_logo');
|
|
if ($logo) {
|
|
$logoUrl = str_starts_with($logo, 'http') ? $logo : asset('storage/' . ltrim($logo, '/'));
|
|
$node['logo'] = [
|
|
'@type' => 'ImageObject',
|
|
'url' => $logoUrl,
|
|
];
|
|
}
|
|
|
|
$phone = setting('contact_phone');
|
|
if ($phone) {
|
|
$node['telephone'] = $phone;
|
|
}
|
|
|
|
$email = setting('contact_email');
|
|
if ($email) {
|
|
$node['email'] = $email;
|
|
}
|
|
|
|
$address = setting('contact_address');
|
|
if ($address) {
|
|
$node['address'] = [
|
|
'@type' => 'PostalAddress',
|
|
'streetAddress' => $address,
|
|
];
|
|
}
|
|
|
|
$socialLinks = setting('social_links');
|
|
if ($socialLinks) {
|
|
$links = is_string($socialLinks) ? json_decode($socialLinks, true) : $socialLinks;
|
|
if (is_array($links)) {
|
|
$sameAs = [];
|
|
foreach ($links as $platform => $url) {
|
|
if (!empty($url)) {
|
|
$sameAs[] = $url;
|
|
}
|
|
}
|
|
if (!empty($sameAs)) {
|
|
$node['sameAs'] = $sameAs;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $node;
|
|
}
|
|
|
|
/**
|
|
* @param array<int, array{name: string, item: string}> $items
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected static function breadcrumbNode(string $pageUrl, array $items): array
|
|
{
|
|
$elements = [];
|
|
|
|
foreach ($items as $index => $item) {
|
|
$elements[] = [
|
|
'@type' => 'ListItem',
|
|
'position' => $index + 1,
|
|
'name' => $item['name'],
|
|
'item' => $item['item'],
|
|
];
|
|
}
|
|
|
|
return [
|
|
'@type' => 'BreadcrumbList',
|
|
'@id' => $pageUrl . '#breadcrumb',
|
|
'itemListElement' => $elements,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $extra
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected static function webPageNode(
|
|
string $pageUrl,
|
|
string $name,
|
|
?string $description = null,
|
|
array $extra = [],
|
|
): array {
|
|
$node = array_merge([
|
|
'@type' => 'WebPage',
|
|
'@id' => $pageUrl . '#webpage',
|
|
'url' => $pageUrl,
|
|
'name' => $name,
|
|
'inLanguage' => app()->getLocale(),
|
|
'isPartOf' => ['@id' => static::siteUrl() . '#website'],
|
|
'breadcrumb' => ['@id' => $pageUrl . '#breadcrumb'],
|
|
], $extra);
|
|
|
|
if ($description) {
|
|
$node['description'] = $description;
|
|
}
|
|
|
|
return $node;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected static function listItem(int $position, array $item): array
|
|
{
|
|
return [
|
|
'@type' => 'ListItem',
|
|
'position' => $position,
|
|
'item' => $item,
|
|
];
|
|
}
|
|
}
|