schemadotorg_starterkit_podcast-1.0.x-dev/schemadotorg_starterkit_podcast.module
schemadotorg_starterkit_podcast.module
<?php
/**
* @file
* A starter kit that creates Schema.org PodcastSeries and PodcastEpisode types.
*/
declare(strict_types=1);
use Drupal\Core\Entity\EntityInterface;
use Drupal\node\NodeInterface;
/**
* Implements hook_ENTITY_TYPE_create().
*/
function schemadotorg_starterkit_podcast_node_create(NodeInterface $node): void {
if ($node->getType() !== 'podcast_episode'
|| !$node->hasField('schema_part_of_series')) {
return;
}
$part_of_series = \Drupal::requestStack()->getCurrentRequest()->query->get('part_of_series')
?? $node->schema_part_of_series->target_id;
_schemadotorg_starterkit_podcast_set_episode_number($node, $part_of_series);
}
/**
* Implements hook_ENTITY_TYPE_presave().
*/
function schemadotorg_starterkit_podcast_node_presave(NodeInterface $node): void {
if ($node->getType() !== 'podcast_episode'
|| !$node->hasField('schema_part_of_series')) {
return;
}
/** @var \Drupal\node\NodeInterface|null $series_node */
$series_node = $node->schema_part_of_series->entity;
if (!$series_node) {
return;
}
// Update the Podcast Series changed time when a new episode is added.
$series_node->setChangedTime(time())
->setSyncing(TRUE)
->save();
// Check that devel is generating a content entity.
// @see https://www.drupal.org/project/devel/issues/2582845
if (!empty($node->devel_generate)) {
// Set episode number to NULL to force it to be populated.
$node->schema_episode_number->value = NULL;
_schemadotorg_starterkit_podcast_set_episode_number($node, $series_node->id());
}
}
/**
* Implements hook_schemadotorg_jsonld_schema_type_entity_alter().
*/
function schemadotorg_starterkit_podcast_schemadotorg_jsonld_schema_type_entity_alter(array &$data, EntityInterface $entity): void {
// Use computed podcast episode's label which includes the series and episode
// number via JSON-LD.
// @see /admin/structure/types/manage/podcast_episode/auto-label
if ($entity->getEntityTypeId() === 'node' && $entity->bundle() === 'podcast_episode') {
$data['name'] = $entity->label();
}
}
/* ************************************************************************** */
// Private functions.
/* ************************************************************************** */
/**
* Set a new podcast episode's episode number.
*
* @param \Drupal\node\NodeInterface $node
* A node.
* @param int|string|null $series_nid
* The podcast episode's podcast series node id.
*/
function _schemadotorg_starterkit_podcast_set_episode_number(NodeInterface $node, int|string|null $series_nid): void {
if (empty($series_nid)
|| $node->getType() !== 'podcast_episode'
|| !empty($node->schema_episode_number->value)) {
return;
}
$episode_nids = \Drupal::entityQuery('node')
->accessCheck(FALSE)
->condition('type', 'podcast_episode')
->condition('schema_part_of_series.target_id', $series_nid)
->execute();
if ($episode_nids) {
$query = \Drupal::database()->select('node__schema_episode_number');
$query->condition('entity_id', $episode_nids, 'IN');
$query->addExpression('MAX(schema_episode_number_value)');
$next_episode_number = ($query->execute()->fetchField() ?? 0) + 1;
}
else {
$next_episode_number = 1;
}
$node->schema_episode_number->value = $next_episode_number;
}
