2021-11-12 16:31:35 +00:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
use App\Entities\Actor;
|
2023-04-14 11:11:53 +00:00
|
|
|
|
|
2021-11-12 16:31:35 +00:00
|
|
|
|
use App\Entities\Episode;
|
|
|
|
|
use App\Entities\EpisodeComment;
|
|
|
|
|
use App\Entities\Page;
|
|
|
|
|
use App\Entities\Podcast;
|
|
|
|
|
use App\Entities\Post;
|
2023-08-27 13:26:06 +00:00
|
|
|
|
use Config\Embed;
|
|
|
|
|
use Config\Images;
|
2021-11-12 16:31:35 +00:00
|
|
|
|
use Melbahja\Seo\MetaTags;
|
|
|
|
|
use Melbahja\Seo\Schema;
|
|
|
|
|
use Melbahja\Seo\Schema\Thing;
|
2023-04-14 11:11:53 +00:00
|
|
|
|
use Modules\Fediverse\Entities\PreviewCard;
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
/**
|
2022-02-19 16:06:11 +00:00
|
|
|
|
* @copyright 2021 Ad Aures
|
2021-11-12 16:31:35 +00:00
|
|
|
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
|
|
|
|
* @link https://castopod.org/
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_podcast_metatags')) {
|
|
|
|
|
function get_podcast_metatags(Podcast $podcast, string $page): string
|
|
|
|
|
{
|
2022-01-20 16:50:26 +00:00
|
|
|
|
$category = '';
|
|
|
|
|
if ($podcast->category->parent_id !== null) {
|
2022-01-23 19:58:30 +00:00
|
|
|
|
$category .= $podcast->category->parent->apple_category . ' › ';
|
2022-01-20 16:50:26 +00:00
|
|
|
|
}
|
2022-03-04 14:33:48 +00:00
|
|
|
|
|
2022-01-20 16:50:26 +00:00
|
|
|
|
$category .= $podcast->category->apple_category;
|
|
|
|
|
|
2021-11-12 16:31:35 +00:00
|
|
|
|
$schema = new Schema(
|
|
|
|
|
new Thing('PodcastSeries', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'name' => $podcast->title,
|
|
|
|
|
'headline' => $podcast->title,
|
|
|
|
|
'url' => current_url(),
|
|
|
|
|
'sameAs' => $podcast->link,
|
|
|
|
|
'identifier' => $podcast->guid,
|
|
|
|
|
'image' => $podcast->cover->feed_url,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'description' => $podcast->description,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'webFeed' => $podcast->feed_url,
|
|
|
|
|
'accessMode' => 'auditory',
|
|
|
|
|
'author' => $podcast->owner_name,
|
|
|
|
|
'creator' => $podcast->owner_name,
|
|
|
|
|
'publisher' => $podcast->publisher,
|
|
|
|
|
'inLanguage' => $podcast->language_code,
|
|
|
|
|
'genre' => $category,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
])
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
|
|
|
|
|
$metatags
|
2022-03-25 14:37:14 +00:00
|
|
|
|
->title($podcast->title . ' (@' . $podcast->handle . ') • ' . lang('Podcast.' . $page))
|
|
|
|
|
->description(esc($podcast->description))
|
2022-01-23 12:14:15 +00:00
|
|
|
|
->image((string) $podcast->cover->og_url)
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->canonical((string) current_url())
|
2023-08-27 13:26:06 +00:00
|
|
|
|
->og('image:width', (string) config(Images::class)->podcastCoverSizes['og']['width'])
|
|
|
|
|
->og('image:height', (string) config(Images::class)->podcastCoverSizes['og']['height'])
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->og('locale', $podcast->language_code)
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')))
|
2022-01-10 16:05:16 +00:00
|
|
|
|
->push('link', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'rel' => 'alternate',
|
2022-01-10 16:05:16 +00:00
|
|
|
|
'type' => 'application/activity+json',
|
2022-03-04 14:33:48 +00:00
|
|
|
|
'href' => url_to('podcast-activity', esc($podcast->handle)),
|
2022-01-10 16:05:16 +00:00
|
|
|
|
]);
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
if ($podcast->payment_pointer) {
|
|
|
|
|
$metatags->meta('monetization', $podcast->payment_pointer);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-04 14:33:48 +00:00
|
|
|
|
return '<link type="application/rss+xml" rel="alternate" title="' . esc(
|
|
|
|
|
$podcast->title
|
|
|
|
|
) . '" href="' . $podcast->feed_url . '" />' . PHP_EOL . $metatags->__toString() . PHP_EOL . $schema->__toString();
|
2021-11-12 16:31:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_episode_metatags')) {
|
|
|
|
|
function get_episode_metatags(Episode $episode): string
|
|
|
|
|
{
|
|
|
|
|
$schema = new Schema(
|
|
|
|
|
new Thing('PodcastEpisode', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'url' => url_to('episode', esc($episode->podcast->handle), $episode->slug),
|
|
|
|
|
'name' => $episode->title,
|
|
|
|
|
'image' => $episode->cover->feed_url,
|
|
|
|
|
'description' => $episode->description,
|
|
|
|
|
'datePublished' => $episode->published_at->format(DATE_ISO8601),
|
|
|
|
|
'timeRequired' => iso8601_duration($episode->audio->duration),
|
|
|
|
|
'duration' => iso8601_duration($episode->audio->duration),
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'associatedMedia' => new Thing('MediaObject', [
|
2022-12-09 15:04:42 +00:00
|
|
|
|
'contentUrl' => $episode->audio_url,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
]),
|
|
|
|
|
'partOfSeries' => new Thing('PodcastSeries', [
|
2022-03-25 14:37:14 +00:00
|
|
|
|
'name' => $episode->podcast->title,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'url' => $episode->podcast->link,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
]),
|
|
|
|
|
])
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
|
|
|
|
|
$metatags
|
|
|
|
|
->title($episode->title)
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->description(esc($episode->description))
|
2022-01-23 12:14:15 +00:00
|
|
|
|
->image((string) $episode->cover->og_url, 'player')
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->canonical($episode->link)
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')))
|
2023-08-27 13:26:06 +00:00
|
|
|
|
->og('image:width', (string) config(Images::class)->podcastCoverSizes['og']['width'])
|
|
|
|
|
->og('image:height', (string) config(Images::class)->podcastCoverSizes['og']['height'])
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->og('locale', $episode->podcast->language_code)
|
2022-01-21 08:52:28 +00:00
|
|
|
|
->og('audio', $episode->audio_opengraph_url)
|
2021-12-17 17:14:37 +00:00
|
|
|
|
->og('audio:type', $episode->audio->file_mimetype)
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->meta('article:published_time', $episode->published_at->format(DATE_ISO8601))
|
|
|
|
|
->meta('article:modified_time', $episode->updated_at->format(DATE_ISO8601))
|
|
|
|
|
->twitter('audio:partner', $episode->podcast->publisher ?? '')
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->twitter('audio:artist_name', esc($episode->podcast->owner_name))
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->twitter('player', $episode->getEmbedUrl('light'))
|
2023-08-27 13:26:06 +00:00
|
|
|
|
->twitter('player:width', (string) config(Embed::class)->width)
|
|
|
|
|
->twitter('player:height', (string) config(Embed::class)->height)
|
2022-01-10 16:05:16 +00:00
|
|
|
|
->push('link', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'rel' => 'alternate',
|
2022-01-10 16:05:16 +00:00
|
|
|
|
'type' => 'application/activity+json',
|
|
|
|
|
'href' => url_to('episode', $episode->podcast->handle, $episode->slug),
|
|
|
|
|
]);
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
if ($episode->podcast->payment_pointer) {
|
|
|
|
|
$metatags->meta('monetization', $episode->podcast->payment_pointer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $metatags->__toString() . PHP_EOL . '<link rel="alternate" type="application/json+oembed" href="' . base_url(
|
|
|
|
|
route_to('episode-oembed-json', $episode->podcast->handle, $episode->slug)
|
2022-03-04 14:33:48 +00:00
|
|
|
|
) . '" title="' . esc(
|
|
|
|
|
$episode->title
|
|
|
|
|
) . ' oEmbed json" />' . PHP_EOL . '<link rel="alternate" type="text/xml+oembed" href="' . base_url(
|
2021-11-12 16:31:35 +00:00
|
|
|
|
route_to('episode-oembed-xml', $episode->podcast->handle, $episode->slug)
|
2022-03-04 14:33:48 +00:00
|
|
|
|
) . '" title="' . esc($episode->title) . ' oEmbed xml" />' . PHP_EOL . $schema->__toString();
|
2021-11-12 16:31:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_post_metatags')) {
|
|
|
|
|
function get_post_metatags(Post $post): string
|
|
|
|
|
{
|
|
|
|
|
$socialMediaPosting = new Thing('SocialMediaPosting', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'@id' => url_to('post', esc($post->actor->username), $post->id),
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'datePublished' => $post->published_at->format(DATE_ISO8601),
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'author' => new Thing('Person', [
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'name' => $post->actor->display_name,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'url' => $post->actor->uri,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
]),
|
|
|
|
|
'text' => $post->message,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
if ($post->episode_id !== null) {
|
|
|
|
|
$socialMediaPosting->__set('sharedContent', new Thing('Audio', [
|
|
|
|
|
'headline' => $post->episode->title,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'url' => $post->episode->link,
|
|
|
|
|
'author' => new Thing('Person', [
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'name' => $post->episode->podcast->owner_name,
|
|
|
|
|
]),
|
|
|
|
|
]));
|
2023-04-14 11:11:53 +00:00
|
|
|
|
} elseif ($post->preview_card instanceof PreviewCard) {
|
2021-11-12 16:31:35 +00:00
|
|
|
|
$socialMediaPosting->__set('sharedContent', new Thing('WebPage', [
|
|
|
|
|
'headline' => $post->preview_card->title,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'url' => $post->preview_card->url,
|
|
|
|
|
'author' => new Thing('Person', [
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'name' => $post->preview_card->author_name,
|
|
|
|
|
]),
|
|
|
|
|
]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$schema = new Schema($socialMediaPosting);
|
|
|
|
|
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
$metatags
|
|
|
|
|
->title(lang('Post.title', [
|
|
|
|
|
'actorDisplayName' => $post->actor->display_name,
|
|
|
|
|
]))
|
|
|
|
|
->description($post->message)
|
|
|
|
|
->image($post->actor->avatar_image_url)
|
|
|
|
|
->canonical((string) current_url())
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')))
|
2022-01-10 16:05:16 +00:00
|
|
|
|
->push('link', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'rel' => 'alternate',
|
2022-01-10 16:05:16 +00:00
|
|
|
|
'type' => 'application/activity+json',
|
2022-03-04 14:33:48 +00:00
|
|
|
|
'href' => url_to('post', esc($post->actor->username), $post->id),
|
2022-01-10 16:05:16 +00:00
|
|
|
|
]);
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
return $metatags->__toString() . PHP_EOL . $schema->__toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_episode_comment_metatags')) {
|
|
|
|
|
function get_episode_comment_metatags(EpisodeComment $episodeComment): string
|
|
|
|
|
{
|
|
|
|
|
$schema = new Schema(new Thing('SocialMediaPosting', [
|
|
|
|
|
'@id' => url_to(
|
|
|
|
|
'episode-comment',
|
2022-03-04 14:33:48 +00:00
|
|
|
|
esc($episodeComment->actor->username),
|
2021-11-12 16:31:35 +00:00
|
|
|
|
$episodeComment->episode->slug,
|
|
|
|
|
$episodeComment->id
|
|
|
|
|
),
|
|
|
|
|
'datePublished' => $episodeComment->created_at->format(DATE_ISO8601),
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'author' => new Thing('Person', [
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'name' => $episodeComment->actor->display_name,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'url' => $episodeComment->actor->uri,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
]),
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'text' => $episodeComment->message,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'upvoteCount' => $episodeComment->likes_count,
|
|
|
|
|
]));
|
|
|
|
|
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
$metatags
|
|
|
|
|
->title(lang('Comment.title', [
|
|
|
|
|
'actorDisplayName' => $episodeComment->actor->display_name,
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'episodeTitle' => $episodeComment->episode->title,
|
2021-11-12 16:31:35 +00:00
|
|
|
|
]))
|
|
|
|
|
->description($episodeComment->message)
|
|
|
|
|
->image($episodeComment->actor->avatar_image_url)
|
|
|
|
|
->canonical((string) current_url())
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')))
|
2022-01-10 16:05:16 +00:00
|
|
|
|
->push('link', [
|
2023-06-12 14:47:38 +00:00
|
|
|
|
'rel' => 'alternate',
|
2022-01-10 16:05:16 +00:00
|
|
|
|
'type' => 'application/activity+json',
|
|
|
|
|
'href' => url_to(
|
|
|
|
|
'episode-comment',
|
|
|
|
|
$episodeComment->actor->username,
|
|
|
|
|
$episodeComment->episode->slug,
|
|
|
|
|
$episodeComment->id
|
|
|
|
|
),
|
|
|
|
|
]);
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
return $metatags->__toString() . PHP_EOL . $schema->__toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_follow_metatags')) {
|
|
|
|
|
function get_follow_metatags(Actor $actor): string
|
|
|
|
|
{
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
$metatags
|
|
|
|
|
->title(lang('Podcast.followTitle', [
|
|
|
|
|
'actorDisplayName' => $actor->display_name,
|
|
|
|
|
]))
|
|
|
|
|
->description($actor->summary)
|
|
|
|
|
->image($actor->avatar_image_url)
|
|
|
|
|
->canonical((string) current_url())
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')));
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
return $metatags->__toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_remote_actions_metatags')) {
|
|
|
|
|
function get_remote_actions_metatags(Post $post, string $action): string
|
|
|
|
|
{
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
$metatags
|
|
|
|
|
->title(lang('Fediverse.' . $action . '.title', [
|
|
|
|
|
'actorDisplayName' => $post->actor->display_name,
|
|
|
|
|
],))
|
|
|
|
|
->description($post->message)
|
|
|
|
|
->image($post->actor->avatar_image_url)
|
|
|
|
|
->canonical((string) current_url())
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')));
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
return $metatags->__toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_home_metatags')) {
|
|
|
|
|
function get_home_metatags(): string
|
|
|
|
|
{
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
$metatags
|
2022-03-25 14:37:14 +00:00
|
|
|
|
->title(service('settings')->get('App.siteName'))
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->description(esc(service('settings')->get('App.siteDescription')))
|
2023-04-13 11:45:03 +00:00
|
|
|
|
->image(get_site_icon_url('512'))
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->canonical((string) current_url())
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')));
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
return $metatags->__toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('get_page_metatags')) {
|
|
|
|
|
function get_page_metatags(Page $page): string
|
|
|
|
|
{
|
|
|
|
|
$metatags = new MetaTags();
|
|
|
|
|
$metatags
|
|
|
|
|
->title(
|
2022-03-25 14:37:14 +00:00
|
|
|
|
$page->title . service('settings')->get('App.siteTitleSeparator') . service(
|
2021-11-12 16:31:35 +00:00
|
|
|
|
'settings'
|
2022-03-25 14:37:14 +00:00
|
|
|
|
)->get('App.siteName')
|
2021-11-12 16:31:35 +00:00
|
|
|
|
)
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->description(esc(service('settings')->get('App.siteDescription')))
|
2023-04-13 11:45:03 +00:00
|
|
|
|
->image(get_site_icon_url('512'))
|
2021-11-12 16:31:35 +00:00
|
|
|
|
->canonical((string) current_url())
|
2022-03-04 14:33:48 +00:00
|
|
|
|
->og('site_name', esc(service('settings')->get('App.siteName')));
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
return $metatags->__toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! function_exists('iso8601_duration')) {
|
|
|
|
|
// From https://stackoverflow.com/a/40761380
|
|
|
|
|
function iso8601_duration(float $seconds): string
|
|
|
|
|
{
|
|
|
|
|
$days = floor($seconds / 86400);
|
2022-07-02 10:37:38 +00:00
|
|
|
|
$seconds = (int) $seconds % 86400;
|
2021-11-12 16:31:35 +00:00
|
|
|
|
|
|
|
|
|
$hours = floor($seconds / 3600);
|
|
|
|
|
$seconds %= 3600;
|
|
|
|
|
|
|
|
|
|
$minutes = floor($seconds / 60);
|
|
|
|
|
$seconds %= 60;
|
|
|
|
|
|
|
|
|
|
return sprintf('P%dDT%dH%dM%dS', $days, $hours, $minutes, $seconds);
|
|
|
|
|
}
|
|
|
|
|
}
|