last update
This commit is contained in:
parent
d494df71d6
commit
35db57fd37
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster;
|
||||
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Route,
|
||||
Url;
|
||||
|
||||
use Cms\Classes\Controller;
|
||||
|
||||
use System\Classes\PluginBase,
|
||||
System\Classes\PluginManager;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Feedster,
|
||||
KoderHut\RssFeedster\Classes\DataSource\NewsSource,
|
||||
KoderHut\RssFeedster\Classes\View\XmlRenderer,
|
||||
KoderHut\RssFeedster\Models\Settings,
|
||||
KoderHut\RssFeedster\Classes\Support\Adapters\NewsXmlAdapter,
|
||||
KoderHut\RssFeedster\Classes\Contracts\IAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* RssFeed Plugin Information File
|
||||
*/
|
||||
class Plugin
|
||||
extends PluginBase
|
||||
{
|
||||
/**
|
||||
* Namespace const
|
||||
*/
|
||||
const KODERHUT_RSSFEEDSTER_NS = 'KoderHut\RssFeedster';
|
||||
|
||||
/**
|
||||
* Define the plug-in dependencies
|
||||
*
|
||||
* @var array Plugin dependencies
|
||||
*/
|
||||
public $require = ['Indikator.News'];
|
||||
|
||||
/**
|
||||
* Returns information about this plugin.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function pluginDetails()
|
||||
{
|
||||
return [
|
||||
'name' => 'koderhut.rssfeedster::lang.plugin.name',
|
||||
'description' => 'koderhut.rssfeedster::lang.plugin.description',
|
||||
'author' => 'Denis-Florin Rendler (KoderHut)',
|
||||
'icon' => 'icon-rss',
|
||||
'homepage' => 'https://github.com/rendler-denis/rssfeedster',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the route for the RSS builder
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$rssUrl = Settings::get('feed_url');
|
||||
|
||||
Route::get('/{locale?}'.$rssUrl, 'KoderHut\RssFeedster\Controllers\Rss@buildRssFeed');
|
||||
|
||||
$this->app->bind('KoderHut\RssFeedster\Feed', function($app)
|
||||
{
|
||||
return new Feedster();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register our data source and renderer
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
/**
|
||||
* Set up the data source for the feed
|
||||
*/
|
||||
$this->app->bind('KoderHut\RssFeedster\DataSource', function($app)
|
||||
{
|
||||
$config['page'] = Settings::get('post_page');
|
||||
$config['comments_anchor'] = Settings::get('comments_anchor');
|
||||
$config['controller'] = new Controller();
|
||||
|
||||
return new NewsSource($config);
|
||||
});
|
||||
|
||||
/**
|
||||
* Set up the adapter interface between the XML renderer and
|
||||
* the blog posts data
|
||||
*/
|
||||
$this->app->bind(IAdapter::DI_NAMESPACE, function () {
|
||||
return new NewsXmlAdapter();
|
||||
});
|
||||
|
||||
/**
|
||||
* Set up the feed renderer
|
||||
*/
|
||||
$this->app->bind('KoderHut\RssFeedster\Renderer', function($app)
|
||||
{
|
||||
$config = [
|
||||
'description' => Settings::get('feed_description'),
|
||||
'title' => Settings::get('feed_title'),
|
||||
'category' => Settings::get('feed_category'),
|
||||
'copyright' => Settings::get('feed_copyright'),
|
||||
'language' => App::getLocale(),
|
||||
'link' => Url::action('KoderHut\RssFeedster\Controllers\Rss@buildRssFeed'),
|
||||
];
|
||||
$pluginPath = PluginManager::instance()->getPluginPath(Plugin::KODERHUT_RSSFEEDSTER_NS);
|
||||
$xmlTemplate = $pluginPath . DIRECTORY_SEPARATOR . 'resources'
|
||||
. DIRECTORY_SEPARATOR . 'feed-template.xml';
|
||||
|
||||
return
|
||||
new XmlRenderer(
|
||||
$config,
|
||||
file_get_contents($xmlTemplate),
|
||||
$this->app->make(IAdapter::DI_NAMESPACE)
|
||||
);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the plug-in settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function registerSettings()
|
||||
{
|
||||
return [
|
||||
'settings' => [
|
||||
'label' => 'koderhut.rssfeedster::lang.plugin.name',
|
||||
'description' => 'koderhut.rssfeedster::lang.settings.base.description',
|
||||
'icon' => 'icon-rss',
|
||||
'class' => 'KoderHut\RssFeedster\Models\Settings',
|
||||
'order' => 500,
|
||||
'keywords' => 'rss feed',
|
||||
'category' => 'KoderHut',
|
||||
'permissions' => ['koderhut.rssfeedster.access_config'],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plug-in permissions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function registerPermissions()
|
||||
{
|
||||
return [
|
||||
'koderhut.rssfeedster.access_config' => [
|
||||
'label' => 'koderhut.rssfeedster::lang.messages.permissions.access_config_label',
|
||||
'tab' => 'koderhut.rssfeedster::lang.plugin.name'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
## RssFeedster
|
||||
|
||||
> Note: This plug-in extends and depends on the [RainLab's Blog](https://octobercms.com/plugin/rainlab-blog) plug-in to generate the feed.
|
||||
|
||||
An on-the-fly, W3C validated, customisable RSS feed builder plug-in.
|
||||
The generated RSS feed was built according to the W3C standards. It includes all the required tags as well as a few optional ones, like copyright, feed category, feed language. These optional tags can help feed aggregators to better promote your feed.
|
||||
|
||||
The feed is built on request, so it always generates an up-to-date feed.
|
||||
The plug-in is very customisable by both end-user as well as extendable by other developers.
|
||||
|
||||
## Features
|
||||
- customisable URL
|
||||
- feed built on request
|
||||
- includes optional RSS fields for better integration with feed aggregators
|
||||
- data source and renderer easily extendable by developers.
|
||||
|
||||
## License
|
||||
|
||||
The License is MIT with the exception that you are NOT allowed to sell the plug-in under ANY circumstance.
|
||||
You can install, debug and fix the code for your clients and charge for those services but you are NOT allowed to charge for the plug-in itself.
|
||||
|
||||
If you are in doubt about the license you can contact me at connect [ at ] rendler.me
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes;
|
||||
|
||||
use October\Rain\Exception\ApplicationException;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IDataSource,
|
||||
KoderHut\RssFeedster\Classes\Contracts\IRenderer,
|
||||
KoderHut\RssFeedster\Models\Settings,
|
||||
KoderHut\RssFeedster\Classes\Support\Facades\Renderer,
|
||||
KoderHut\RssFeedster\Classes\Support\Facades\DataSource;
|
||||
|
||||
/**
|
||||
* Class Feedster
|
||||
* Service class in charge of collecting the feed data
|
||||
* and rendering it
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes
|
||||
*/
|
||||
class Feedster
|
||||
{
|
||||
/**
|
||||
* The feed generator name
|
||||
*/
|
||||
const FEED_GENERATOR_NAME = 'KoderHut.eu - RSSFeedster for OctoberCMS';
|
||||
|
||||
/**
|
||||
* Feed title
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $feedTitle = '';
|
||||
|
||||
/**
|
||||
* Maximum number of rows to retrieve and render
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $dataRowsLimit = 1;
|
||||
|
||||
/**
|
||||
* Either to display the full content
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $fullContent = false;
|
||||
|
||||
/**
|
||||
* Data source for retrieving the feed data
|
||||
*
|
||||
* @var IDataSource
|
||||
*/
|
||||
protected $source = null;
|
||||
|
||||
/**
|
||||
* Feed renderer
|
||||
*
|
||||
* @var IRenderer
|
||||
*/
|
||||
protected $renderer = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @throws ApplicationException
|
||||
*/
|
||||
public function __construct(IDataSource $source = null, IRenderer $renderer = null, Settings $config = null)
|
||||
{
|
||||
$config = $config instanceof Settings ? $config : Settings::instance();
|
||||
|
||||
$this->validateSettings($config);
|
||||
|
||||
$this->feedTitle = $config->feed_title;
|
||||
$this->dataRowsLimit = $config->post_max_number;
|
||||
$this->fullContent = $config->post_full_content;
|
||||
|
||||
$this->source = $source ?: DataSource::getFacadeRoot();
|
||||
$this->renderer = $renderer ?: Renderer::getFacadeRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate required settings
|
||||
*
|
||||
* @param Settings $settings
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ApplicationException
|
||||
*/
|
||||
protected function validateSettings(Settings $settings)
|
||||
{
|
||||
if (empty($settings->feed_title)) {
|
||||
throw new ApplicationException('Feed Title is required!');
|
||||
}
|
||||
|
||||
if ($settings->post_max_number <= 0) {
|
||||
$this->dataRowsLimit = 1000;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a data source for building the feed
|
||||
*
|
||||
* @param IDataSource $source
|
||||
*/
|
||||
public function setSource(IDataSource $source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a renderer for the feed
|
||||
*
|
||||
* @param Renderer $renderer
|
||||
*/
|
||||
public function setRenderer(IRenderer $renderer)
|
||||
{
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rendered feed data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFeed()
|
||||
{
|
||||
$feedData = $this->source->getData($this->dataRowsLimit);
|
||||
$renderedData = $this->renderer->renderData($feedData);
|
||||
|
||||
return $renderedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content-type for this renderer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->renderer->getContentType();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 13/10/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\Contracts;
|
||||
|
||||
/**
|
||||
* Interface IAdapter
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\Contracts
|
||||
*/
|
||||
interface IAdapter
|
||||
{
|
||||
/**
|
||||
* Namespace const used for DI
|
||||
*/
|
||||
const DI_NAMESPACE = 'KoderHut\RssFeedster\Adapter';
|
||||
|
||||
/**
|
||||
* Method used to connect a data source to a renderer
|
||||
*
|
||||
* @param mixed $item
|
||||
* @param mixed $dataItem
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDataValue($item, $dataItem);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\Contracts;
|
||||
|
||||
/**
|
||||
* Interface IDataSource
|
||||
*
|
||||
* Data source interface
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\Contracts
|
||||
*/
|
||||
interface IDataSource
|
||||
{
|
||||
/**
|
||||
* Load the data from source
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function loadData();
|
||||
|
||||
/**
|
||||
* Load, if not laready loaded, and return the data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData();
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\Contracts;
|
||||
|
||||
/**
|
||||
* Interface IRenderer
|
||||
*
|
||||
* Renderer interface
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\Interfaces
|
||||
*/
|
||||
interface IRenderer
|
||||
{
|
||||
/**
|
||||
* Render the data
|
||||
*
|
||||
* @param $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function renderData($data);
|
||||
|
||||
/**
|
||||
* Return the content-type for this renderer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType();
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\DataSource;
|
||||
|
||||
use \Indikator\News\Models\Posts;
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IDataSource;
|
||||
|
||||
class NewsSource implements IDataSource
|
||||
{
|
||||
/**
|
||||
* Maximum number of items to display in the feed
|
||||
*/
|
||||
const MAX_NO_ITEMS = 10;
|
||||
|
||||
/**
|
||||
* Cache for the data
|
||||
*
|
||||
* @var array|mixed
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Disaply the full content of the post
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $displayFullContent = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct($params = null)
|
||||
{
|
||||
if (null === $params) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->page = $params['page'];
|
||||
$this->controller = $params['controller'];
|
||||
$this->commentsAnchor = $params['comments_anchor'];
|
||||
}
|
||||
/**
|
||||
* Load the news
|
||||
*
|
||||
* @param int $maxItems
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function loadData($maxItems = self::MAX_NO_ITEMS)
|
||||
{
|
||||
$posts = null;
|
||||
|
||||
if (!empty($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
$model = new Posts();
|
||||
$locale = request('locale');
|
||||
|
||||
$posts = $model->listFrontEnd([
|
||||
'sort' => 'published_at desc',
|
||||
'perPage' => $maxItems,
|
||||
'locale' => in_array($locale,['ru','en','tk'])? $locale : 'en'
|
||||
]);
|
||||
|
||||
|
||||
foreach ($posts as $post) {
|
||||
$post->setUrl($this->page, $this->controller);
|
||||
// $post->comments_url = "{$post->url}/#{$this->commentsAnchor}";
|
||||
$post->feed_content = true === $this->displayFullContent ? $post->content : $post->introductory;
|
||||
}
|
||||
|
||||
return $this->data = $posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve posts from cache or load them and then return them
|
||||
*
|
||||
* @param int $maxItems
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData($maxItems = self::MAX_NO_ITEMS)
|
||||
{
|
||||
|
||||
if (null !== $this->data && !empty($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$this->data = $this->loadData($maxItems);
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if we display the full post content or a summary
|
||||
*
|
||||
* @param bool $fullContent
|
||||
*/
|
||||
public function setDisplayFullContent($fullContent = true)
|
||||
{
|
||||
$this->displayFullContent = $fullContent;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\DataSource;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IDataSource;
|
||||
|
||||
use RainLab\Blog\Models\Post;
|
||||
|
||||
/**
|
||||
* Class PostsSource
|
||||
*
|
||||
* Feed data source retrieving blog posts.
|
||||
* Requires: RainLab.Blog plug-in
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\DataSource
|
||||
*/
|
||||
class PostsSource
|
||||
implements IDataSource
|
||||
{
|
||||
/**
|
||||
* Maximum number of items to display in the feed
|
||||
*/
|
||||
const MAX_NO_ITEMS = 10;
|
||||
|
||||
/**
|
||||
* Cache for the data
|
||||
*
|
||||
* @var array|mixed
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Disaply the full content of the post
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $displayFullContent = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct($params = null)
|
||||
{
|
||||
if (null === $params) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->page = $params['page'];
|
||||
$this->controller = $params['controller'];
|
||||
$this->commentsAnchor = $params['comments_anchor'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the blog posts
|
||||
*
|
||||
* @param int $maxItems
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function loadData($maxItems = self::MAX_NO_ITEMS)
|
||||
{
|
||||
$posts = null;
|
||||
|
||||
if (!empty($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
$model = new Post();
|
||||
$posts = $model->listFrontEnd([
|
||||
'sort' => 'published_at desc',
|
||||
'perPage' => $maxItems,
|
||||
]);
|
||||
|
||||
foreach ($posts as $post) {
|
||||
$post->setUrl($this->page, $this->controller);
|
||||
$post->comments_url = "{$post->url}/#{$this->commentsAnchor}";
|
||||
$post->feed_content = true === $this->displayFullContent ? $post->content : $post->summary;
|
||||
}
|
||||
|
||||
return $this->data = $posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve posts from cache or load them and then return them
|
||||
*
|
||||
* @param int $maxItems
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData($maxItems = self::MAX_NO_ITEMS)
|
||||
{
|
||||
if (null !== $this->data && !empty($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$this->data = $this->loadData($maxItems);
|
||||
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if we display the full post content or a summary
|
||||
*
|
||||
* @param bool $fullContent
|
||||
*/
|
||||
public function setDisplayFullContent($fullContent = true)
|
||||
{
|
||||
$this->displayFullContent = $fullContent;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 13/10/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\Support\Adapters;
|
||||
|
||||
use DomElement,
|
||||
DOMCdataSection;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IAdapter;
|
||||
|
||||
/**
|
||||
* Class BlogPostXmlAdapter
|
||||
* Adapter between the Posts data source and the XML renderer
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\Support\Adapters
|
||||
*/
|
||||
class BlogPostXmlAdapter
|
||||
implements IAdapter
|
||||
{
|
||||
|
||||
/**
|
||||
* Transform Post data into XML elements
|
||||
*
|
||||
* @param mixed $item
|
||||
* @param mixed $dataItem
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getDataValue($item, $dataItem)
|
||||
{
|
||||
switch ($item->tagName) {
|
||||
case 'title':
|
||||
$item->nodeValue = $dataItem->title;
|
||||
break;
|
||||
|
||||
case 'link':
|
||||
case 'guid':
|
||||
$item->nodeValue = $dataItem->url;
|
||||
break;
|
||||
|
||||
case 'pubDate':
|
||||
$item->nodeValue = $dataItem->published_at->format('r');
|
||||
break;
|
||||
|
||||
case 'dc:creator':
|
||||
if (!$dataItem->user instanceof User) {
|
||||
break;
|
||||
}
|
||||
$creator = new DOMCdataSection(
|
||||
"{$dataItem->user->email} ({$dataItem->user->full_name})"
|
||||
);
|
||||
$item->appendChild($creator);
|
||||
break;
|
||||
|
||||
case 'category':
|
||||
$categories = $dataItem->categories;
|
||||
|
||||
if (!empty($item->nodeValue)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 !== $categories->count()) {
|
||||
$this->addCategories($item, $categories->lists('name'));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'description':
|
||||
$description = new DOMCdataSection($dataItem->summary);
|
||||
$item->appendChild($description);
|
||||
break;
|
||||
|
||||
case 'content:encoded':
|
||||
$content = new DOMCdataSection($dataItem->feed_content);
|
||||
$item->appendChild($content);
|
||||
break;
|
||||
|
||||
case 'comments':
|
||||
$item->nodeValue = $dataItem->comments_url;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and add the categories of the post to the current item
|
||||
*
|
||||
* @param DomElement $categoryNode
|
||||
* @param array $categories
|
||||
*/
|
||||
protected function addCategories(DomElement $categoryNode, $categories)
|
||||
{
|
||||
$itemNode = $categoryNode->parentNode;
|
||||
$itemNode->removeChild($categoryNode);
|
||||
|
||||
foreach ($categories as $categoryName) {
|
||||
$newCategNode = clone($categoryNode);
|
||||
$newCategNode->appendChild(new DOMCdataSection($categoryName));
|
||||
|
||||
$itemNode->appendChild($newCategNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\Support\Adapters;
|
||||
|
||||
|
||||
use DomElement,
|
||||
DOMCdataSection;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IAdapter;
|
||||
|
||||
class NewsXmlAdapter implements IAdapter
|
||||
{
|
||||
|
||||
/**
|
||||
* Transform Post data into XML elements
|
||||
*
|
||||
* @param mixed $item
|
||||
* @param mixed $dataItem
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getDataValue($item, $dataItem)
|
||||
{
|
||||
switch ($item->tagName) {
|
||||
case 'title':
|
||||
$item->nodeValue = $dataItem->title;
|
||||
break;
|
||||
|
||||
case 'link':
|
||||
case 'guid':
|
||||
$item->nodeValue = $dataItem->url;
|
||||
break;
|
||||
|
||||
case 'pubDate':
|
||||
$item->nodeValue = $dataItem->published_at->format('r');
|
||||
break;
|
||||
|
||||
case 'dc:creator':
|
||||
if (!$dataItem->user instanceof User) {
|
||||
break;
|
||||
}
|
||||
$creator = new DOMCdataSection(
|
||||
"{$dataItem->user->email} ({$dataItem->user->full_name})"
|
||||
);
|
||||
$item->appendChild($creator);
|
||||
break;
|
||||
|
||||
// case 'category':
|
||||
// $categories = $dataItem->categories;
|
||||
//
|
||||
// if (!empty($item->nodeValue)) {
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if (0 !== $categories->count()) {
|
||||
// $this->addCategory($item, $categories->lists('name'));
|
||||
// }
|
||||
// break;
|
||||
|
||||
case 'description':
|
||||
$description = new DOMCdataSection($dataItem->seo_desc);
|
||||
$item->appendChild($description);
|
||||
break;
|
||||
|
||||
case 'content:encoded':
|
||||
$content = new DOMCdataSection($dataItem->feed_content);
|
||||
$item->appendChild($content);
|
||||
break;
|
||||
|
||||
case 'comments':
|
||||
$item->nodeValue = $dataItem->comments_url;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * Parse and add the categories of the post to the current item
|
||||
// *
|
||||
// * @param DomElement $categoryNode
|
||||
// * @param array $categories
|
||||
// */
|
||||
// protected function addCategory(DomElement $categoryNode, $categories)
|
||||
// {
|
||||
// $itemNode = $categoryNode->parentNode;
|
||||
// $itemNode->removeChild($categoryNode);
|
||||
//
|
||||
// foreach ($categories as $categoryName) {
|
||||
// $newCategNode = clone($categoryNode);
|
||||
// $newCategNode->appendChild(new DOMCdataSection($categoryName));
|
||||
//
|
||||
// $itemNode->appendChild($newCategNode);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\Support\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
/**
|
||||
* Class DataSource
|
||||
* Facade for the data source object
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\Support\Facades
|
||||
*/
|
||||
class DataSource
|
||||
extends Facade
|
||||
{
|
||||
/**
|
||||
* Return the facade namespace
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor() {
|
||||
return 'KoderHut\RssFeedster\DataSource';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\Support\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
/**
|
||||
* Class Renderer
|
||||
* Facade for the renderer object
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\Support\Facades
|
||||
*/
|
||||
class Renderer
|
||||
extends Facade
|
||||
{
|
||||
|
||||
/**
|
||||
* Return the facade namespace
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor() {
|
||||
return 'KoderHut\RssFeedster\Renderer';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Classes\View;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IAdapter;
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IRenderer as Renderer;
|
||||
use KoderHut\RssFeedster\Classes\Feedster;
|
||||
|
||||
|
||||
/**
|
||||
* Class XmlRenderer
|
||||
* Build an RSS Atom valid feed xml file based on the data passed
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\View
|
||||
*/
|
||||
class XmlRenderer
|
||||
implements Renderer
|
||||
{
|
||||
/**
|
||||
* Content type header
|
||||
*/
|
||||
const RENDERER_CONTENT_TYPE = 'text/xml';
|
||||
|
||||
/**
|
||||
* Sections that need to be wrapped into a CDATA element
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $cdataSections = ['link', 'description', ];
|
||||
|
||||
/**
|
||||
* Init method used to initialize the feed document
|
||||
*
|
||||
* @param array $channelData base channel data taken from settings
|
||||
* @param string $xmlTemplate
|
||||
* @param IAdapter $adapter
|
||||
*/
|
||||
public function __construct($channelData = [], $xmlTemplate = null, IAdapter $adapter = null)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
|
||||
$xmlDoc = new \DOMDocument('1.0', 'UTF-8');
|
||||
$xmlDoc->formatOutput = true;
|
||||
|
||||
if (null !== $xmlTemplate) {
|
||||
$xmlDoc->loadXML($xmlTemplate);
|
||||
}
|
||||
|
||||
$this->itemTmpl = $xmlDoc->getElementsByTagName('item')->item(0);
|
||||
|
||||
if (null !== $this->itemTmpl) {
|
||||
$channelElement = $xmlDoc->getElementsByTagName('channel')->item(0);
|
||||
$channelElement->removeChild($this->itemTmpl);
|
||||
}
|
||||
|
||||
$this->addChannelData($channelData, $xmlDoc);
|
||||
|
||||
$this->xml = $xmlDoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the feed items and attach them to the feed document
|
||||
*
|
||||
* @param array|Illuminate\Contracts\Pagination\Paginator $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function renderData($data = [])
|
||||
{
|
||||
$channel = $this->xml->getElementsByTagName('channel')->item(0);
|
||||
|
||||
if (0 == count($data) || null === $this->itemTmpl || !$this->itemTmpl->hasChildNodes()) {
|
||||
return $this->xml->saveXML();
|
||||
}
|
||||
|
||||
foreach ($data as $dataItem) {
|
||||
$xmlItem = clone($this->itemTmpl);
|
||||
|
||||
foreach ($xmlItem->childNodes as $node) {
|
||||
if (!$node instanceof \DOMElement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->adapter->getDataValue($node, $dataItem);
|
||||
}
|
||||
|
||||
$channel->appendChild($xmlItem);
|
||||
}
|
||||
|
||||
return $this->xml->saveXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content-type for this renderer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return self::RENDERER_CONTENT_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the channel data
|
||||
*
|
||||
* @param \DomDocument $xmlDoc
|
||||
* @param array $channelData
|
||||
*/
|
||||
protected function addChannelData($channelData, $xmlDoc)
|
||||
{
|
||||
// $xmlDoc->getElementsByTagName('generator')->item(0)
|
||||
// ->textContent = Feedster::FEED_GENERATOR_NAME;
|
||||
$xmlDoc->getElementsByTagName('lastBuildDate')->item(0)
|
||||
->textContent = date('r');
|
||||
|
||||
foreach ($channelData as $element => $elValue) {
|
||||
$xmlItem = $xmlDoc->getElementsByTagName($element)->item(0);
|
||||
|
||||
if ($xmlItem instanceof \DOMElement) {
|
||||
$xmlItem->textContent = $elValue;
|
||||
}
|
||||
}
|
||||
|
||||
$atomLink = $xmlDoc->getElementsByTagNameNS($xmlDoc->lookupNamespaceUri('atom'), 'link')->item(0);
|
||||
if ($atomLink instanceof \DOMElement) {
|
||||
$atomLink->setAttribute('href', isset($channelData['link']) ? $channelData['link']: '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
"Afrikaans": af
|
||||
"Albanian": sq
|
||||
"Basque": eu
|
||||
"Belarusian": be
|
||||
"Bulgarian": bg
|
||||
"Catalan": ca
|
||||
"Chinese (Simplified)": zh-cn
|
||||
"Chinese (Traditional)": zh-tw
|
||||
"Croatian": hr
|
||||
"Czech": cs
|
||||
"Danish": da
|
||||
"Dutch": nl
|
||||
"Dutch (Belgium)": nl-be
|
||||
"Dutch (Netherlands)": nl-nl
|
||||
"English": en
|
||||
"English (Australia)": en-au
|
||||
"English (Belize)": en-bz
|
||||
"English (Canada)": en-ca
|
||||
"English (Ireland)": en-ie
|
||||
"English (Jamaica)": en-jm
|
||||
"English (New Zealand)": en-nz
|
||||
"English (Phillipines)": en-ph
|
||||
"English (South Africa)": en-za
|
||||
"English (Trinidad)": en-tt
|
||||
"English (United Kingdom)": en-gb
|
||||
"English (United States)": en-us
|
||||
"English (Zimbabwe)": en-zw
|
||||
"Estonian": et
|
||||
"Faeroese": fo
|
||||
"Finnish": fi
|
||||
"French": fr
|
||||
"French (Belgium)": fr-be
|
||||
"French (Canada)": fr-ca
|
||||
"French (France)": fr-fr
|
||||
"French (Luxembourg)": fr-lu
|
||||
"French (Monaco)": fr-mc
|
||||
"French (Switzerland)": fr-ch
|
||||
"Galician": gl
|
||||
"Gaelic": gd
|
||||
"German": de
|
||||
"German (Austria)": de-at
|
||||
"German (Germany)": de-de
|
||||
"German (Liechtenstein)": de-li
|
||||
"German (Luxembourg)": de-lu
|
||||
"German (Switzerland)": de-ch
|
||||
"Greek": el
|
||||
"Hawaiian": haw
|
||||
"Hungarian": hu
|
||||
"Icelandic": is
|
||||
"Indonesian": in
|
||||
"Irish": ga
|
||||
"Italian": it
|
||||
"Italian (Italy)": it-it
|
||||
"Italian (Switzerland)": it-ch
|
||||
"Japanese": ja
|
||||
"Korean": ko
|
||||
"Macedonian": mk
|
||||
"Norwegian": no
|
||||
"Polish": pl
|
||||
"Portuguese": pt
|
||||
"Portuguese (Brazil)": pt-br
|
||||
"Portuguese (Portugal)": pt-pt
|
||||
"Romanian": ro
|
||||
"Romanian (Moldova)": ro-mo
|
||||
"Romanian (Romania)": ro-ro
|
||||
"Russian": ru
|
||||
"Russian (Moldova)": ru-mo
|
||||
"Russian (Russia)": ru-ru
|
||||
"Serbian": sr
|
||||
"Slovak": sk
|
||||
"Slovenian": sl
|
||||
"Spanish": es
|
||||
"Spanish (Argentina)": es-ar
|
||||
"Spanish (Bolivia)": es-bo
|
||||
"Spanish (Chile)": es-cl
|
||||
"Spanish (Colombia)": es-co
|
||||
"Spanish (Costa Rica)": es-cr
|
||||
"Spanish (Dominican Republic)": es-do
|
||||
"Spanish (Ecuador)": es-ec
|
||||
"Spanish (El Salvador)": es-sv
|
||||
"Spanish (Guatemala)": es-gt
|
||||
"Spanish (Honduras)": es-hn
|
||||
"Spanish (Mexico)": es-mx
|
||||
"Spanish (Nicaragua)": es-ni
|
||||
"Spanish (Panama)": es-pa
|
||||
"Spanish (Paraguay)": es-py
|
||||
"Spanish (Peru)": es-pe
|
||||
"Spanish (Puerto Rico)": es-pr
|
||||
"Spanish (Spain)": es-es
|
||||
"Spanish (Uruguay)": es-uy
|
||||
"Spanish (Venezuela)": es-ve
|
||||
"Swedish": sv
|
||||
"Swedish (Finland)": sv-fi
|
||||
"Swedish (Sweden)": sv-se
|
||||
"Turkish": tr
|
||||
"Turkmen": tk
|
||||
"Ukranian": uk
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Controllers;
|
||||
|
||||
use App;
|
||||
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Routing\Controller as ControllerBase;
|
||||
|
||||
|
||||
/**
|
||||
* Rss feed builder controller
|
||||
*/
|
||||
class Rss
|
||||
extends ControllerBase
|
||||
{
|
||||
/**
|
||||
* Build the RSS feed action
|
||||
*/
|
||||
public function buildRssFeed($locale = 'en')
|
||||
{
|
||||
$feedster = App::make('KoderHut\RssFeedster\Feed');
|
||||
|
||||
return Response::make($feedster->getFeed($locale))
|
||||
->header('Content-Type', $feedster->getContentType());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'plugin' => [
|
||||
'name' => 'RSSFeedster',
|
||||
'description' => 'RSS Feed on-the-fly generator.',
|
||||
'namespace' => 'KoderHut',
|
||||
],
|
||||
|
||||
'settings' => [
|
||||
'base' => [
|
||||
'description' => 'Manage RSSFeedster base settings.',
|
||||
],
|
||||
'tabs' => [
|
||||
'general_title' => 'General Options',
|
||||
'posts_title' => 'Posts Options',
|
||||
],
|
||||
|
||||
'fields' => [
|
||||
'feed_url' => [
|
||||
'label' => 'RSS Feed URL (without domain)',
|
||||
'comment' => 'The URL you want assigned to the RSS feed without the install path',
|
||||
'description' => '',
|
||||
'default' => '/rss.xml',
|
||||
],
|
||||
|
||||
'feed_title' => [
|
||||
'label' => 'RSS Feed Title',
|
||||
'comment' => 'The title of your RSS feed (can also be the site name)',
|
||||
'description' => 'The title of your RSS feed (can also be the site name)',
|
||||
'placeholder' => '',
|
||||
'default' => 'RSS Feed Title',
|
||||
],
|
||||
|
||||
'feed_description' => [
|
||||
'label' => 'Short Description of The RSS Feed',
|
||||
'comment' => 'A short description of the website that will be displayed on the feed',
|
||||
'description' => 'A short description of the website that will be displayed on the feed',
|
||||
],
|
||||
|
||||
'feed_category' => [
|
||||
'label' => 'RSS Feed Category',
|
||||
'comment' => 'The category element is used to specify a category for your feed.',
|
||||
'description' => 'The category element makes it possible for RSS aggregators to group sites based on category.',
|
||||
'placeholder' => '',
|
||||
],
|
||||
|
||||
'feed_copyright' => [
|
||||
'label' => 'RSS Feed Copyright Notice',
|
||||
'comment' => 'The copyright element notifies about copyrighted material.',
|
||||
'description' => 'The copyright element notifies about copyrighted material.',
|
||||
'placeholder' => '',
|
||||
],
|
||||
|
||||
'feed_language' => [
|
||||
'label' => 'RSS Feed Language',
|
||||
'comment' => 'The language element is used to specify the language used to write your document.',
|
||||
'description' => 'The language element makes it possible for RSS aggregators to group sites based on language',
|
||||
'placeholder' => '',
|
||||
],
|
||||
|
||||
'post_max_number' => [
|
||||
'label' => 'Max No. of Posts',
|
||||
'comment' => 'The maximum number of posts to display into the feed. Could generate overload if the number is to high! Use -1 to disable this limit.',
|
||||
'description' => 'The maximum number of posts to display into the feed. Could generate overload if the number is to high!',
|
||||
],
|
||||
|
||||
'post_full_content' => [
|
||||
'label' => 'Display Full Content',
|
||||
'comment' => 'Display the full post content into the feed or an excerpt',
|
||||
'description' => 'Display the full post content into the feed or an excerpt',
|
||||
],
|
||||
|
||||
'post_page' => [
|
||||
'label' => 'Post page',
|
||||
'comment' => 'Set the page used to render the post',
|
||||
'description' => 'Set the page used to render the post',
|
||||
],
|
||||
|
||||
'comments_anchor' => [
|
||||
'label' => 'Comments section anchor',
|
||||
'comment' => 'Set ID of the element hosting the comments section',
|
||||
'description' => 'Set ID of the element hosting the comments section',
|
||||
'placeholder' => 'post-comments',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
'messages' => [
|
||||
'permissions' => [
|
||||
'access_config_label' => 'Access Feed Configs'
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Models;
|
||||
|
||||
use Model,
|
||||
Lang,
|
||||
File,
|
||||
Yaml as YamlParser;
|
||||
|
||||
use System\Classes\PluginManager;
|
||||
|
||||
use Cms\Classes\Page;
|
||||
|
||||
use KoderHut\RssFeedster\Plugin;
|
||||
|
||||
/**
|
||||
* Settings Model
|
||||
*/
|
||||
class Settings
|
||||
extends Model
|
||||
{
|
||||
use \October\Rain\Database\Traits\Validation;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $implement = ['System.Behaviors.SettingsModel'];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $settingsCode = 'koderhut_rssfeedster_settings';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $settingsFields = 'fields.yaml';
|
||||
|
||||
/**
|
||||
* Validation rules
|
||||
*/
|
||||
public $rules = [
|
||||
'feed_url' => 'required',
|
||||
'feed_title' => 'required',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Init default data
|
||||
*/
|
||||
public function initSettingsData()
|
||||
{
|
||||
$this->feed_title
|
||||
= Lang::get('koderhut.rssfeedster::lang.settings.fields.feed_title.default');
|
||||
$this->feed_url
|
||||
= Lang::get('koderhut.rssfeedster::lang.settings.fields.feed_url.default');
|
||||
$this->post_page = '404';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the post_page dropdown options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPostPageOptions()
|
||||
{
|
||||
return Page::sortBy('baseFileName')->lists('baseFileName', 'baseFileName');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and return the feed_language dropdown options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFeedLanguageOptions()
|
||||
{
|
||||
$pluginPath = PluginManager::instance()->getPluginPath(Plugin::KODERHUT_RSSFEEDSTER_NS);
|
||||
$path = $pluginPath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'language_codes.yaml';
|
||||
|
||||
if (!File::exists($path)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$languages = YamlParser::parseFile($path);
|
||||
|
||||
$languages = is_array($languages) ? array_flip($languages) : [];
|
||||
|
||||
return $languages;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
fields:
|
||||
feed_url:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.general_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.feed_url.label
|
||||
commentAbove: koderhut.rssfeedster::lang.settings.fields.feed_url.comment
|
||||
default: '/rss.xml'
|
||||
|
||||
tabs:
|
||||
fields:
|
||||
# General tab
|
||||
feed_title:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.general_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.feed_title.label
|
||||
placeholder: koderhut.rssfeedster::lang.settings.fields.feed_title.placeholder
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.feed_title.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.feed_title.description
|
||||
|
||||
feed_description:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.general_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.feed_description.label
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.feed_description.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.feed_description.description
|
||||
type: textarea
|
||||
size: small
|
||||
|
||||
feed_category:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.general_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.feed_category.label
|
||||
placeholder: koderhut.rssfeedster::lang.settings.fields.feed_category.placeholder
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.feed_category.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.feed_category.description
|
||||
|
||||
feed_copyright:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.general_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.feed_copyright.label
|
||||
placeholder: koderhut.rssfeedster::lang.settings.fields.feed_copyright.placeholder
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.feed_copyright.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.feed_copyright.description
|
||||
|
||||
feed_language:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.general_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.feed_language.label
|
||||
placeholder: koderhut.rssfeedster::lang.settings.fields.feed_language.placeholder
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.feed_language.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.feed_language.description
|
||||
type: dropdown
|
||||
|
||||
comments_anchor:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.general_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.comments_anchor.label
|
||||
placeholder: koderhut.rssfeedster::lang.settings.fields.comments_anchor.placeholder
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.comments_anchor.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.comments_anchor.description
|
||||
type: text
|
||||
|
||||
|
||||
# Posts tab
|
||||
post_max_number:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.posts_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.post_max_number.label
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.post_max_number.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.post_max_number.description
|
||||
default: 20
|
||||
|
||||
post_full_content:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.posts_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.post_full_content.label
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.post_full_content.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.post_full_content.description
|
||||
type: checkbox
|
||||
|
||||
post_page:
|
||||
tab: koderhut.rssfeedster::lang.settings.tabs.posts_title
|
||||
label: koderhut.rssfeedster::lang.settings.fields.post_page.label
|
||||
comment: koderhut.rssfeedster::lang.settings.fields.post_page.comment
|
||||
description: koderhut.rssfeedster::lang.settings.fields.post_full_content.description
|
||||
type: dropdown
|
||||
default: 'blog/post'
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="../../../tests/bootstrap.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="KoderHut.RssFeedster Unit Test Suite">
|
||||
<directory>./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<php>
|
||||
<env name="APP_ENV" value="testing"/>
|
||||
<env name="CACHE_DRIVER" value="array"/>
|
||||
<env name="SESSION_DRIVER" value="array"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<rss version="2.0"
|
||||
xmlns:content="http://purl.org/rss/1.0/modules/content/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
>
|
||||
|
||||
<channel>
|
||||
<title />
|
||||
<link />
|
||||
<atom:link href="" rel="self" type="application/rss+xml" />
|
||||
<description />
|
||||
<copyright />
|
||||
<lastBuildDate />
|
||||
<language />
|
||||
<docs>http://www.rssboard.org/rss-specification</docs>
|
||||
|
||||
<item>
|
||||
<link />
|
||||
<title />
|
||||
<guid isPermaLink="false" />
|
||||
<pubDate />
|
||||
<dc:creator />
|
||||
<description />
|
||||
<content:encoded />
|
||||
<comments />
|
||||
<category />
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Tests\Classes;
|
||||
|
||||
use App,
|
||||
PluginTestCase;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Feedster,
|
||||
KoderHut\RssFeedster\Classes\Support\Facades\DataSource,
|
||||
KoderHut\RssFeedster\Classes\Support\Facades\Renderer,
|
||||
KoderHut\RssFeedster\Models\Settings;
|
||||
|
||||
use KoderHut\RssFeedster\Tests\Mock\DataSource\MockDataSource;
|
||||
use KoderHut\RssFeedster\Tests\Mock\View\MockBlankRenderer;
|
||||
use KoderHut\RssFeedster\Tests\Mock\View\MockJsonRenderer;
|
||||
|
||||
|
||||
/**
|
||||
* Class FeedsterTest
|
||||
* @package KoderHut\RssFeedster\Tests\Classes
|
||||
*/
|
||||
class FeedsterTest
|
||||
extends PluginTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Set up the test case
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
/**
|
||||
* Create a mock-up of the Settings object
|
||||
* TODO: find a better way to mock this object
|
||||
*/
|
||||
$config = Settings::instance();
|
||||
$config->setAttribute('feed_title', 'test');
|
||||
|
||||
/**
|
||||
* Set up the data source for the feed
|
||||
*/
|
||||
App::bind('KoderHut\RssFeedster\DataSource', function($app)
|
||||
{
|
||||
return new MockDataSource();
|
||||
});
|
||||
|
||||
/**
|
||||
* Set up the feed renderer
|
||||
*/
|
||||
App::bind('KoderHut\RssFeedster\Renderer', function($app)
|
||||
{
|
||||
$config = [
|
||||
'description' => 'feed description',
|
||||
'title' => 'feed title',
|
||||
'category' => 'feed category',
|
||||
'copyright' => 'feed copyright',
|
||||
'language' => 'feed language',
|
||||
'link' => 'feed url',
|
||||
];
|
||||
|
||||
return new MockJsonRenderer($config);
|
||||
});
|
||||
|
||||
$this->feed = new Feedster(null, null, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test object injection replacement
|
||||
*/
|
||||
public function testObjectReplacement()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
'KoderHut\RssFeedster\Tests\Mock\DataSource\MockDataSource',
|
||||
DataSource::getFacadeRoot()
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
'KoderHut\RssFeedster\Tests\Mock\View\MockJsonRenderer',
|
||||
Renderer::getFacadeRoot()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we successfully changed the renderer to
|
||||
* a JSON renderer
|
||||
*/
|
||||
public function testJsonReplacementRenderer()
|
||||
{
|
||||
$this->assertJson($this->feed->getFeed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we successfully changed the sources
|
||||
*/
|
||||
public function testSources()
|
||||
{
|
||||
$this->feed->setRenderer(new MockBlankRenderer(['customCfgData' => 'data']));
|
||||
$feedData = $this->feed->getFeed();
|
||||
|
||||
$this->assertArrayHasKey('customCfgData', $feedData['channel']);
|
||||
|
||||
$this->assertCount(3, $feedData['items']);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 21/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Tests\Classes\View;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use KoderHut\RssFeedster\Classes\Support\Adapters\BlogPostXmlAdapter;
|
||||
use PluginTestCase,
|
||||
Model;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IAdapter;
|
||||
use KoderHut\RssFeedster\Classes\View\XmlRenderer;
|
||||
|
||||
/**
|
||||
* Class XmlRendererTest
|
||||
* @package KoderHut\RssFeedster\Tests\Classes\View
|
||||
*/
|
||||
class XmlRendererTest
|
||||
extends PluginTestCase
|
||||
{
|
||||
/**
|
||||
* Base feed XML structure
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $xmlBaseStructure = <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<description />
|
||||
<title />
|
||||
<category />
|
||||
<copyright />
|
||||
<language />
|
||||
<link />
|
||||
<atom:link rel="self" type="application/atom+xml" href=""/>
|
||||
<generator />
|
||||
<lastBuildDate />
|
||||
</channel>
|
||||
</rss>
|
||||
XML;
|
||||
|
||||
/**
|
||||
* Base feed XML structure for the channel tag
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $xmlItemStructure = <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<description />
|
||||
<title />
|
||||
<category />
|
||||
<copyright />
|
||||
<language />
|
||||
<link />
|
||||
<atom:link rel="self" type="application/atom+xml" href=""/>
|
||||
<generator />
|
||||
<lastBuildDate />
|
||||
|
||||
<item>
|
||||
<title />
|
||||
<link />
|
||||
<guid />
|
||||
<description />
|
||||
<pubDate />
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
XML;
|
||||
|
||||
private $xmlTestItemStructure = <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<description />
|
||||
<title />
|
||||
<category />
|
||||
<copyright />
|
||||
<language />
|
||||
<link />
|
||||
<atom:link rel="self" type="application/atom+xml" href=""/>
|
||||
<generator />
|
||||
<lastBuildDate />
|
||||
|
||||
<item>
|
||||
<title>post title</title>
|
||||
<link><![CDATA[post url]]></link>
|
||||
<guid><![CDATA[post url]]></guid>
|
||||
<description><![CDATA[post summary]]></description>
|
||||
<pubDate>Tue, 29-Sep-2015</pubDate>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
XML;
|
||||
|
||||
/**
|
||||
* Object placeholder
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $stub = null;
|
||||
|
||||
/**
|
||||
* Set up the test
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$adapterObj = new BlogPostXmlAdapter();
|
||||
|
||||
$this->stub
|
||||
= $this->getMockBuilder(IAdapter::class)->getMock();
|
||||
|
||||
$this->stub
|
||||
->method('getDataValue')
|
||||
->willReturnCallback([$adapterObj, 'getDataValue']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down after test
|
||||
*/
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->stub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the XMLRenderer initial object
|
||||
*/
|
||||
public function testObjectBuild()
|
||||
{
|
||||
$xml = new XmlRenderer(
|
||||
[
|
||||
'description' => 'feed description',
|
||||
'title' => 'feed title',
|
||||
'category' => 'feed category',
|
||||
'copyright' => 'feed copyright',
|
||||
'language' => 'en_gb',
|
||||
'link' => 'http://koderhut.eu'
|
||||
],
|
||||
$this->xmlBaseStructure,
|
||||
$this->stub
|
||||
);
|
||||
$baseXmlDoc = new \DOMDocument();
|
||||
$objXmlDoc = new \DOMDocument();
|
||||
|
||||
$objXmlDoc->loadXml($xml->renderData());
|
||||
$baseXmlDoc->loadXml($this->xmlBaseStructure);
|
||||
|
||||
$this->assertEquals(XmlRenderer::RENDERER_CONTENT_TYPE, $xml->getContentType());
|
||||
|
||||
$this->assertEqualXMLStructure($baseXmlDoc->firstChild, $objXmlDoc->firstChild);
|
||||
|
||||
$this->assertEqualXMLStructure($baseXmlDoc->firstChild, $objXmlDoc->firstChild, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the XMLRenderer object with data
|
||||
*/
|
||||
public function testItemRender()
|
||||
{
|
||||
$xml = new XmlRenderer(
|
||||
[
|
||||
'description' => 'feed description',
|
||||
'title' => 'feed title',
|
||||
'category' => 'feed category',
|
||||
'copyright' => 'feed copyright',
|
||||
'language' => 'en_gb',
|
||||
'link' => 'http://koderhut.eu'
|
||||
],
|
||||
$this->xmlItemStructure,
|
||||
$this->stub
|
||||
);
|
||||
$objXmlDoc = new \DOMDocument();
|
||||
$baseRssDoc = new \DOMDocument();
|
||||
$objItem = false;
|
||||
$baseItem = false;
|
||||
$attributes = [
|
||||
'title' => 'post title',
|
||||
'url' => 'post url',
|
||||
'summary' => 'post summary',
|
||||
'published_at' => new Carbon('Tue, 29-Sep-2015'),
|
||||
];
|
||||
$items = [
|
||||
Model::make($attributes),
|
||||
Model::make($attributes),
|
||||
Model::make($attributes),
|
||||
];
|
||||
|
||||
$objXmlDoc->loadXml($xml->renderData($items));
|
||||
$baseRssDoc->loadXml($this->xmlTestItemStructure);
|
||||
|
||||
$this->assertEqualXMLStructure(
|
||||
$baseRssDoc->getElementsByTagName('item')->item(0),
|
||||
$objXmlDoc->getElementsByTagName('item')->item(0)
|
||||
);
|
||||
|
||||
$objItem = $objXmlDoc->getElementsByTagName('item')->item(0);
|
||||
$baseItem = $baseRssDoc->getElementsByTagName('item')->item(0);
|
||||
|
||||
$this->assertTrue($objItem->hasChildNodes());
|
||||
|
||||
$this->assertEquals(
|
||||
$baseItem->getElementsByTagName('title')->item(0)->nodeValue,
|
||||
$objItem->getElementsByTagName('title')->item(0)->nodeValue
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$baseItem->getElementsByTagName('link')->item(0)->nodeValue,
|
||||
$objItem->getElementsByTagName('link')->item(0)->nodeValue
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 22/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Tests\Mock\DataSource;
|
||||
|
||||
use Model;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IDataSource;
|
||||
|
||||
/**
|
||||
* Class PostsSource
|
||||
*
|
||||
* Feed data source retrieving blog posts.
|
||||
* Requires: RainLab.Blog plug-in
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\DataSource
|
||||
*/
|
||||
class MockDataSource
|
||||
implements IDataSource
|
||||
{
|
||||
/**
|
||||
* Cache for the data
|
||||
*
|
||||
* @var array|mixed
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Load the blog posts
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function loadData()
|
||||
{
|
||||
$items = [];
|
||||
$attributes = [
|
||||
'title' => 'post title',
|
||||
'url' => 'post url',
|
||||
'summary' => 'post summary',
|
||||
'pubDate' => 'Tue, 29-Sep-2015',
|
||||
];
|
||||
|
||||
if (!empty($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$items = [
|
||||
Model::make($attributes),
|
||||
Model::make($attributes),
|
||||
Model::make($attributes),
|
||||
];
|
||||
|
||||
return $this->data = $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve posts from cache or load them and then return them
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
if (null !== $this->data && !empty($this->data)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$this->data = $this->loadData();
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 22/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Tests\Mock\View;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IRenderer as Renderer;
|
||||
|
||||
|
||||
/**
|
||||
* Class MockBlankRenderer
|
||||
* Build an RSS Atom valid feed xml file based on the data passed
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\View
|
||||
*/
|
||||
class MockBlankRenderer
|
||||
implements Renderer
|
||||
{
|
||||
/**
|
||||
* Content type header
|
||||
*/
|
||||
const RENDERER_CONTENT_TYPE = 'text/html';
|
||||
|
||||
/**
|
||||
* Init method used to initialize the feed document
|
||||
*
|
||||
* @param array $channelData base channel data taken from settings
|
||||
*/
|
||||
public function __construct($channelData = [])
|
||||
{
|
||||
$this->data['channel'] = $channelData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the feed items and attach them to the feed document
|
||||
*
|
||||
* @param array|Illuminate\Contracts\Pagination\Paginator $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function renderData($data = [])
|
||||
{
|
||||
if (empty($data)) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$this->data['items'] = $data;
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content-type for this renderer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return self::RENDERER_CONTENT_TYPE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
/**
|
||||
* Author : Denis-Florin Rendler
|
||||
* Date : 22/09/15
|
||||
* Copyright (c) 2015 Denis-Florin Rendler <connect@rendler.me>
|
||||
*/
|
||||
|
||||
namespace KoderHut\RssFeedster\Tests\Mock\View;
|
||||
|
||||
use KoderHut\RssFeedster\Classes\Contracts\IRenderer as Renderer;
|
||||
use KoderHut\RssFeedster\Classes\Feedster;
|
||||
|
||||
|
||||
/**
|
||||
* Class XmlRenderer
|
||||
* Build an RSS Atom valid feed xml file based on the data passed
|
||||
*
|
||||
* @package KoderHut\RssFeedster\Classes\View
|
||||
*/
|
||||
class MockJsonRenderer
|
||||
implements Renderer
|
||||
{
|
||||
/**
|
||||
* Content type header
|
||||
*/
|
||||
const RENDERER_CONTENT_TYPE = 'application/json';
|
||||
|
||||
/**
|
||||
* Init method used to initialize the feed document
|
||||
*
|
||||
* @param array $channelData base channel data taken from settings
|
||||
*/
|
||||
public function __construct($channelData = [])
|
||||
{
|
||||
$jsonDoc = new \StdClass();
|
||||
$rssElement = new \StdClass();
|
||||
$channelElement = new \StdClass();
|
||||
|
||||
|
||||
$this->addChannelData($channelElement, $channelData, $jsonDoc);
|
||||
|
||||
$rssElement->channel = $channelElement;
|
||||
|
||||
$jsonDoc->rss = $rssElement;
|
||||
|
||||
$this->jsonDoc = $jsonDoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the feed items and attach them to the feed document
|
||||
*
|
||||
* @param array|Illuminate\Contracts\Pagination\Paginator $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function renderData($data = [])
|
||||
{
|
||||
$channel = $this->jsonDoc->rss->channel;
|
||||
|
||||
if (empty($data)) {
|
||||
return json_encode($this->jsonDoc);
|
||||
}
|
||||
|
||||
foreach ($data as $item) {
|
||||
$jsonItem = new \StdClass();
|
||||
|
||||
$jsonItem->title = $item->title;
|
||||
$jsonItem->link = $item->url;
|
||||
$jsonItem->guid = $item->url;
|
||||
$jsonItem->description = $item->description;
|
||||
$jsonItem->pubDate = date('D, d-M-Y', $item->published_at);
|
||||
|
||||
$channelItems[] = $jsonItem;
|
||||
}
|
||||
|
||||
$channel->item = $channelItems;
|
||||
|
||||
return json_encode($this->jsonDoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content-type for this renderer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return self::RENDERER_CONTENT_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the channel data
|
||||
*
|
||||
* @param \DomDocument $xmlDoc
|
||||
* @param array $channelData
|
||||
*/
|
||||
protected function addChannelData($channelEl, $channelData, $jsonDoc)
|
||||
{
|
||||
$jsonDoc->generator = Feedster::FEED_GENERATOR_NAME;
|
||||
$jsonDoc->lastBuildDate = date('D, d-M-Y');
|
||||
|
||||
foreach ($channelData as $element => $elValue) {
|
||||
$channelEl->$element = $elValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
1.0.1:
|
||||
- First version of RssFeedster plug-in
|
||||
1.0.2:
|
||||
- Fix functionality bugs and plug-in description bugs
|
||||
1.1.1:
|
||||
- Add XML template for the RSS feed and cleanup of feed generation code
|
||||
1.2.1:
|
||||
- Add plug-in permissions for the configuration section
|
||||
1.2.2:
|
||||
- Fix typo preventing proper sorting of Posts when listing RSS feed. Thanks go to @Abhimanyu Saharan
|
||||
1.2.3:
|
||||
- Fix crash when installing plugin along default blog post
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
title = "Page not found (404)"
|
||||
url = "/404"
|
||||
layout = "default"
|
||||
is_hidden = 0
|
||||
==
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
title = "Error page (500)"
|
||||
url = "/error"
|
||||
layout = "default"
|
||||
is_hidden = 0
|
||||
==
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<h1>Error</h1>
|
||||
<p>We're sorry, but something went wrong and the page cannot be displayed.</p>
|
||||
<p>We're sorry, but sometmhing went wrong and the page cannot be displayed.</p>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in New Issue