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);
}
}
