simplepodcast-8.x-1.x-dev/src/Controller/SimplePodcastController.php
src/Controller/SimplePodcastController.php
<?php namespace Drupal\simplepodcast\Controller; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Path\AliasManager; use Drupal\node\Entity\Node; use Drupal\node\NodeInterface; use Drupal\simplepodcast\SimplePodcastCommonFunctions; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; /** * Class SimplePodcastController. * * Controller that builds the XML for the Podcast feed. */ class SimplePodcastController extends ControllerBase { /** * Content type machine name for Episodes. */ const EPISODE_CONTENT_TYPE = 'episode_content_type'; /** * AliasManager. * * @var \Drupal\Core\Path\AliasManager */ private $aliasManager; /** * @var \Drupal\Core\Extension\ModuleHandlerInterface */ protected $moduleHandler; /** * SimplePodcastController constructor. * * @param \Drupal\Core\Path\AliasManager $aliasManager * AliasManager. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * Module Handler. */ public function __construct(AliasManager $aliasManager, ModuleHandlerInterface $module_handler) { $this->aliasManager = $aliasManager; $this->moduleHandler = $module_handler; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('path.alias_manager'), $container->get('module_handler') ); } /** * Build and return a render array of the content for the feed. * * @return \Symfony\Component\HttpFoundation\Response * Render array for the XML output. */ public function content() { $title = SimplePodcastCommonFunctions::getConfig('title'); $descr = SimplePodcastCommonFunctions::getConfig('description'); $link = \Drupal::request()->getSchemeAndHttpHost(); $lang = SimplePodcastCommonFunctions::getConfig('language'); $owner = SimplePodcastCommonFunctions::getConfig('owner_name'); $author = SimplePodcastCommonFunctions::getConfig('owner_author'); $copy = SimplePodcastCommonFunctions::getConfig('copyright'); $email = SimplePodcastCommonFunctions::getConfig('owner_email'); $channel_image = SimplePodcastCommonFunctions::getConfig('channel_image'); $cat1 = SimplePodcastCommonFunctions::getConfig('category_1'); $cat2 = SimplePodcastCommonFunctions::getConfig('category_2'); $cat3 = SimplePodcastCommonFunctions::getConfig('category_3'); $items = $this->buildItems(); $rss_link = \Drupal::request()->getSchemeAndHttpHost() . '/' . SimplePodcastCommonFunctions::getConfig('rss_path_name'); $explicit = SimplePodcastCommonFunctions::getConfig('explicit') ? 'Yes' : 'No'; $categories = [$this->buildCategory($cat1)]; if ($cat2 != '') { array_push($categories, $this->buildCategory($cat2)); } if ($cat3 != '') { array_push($categories, $this->buildCategory($cat3)); } $response = new Response(); $response->headers->set('Content-Type', 'application/xml'); $render = [ '#theme' => 'simplepodcast_xml', '#channel_title' => $this->t($title), '#channel_link' => $link, '#channel_lang' => $this->t($lang), '#channel_copyright' => $this->t($copy), '#channel_description' => $this->t($descr), '#channel_explicit' => $this->t($explicit), '#channel_rss_url' => $rss_link, '#channel_owner_name' => $this->t($owner), '#channel_owner_author' => $this->t($author), '#channel_owner_email' => $email, '#channel_image_url' => $channel_image, '#channel_categories' => $categories, '#items' => $items, ]; // Allow modules to alter the output. $this->moduleHandler->alter('simplepodcast_xml_render', $render); $xml = \Drupal::service('renderer')->renderRoot($render); $response->setContent($xml); return $response; } /** * Break out the category string into an associative array. * * @param string $category_string * The delimited category string. * * @return array * The subcategory and/or main category. */ private function buildCategory($category_string) { list($main_cat, $sub_cat) = explode('|', $category_string); if ($sub_cat) { return ['main' => $main_cat, 'sub' => $sub_cat]; } else { return ['main' => $main_cat]; } } /** * Build the data for all episodes. * * @return array * The built data for all episodes. */ private function buildItems() { $items = []; $episode_ids = $this->getIDS(); foreach ($episode_ids as $episode) { $items[] = $this->buildItem($episode); } return $items; } /** * Get the node id(s) for the Episode content type. * * @return array|int * Node ids for the episode content type. */ private function getIDS() { $query = \Drupal::entityQuery('node') ->condition('status', NodeInterface::PUBLISHED) ->condition('type', SimplePodcastCommonFunctions::getConfig(self::EPISODE_CONTENT_TYPE)) ->sort('created', 'DESC'); $nids = $query->execute(); return $nids; } /** * Build the data for an episode. * * @param int $id * The node id. * * @return array * The built data for an episode. */ private function buildItem($id) { $node = Node::load($id); //item title //$title = $node->title->value; $title_field = SimplePodcastCommonFunctions::getConfig('item_title'); $title = SimplePodcastCommonFunctions::getFieldValue($node, $title_field); $title_safe = $this->makeXmlSafe($title); $author_field = SimplePodcastCommonFunctions::getConfig('item_author'); $author = SimplePodcastCommonFunctions::getFieldValue($node, $author_field); $subtitle_field = SimplePodcastCommonFunctions::getConfig('item_subtitle'); $subtitle = SimplePodcastCommonFunctions::getFieldValue($node, $subtitle_field); $subtitle_safe = $this->makeXmlSafe($subtitle); //item link $link = $this->aliasManager->getAliasByPath('/node/' . $id); $link = \Drupal::request()->getSchemeAndHttpHost() . $link; //item description $summary_field = SimplePodcastCommonFunctions::getConfig('item_summary'); $summary = SimplePodcastCommonFunctions::getFieldValue($node, $summary_field); $summary_safe = $this->makeCdataSafe($summary); //image $image_field = SimplePodcastCommonFunctions::getConfig('item_image'); $image_url = SimplePodcastCommonFunctions::getFieldImage($node, $image_field); //enclosure $media_field = SimplePodcastCommonFunctions::getConfig('item_media'); $media = SimplePodcastCommonFunctions::getFieldUri($node, $media_field); $media_length_field = SimplePodcastCommonFunctions::getConfig('item_media_length'); $media_length = SimplePodcastCommonFunctions::getFieldValue($node, $media_length_field); $media_length = ($media_length > 0) ? $media_length : 0; $duration_field = SimplePodcastCommonFunctions::getConfig('item_media_duration'); $duration = SimplePodcastCommonFunctions::getFieldValue($node, $duration_field); $duration_formatted = str_pad(floor($duration / 3600), 2, '0', STR_PAD_LEFT) . ":" . str_pad(floor(($duration / 60) % 60), 2, '0', STR_PAD_LEFT) . ":" . str_pad($duration % 60, 2, '0', STR_PAD_LEFT); //pubdate $created_date_formatted = date('r', $node->created->value); $item = [ 'item_title' => $this->t($title_safe), 'item_author' => $this->t($author), 'item_subtitle' => $this->t($subtitle_safe), 'item_summary' => $this->t($summary_safe), 'item_image_url' => $image_url, 'item_media_url' => $media, 'item_media_length' => $media_length, 'item_guid' => $link, 'item_pubdate' => $created_date_formatted, 'item_duration' => $duration_formatted, ]; return $item; } /** * Remove invalid characters. * * @param string $text * The text to be cleaned. * * @return string|string[]|null * Returned the sanitized string. */ private function makeXmlSafe($text) { if (!$text) { return ''; } $invalid_characters = '/[^\x9\xa\x20-\xD7FF\xE000-\xFFFD]/'; return preg_replace($invalid_characters, '', $text); } /** * Remove invalid characters. * * @param string $text * The text to be cleaned. * * @return string|string[]|null * Returned the sanitized string. */ private function makeCdataSafe($text) { return $this->makeXmlSafe($text); } }