| Current Path : /home/digilove/www/41423/ |
| Current File : /home/digilove/www/41423/Feed.tar |
Parser/Rss/ItunesRssParser.php 0000644 00000002651 15234540332 0012401 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed\Parser\Rss;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Feed\Feed;
use Joomla\CMS\Feed\FeedEntry;
use Joomla\CMS\Feed\Parser\NamespaceParserInterface;
/**
* RSS Feed Parser Namespace handler for iTunes.
*
* @link https://itunespartner.apple.com/en/podcasts/overview
* @since 3.1.4
*/
class ItunesRssParser implements NamespaceParserInterface
{
/**
* Method to handle an element for the feed given that the itunes namespace is present.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
public function processElementForFeed(Feed $feed, \SimpleXMLElement $el)
{
return;
}
/**
* Method to handle the feed entry element for the feed given that the itunes namespace is present.
*
* @param FeedEntry $entry The FeedEntry object being built from the parsed feed entry.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
public function processElementForFeedEntry(FeedEntry $entry, \SimpleXMLElement $el)
{
return;
}
}
Parser/Rss/MediaRssParser.php 0000644 00000002626 15234540332 0012153 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed\Parser\Rss;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Feed\Feed;
use Joomla\CMS\Feed\FeedEntry;
use Joomla\CMS\Feed\Parser\NamespaceParserInterface;
/**
* RSS Feed Parser Namespace handler for MediaRSS.
*
* @link http://video.search.yahoo.com/mrss
* @since 3.1.4
*/
class MediaRssParser implements NamespaceParserInterface
{
/**
* Method to handle an element for the feed given that the media namespace is present.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
public function processElementForFeed(Feed $feed, \SimpleXMLElement $el)
{
return;
}
/**
* Method to handle the feed entry element for the feed given that the media namespace is present.
*
* @param FeedEntry $entry The FeedEntry object being built from the parsed feed entry.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
public function processElementForFeedEntry(FeedEntry $entry, \SimpleXMLElement $el)
{
return;
}
}
Parser/AtomParser.php 0000644 00000015756 15234540332 0010605 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed\Parser;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Feed\Feed;
use Joomla\CMS\Feed\FeedEntry;
use Joomla\CMS\Feed\FeedLink;
use Joomla\CMS\Feed\FeedParser;
/**
* ATOM Feed Parser class.
*
* @link http://www.atomenabled.org/developers/syndication/
* @since 3.1.4
*/
class AtomParser extends FeedParser
{
/**
* @var string The feed format version.
* @since 3.1.4
*/
protected $version;
/**
* Method to handle the `<author>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleAuthor(Feed $feed, \SimpleXMLElement $el)
{
// Set the author information from the XML element.
$feed->setAuthor(
$this->inputFilter->clean((string) $el->name, 'html'),
filter_var((string) $el->email, FILTER_VALIDATE_EMAIL),
filter_var((string) $el->uri, FILTER_VALIDATE_URL)
);
}
/**
* Method to handle the `<contributor>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleContributor(Feed $feed, \SimpleXMLElement $el)
{
$feed->addContributor(
$this->inputFilter->clean((string) $el->name, 'html'),
filter_var((string) $el->email, FILTER_VALIDATE_EMAIL),
filter_var((string) $el->uri, FILTER_VALIDATE_URL)
);
}
/**
* Method to handle the `<generator>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleGenerator(Feed $feed, \SimpleXMLElement $el)
{
$feed->generator = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<id>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleId(Feed $feed, \SimpleXMLElement $el)
{
$feed->uri = (string) $el;
}
/**
* Method to handle the `<link>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleLink(Feed $feed, \SimpleXMLElement $el)
{
$link = new FeedLink;
$link->uri = (string) $el['href'];
$link->language = (string) $el['hreflang'];
$link->length = (int) $el['length'];
$link->relation = (string) $el['rel'];
$link->title = $this->inputFilter->clean((string) $el['title'], 'html');
$link->type = (string) $el['type'];
$feed->link = $link;
}
/**
* Method to handle the `<rights>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleRights(Feed $feed, \SimpleXMLElement $el)
{
$feed->copyright = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<subtitle>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleSubtitle(Feed $feed, \SimpleXMLElement $el)
{
$feed->description = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<title>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleTitle(Feed $feed, \SimpleXMLElement $el)
{
$feed->title = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<updated>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleUpdated(Feed $feed, \SimpleXMLElement $el)
{
$feed->updatedDate = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to initialise the feed for parsing. Here we detect the version and advance the stream
* reader so that it is ready to parse feed elements.
*
* @return void
*
* @since 3.1.4
*/
protected function initialise()
{
// Read the version attribute.
$this->version = ($this->stream->getAttribute('version') == '0.3') ? '0.3' : '1.0';
// We want to move forward to the first element after the root element.
$this->moveToNextElement();
}
/**
* Method to handle a `<entry>` element for the feed.
*
* @param FeedEntry $entry The FeedEntry object being built from the parsed feed entry.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function processFeedEntry(FeedEntry $entry, \SimpleXMLElement $el)
{
$entry->uri = (string) $el->id;
$entry->title = $this->inputFilter->clean((string) $el->title, 'html');
$entry->updatedDate = $this->inputFilter->clean((string) $el->updated, 'html');
$entry->content = $this->inputFilter->clean((string) $el->summary, 'html');
if (!$entry->content)
{
$entry->content = $this->inputFilter->clean((string) $el->content, 'html');
}
if (filter_var($entry->uri, FILTER_VALIDATE_URL) === false && !is_null($el->link) && $el->link)
{
$link = $el->link;
if (is_array($link))
{
$link = $this->bestLinkForUri($link);
}
$uri = (string) $link['href'];
if ($uri)
{
$entry->uri = $uri;
}
}
}
/**
* If there is more than one <link> in the feed entry, find the most appropriate one and return it.
*
* @param array $links Array of <link> elements from the feed entry.
*
* @return \SimpleXMLElement
*/
private function bestLinkForUri(array $links)
{
$linkPrefs = array('', 'self', 'alternate');
foreach ($linkPrefs as $pref)
{
foreach ($links as $link)
{
$rel = (string) $link['rel'];
if ($rel === $pref)
{
return $link;
}
}
}
return array_shift($links);
}
}
Parser/NamespaceParserInterface.php 0000644 00000002345 15234540332 0013410 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed\Parser;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Feed\Feed;
use Joomla\CMS\Feed\FeedEntry;
/**
* Feed Namespace interface.
*
* @since 3.1.4
*/
interface NamespaceParserInterface
{
/**
* Method to handle an element for the feed given that a certain namespace is present.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
public function processElementForFeed(Feed $feed, \SimpleXMLElement $el);
/**
* Method to handle the feed entry element for the feed given that a certain namespace is present.
*
* @param FeedEntry $entry The FeedEntry object being built from the parsed feed entry.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
public function processElementForFeedEntry(FeedEntry $entry, \SimpleXMLElement $el);
}
Parser/RssParser.php 0000644 00000027550 15234540332 0010447 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed\Parser;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Feed\Feed;
use Joomla\CMS\Feed\FeedEntry;
use Joomla\CMS\Feed\FeedLink;
use Joomla\CMS\Feed\FeedParser;
use Joomla\CMS\Feed\FeedPerson;
/**
* RSS Feed Parser class.
*
* @link http://cyber.law.harvard.edu/rss/rss.html
* @since 3.1.4
*/
class RssParser extends FeedParser
{
/**
* @var string The feed element name for the entry elements.
* @since 3.1.4
*/
protected $entryElementName = 'item';
/**
* @var string The feed format version.
* @since 3.1.4
*/
protected $version;
/**
* Method to handle the `<category>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleCategory(Feed $feed, \SimpleXMLElement $el)
{
// Get the data from the element.
$domain = (string) $el['domain'];
$category = $this->inputFilter->clean((string) $el, 'html');
$feed->addCategory($category, $domain);
}
/**
* Method to handle the `<cloud>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleCloud(Feed $feed, \SimpleXMLElement $el)
{
$cloud = new \stdClass;
$cloud->domain = (string) $el['domain'];
$cloud->port = (string) $el['port'];
$cloud->path = (string) $el['path'];
$cloud->protocol = (string) $el['protocol'];
$cloud->registerProcedure = (string) $el['registerProcedure'];
$feed->cloud = $cloud;
}
/**
* Method to handle the `<copyright>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleCopyright(Feed $feed, \SimpleXMLElement $el)
{
$feed->copyright = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<description>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleDescription(Feed $feed, \SimpleXMLElement $el)
{
$feed->description = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<generator>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleGenerator(Feed $feed, \SimpleXMLElement $el)
{
$feed->generator = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<image>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleImage(Feed $feed, \SimpleXMLElement $el)
{
// Create a feed link object for the image.
$image = new FeedLink(
(string) $el->url,
null,
'logo',
null,
$this->inputFilter->clean((string) $el->title, 'html')
);
// Populate extra fields if they exist.
$image->link = (string) filter_var($el->link, FILTER_VALIDATE_URL);
$image->description = $this->inputFilter->clean((string) $el->description, 'html');
$image->height = (string) $el->height;
$image->width = (string) $el->width;
$feed->image = $image;
}
/**
* Method to handle the `<language>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleLanguage(Feed $feed, \SimpleXMLElement $el)
{
$feed->language = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<lastBuildDate>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleLastBuildDate(Feed $feed, \SimpleXMLElement $el)
{
$feed->updatedDate = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<link>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleLink(Feed $feed, \SimpleXMLElement $el)
{
$link = new FeedLink;
$link->uri = (string) $el['href'];
$feed->link = $link;
}
/**
* Method to handle the `<managingEditor>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleManagingEditor(Feed $feed, \SimpleXMLElement $el)
{
$feed->author = $this->processPerson((string) $el);
}
/**
* Method to handle the `<skipDays>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleSkipDays(Feed $feed, \SimpleXMLElement $el)
{
// Initialise the array.
$days = array();
// Add all of the day values from the feed to the array.
foreach ($el->day as $day)
{
$days[] = (string) $day;
}
$feed->skipDays = $days;
}
/**
* Method to handle the `<skipHours>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleSkipHours(Feed $feed, \SimpleXMLElement $el)
{
// Initialise the array.
$hours = array();
// Add all of the day values from the feed to the array.
foreach ($el->hour as $hour)
{
$hours[] = (int) $hour;
}
$feed->skipHours = $hours;
}
/**
* Method to handle the `<pubDate>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handlePubDate(Feed $feed, \SimpleXMLElement $el)
{
$feed->publishedDate = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<title>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleTitle(Feed $feed, \SimpleXMLElement $el)
{
$feed->title = $this->inputFilter->clean((string) $el, 'html');
}
/**
* Method to handle the `<ttl>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleTtl(Feed $feed, \SimpleXMLElement $el)
{
$feed->ttl = (integer) $this->inputFilter->clean((string) $el, 'int');
}
/**
* Method to handle the `<webmaster>` element for the feed.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function handleWebmaster(Feed $feed, \SimpleXMLElement $el)
{
// Get the tag contents and split it over the first space.
$tmp = (string) $el;
$tmp = explode(' ', $tmp, 2);
// This is really cheap parsing. Probably need to create a method to do this more robustly.
$name = null;
if (isset($tmp[1]))
{
$name = trim(
$this->inputFilter->clean($tmp[1], 'html'),
' ()'
);
}
$email = trim(
filter_var((string) $tmp[0], FILTER_VALIDATE_EMAIL)
);
$feed->addContributor($name, $email, null, 'webmaster');
}
/**
* Method to initialise the feed for parsing. Here we detect the version and advance the stream
* reader so that it is ready to parse feed elements.
*
* @return void
*
* @since 3.1.4
*/
protected function initialise()
{
// Read the version attribute.
$this->version = $this->stream->getAttribute('version');
// We want to move forward to the first element after the <channel> element.
$this->moveToNextElement('channel');
$this->moveToNextElement();
}
/**
* Method to handle a `<item>` element for the feed.
*
* @param FeedEntry $entry The FeedEntry object being built from the parsed feed entry.
* @param \SimpleXMLElement $el The current XML element object to handle.
*
* @return void
*
* @since 3.1.4
*/
protected function processFeedEntry(FeedEntry $entry, \SimpleXMLElement $el)
{
$entry->uri = (string) filter_var($el->link, FILTER_VALIDATE_URL);
$entry->title = $this->inputFilter->clean((string) $el->title, 'html');
$entry->publishedDate = $this->inputFilter->clean((string) $el->pubDate, 'html');
$entry->updatedDate = $this->inputFilter->clean((string) $el->pubDate, 'html');
$entry->content = $this->inputFilter->clean((string) $el->description, 'html');
$entry->guid = $this->inputFilter->clean((string) $el->guid, 'html');
$entry->isPermaLink = $entry->guid === '' || (string) $el->guid['isPermaLink'] === 'false' ? false : true;
$entry->comments = $this->inputFilter->clean((string) $el->comments, 'html');
// Add the feed entry author if available.
$author = $this->inputFilter->clean((string) $el->author, 'html');
if (!empty($author))
{
$entry->author = $this->processPerson($author);
}
// Add any categories to the entry.
foreach ($el->category as $category)
{
$entry->addCategory((string) $category, (string) $category['domain']);
}
// Add any enclosures to the entry.
foreach ($el->enclosure as $enclosure)
{
$link = new FeedLink(
(string) $enclosure['url'],
null,
(string) $enclosure['type'],
null,
null,
(int) $enclosure['length']
);
$entry->addLink($link);
}
}
/**
* Method to parse a string with person data and return a FeedPerson object.
*
* @param string $data The string to parse for a person.
*
* @return FeedPerson
*
* @since 3.1.4
*/
protected function processPerson($data)
{
// Create a new person object.
$person = new FeedPerson;
// This is really cheap parsing, but so far good enough. :)
$data = explode(' ', $data, 2);
if (isset($data[1]))
{
$person->name = trim(
$this->inputFilter->clean($data[1], 'html'),
' ()'
);
}
// Set the email for the person.
$person->email = trim(
filter_var((string) $data[0], FILTER_VALIDATE_EMAIL)
);
return $person;
}
}
Feed.php 0000644 00000021556 15234540332 0006132 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed;
defined('JPATH_PLATFORM') or die();
use Joomla\CMS\Date\Date;
/**
* Class to encapsulate a feed for the Joomla Platform.
*
* @property FeedPerson $author Person responsible for feed content.
* @property array $categories Categories to which the feed belongs.
* @property array $contributors People who contributed to the feed content.
* @property string $copyright Information about rights, e.g. copyrights, held in and over the feed.
* @property string $description A phrase or sentence describing the feed.
* @property string $generator A string indicating the program used to generate the feed.
* @property FeedLink|null $image FeedLink object containing feed image properties.
* @property Date $publishedDate The publication date for the feed content.
* @property string $title A human readable title for the feed.
* @property Date $updatedDate The last time the content of the feed changed.
* @property string $uri Universal, permanent identifier for the feed.
*
* @since 3.1.4
*/
class Feed implements \ArrayAccess, \Countable
{
/**
* @var array The entry properties.
* @since 3.1.4
*/
protected $properties = array(
'uri' => '',
'title' => '',
'updatedDate' => '',
'description' => '',
'categories' => array(),
'contributors' => array(),
);
/**
* @var array The list of feed entry objects.
* @since 3.1.4
*/
protected $entries = array();
/**
* Magic method to return values for feed properties.
*
* @param string $name The name of the property.
*
* @return mixed
*
* @since 3.1.4
*/
public function __get($name)
{
return isset($this->properties[$name]) ? $this->properties[$name] : null;
}
/**
* Magic method to set values for feed properties.
*
* @param string $name The name of the property.
* @param mixed $value The value to set for the property.
*
* @return void
*
* @since 3.1.4
*/
public function __set($name, $value)
{
// Ensure that setting a date always sets a JDate instance.
if ((($name == 'updatedDate') || ($name == 'publishedDate')) && !($value instanceof Date))
{
$value = new Date($value);
}
// Validate that any authors that are set are instances of JFeedPerson or null.
if (($name == 'author') && (!($value instanceof FeedPerson) || ($value === null)))
{
throw new \InvalidArgumentException(
sprintf(
'%1$s "author" must be an instance of Joomla\\CMS\\Feed\\FeedPerson. %2$s given.',
get_class($this),
gettype($value) === 'object' ? get_class($value) : gettype($value)
)
);
}
// Disallow setting categories or contributors directly.
if (in_array($name, array('categories', 'contributors')))
{
throw new \InvalidArgumentException(
sprintf(
'Cannot directly set %1$s property "%2$s".',
get_class($this),
$name
)
);
}
$this->properties[$name] = $value;
}
/**
* Method to add a category to the feed object.
*
* @param string $name The name of the category to add.
* @param string $uri The optional URI for the category to add.
*
* @return Feed
*
* @since 3.1.4
*/
public function addCategory($name, $uri = '')
{
$this->properties['categories'][$name] = $uri;
return $this;
}
/**
* Method to add a contributor to the feed object.
*
* @param string $name The full name of the person to add.
* @param string $email The email address of the person to add.
* @param string $uri The optional URI for the person to add.
* @param string $type The optional type of person to add.
*
* @return Feed
*
* @since 3.1.4
*/
public function addContributor($name, $email, $uri = null, $type = null)
{
$contributor = new FeedPerson($name, $email, $uri, $type);
// If the new contributor already exists then there is nothing to do, so just return.
foreach ($this->properties['contributors'] as $c)
{
if ($c == $contributor)
{
return $this;
}
}
// Add the new contributor.
$this->properties['contributors'][] = $contributor;
return $this;
}
/**
* Method to add an entry to the feed object.
*
* @param FeedEntry $entry The entry object to add.
*
* @return Feed
*
* @since 3.1.4
*/
public function addEntry(FeedEntry $entry)
{
// If the new entry already exists then there is nothing to do, so just return.
foreach ($this->entries as $e)
{
if ($e == $entry)
{
return $this;
}
}
// Add the new entry.
$this->entries[] = $entry;
return $this;
}
/**
* Returns a count of the number of entries in the feed.
*
* This method is here to implement the Countable interface.
* You can call it by doing count($feed) rather than $feed->count();
*
* @return integer number of entries in the feed.
*/
public function count()
{
return count($this->entries);
}
/**
* Whether or not an offset exists. This method is executed when using isset() or empty() on
* objects implementing ArrayAccess.
*
* @param mixed $offset An offset to check for.
*
* @return boolean
*
* @see ArrayAccess::offsetExists()
* @since 3.1.4
*/
public function offsetExists($offset)
{
return isset($this->entries[$offset]);
}
/**
* Returns the value at specified offset.
*
* @param mixed $offset The offset to retrieve.
*
* @return mixed The value at the offset.
*
* @see ArrayAccess::offsetGet()
* @since 3.1.4
*/
public function offsetGet($offset)
{
return $this->entries[$offset];
}
/**
* Assigns a value to the specified offset.
*
* @param mixed $offset The offset to assign the value to.
* @param FeedEntry $value The JFeedEntry to set.
*
* @return boolean
*
* @see ArrayAccess::offsetSet()
* @since 3.1.4
* @throws \InvalidArgumentException
*/
public function offsetSet($offset, $value)
{
if (!($value instanceof FeedEntry))
{
throw new \InvalidArgumentException(
sprintf(
'%1$s entries must be an instance of Joomla\\CMS\\Feed\\FeedPerson. %2$s given.',
get_class($this),
gettype($value) === 'object' ? get_class($value) : gettype($value)
)
);
}
$this->entries[$offset] = $value;
return true;
}
/**
* Unsets an offset.
*
* @param mixed $offset The offset to unset.
*
* @return void
*
* @see ArrayAccess::offsetUnset()
* @since 3.1.4
*/
public function offsetUnset($offset)
{
unset($this->entries[$offset]);
}
/**
* Method to remove a category from the feed object.
*
* @param string $name The name of the category to remove.
*
* @return Feed
*
* @since 3.1.4
*/
public function removeCategory($name)
{
unset($this->properties['categories'][$name]);
return $this;
}
/**
* Method to remove a contributor from the feed object.
*
* @param FeedPerson $contributor The person object to remove.
*
* @return Feed
*
* @since 3.1.4
*/
public function removeContributor(FeedPerson $contributor)
{
// If the contributor exists remove it.
foreach ($this->properties['contributors'] as $k => $c)
{
if ($c == $contributor)
{
unset($this->properties['contributors'][$k]);
$this->properties['contributors'] = array_values($this->properties['contributors']);
return $this;
}
}
return $this;
}
/**
* Method to remove an entry from the feed object.
*
* @param FeedEntry $entry The entry object to remove.
*
* @return Feed
*
* @since 3.1.4
*/
public function removeEntry(FeedEntry $entry)
{
// If the entry exists remove it.
foreach ($this->entries as $k => $e)
{
if ($e == $entry)
{
unset($this->entries[$k]);
$this->entries = array_values($this->entries);
return $this;
}
}
return $this;
}
/**
* Shortcut method to set the author for the feed object.
*
* @param string $name The full name of the person to set.
* @param string $email The email address of the person to set.
* @param string $uri The optional URI for the person to set.
* @param string $type The optional type of person to set.
*
* @return Feed
*
* @since 3.1.4
*/
public function setAuthor($name, $email, $uri = null, $type = null)
{
$author = new FeedPerson($name, $email, $uri, $type);
$this->properties['author'] = $author;
return $this;
}
/**
* Method to reverse the items if display is set to 'oldest first'
*
* @return Feed
*
* @since 3.1.4
*/
public function reverseItems()
{
if (is_array($this->entries) && !empty($this->entries))
{
$this->entries = array_reverse($this->entries);
}
return $this;
}
}
FeedEntry.php 0000644 00000016074 15234540332 0007153 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Date\Date;
/**
* Class to encapsulate a feed entry for the Joomla Platform.
*
* @property FeedPerson $author Person responsible for feed entry content.
* @property array $categories Categories to which the feed entry belongs.
* @property string $content The content of the feed entry.
* @property array $contributors People who contributed to the feed entry content.
* @property string $copyright Information about rights, e.g. copyrights, held in and over the feed entry.
* @property array $links Links associated with the feed entry.
* @property Date $publishedDate The publication date for the feed entry.
* @property Feed $source The feed from which the entry is sourced.
* @property string $title A human readable title for the feed entry.
* @property Date $updatedDate The last time the content of the feed entry changed.
* @property string $uri Universal, permanent identifier for the feed entry.
*
* @since 3.1.4
*/
class FeedEntry
{
/**
* @var array The entry properties.
* @since 3.1.4
*/
protected $properties = array(
'uri' => '',
'title' => '',
'updatedDate' => '',
'content' => '',
'categories' => array(),
'contributors' => array(),
'links' => array(),
);
/**
* Magic method to return values for feed entry properties.
*
* @param string $name The name of the property.
*
* @return mixed
*
* @since 3.1.4
*/
public function __get($name)
{
return (isset($this->properties[$name])) ? $this->properties[$name] : null;
}
/**
* Magic method to set values for feed properties.
*
* @param string $name The name of the property.
* @param mixed $value The value to set for the property.
*
* @return void
*
* @since 3.1.4
*/
public function __set($name, $value)
{
// Ensure that setting a date always sets a JDate instance.
if ((($name == 'updatedDate') || ($name == 'publishedDate')) && !($value instanceof Date))
{
$value = new Date($value);
}
// Validate that any authors that are set are instances of JFeedPerson or null.
if (($name == 'author') && (!($value instanceof FeedPerson) || ($value === null)))
{
throw new \InvalidArgumentException(
sprintf(
'%1$s "author" must be an instance of Joomla\\CMS\\Feed\\FeedPerson. %2$s given.',
get_class($this),
gettype($value) === 'object' ? get_class($value) : gettype($value)
)
);
}
// Validate that any sources that are set are instances of JFeed or null.
if (($name == 'source') && (!($value instanceof Feed) || ($value === null)))
{
throw new \InvalidArgumentException(
sprintf(
'%1$s "source" must be an instance of Joomla\\CMS\\Feed\\Feed. %2$s given.',
get_class($this),
gettype($value) === 'object' ? get_class($value) : gettype($value)
)
);
}
// Disallow setting categories, contributors, or links directly.
if (in_array($name, array('categories', 'contributors', 'links')))
{
throw new \InvalidArgumentException(
sprintf(
'Cannot directly set %1$s property "%2$s".',
get_class($this),
$name
)
);
}
$this->properties[$name] = $value;
}
/**
* Method to add a category to the feed entry object.
*
* @param string $name The name of the category to add.
* @param string $uri The optional URI for the category to add.
*
* @return FeedEntry
*
* @since 3.1.4
*/
public function addCategory($name, $uri = '')
{
$this->properties['categories'][$name] = $uri;
return $this;
}
/**
* Method to add a contributor to the feed entry object.
*
* @param string $name The full name of the person to add.
* @param string $email The email address of the person to add.
* @param string $uri The optional URI for the person to add.
* @param string $type The optional type of person to add.
*
* @return FeedEntry
*
* @since 3.1.4
*/
public function addContributor($name, $email, $uri = null, $type = null)
{
$contributor = new FeedPerson($name, $email, $uri, $type);
// If the new contributor already exists then there is nothing to do, so just return.
foreach ($this->properties['contributors'] as $c)
{
if ($c == $contributor)
{
return $this;
}
}
// Add the new contributor.
$this->properties['contributors'][] = $contributor;
return $this;
}
/**
* Method to add a link to the feed entry object.
*
* @param FeedLink $link The link object to add.
*
* @return FeedEntry
*
* @since 3.1.4
*/
public function addLink(FeedLink $link)
{
// If the new link already exists then there is nothing to do, so just return.
foreach ($this->properties['links'] as $l)
{
if ($l == $link)
{
return $this;
}
}
// Add the new link.
$this->properties['links'][] = $link;
return $this;
}
/**
* Method to remove a category from the feed entry object.
*
* @param string $name The name of the category to remove.
*
* @return FeedEntry
*
* @since 3.1.4
*/
public function removeCategory($name)
{
unset($this->properties['categories'][$name]);
return $this;
}
/**
* Method to remove a contributor from the feed entry object.
*
* @param FeedPerson $contributor The person object to remove.
*
* @return FeedEntry
*
* @since 3.1.4
*/
public function removeContributor(FeedPerson $contributor)
{
// If the contributor exists remove it.
foreach ($this->properties['contributors'] as $k => $c)
{
if ($c == $contributor)
{
unset($this->properties['contributors'][$k]);
$this->properties['contributors'] = array_values($this->properties['contributors']);
return $this;
}
}
return $this;
}
/**
* Method to remove a link from the feed entry object.
*
* @param FeedLink $link The link object to remove.
*
* @return FeedEntry
*
* @since 3.1.4
*/
public function removeLink(FeedLink $link)
{
// If the link exists remove it.
foreach ($this->properties['links'] as $k => $l)
{
if ($l == $link)
{
unset($this->properties['links'][$k]);
$this->properties['links'] = array_values($this->properties['links']);
return $this;
}
}
return $this;
}
/**
* Shortcut method to set the author for the feed entry object.
*
* @param string $name The full name of the person to set.
* @param string $email The email address of the person to set.
* @param string $uri The optional URI for the person to set.
* @param string $type The optional type of person to set.
*
* @return FeedEntry
*
* @since 3.1.4
*/
public function setAuthor($name, $email, $uri = null, $type = null)
{
$author = new FeedPerson($name, $email, $uri, $type);
$this->properties['author'] = $author;
return $this;
}
}
FeedFactory.php 0000644 00000010154 15234540332 0007452 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Http\HttpFactory;
use Joomla\Registry\Registry;
/**
* Feed factory class.
*
* @since 3.1.4
*/
class FeedFactory
{
/**
* @var array The list of registered parser classes for feeds.
* @since 3.1.4
*/
protected $parsers = array('rss' => 'Joomla\\CMS\\Feed\\Parser\\RssParser', 'feed' => 'Joomla\\CMS\\Feed\\Parser\\AtomParser');
/**
* Method to load a URI into the feed reader for parsing.
*
* @param string $uri The URI of the feed to load. Idn uris must be passed already converted to punycode.
*
* @return Feed
*
* @since 3.1.4
* @throws \InvalidArgumentException
* @throws \RuntimeException
*/
public function getFeed($uri)
{
// Create the XMLReader object.
$reader = new \XMLReader;
// Open the URI within the stream reader.
if (!@$reader->open($uri, null, LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_NOWARNING))
{
// Retry with JHttpFactory that allow using CURL and Sockets as alternative method when available
// Adding a valid user agent string, otherwise some feed-servers returning an error
$options = new Registry;
$options->set('userAgent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0');
try
{
$response = HttpFactory::getHttp($options)->get($uri);
}
catch (RuntimeException $e)
{
throw new \RuntimeException('Unable to open the feed.', $e->getCode(), $e);
}
if ($response->code != 200)
{
throw new \RuntimeException('Unable to open the feed.');
}
// Set the value to the XMLReader parser
if (!$reader->xml($response->body, null, LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_NOWARNING))
{
throw new \RuntimeException('Unable to parse the feed.');
}
}
try
{
// Skip ahead to the root node.
while ($reader->read())
{
if ($reader->nodeType == \XMLReader::ELEMENT)
{
break;
}
}
}
catch (\Exception $e)
{
throw new \RuntimeException('Error reading feed.', $e->getCode(), $e);
}
// Setup the appropriate feed parser for the feed.
$parser = $this->_fetchFeedParser($reader->name, $reader);
return $parser->parse();
}
/**
* Method to register a FeedParser class for a given root tag name.
*
* @param string $tagName The root tag name for which to register the parser class.
* @param string $className The FeedParser class name to register for a root tag name.
* @param boolean $overwrite True to overwrite the parser class if one is already registered.
*
* @return FeedFactory
*
* @since 3.1.4
* @throws \InvalidArgumentException
*/
public function registerParser($tagName, $className, $overwrite = false)
{
// Verify that the class exists.
if (!class_exists($className))
{
throw new \InvalidArgumentException('The feed parser class ' . $className . ' does not exist.');
}
// Validate that the tag name is valid.
if (!preg_match('/\A(?!XML)[a-z][\w0-9-]*/i', $tagName))
{
throw new \InvalidArgumentException('The tag name ' . $tagName . ' is not valid.');
}
// Register the given parser class for the tag name if nothing registered or the overwrite flag set.
if (empty($this->parsers[$tagName]) || (bool) $overwrite)
{
$this->parsers[(string) $tagName] = (string) $className;
}
return $this;
}
/**
* Method to return a new JFeedParser object based on the registered parsers and a given type.
*
* @param string $type The name of parser to return.
* @param \XMLReader $reader The XMLReader instance for the feed.
*
* @return FeedParser
*
* @since 3.1.4
* @throws \LogicException
*/
private function _fetchFeedParser($type, \XMLReader $reader)
{
// Look for a registered parser for the feed type.
if (empty($this->parsers[$type]))
{
throw new \LogicException('No registered feed parser for type ' . $type . '.');
}
return new $this->parsers[$type]($reader);
}
}
FeedLink.php 0000644 00000003660 15234540332 0006744 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed;
defined('JPATH_PLATFORM') or die;
/**
* Feed Link class.
*
* @since 3.1.4
*/
class FeedLink
{
/**
* The URI to the linked resource.
*
* @var string
* @since 3.1.4
*/
public $uri;
/**
* The relationship between the feed and the linked resource.
*
* @var string
* @since 3.1.4
*/
public $relation;
/**
* The resource type.
*
* @var string
* @since 3.1.4
*/
public $type;
/**
* The language of the resource found at the given URI.
*
* @var string
* @since 3.1.4
*/
public $language;
/**
* The title of the resource.
*
* @var string
* @since 3.1.4
*/
public $title;
/**
* The length of the resource in bytes.
*
* @var integer
* @since 3.1.4
*/
public $length;
/**
* Constructor.
*
* @param string $uri The URI to the linked resource.
* @param string $relation The relationship between the feed and the linked resource.
* @param string $type The resource type.
* @param string $language The language of the resource found at the given URI.
* @param string $title The title of the resource.
* @param integer $length The length of the resource in bytes.
*
* @since 3.1.4
* @throws \InvalidArgumentException
*/
public function __construct($uri = null, $relation = null, $type = null, $language = null, $title = null, $length = null)
{
$this->uri = $uri;
$this->relation = $relation;
$this->type = $type;
$this->language = $language;
$this->title = $title;
// Validate the length input.
if (isset($length) && !is_numeric($length))
{
throw new \InvalidArgumentException('Length must be numeric.');
}
$this->length = (int) $length;
}
}
FeedParser.php 0000644 00000015470 15234540332 0007305 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Feed\Parser\NamespaceParserInterface;
use Joomla\CMS\Filter\InputFilter;
/**
* Feed Parser class.
*
* @since 3.1.4
*/
abstract class FeedParser
{
/**
* The feed element name for the entry elements.
*
* @var string
* @since 3.1.4
*/
protected $entryElementName = 'entry';
/**
* Array of NamespaceParserInterface objects
*
* @var array
* @since 3.1.4
*/
protected $namespaces = array();
/**
* The XMLReader stream object for the feed.
*
* @var \XMLReader
* @since 3.1.4
*/
protected $stream;
/**
* The InputFilter
*
* @var InputFilter
* @since 3.9.25
*/
protected $inputFilter;
/**
* Constructor.
*
* @param \XMLReader $stream The XMLReader stream object for the feed.
* @param InputFilter $inputFilter The InputFilter object to be used
*
* @since 3.1.4
*/
public function __construct(\XMLReader $stream, InputFilter $inputFilter = null)
{
$this->stream = $stream;
$this->inputFilter = $inputFilter ? $inputFilter : InputFilter::getInstance(array(), array(), 1, 1);
}
/**
* Method to parse the feed into a JFeed object.
*
* @return Feed
*
* @since 3.1.4
*/
public function parse()
{
$feed = new Feed;
// Detect the feed version.
$this->initialise();
// Let's get this party started...
do
{
// Expand the element for processing.
$el = new \SimpleXMLElement($this->stream->readOuterXml());
// Get the list of namespaces used within this element.
$ns = $el->getNamespaces(true);
// Get an array of available namespace objects for the element.
$namespaces = array();
foreach ($ns as $prefix => $uri)
{
// Ignore the empty namespace prefix.
if (empty($prefix))
{
continue;
}
// Get the necessary namespace objects for the element.
$namespace = $this->fetchNamespace($prefix);
if ($namespace)
{
$namespaces[] = $namespace;
}
}
// Process the element.
$this->processElement($feed, $el, $namespaces);
// Skip over this element's children since it has been processed.
$this->moveToClosingElement();
}
while ($this->moveToNextElement());
return $feed;
}
/**
* Method to register a namespace handler object.
*
* @param string $prefix The XML namespace prefix for which to register the namespace object.
* @param NamespaceParserInterface $namespace The namespace object to register.
*
* @return JFeed
*
* @since 3.1.4
*/
public function registerNamespace($prefix, NamespaceParserInterface $namespace)
{
$this->namespaces[$prefix] = $namespace;
return $this;
}
/**
* Method to initialise the feed for parsing. If child parsers need to detect versions or other
* such things this is where you'll want to implement that logic.
*
* @return void
*
* @since 3.1.4
*/
abstract protected function initialise();
/**
* Method to parse a specific feed element.
*
* @param Feed $feed The Feed object being built from the parsed feed.
* @param \SimpleXMLElement $el The current XML element object to handle.
* @param array $namespaces The array of relevant namespace objects to process for the element.
*
* @return void
*
* @since 3.1.4
*/
protected function processElement(Feed $feed, \SimpleXMLElement $el, array $namespaces)
{
// Build the internal method name.
$method = 'handle' . ucfirst($el->getName());
// If we are dealing with an item then it is feed entry time.
if ($el->getName() == $this->entryElementName)
{
// Create a new feed entry for the item.
$entry = new FeedEntry;
// First call the internal method.
$this->processFeedEntry($entry, $el);
foreach ($namespaces as $namespace)
{
if ($namespace instanceof NamespaceParserInterface)
{
$namespace->processElementForFeedEntry($entry, $el);
}
}
// Add the new entry to the feed.
$feed->addEntry($entry);
return;
}
// Otherwise we treat it like any other element.
// First call the internal method.
if (is_callable(array($this, $method)))
{
$this->$method($feed, $el);
}
foreach ($namespaces as $namespace)
{
if ($namespace instanceof NamespaceParserInterface)
{
$namespace->processElementForFeed($feed, $el);
}
}
}
/**
* Method to get a namespace object for a given namespace prefix.
*
* @param string $prefix The XML prefix for which to fetch the namespace object.
*
* @return mixed NamespaceParserInterface or false if none exists.
*
* @since 3.1.4
*/
protected function fetchNamespace($prefix)
{
if (isset($this->namespaces[$prefix]))
{
return $this->namespaces[$prefix];
}
$className = get_class($this) . ucfirst($prefix);
if (class_exists($className))
{
$this->namespaces[$prefix] = new $className;
return $this->namespaces[$prefix];
}
return false;
}
/**
* Method to move the stream parser to the next XML element node.
*
* @param string $name The name of the element for which to move the stream forward until is found.
*
* @return boolean True if the stream parser is on an XML element node.
*
* @since 3.1.4
*/
protected function moveToNextElement($name = null)
{
// Only keep looking until the end of the stream.
while ($this->stream->read())
{
// As soon as we get to the next ELEMENT node we are done.
if ($this->stream->nodeType == \XMLReader::ELEMENT)
{
// If we are looking for a specific name make sure we have it.
if (isset($name) && ($this->stream->name != $name))
{
continue;
}
return true;
}
}
return false;
}
/**
* Method to move the stream parser to the closing XML node of the current element.
*
* @return void
*
* @since 3.1.4
* @throws \RuntimeException If the closing tag cannot be found.
*/
protected function moveToClosingElement()
{
// If we are on a self-closing tag then there is nothing to do.
if ($this->stream->isEmptyElement)
{
return;
}
// Get the name and depth for the current node so that we can match the closing node.
$name = $this->stream->name;
$depth = $this->stream->depth;
// Only keep looking until the end of the stream.
while ($this->stream->read())
{
// If we have an END_ELEMENT node with the same name and depth as the node we started with we have a bingo. :-)
if (($this->stream->name == $name) && ($this->stream->depth == $depth) && ($this->stream->nodeType == \XMLReader::END_ELEMENT))
{
return;
}
}
throw new \RuntimeException('Unable to find the closing XML node.');
}
}
FeedPerson.php 0000644 00000002247 15234540332 0007315 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Feed;
defined('JPATH_PLATFORM') or die;
/**
* Feed Person class.
*
* @since 3.1.4
*/
class FeedPerson
{
/**
* The email address of the person.
*
* @var string
* @since 3.1.4
*/
public $email;
/**
* The full name of the person.
*
* @var string
* @since 3.1.4
*/
public $name;
/**
* The type of person.
*
* @var string
* @since 3.1.4
*/
public $type;
/**
* The URI for the person.
*
* @var string
* @since 3.1.4
*/
public $uri;
/**
* Constructor.
*
* @param string $name The full name of the person.
* @param string $email The email address of the person.
* @param string $uri The URI for the person.
* @param string $type The type of person.
*
* @since 3.1.4
*/
public function __construct($name = null, $email = null, $uri = null, $type = null)
{
$this->name = $name;
$this->email = $email;
$this->uri = $uri;
$this->type = $type;
}
}
FeedEnclosure.php 0000644 00000001326 15234631472 0010011 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Document\Feed;
defined('JPATH_PLATFORM') or die;
/**
* Data object representing a feed enclosure
*
* @since 1.7.0
*/
class FeedEnclosure
{
/**
* URL enclosure element
*
* required
*
* @var string
* @since 1.7.0
*/
public $url = '';
/**
* Length enclosure element
*
* required
*
* @var string
* @since 1.7.0
*/
public $length = '';
/**
* Type enclosure element
*
* required
*
* @var string
* @since 1.7.0
*/
public $type = '';
}
FeedImage.php 0000644 00000002030 15234631472 0007065 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Document\Feed;
defined('JPATH_PLATFORM') or die;
/**
* Data object representing a feed image
*
* @since 1.7.0
*/
class FeedImage
{
/**
* Title image attribute
*
* required
*
* @var string
* @since 1.7.0
*/
public $title = '';
/**
* URL image attribute
*
* required
*
* @var string
* @since 1.7.0
*/
public $url = '';
/**
* Link image attribute
*
* required
*
* @var string
* @since 1.7.0
*/
public $link = '';
/**
* Width image attribute
*
* optional
*
* @var string
* @since 1.7.0
*/
public $width;
/**
* Title feed attribute
*
* optional
*
* @var string
* @since 1.7.0
*/
public $height;
/**
* Title feed attribute
*
* optional
*
* @var string
* @since 1.7.0
*/
public $description;
}
FeedItem.php 0000644 00000004077 15234631472 0006756 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Document\Feed;
defined('JPATH_PLATFORM') or die;
/**
* Data object representing a feed item
*
* @since 1.7.0
*/
class FeedItem
{
/**
* Title item element
*
* required
*
* @var string
* @since 1.7.0
*/
public $title;
/**
* Link item element
*
* required
*
* @var string
* @since 1.7.0
*/
public $link;
/**
* Description item element
*
* required
*
* @var string
* @since 1.7.0
*/
public $description;
/**
* Author item element
*
* optional
*
* @var string
* @since 1.7.0
*/
public $author;
/**
* Author email element
*
* optional
*
* @var string
* @since 1.7.0
*/
public $authorEmail;
/**
* Category element
*
* optional
*
* @var array or string
* @since 1.7.0
*/
public $category;
/**
* Comments element
*
* optional
*
* @var string
* @since 1.7.0
*/
public $comments;
/**
* Enclosure element
*
* @var FeedEnclosure
* @since 1.7.0
*/
public $enclosure = null;
/**
* Guid element
*
* optional
*
* @var string
* @since 1.7.0
*/
public $guid;
/**
* Published date
*
* optional
*
* May be in one of the following formats:
*
* RFC 822:
* "Mon, 20 Jan 03 18:05:41 +0400"
* "20 Jan 03 18:05:41 +0000"
*
* ISO 8601:
* "2003-01-20T18:05:41+04:00"
*
* Unix:
* 1043082341
*
* @var string
* @since 1.7.0
*/
public $date;
/**
* Source element
*
* optional
*
* @var string
* @since 1.7.0
*/
public $source;
/**
* Set the FeedEnclosure for this item
*
* @param FeedEnclosure $enclosure The FeedEnclosure to add to the feed.
*
* @return FeedItem instance of $this to allow chaining
*
* @since 1.7.0
*/
public function setEnclosure(FeedEnclosure $enclosure)
{
$this->enclosure = $enclosure;
return $this;
}
}
RssRenderer.php 0000644 00000017600 15235772577 0007543 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Document\Renderer\Feed;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Uri\Uri;
/**
* RssRenderer is a feed that implements RSS 2.0 Specification
*
* @link http://www.rssboard.org/rss-specification
* @since 3.5
*
* @property-read \Joomla\CMS\Document\FeedDocument $_doc Reference to the Document object that instantiated the renderer
*/
class RssRenderer extends DocumentRenderer
{
/**
* Renderer mime type
*
* @var string
* @since 3.5
*/
protected $_mime = 'application/rss+xml';
/**
* Render the feed.
*
* @param string $name The name of the element to render
* @param array $params Array of values
* @param string $content Override the output of the renderer
*
* @return string The output of the script
*
* @see DocumentRenderer::render()
* @since 3.5
*/
public function render($name = '', $params = null, $content = null)
{
$app = \JFactory::getApplication();
// Gets and sets timezone offset from site configuration
$tz = new \DateTimeZone($app->get('offset'));
$now = \JFactory::getDate();
$now->setTimeZone($tz);
$data = $this->_doc;
$url = Uri::getInstance()->toString(array('scheme', 'user', 'pass', 'host', 'port'));
$syndicationURL = \JRoute::_('&format=feed&type=rss');
$title = $data->getTitle();
if ($app->get('sitename_pagetitles', 0) == 1)
{
$title = \JText::sprintf('JPAGETITLE', $app->get('sitename'), $data->getTitle());
}
elseif ($app->get('sitename_pagetitles', 0) == 2)
{
$title = \JText::sprintf('JPAGETITLE', $data->getTitle(), $app->get('sitename'));
}
$feed_title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8');
$datalink = $data->getLink();
if (preg_match('/[\x80-\xFF]/', $datalink))
{
$datalink = implode('/', array_map('rawurlencode', explode('/', $datalink)));
}
$feed = "<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n";
$feed .= " <channel>\n";
$feed .= " <title>" . $feed_title . "</title>\n";
$feed .= " <description><![CDATA[" . $data->getDescription() . "]]></description>\n";
$feed .= " <link>" . str_replace(' ', '%20', $url . $datalink) . "</link>\n";
$feed .= " <lastBuildDate>" . htmlspecialchars($now->toRFC822(true), ENT_COMPAT, 'UTF-8') . "</lastBuildDate>\n";
$feed .= " <generator>" . $data->getGenerator() . "</generator>\n";
$feed .= " <atom:link rel=\"self\" type=\"application/rss+xml\" href=\"" . str_replace(' ', '%20', $url . $syndicationURL) . "\"/>\n";
if ($data->image != null)
{
$feed .= " <image>\n";
$feed .= " <url>" . $data->image->url . "</url>\n";
$feed .= " <title>" . htmlspecialchars($data->image->title, ENT_COMPAT, 'UTF-8') . "</title>\n";
$feed .= " <link>" . str_replace(' ', '%20', $data->image->link) . "</link>\n";
if ($data->image->width != '')
{
$feed .= " <width>" . $data->image->width . "</width>\n";
}
if ($data->image->height != '')
{
$feed .= " <height>" . $data->image->height . "</height>\n";
}
if ($data->image->description != '')
{
$feed .= " <description><![CDATA[" . $data->image->description . "]]></description>\n";
}
$feed .= " </image>\n";
}
if ($data->getLanguage() !== '')
{
$feed .= " <language>" . $data->getLanguage() . "</language>\n";
}
if ($data->copyright != '')
{
$feed .= " <copyright>" . htmlspecialchars($data->copyright, ENT_COMPAT, 'UTF-8') . "</copyright>\n";
}
if ($data->editorEmail != '')
{
$feed .= " <managingEditor>" . htmlspecialchars($data->editorEmail, ENT_COMPAT, 'UTF-8') . ' ('
. htmlspecialchars($data->editor, ENT_COMPAT, 'UTF-8') . ")</managingEditor>\n";
}
if ($data->webmaster != '')
{
$feed .= " <webMaster>" . htmlspecialchars($data->webmaster, ENT_COMPAT, 'UTF-8') . "</webMaster>\n";
}
if ($data->pubDate != '')
{
$pubDate = \JFactory::getDate($data->pubDate);
$pubDate->setTimeZone($tz);
$feed .= " <pubDate>" . htmlspecialchars($pubDate->toRFC822(true), ENT_COMPAT, 'UTF-8') . "</pubDate>\n";
}
if (!empty($data->category))
{
if (is_array($data->category))
{
foreach ($data->category as $cat)
{
$feed .= " <category>" . htmlspecialchars($cat, ENT_COMPAT, 'UTF-8') . "</category>\n";
}
}
else
{
$feed .= " <category>" . htmlspecialchars($data->category, ENT_COMPAT, 'UTF-8') . "</category>\n";
}
}
if ($data->docs != '')
{
$feed .= " <docs>" . htmlspecialchars($data->docs, ENT_COMPAT, 'UTF-8') . "</docs>\n";
}
if ($data->ttl != '')
{
$feed .= " <ttl>" . htmlspecialchars($data->ttl, ENT_COMPAT, 'UTF-8') . "</ttl>\n";
}
if ($data->rating != '')
{
$feed .= " <rating>" . htmlspecialchars($data->rating, ENT_COMPAT, 'UTF-8') . "</rating>\n";
}
if ($data->skipHours != '')
{
$feed .= " <skipHours>" . htmlspecialchars($data->skipHours, ENT_COMPAT, 'UTF-8') . "</skipHours>\n";
}
if ($data->skipDays != '')
{
$feed .= " <skipDays>" . htmlspecialchars($data->skipDays, ENT_COMPAT, 'UTF-8') . "</skipDays>\n";
}
for ($i = 0, $count = count($data->items); $i < $count; $i++)
{
$itemlink = $data->items[$i]->link;
if (preg_match('/[\x80-\xFF]/', $itemlink))
{
$itemlink = implode('/', array_map('rawurlencode', explode('/', $itemlink)));
}
if ((strpos($itemlink, 'http://') === false) && (strpos($itemlink, 'https://') === false))
{
$itemlink = str_replace(' ', '%20', $url . $itemlink);
}
$feed .= " <item>\n";
$feed .= " <title>" . htmlspecialchars(strip_tags($data->items[$i]->title), ENT_COMPAT, 'UTF-8') . "</title>\n";
$feed .= " <link>" . str_replace(' ', '%20', $itemlink) . "</link>\n";
if (empty($data->items[$i]->guid))
{
$feed .= " <guid isPermaLink=\"true\">" . str_replace(' ', '%20', $itemlink) . "</guid>\n";
}
else
{
$feed .= " <guid isPermaLink=\"false\">" . htmlspecialchars($data->items[$i]->guid, ENT_COMPAT, 'UTF-8') . "</guid>\n";
}
$feed .= " <description><![CDATA[" . $this->_relToAbs($data->items[$i]->description) . "]]></description>\n";
if ($data->items[$i]->authorEmail != '')
{
$feed .= ' <author>'
. htmlspecialchars($data->items[$i]->authorEmail . ' (' . $data->items[$i]->author . ')', ENT_COMPAT, 'UTF-8') . "</author>\n";
}
/*
* @todo: On hold
* if ($data->items[$i]->source!='')
* {
* $data.= " <source>" . htmlspecialchars($data->items[$i]->source, ENT_COMPAT, 'UTF-8') . "</source>\n";
* }
*/
if (empty($data->items[$i]->category) === false)
{
if (is_array($data->items[$i]->category))
{
foreach ($data->items[$i]->category as $cat)
{
$feed .= " <category>" . htmlspecialchars($cat, ENT_COMPAT, 'UTF-8') . "</category>\n";
}
}
else
{
$feed .= " <category>" . htmlspecialchars($data->items[$i]->category, ENT_COMPAT, 'UTF-8') . "</category>\n";
}
}
if ($data->items[$i]->comments != '')
{
$feed .= " <comments>" . htmlspecialchars($data->items[$i]->comments, ENT_COMPAT, 'UTF-8') . "</comments>\n";
}
if ($data->items[$i]->date != '')
{
$itemDate = \JFactory::getDate($data->items[$i]->date);
$itemDate->setTimeZone($tz);
$feed .= " <pubDate>" . htmlspecialchars($itemDate->toRFC822(true), ENT_COMPAT, 'UTF-8') . "</pubDate>\n";
}
if ($data->items[$i]->enclosure != null)
{
$feed .= " <enclosure url=\"";
$feed .= $data->items[$i]->enclosure->url;
$feed .= "\" length=\"";
$feed .= $data->items[$i]->enclosure->length;
$feed .= "\" type=\"";
$feed .= $data->items[$i]->enclosure->type;
$feed .= "\"/>\n";
}
$feed .= " </item>\n";
}
$feed .= " </channel>\n";
$feed .= "</rss>\n";
return $feed;
}
}
AtomRenderer.php 0000644 00000014743 15235772577 0007701 0 ustar 00 <?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Document\Renderer\Feed;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Uri\Uri;
/**
* AtomRenderer is a feed that implements the atom specification
*
* Please note that just by using this class you won't automatically
* produce valid atom files. For example, you have to specify either an editor
* for the feed or an author for every single feed item.
*
* @link http://www.atomenabled.org/developers/syndication/atom-format-spec.php
* @since 3.5
*
* @property-read \Joomla\CMS\Document\FeedDocument $_doc Reference to the Document object that instantiated the renderer
*/
class AtomRenderer extends DocumentRenderer
{
/**
* Document mime type
*
* @var string
* @since 3.5
*/
protected $_mime = 'application/atom+xml';
/**
* Render the feed.
*
* @param string $name The name of the element to render
* @param array $params Array of values
* @param string $content Override the output of the renderer
*
* @return string The output of the script
*
* @see DocumentRenderer::render()
* @since 3.5
*/
public function render($name = '', $params = null, $content = null)
{
$app = \JFactory::getApplication();
// Gets and sets timezone offset from site configuration
$tz = new \DateTimeZone($app->get('offset'));
$now = \JFactory::getDate();
$now->setTimeZone($tz);
$data = $this->_doc;
$url = Uri::getInstance()->toString(array('scheme', 'user', 'pass', 'host', 'port'));
$syndicationURL = \JRoute::_('&format=feed&type=atom');
$title = $data->getTitle();
if ($app->get('sitename_pagetitles', 0) == 1)
{
$title = \JText::sprintf('JPAGETITLE', $app->get('sitename'), $data->getTitle());
}
elseif ($app->get('sitename_pagetitles', 0) == 2)
{
$title = \JText::sprintf('JPAGETITLE', $data->getTitle(), $app->get('sitename'));
}
$feed_title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8');
$feed = "<feed xmlns=\"http://www.w3.org/2005/Atom\" ";
if ($data->getLanguage() != '')
{
$feed .= " xml:lang=\"" . $data->getLanguage() . "\"";
}
$feed .= ">\n";
$feed .= " <title type=\"text\">" . $feed_title . "</title>\n";
$feed .= " <subtitle type=\"text\">" . htmlspecialchars($data->getDescription(), ENT_COMPAT, 'UTF-8') . "</subtitle>\n";
if (!empty($data->category))
{
if (is_array($data->category))
{
foreach ($data->category as $cat)
{
$feed .= " <category term=\"" . htmlspecialchars($cat, ENT_COMPAT, 'UTF-8') . "\" />\n";
}
}
else
{
$feed .= " <category term=\"" . htmlspecialchars($data->category, ENT_COMPAT, 'UTF-8') . "\" />\n";
}
}
$feed .= " <link rel=\"alternate\" type=\"text/html\" href=\"" . $url . "\"/>\n";
$feed .= " <id>" . str_replace(' ', '%20', $data->getBase()) . "</id>\n";
$feed .= " <updated>" . htmlspecialchars($now->toISO8601(true), ENT_COMPAT, 'UTF-8') . "</updated>\n";
if ($data->editor != '')
{
$feed .= " <author>\n";
$feed .= " <name>" . $data->editor . "</name>\n";
if ($data->editorEmail != '')
{
$feed .= " <email>" . htmlspecialchars($data->editorEmail, ENT_COMPAT, 'UTF-8') . "</email>\n";
}
$feed .= " </author>\n";
}
$versionHtmlEscaped = '';
if ($app->get('MetaVersion', 0))
{
$minorVersion = \JVersion::MAJOR_VERSION . '.' . \JVersion::MINOR_VERSION;
$versionHtmlEscaped = ' version="' . htmlspecialchars($minorVersion, ENT_COMPAT, 'UTF-8') . '"';
}
$feed .= " <generator uri=\"https://www.joomla.org\"" . $versionHtmlEscaped . ">" . $data->getGenerator() . "</generator>\n";
$feed .= " <link rel=\"self\" type=\"application/atom+xml\" href=\"" . str_replace(' ', '%20', $url . $syndicationURL) . "\"/>\n";
for ($i = 0, $count = count($data->items); $i < $count; $i++)
{
$itemlink = $data->items[$i]->link;
if (preg_match('/[\x80-\xFF]/', $itemlink))
{
$itemlink = implode('/', array_map('rawurlencode', explode('/', $itemlink)));
}
$feed .= " <entry>\n";
$feed .= " <title>" . htmlspecialchars(strip_tags($data->items[$i]->title), ENT_COMPAT, 'UTF-8') . "</title>\n";
$feed .= " <link rel=\"alternate\" type=\"text/html\" href=\"" . $url . $itemlink . "\"/>\n";
if ($data->items[$i]->date == '')
{
$data->items[$i]->date = $now->toUnix();
}
$itemDate = \JFactory::getDate($data->items[$i]->date);
$itemDate->setTimeZone($tz);
$feed .= " <published>" . htmlspecialchars($itemDate->toISO8601(true), ENT_COMPAT, 'UTF-8') . "</published>\n";
$feed .= " <updated>" . htmlspecialchars($itemDate->toISO8601(true), ENT_COMPAT, 'UTF-8') . "</updated>\n";
if (empty($data->items[$i]->guid))
{
$itemGuid = str_replace(' ', '%20', $url . $itemlink);
}
else
{
$itemGuid = htmlspecialchars($data->items[$i]->guid, ENT_COMPAT, 'UTF-8');
}
$feed .= " <id>" . $itemGuid . "</id>\n";
if ($data->items[$i]->author != '')
{
$feed .= " <author>\n";
$feed .= " <name>" . htmlspecialchars($data->items[$i]->author, ENT_COMPAT, 'UTF-8') . "</name>\n";
if (!empty($data->items[$i]->authorEmail))
{
$feed .= " <email>" . htmlspecialchars($data->items[$i]->authorEmail, ENT_COMPAT, 'UTF-8') . "</email>\n";
}
$feed .= " </author>\n";
}
if (!empty($data->items[$i]->description))
{
$feed .= " <summary type=\"html\">" . htmlspecialchars($this->_relToAbs($data->items[$i]->description), ENT_COMPAT, 'UTF-8') . "</summary>\n";
$feed .= " <content type=\"html\">" . htmlspecialchars($this->_relToAbs($data->items[$i]->description), ENT_COMPAT, 'UTF-8') . "</content>\n";
}
if (!empty($data->items[$i]->category))
{
if (is_array($data->items[$i]->category))
{
foreach ($data->items[$i]->category as $cat)
{
$feed .= " <category term=\"" . htmlspecialchars($cat, ENT_COMPAT, 'UTF-8') . "\" />\n";
}
}
else
{
$feed .= " <category term=\"" . htmlspecialchars($data->items[$i]->category, ENT_COMPAT, 'UTF-8') . "\" />\n";
}
}
if ($data->items[$i]->enclosure != null)
{
$feed .= " <link rel=\"enclosure\" href=\"" . $data->items[$i]->enclosure->url . "\" type=\""
. $data->items[$i]->enclosure->type . "\" length=\"" . $data->items[$i]->enclosure->length . "\" />\n";
}
$feed .= " </entry>\n";
}
$feed .= "</feed>\n";
return $feed;
}
}