diff --git a/composer.json b/composer.json index f8b4473b0154f8eaf0411115f05b2472fa9d7e70..97ef123ebee2c8919fc83f0196f98f6fff73a618 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ "kriswallsmith/assetic": "1.1.*@alpha", "symfony-cmf/routing": "1.1.*@alpha", "easyrdf/easyrdf": "0.8.*@beta", - "phpunit/phpunit": "3.7.*" + "phpunit/phpunit": "3.7.*", + "zendframework/zend-feed": "2.2.*" }, "autoload": { "psr-0": { diff --git a/composer.lock b/composer.lock index dea5f2458d95799a6277b97de2cc2a80e2b139dc..75394bafe5020a74b6617a8bfffdf65a256c3226 100644 --- a/composer.lock +++ b/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "e2836b171e18ace7a3f758875041815a", + "hash": "9cad5a32fc0b4c0fac16fbda1b8ead16", "packages": [ { "name": "doctrine/common", @@ -791,27 +791,27 @@ }, { "name": "symfony-cmf/routing", - "version": "1.1.0-alpha2", + "version": "1.1.0-beta1", "target-dir": "Symfony/Cmf/Component/Routing", "source": { "type": "git", "url": "https://github.com/symfony-cmf/Routing.git", - "reference": "1.1.0-alpha2" + "reference": "1.1.0-beta1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony-cmf/Routing/zipball/1.1.0-alpha2", - "reference": "1.1.0-alpha2", + "url": "https://api.github.com/repos/symfony-cmf/Routing/zipball/1.1.0-beta1", + "reference": "1.1.0-beta1", "shasum": "" }, "require": { - "php": ">=5.3.2", + "php": ">=5.3.3", "psr/log": ">=1.0,<2.0", - "symfony/http-kernel": ">=2.2,<2.4-dev", - "symfony/routing": ">=2.2,<2.4-dev" + "symfony/http-kernel": ">=2.2,<3.0", + "symfony/routing": ">=2.2,<3.0" }, "suggest": { - "symfony/http-foundation": "ChainRouter/DynamicRouter have optional support for Request instances, several enhancers require a Request instances, >=2.2,<2.3-dev" + "symfony/http-foundation": "ChainRouter/DynamicRouter have optional support for Request instances, several enhancers require a Request instances, ~2.2" }, "type": "library", "extra": { @@ -840,7 +840,7 @@ "database", "routing" ], - "time": "2013-05-28 19:50:20" + "time": "2013-06-03 17:23:01" }, { "name": "symfony/class-loader", @@ -1448,17 +1448,17 @@ }, { "name": "symfony/yaml", - "version": "v2.3.0", + "version": "v2.3.1", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "v2.3.0-RC1" + "reference": "v2.3.1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.0-RC1", - "reference": "v2.3.0-RC1", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.1", + "reference": "v2.3.1", "shasum": "" }, "require": { @@ -1541,6 +1541,138 @@ "templating" ], "time": "2013-04-08 12:40:11" + }, + { + "name": "zendframework/zend-escaper", + "version": "2.2.1", + "target-dir": "Zend/Escaper", + "source": { + "type": "git", + "url": "https://github.com/zendframework/Component_ZendEscaper.git", + "reference": "release-2.2.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/Component_ZendEscaper/zipball/release-2.2.1", + "reference": "release-2.2.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + }, + "autoload": { + "psr-0": { + "Zend\\Escaper\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "keywords": [ + "escaper", + "zf2" + ], + "time": "2013-05-01 21:53:03" + }, + { + "name": "zendframework/zend-feed", + "version": "2.2.1", + "target-dir": "Zend/Feed", + "source": { + "type": "git", + "url": "https://github.com/zendframework/Component_ZendFeed.git", + "reference": "release-2.2.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/Component_ZendFeed/zipball/release-2.2.1", + "reference": "release-2.2.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "zendframework/zend-escaper": "self.version", + "zendframework/zend-stdlib": "self.version" + }, + "suggest": { + "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for default/recommended ExtensionManager implementations", + "zendframework/zend-validator": "Zend\\Validator component" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + }, + "autoload": { + "psr-0": { + "Zend\\Feed\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides functionality for consuming RSS and Atom feeds", + "keywords": [ + "feed", + "zf2" + ], + "time": "2013-06-12 19:45:31" + }, + { + "name": "zendframework/zend-stdlib", + "version": "2.2.1", + "target-dir": "Zend/Stdlib", + "source": { + "type": "git", + "url": "https://github.com/zendframework/Component_ZendStdlib.git", + "reference": "release-2.2.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/Component_ZendStdlib/zipball/release-2.2.1", + "reference": "release-2.2.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "zendframework/zend-eventmanager": "To support aggregate hydrator usage", + "zendframework/zend-servicemanager": "To support hydrator plugin manager usage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + }, + "autoload": { + "psr-0": { + "Zend\\Stdlib\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "keywords": [ + "stdlib", + "zf2" + ], + "time": "2013-06-12 19:46:58" } ], "packages-dev": [ diff --git a/core/core.services.yml b/core/core.services.yml index 03b8c7cf0d5de357d77784dcdc7ef724f9a856b8..50775db7fd2ab7c9e54624ed7c96bb0f34740d44 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -465,3 +465,57 @@ services: date: class: Drupal\Core\Datetime\Date arguments: ['@config.factory', '@language_manager'] + feed.bridge.reader: + class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer + calls: + - [setContainer, ['@service_container']] + arguments: ['feed.reader.'] + feed.bridge.writer: + class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer + calls: + - [setContainer, ['@service_container']] + arguments: ['feed.writer.'] +# Zend Feed reader plugins + feed.reader.dublincoreentry: + class: Zend\Feed\Reader\Extension\DublinCore\Entry + feed.reader.dublincorefeed: + class: Zend\Feed\Reader\Extension\DublinCore\Feed + feed.reader.contententry: + class: Zend\Feed\Reader\Extension\Content\Entry + feed.reader.atomentry: + class: Zend\Feed\Reader\Extension\Atom\Entry + feed.reader.atomfeed: + class: Zend\Feed\Reader\Extension\Atom\Feed + feed.reader.slashentry: + class: Zend\Feed\Reader\Extension\Slash\Entry + feed.reader.wellformedwebentry: + class: Zend\Feed\Reader\Extension\WellFormedWeb\Entry + feed.reader.threadentry: + class: Zend\Feed\Reader\Extension\Thread\Entry + feed.reader.podcastentry: + class: Zend\Feed\Reader\Extension\Podcast\Entry + feed.reader.podcastfeed: + class: Zend\Feed\Reader\Extension\Podcast\Feed +# Zend Feed writer plugins + feed.writer.atomrendererfeed: + class: Zend\Feed\Writer\Extension\Atom\Renderer\Feed + feed.writer.contentrendererentry: + class: Zend\Feed\Writer\Extension\Content\Renderer\Entry + feed.writer.dublincorerendererentry: + class: Zend\Feed\Writer\Extension\DublinCore\Renderer\Entry + feed.writer.dublincorerendererfeed: + class: Zend\Feed\Writer\Extension\DublinCore\Renderer\Feed + feed.writer.itunesentry: + class: Zend\Feed\Writer\Extension\ITunes\Entry + feed.writer.itunesfeed: + class: Zend\Feed\Writer\Extension\ITunes\Feed + feed.writer.itunesrendererentry: + class: Zend\Feed\Writer\Extension\ITunes\Renderer\Entry + feed.writer.itunesrendererfeed: + class: Zend\Feed\Writer\Extension\ITunes\Renderer\Feed + feed.writer.slashrendererentry: + class: Zend\Feed\Writer\Extension\Slash\Renderer\Entry + feed.writer.threadingrendererentry: + class: Zend\Feed\Writer\Extension\Threading\Renderer\Entry + feed.writer.wellformedwebrendererentry: + class: Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry diff --git a/core/includes/common.inc b/core/includes/common.inc index d8638feaaf6e138840e550f0a5b3ba2c4fba652c..a392a5aa4b4f856cadcb6b7eeedc0b69f712e55a 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -22,6 +22,8 @@ use Drupal\Core\Routing\GeneratorNotInitializedException; use Drupal\Core\SystemListingInfo; use Drupal\Core\Template\Attribute; +use Zend\Feed\Writer\Writer; +use Zend\Feed\Reader\Reader; /** * @file @@ -3988,6 +3990,10 @@ function _drupal_bootstrap_code() { // Load all enabled modules Drupal::moduleHandler()->loadAll(); + // Set our bridge extension manager to Zend Feed. + Reader::setExtensionManager(Drupal::service('feed.bridge.reader')); + Writer::setExtensionManager(Drupal::service('feed.bridge.writer')); + // Make sure all stream wrappers are registered. file_get_stream_wrappers(); diff --git a/core/lib/Drupal/Component/Bridge/ZfExtensionManagerSfContainer.php b/core/lib/Drupal/Component/Bridge/ZfExtensionManagerSfContainer.php new file mode 100644 index 0000000000000000000000000000000000000000..94d969b8e73c0adc586f7db97dff2176cc73495f --- /dev/null +++ b/core/lib/Drupal/Component/Bridge/ZfExtensionManagerSfContainer.php @@ -0,0 +1,95 @@ +<?php + +/** + * @file + * Contains \Drupal\Component\Bridge\ZfExtensionManagerSfContainer + */ +namespace Drupal\Component\Bridge; + +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Zend\Feed\Reader\ExtensionManagerInterface as ReaderManagerInterface; +use Zend\Feed\Writer\ExtensionManagerInterface as WriterManagerInterface; + +/** + * Defines a bridge between the ZF2 service manager to Symfony container. + */ +class ZfExtensionManagerSfContainer implements ReaderManagerInterface, WriterManagerInterface, ContainerAwareInterface { + + /** + * This property was based from Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * + * A map of characters to be replaced through strtr. + * + * @var array + * + * @see \Drupal\Component\Bridge\ZfExtensionManagerSfContainer::canonicalizeName(). + */ + protected $canonicalNamesReplacements = array('-' => '', '_' => '', ' ' => '', '\\' => '', '/' => ''); + + /** + * The prefix to be used when retrieving plugins from the container. + * + * @var string + */ + protected $prefix = ''; + + /** + * Constructs a ZfExtensionManagerSfContainer object. + * + * @param string $prefix + * The prefix to be used when retrieving plugins from the container. + */ + public function __construct($prefix = '') { + return $this->prefix = $prefix; + } + + /** + * {@inheritdoc} + */ + public function get($extension) { + return $this->container->get($this->prefix . $this->canonicalizeName($extension)); + } + + /** + * {@inheritdoc} + */ + public function has($extension) { + return $this->container->has($this->prefix . $this->canonicalizeName($extension)); + } + + /** + * This method was based from Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * + * Canonicalize the extension name to a service name. + * + * @param string $name + * The extension name. + * + * @return string + * The service name, without the prefix. + */ + protected function canonicalizeName($name) { + if (isset($this->canonicalNames[$name])) { + return $this->canonicalNames[$name]; + } + // This is just for performance instead of using str_replace(). + return $this->canonicalNames[$name] = strtolower(strtr($name, $this->canonicalNamesReplacements)); + } + + /** + * {@inheritdoc} + */ + public function setContainer(ContainerInterface $container = NULL) { + $this->container = $container; + } + +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php index eab6e9baf1e3722bc98e0dea65bdd15cf6b98371..a295749f23e72742058468cc1039900aea406051 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php @@ -11,6 +11,9 @@ use Drupal\aggregator\Plugin\Core\Entity\Feed; use Drupal\aggregator\Annotation\AggregatorParser; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Cache\Cache; +use Zend\Feed\Reader\Reader; +use Zend\Feed\Reader\Exception\ExceptionInterface; /** * Defines a default parser implementation. @@ -26,353 +29,50 @@ class DefaultParser implements ParserInterface { /** - * The extracted channel info. - * - * @var array - */ - protected $channel = array(); - - /** - * The extracted image info. - * - * @var array - */ - protected $image = array(); - - /** - * The extracted items. - * - * @var array - */ - protected $items = array(); - - /** - * The element that is being processed. - * - * @var array - */ - protected $element = array(); - - /** - * The tag that is being processed. - * - * @var string - */ - protected $tag = ''; - - /** - * Key that holds the number of processed "entry" and "item" tags. - * - * @var int - */ - protected $item; - - /** - * Implements \Drupal\aggregator\Plugin\ParserInterface::parse(). + * {@inheritdoc} */ public function parse(Feed $feed) { - // Filter the input data. - if ($this->parseFeed($feed->source_string, $feed)) { - - // Prepare the channel data. - foreach ($this->channel as $key => $value) { - $this->channel[$key] = trim($value); - } - - // Prepare the image data (if any). - foreach ($this->image as $key => $value) { - $this->image[$key] = trim($value); - } - - // Add parsed data to the feed object. - $feed->link->value = !empty($channel['link']) ? $channel['link'] : ''; - $feed->description->value = !empty($channel['description']) ? $channel['description'] : ''; - $feed->image->value = !empty($image['url']) ? $image['url'] : ''; - - // Clear the page and block caches. - cache_invalidate_tags(array('content' => TRUE)); - - return TRUE; + try { + $channel = Reader::importString($feed->source_string); } + catch (ExceptionInterface $e) { + watchdog_exception('aggregator', $e); + drupal_set_message(t('The feed from %site seems to be broken because of error "%error".', array('%site' => $feed->label(), '%error' => $e->getMessage())), 'error'); - return FALSE; - } - - - /** - * Parses a feed and stores its items. - * - * @param string $data - * The feed data. - * @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed - * An object describing the feed to be parsed. - * - * @return bool - * FALSE on error, TRUE otherwise. - */ - protected function parseFeed(&$data, Feed $feed) { - // Parse the data. - $xml_parser = drupal_xml_parser_create($data); - xml_set_element_handler($xml_parser, array($this, 'elementStart'), array($this, 'elementEnd')); - xml_set_character_data_handler($xml_parser, array($this, 'elementData')); - - if (!xml_parse($xml_parser, $data, 1)) { - watchdog('aggregator', 'The feed from %site seems to be broken due to an error "%error" on line %line.', array('%site' => $feed->label(), '%error' => xml_error_string(xml_get_error_code($xml_parser)), '%line' => xml_get_current_line_number($xml_parser)), WATCHDOG_WARNING); - drupal_set_message(t('The feed from %site seems to be broken because of error "%error" on line %line.', array('%site' => $feed->label(), '%error' => xml_error_string(xml_get_error_code($xml_parser)), '%line' => xml_get_current_line_number($xml_parser))), 'error'); return FALSE; } - xml_parser_free($xml_parser); - - // We reverse the array such that we store the first item last, and the last - // item first. In the database, the newest item should be at the top. - $this->items = array_reverse($this->items); + $feed->link->value = $channel->getLink(); + $feed->description->value = $channel->getDescription(); + if ($image = $channel->getImage()) { + $feed->image->value = $image['uri']; + } // Initialize items array. $feed->items = array(); - foreach ($this->items as $item) { - - // Prepare the item: - foreach ($item as $key => $value) { - $item[$key] = trim($value); - } - - // Resolve the item's title. If no title is found, we use up to 40 - // characters of the description ending at a word boundary, but not - // splitting potential entities. - if (!empty($item['title'])) { - $item['title'] = $item['title']; - } - elseif (!empty($item['description'])) { - $item['title'] = preg_replace('/^(.*)[^\w;&].*?$/', "\\1", truncate_utf8($item['description'], 40)); - } - else { - $item['title'] = ''; - } - - // Resolve the items link. - if (!empty($item['link'])) { - $item['link'] = $item['link']; + foreach ($channel as $item) { + // Reset the parsed item. + $parsed_item = array(); + // Move the values to an array as expected by processors. + $parsed_item['title'] = $item->getTitle(); + $parsed_item['guid'] = $item->getId(); + $parsed_item['link'] = $item->getLink(); + $parsed_item['description'] = $item->getDescription(); + $parsed_item['author'] = ''; + if ($author = $item->getAuthor()) { + $parsed_item['author'] = $author['name']; + } + $parsed_item['timestamp'] = ''; + if ($date = $item->getDateModified()) { + $parsed_item['timestamp'] = $date->getTimestamp(); } - else { - $item['link'] = $feed->link->value; - } - - // Atom feeds have an ID tag instead of a GUID tag. - if (!isset($item['guid'])) { - $item['guid'] = isset($item['id']) ? $item['id'] : ''; - } - - // Atom feeds have a content and/or summary tag instead of a description tag. - if (!empty($item['content:encoded'])) { - $item['description'] = $item['content:encoded']; - } - elseif (!empty($item['summary'])) { - $item['description'] = $item['summary']; - } - elseif (!empty($item['content'])) { - $item['description'] = $item['content']; - } - - // Try to resolve and parse the item's publication date. - $date = ''; - foreach (array('pubdate', 'dc:date', 'dcterms:issued', 'dcterms:created', 'dcterms:modified', 'issued', 'created', 'modified', 'published', 'updated') as $key) { - if (!empty($item[$key])) { - $date = $item[$key]; - break; - } - } - - $item['timestamp'] = strtotime($date); - - if ($item['timestamp'] === FALSE) { - $item['timestamp'] = $this->parseW3cdtf($date); // Aggregator_parse_w3cdtf() returns FALSE on failure. - } - - // Resolve dc:creator tag as the item author if author tag is not set. - if (empty($item['author']) && !empty($item['dc:creator'])) { - $item['author'] = $item['dc:creator']; - } - - $item += array('author' => '', 'description' => ''); - // Store on $feed object. This is where processors will look for parsed items. - $feed->items[] = $item; - } - - return TRUE; - } - - /** - * XML parser callback: Perform an action when an opening tag is encountered. - * - * @param resource $parser - * A reference to the XML parser calling the handler. - * @param string $name - * The name of the element for which this handler is called. - * @param array $attributes - * An associative array with the element's attributes (if any). - */ - protected function elementStart($parser, $name, $attributes) { - $name = strtolower($name); - switch ($name) { - case 'image': - case 'textinput': - case 'summary': - case 'tagline': - case 'subtitle': - case 'logo': - case 'info': - $this->element = $name; - break; - case 'id': - case 'content': - if ($this->element != 'item') { - $this->element = $name; - } - case 'link': - // According to RFC 4287, link elements in Atom feeds without a 'rel' - // attribute should be interpreted as though the relation type is - // "alternate". - if (!empty($attributes['HREF']) && (empty($attributes['REL']) || $attributes['REL'] == 'alternate')) { - if ($this->element == 'item') { - $this->items[$this->item]['link'] = $attributes['HREF']; - } - else { - $this->channel['link'] = $attributes['HREF']; - } - } - break; - case 'item': - $this->element = $name; - $this->item += 1; - break; - case 'entry': - $this->element = 'item'; - $this->item += 1; - break; + $feed->items[] = $parsed_item; } - $this->tag = $name; - } - - /** - * XML parser callback: Perform an action when a closing tag is encountered. - * - * @param resource $parser - * A reference to the XML parser calling the handler. - * @param string $name - * The name of the element for which this handler is called. - * @param array $attributes - * An associative array with the element's attributes (if any). - */ - protected function elementEnd($parser, $name) { - switch ($name) { - case 'image': - case 'textinput': - case 'item': - case 'entry': - case 'info': - $this->element = ''; - break; - case 'id': - case 'content': - if ($this->element == $name) { - $this->element = ''; - } - } - } + // Clear the page and block caches. + Cache::invalidateTags(array('content' => TRUE)); - /** - * XML parser callback: Perform an action when data is encountered. - * - * @param resource $parser - * A reference to the XML parser calling the handler. - * @param string $name - * The name of the element for which this handler is called. - * @param array $attributes - * An associative array with the element's attributes (if any). - */ - function elementData($parser, $data) { - $this->items += array($this->item => array()); - switch ($this->element) { - case 'item': - $this->items[$this->item] += array($this->tag => ''); - $this->items[$this->item][$this->tag] .= $data; - break; - case 'image': - case 'logo': - $this->image += array($this->tag => ''); - $this->image[$this->tag] .= $data; - break; - case 'link': - if ($data) { - $this->items[$this->item] += array($tag => ''); - $this->items[$this->item][$this->tag] .= $data; - } - break; - case 'content': - $this->items[$this->item] += array('content' => ''); - $this->items[$this->item]['content'] .= $data; - break; - case 'summary': - $this->items[$this->item] += array('summary' => ''); - $this->items[$this->item]['summary'] .= $data; - break; - case 'tagline': - case 'subtitle': - $this->channel += array('description' => ''); - $this->channel['description'] .= $data; - break; - case 'info': - case 'id': - case 'textinput': - // The sub-element is not supported. However, we must recognize - // it or its contents will end up in the item array. - break; - default: - $this->channel += array($this->tag => ''); - $this->channel[$this->tag] .= $data; - } + return TRUE; } - /** - * Parses the W3C date/time format, a subset of ISO 8601. - * - * PHP date parsing functions do not handle this format. See - * http://www.w3.org/TR/NOTE-datetime for more information. Originally from - * MagpieRSS (http://magpierss.sourceforge.net/). - * - * @param string $date_str - * A string with a potentially W3C DTF date. - * - * @return int|false - * A timestamp if parsed successfully or FALSE if not. - */ - function parseW3cdtf($date_str) { - if (preg_match('/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/', $date_str, $match)) { - list($year, $month, $day, $hours, $minutes, $seconds) = array($match[1], $match[2], $match[3], $match[4], $match[5], $match[6]); - // Calculate the epoch for current date assuming GMT. - $epoch = gmmktime($hours, $minutes, $seconds, $month, $day, $year); - if ($match[10] != 'Z') { // Z is zulu time, aka GMT - list($tz_mod, $tz_hour, $tz_min) = array($match[8], $match[9], $match[10]); - // Zero out the variables. - if (!$tz_hour) { - $tz_hour = 0; - } - if (!$tz_min) { - $tz_min = 0; - } - $offset_secs = (($tz_hour * 60) + $tz_min) * 60; - // Is timezone ahead of GMT? If yes, subtract offset. - if ($tz_mod == '+') { - $offset_secs *= -1; - } - $epoch += $offset_secs; - } - return $epoch; - } - else { - return FALSE; - } - } } diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php index 5f4f9f9c17a6211b943ae2d650b2bf492c1b2082..bdbe11fcc49e4ca8ea0bf430738ed7e4601cd695 100644 --- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php +++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/FeedParserTest.php @@ -7,6 +7,8 @@ namespace Drupal\aggregator\Tests; +use Zend\Feed\Reader\Reader; + /** * Tests feed parsing in the Aggregator module. */ @@ -25,6 +27,11 @@ function setUp() { // feeds have hardcoded dates in them (which may be expired when this test // is run). config('aggregator.settings')->set('items.expire', AGGREGATOR_CLEAR_NEVER)->save(); + // Reset any reader cache between tests. + Reader::reset(); + // Set our bridge extension manager to Zend Feed. + $bridge = $this->container->get('feed.bridge.reader'); + Reader::setExtensionManager($bridge); } /** diff --git a/core/vendor/autoload.php b/core/vendor/autoload.php index ebc5b04c3cf6b4296350e180aeeccc698522b84d..51fea2c3f72dd0e0a47679b83b2e6282fccdb2a1 100644 --- a/core/vendor/autoload.php +++ b/core/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInitc269e792cec97d4c278bb968546f51b4::getLoader(); +return ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37::getLoader(); diff --git a/core/vendor/composer/ClassLoader.php b/core/vendor/composer/ClassLoader.php index ef9924516ae074b9b6e34174ad485f5a687c617f..1db8d9a0b2e2207309eb93e83ab8ab4736fd4ab2 100644 --- a/core/vendor/composer/ClassLoader.php +++ b/core/vendor/composer/ClassLoader.php @@ -121,8 +121,8 @@ public function add($prefix, $paths, $prepend = false) /** * Registers a set of classes, replacing any others previously set. * - * @param string $prefix The classes prefix - * @param array|string $paths The location(s) of the classes + * @param string $prefix The classes prefix + * @param array|string $paths The location(s) of the classes */ public function set($prefix, $paths) { diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php index 3385df1d10588bf22ed1dc6821a261ea268ba59d..87cf5706b33e0c8c4ccc911a5c3000acebefac2e 100644 --- a/core/vendor/composer/autoload_namespaces.php +++ b/core/vendor/composer/autoload_namespaces.php @@ -6,6 +6,9 @@ $baseDir = dirname(dirname($vendorDir)); return array( + 'Zend\\Stdlib\\' => array($vendorDir . '/zendframework/zend-stdlib'), + 'Zend\\Feed\\' => array($vendorDir . '/zendframework/zend-feed'), + 'Zend\\Escaper\\' => array($vendorDir . '/zendframework/zend-escaper'), 'Twig_' => array($vendorDir . '/twig/twig/lib'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), 'Symfony\\Component\\Validator\\' => array($vendorDir . '/symfony/validator'), diff --git a/core/vendor/composer/autoload_real.php b/core/vendor/composer/autoload_real.php index 843e1e8c0b80ee02d91562951551501714d29be8..7d1d4add74e832ae6292ba818d8a130270530d91 100644 --- a/core/vendor/composer/autoload_real.php +++ b/core/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php generated by Composer -class ComposerAutoloaderInitc269e792cec97d4c278bb968546f51b4 +class ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitc269e792cec97d4c278bb968546f51b4', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitc269e792cec97d4c278bb968546f51b4', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37', 'loadClassLoader')); $vendorDir = dirname(__DIR__); $baseDir = dirname(dirname($vendorDir)); diff --git a/core/vendor/composer/installed.json b/core/vendor/composer/installed.json index 7ee26800b332d7608619d302cd90654384950994..322247d6796312ac23ef236f6fb198236e68665b 100644 --- a/core/vendor/composer/installed.json +++ b/core/vendor/composer/installed.json @@ -179,109 +179,18 @@ "homepage": "http://symfony.com" }, { - "name": "psr/log", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log", - "reference": "1.0.0" - }, - "dist": { - "type": "zip", - "url": "https://github.com/php-fig/log/archive/1.0.0.zip", - "reference": "1.0.0", - "shasum": "" - }, - "time": "2012-12-21 11:40:51", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "Psr\\Log\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "keywords": [ - "log", - "psr", - "psr-3" - ] - }, - { - "name": "twig/twig", - "version": "v1.12.3", - "version_normalized": "1.12.3.0", - "source": { - "type": "git", - "url": "https://github.com/fabpot/Twig.git", - "reference": "v1.12.3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fabpot/Twig/zipball/v1.12.3", - "reference": "v1.12.3", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "time": "2013-04-08 12:40:11", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.12-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Twig_": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", - "keywords": [ - "templating" - ] - }, - { - "name": "symfony/debug", + "name": "symfony/dependency-injection", "version": "v2.3.1", "version_normalized": "2.3.1.0", - "target-dir": "Symfony/Component/Debug", + "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", - "url": "https://github.com/symfony/Debug.git", + "url": "https://github.com/symfony/DependencyInjection.git", "reference": "v2.3.1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Debug/zipball/v2.3.1", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/v2.3.1", "reference": "v2.3.1", "shasum": "" }, @@ -289,15 +198,15 @@ "php": ">=5.3.3" }, "require-dev": { - "symfony/http-foundation": ">=2.1,<3.0", - "symfony/http-kernel": ">=2.1,<3.0" + "symfony/config": ">=2.2,<3.0", + "symfony/yaml": ">=2.0,<3.0" }, "suggest": { - "symfony/class-loader": "", - "symfony/http-foundation": "", - "symfony/http-kernel": "" + "symfony/config": "", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" }, - "time": "2013-06-02 11:58:44", + "time": "2013-06-05 09:51:05", "type": "library", "extra": { "branch-alias": { @@ -307,7 +216,7 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\Debug\\": "" + "Symfony\\Component\\DependencyInjection\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -324,7 +233,7 @@ "homepage": "http://symfony.com/contributors" } ], - "description": "Symfony Debug Component", + "description": "Symfony DependencyInjection Component", "homepage": "http://symfony.com" }, { @@ -380,32 +289,25 @@ "homepage": "http://symfony.com" }, { - "name": "symfony/event-dispatcher", - "version": "v2.3.0", - "version_normalized": "2.3.0.0", - "target-dir": "Symfony/Component/EventDispatcher", + "name": "symfony/serializer", + "version": "v2.3.1", + "version_normalized": "2.3.1.0", + "target-dir": "Symfony/Component/Serializer", "source": { "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "v2.3.0-RC1" + "url": "https://github.com/symfony/Serializer.git", + "reference": "v2.3.1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.0-RC1", - "reference": "v2.3.0-RC1", + "url": "https://api.github.com/repos/symfony/Serializer/zipball/v2.3.1", + "reference": "v2.3.1", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "require-dev": { - "symfony/dependency-injection": ">=2.0,<3.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "time": "2013-05-13 14:36:40", + "time": "2013-05-10 18:12:13", "type": "library", "extra": { "branch-alias": { @@ -415,7 +317,7 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\EventDispatcher\\": "" + "Symfony\\Component\\Serializer\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -432,52 +334,37 @@ "homepage": "http://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "description": "Symfony Serializer Component", "homepage": "http://symfony.com" }, { - "name": "symfony/http-kernel", + "name": "symfony/translation", "version": "v2.3.0", "version_normalized": "2.3.0.0", - "target-dir": "Symfony/Component/HttpKernel", + "target-dir": "Symfony/Component/Translation", "source": { "type": "git", - "url": "https://github.com/symfony/HttpKernel.git", - "reference": "v2.3.0" + "url": "https://github.com/symfony/Translation.git", + "reference": "v2.3.0-RC1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.3.0", - "reference": "v2.3.0", + "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.3.0-RC1", + "reference": "v2.3.0-RC1", "shasum": "" }, "require": { - "php": ">=5.3.3", - "psr/log": ">=1.0,<2.0", - "symfony/debug": ">=2.3,<3.0", - "symfony/event-dispatcher": ">=2.1,<3.0", - "symfony/http-foundation": ">=2.2,<3.0" + "php": ">=5.3.3" }, "require-dev": { - "symfony/browser-kit": "2.2.*", - "symfony/class-loader": ">=2.1,<3.0", "symfony/config": ">=2.0,<3.0", - "symfony/console": "2.2.*", - "symfony/dependency-injection": ">=2.0,<3.0", - "symfony/finder": ">=2.0,<3.0", - "symfony/process": ">=2.0,<3.0", - "symfony/routing": ">=2.2,<3.0", - "symfony/stopwatch": ">=2.2,<3.0" + "symfony/yaml": ">=2.2,<3.0" }, "suggest": { - "symfony/browser-kit": "", - "symfony/class-loader": "", "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "", - "symfony/finder": "" + "symfony/yaml": "" }, - "time": "2013-06-03 14:13:35", + "time": "2013-05-13 14:36:40", "type": "library", "extra": { "branch-alias": { @@ -487,7 +374,7 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\HttpKernel\\": "" + "Symfony\\Component\\Translation\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -504,50 +391,30 @@ "homepage": "http://symfony.com/contributors" } ], - "description": "Symfony HttpKernel Component", + "description": "Symfony Translation Component", "homepage": "http://symfony.com" }, { - "name": "symfony/routing", - "version": "v2.3.0", - "version_normalized": "2.3.0.0", - "target-dir": "Symfony/Component/Routing", + "name": "psr/log", + "version": "1.0.0", + "version_normalized": "1.0.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/Routing.git", - "reference": "v2.3.0" + "url": "https://github.com/php-fig/log", + "reference": "1.0.0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.0", - "reference": "v2.3.0", + "url": "https://github.com/php-fig/log/archive/1.0.0.zip", + "reference": "1.0.0", "shasum": "" }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "doctrine/common": ">=2.2,<3.0", - "psr/log": ">=1.0,<2.0", - "symfony/config": ">=2.2,<3.0", - "symfony/yaml": ">=2.0,<3.0" - }, - "suggest": { - "doctrine/common": "", - "symfony/config": "", - "symfony/yaml": "" - }, - "time": "2013-05-20 08:57:26", + "time": "2012-12-21 11:40:51", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\Routing\\": "" + "Psr\\Log\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -556,101 +423,102 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Symfony Routing Component", - "homepage": "http://symfony.com" + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ] }, { - "name": "symfony-cmf/routing", - "version": "1.1.0-alpha2", - "version_normalized": "1.1.0.0-alpha2", - "target-dir": "Symfony/Cmf/Component/Routing", + "name": "twig/twig", + "version": "v1.12.3", + "version_normalized": "1.12.3.0", "source": { "type": "git", - "url": "https://github.com/symfony-cmf/Routing.git", - "reference": "1.1.0-alpha2" + "url": "https://github.com/fabpot/Twig.git", + "reference": "v1.12.3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony-cmf/Routing/zipball/1.1.0-alpha2", - "reference": "1.1.0-alpha2", + "url": "https://api.github.com/repos/fabpot/Twig/zipball/v1.12.3", + "reference": "v1.12.3", "shasum": "" }, "require": { - "php": ">=5.3.2", - "psr/log": ">=1.0,<2.0", - "symfony/http-kernel": ">=2.2,<2.4-dev", - "symfony/routing": ">=2.2,<2.4-dev" - }, - "suggest": { - "symfony/http-foundation": "ChainRouter/DynamicRouter have optional support for Request instances, several enhancers require a Request instances, >=2.2,<2.3-dev" + "php": ">=5.2.4" }, - "time": "2013-05-28 19:50:20", + "time": "2013-04-08 12:40:11", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.12-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Cmf\\Component\\Routing": "" + "Twig_": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3" ], "authors": [ { - "name": "Symfony CMF Community", - "homepage": "https://github.com/symfony-cmf/Routing/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com" } ], - "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers", - "homepage": "http://cmf.symfony.com", + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", "keywords": [ - "database", - "routing" + "templating" ] }, { - "name": "symfony/dependency-injection", + "name": "symfony/validator", "version": "v2.3.1", "version_normalized": "2.3.1.0", - "target-dir": "Symfony/Component/DependencyInjection", + "target-dir": "Symfony/Component/Validator", "source": { "type": "git", - "url": "https://github.com/symfony/DependencyInjection.git", + "url": "https://github.com/symfony/Validator.git", "reference": "v2.3.1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/v2.3.1", + "url": "https://api.github.com/repos/symfony/Validator/zipball/v2.3.1", "reference": "v2.3.1", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.3", + "symfony/translation": ">=2.0,<3.0" }, "require-dev": { "symfony/config": ">=2.2,<3.0", + "symfony/http-foundation": ">=2.1,<3.0", + "symfony/intl": ">=2.3,<3.0", "symfony/yaml": ">=2.0,<3.0" }, "suggest": { + "doctrine/common": "", "symfony/config": "", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/http-foundation": "", + "symfony/intl": "", "symfony/yaml": "" }, - "time": "2013-06-05 09:51:05", + "time": "2013-06-10 16:23:25", "type": "library", "extra": { "branch-alias": { @@ -660,7 +528,7 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\DependencyInjection\\": "" + "Symfony\\Component\\Validator\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -677,29 +545,36 @@ "homepage": "http://symfony.com/contributors" } ], - "description": "Symfony DependencyInjection Component", + "description": "Symfony Validator Component", "homepage": "http://symfony.com" }, { - "name": "symfony/serializer", - "version": "v2.3.1", - "version_normalized": "2.3.1.0", - "target-dir": "Symfony/Component/Serializer", + "name": "symfony/event-dispatcher", + "version": "v2.3.0", + "version_normalized": "2.3.0.0", + "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", - "url": "https://github.com/symfony/Serializer.git", - "reference": "v2.3.1" + "url": "https://github.com/symfony/EventDispatcher.git", + "reference": "v2.3.0-RC1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Serializer/zipball/v2.3.1", - "reference": "v2.3.1", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.0-RC1", + "reference": "v2.3.0-RC1", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2013-05-10 18:12:13", + "require-dev": { + "symfony/dependency-injection": ">=2.0,<3.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "time": "2013-05-13 14:36:40", "type": "library", "extra": { "branch-alias": { @@ -709,7 +584,7 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\Serializer\\": "" + "Symfony\\Component\\EventDispatcher\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -726,110 +601,86 @@ "homepage": "http://symfony.com/contributors" } ], - "description": "Symfony Serializer Component", + "description": "Symfony EventDispatcher Component", "homepage": "http://symfony.com" }, { - "name": "symfony/translation", - "version": "v2.3.0", - "version_normalized": "2.3.0.0", - "target-dir": "Symfony/Component/Translation", + "name": "guzzle/common", + "version": "v3.1.2", + "version_normalized": "3.1.2.0", + "target-dir": "Guzzle/Common", "source": { "type": "git", - "url": "https://github.com/symfony/Translation.git", - "reference": "v2.3.0-RC1" + "url": "git://github.com/guzzle/common.git", + "reference": "v3.1.2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.3.0-RC1", - "reference": "v2.3.0-RC1", + "url": "https://github.com/guzzle/common/archive/v3.1.2.zip", + "reference": "v3.1.2", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/config": ">=2.0,<3.0", - "symfony/yaml": ">=2.2,<3.0" - }, - "suggest": { - "symfony/config": "", - "symfony/yaml": "" + "php": ">=5.3.2", + "symfony/event-dispatcher": ">=2.1" }, - "time": "2013-05-13 14:36:40", + "time": "2013-01-28 00:07:40", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "3.0-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\Translation\\": "" + "Guzzle\\Common": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - } - ], - "description": "Symfony Translation Component", - "homepage": "http://symfony.com" + "description": "Common libraries used by Guzzle", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "collection", + "common", + "event", + "exception" + ] }, { - "name": "symfony/validator", - "version": "v2.3.1", - "version_normalized": "2.3.1.0", - "target-dir": "Symfony/Component/Validator", + "name": "guzzle/stream", + "version": "v3.1.2", + "version_normalized": "3.1.2.0", + "target-dir": "Guzzle/Stream", "source": { "type": "git", - "url": "https://github.com/symfony/Validator.git", - "reference": "v2.3.1" + "url": "https://github.com/guzzle/stream", + "reference": "v3.0.7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Validator/zipball/v2.3.1", - "reference": "v2.3.1", + "url": "https://github.com/guzzle/stream/archive/v3.0.7.zip", + "reference": "v3.0.7", "shasum": "" }, "require": { - "php": ">=5.3.3", - "symfony/translation": ">=2.0,<3.0" - }, - "require-dev": { - "symfony/config": ">=2.2,<3.0", - "symfony/http-foundation": ">=2.1,<3.0", - "symfony/intl": ">=2.3,<3.0", - "symfony/yaml": ">=2.0,<3.0" - }, - "suggest": { - "doctrine/common": "", - "symfony/config": "", - "symfony/http-foundation": "", - "symfony/intl": "", - "symfony/yaml": "" + "guzzle/common": "self.version", + "php": ">=5.3.2" }, - "time": "2013-06-10 16:23:25", + "time": "2012-12-07 16:45:11", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "3.0-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\Validator\\": "" + "Guzzle\\Stream": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -838,38 +689,39 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Symfony Validator Component", - "homepage": "http://symfony.com" + "description": "Guzzle stream wrapper component", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "component", + "stream" + ] }, { - "name": "guzzle/common", + "name": "guzzle/parser", "version": "v3.1.2", "version_normalized": "3.1.2.0", - "target-dir": "Guzzle/Common", + "target-dir": "Guzzle/Parser", "source": { "type": "git", - "url": "git://github.com/guzzle/common.git", + "url": "git://github.com/guzzle/parser.git", "reference": "v3.1.2" }, "dist": { "type": "zip", - "url": "https://github.com/guzzle/common/archive/v3.1.2.zip", + "url": "https://github.com/guzzle/parser/archive/v3.1.2.zip", "reference": "v3.1.2", "shasum": "" }, "require": { - "php": ">=5.3.2", - "symfony/event-dispatcher": ">=2.1" + "php": ">=5.3.2" }, - "time": "2013-01-28 00:07:40", + "time": "2013-01-12 21:43:21", "type": "library", "extra": { "branch-alias": { @@ -879,43 +731,49 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Guzzle\\Common": "" + "Guzzle\\Parser": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Common libraries used by Guzzle", + "description": "Interchangeable parsers used by Guzzle", "homepage": "http://guzzlephp.org/", "keywords": [ - "collection", - "common", - "event", - "exception" + "URI Template", + "cookie", + "http", + "message", + "url" ] }, { - "name": "guzzle/stream", + "name": "guzzle/http", "version": "v3.1.2", "version_normalized": "3.1.2.0", - "target-dir": "Guzzle/Stream", + "target-dir": "Guzzle/Http", "source": { "type": "git", - "url": "https://github.com/guzzle/stream", - "reference": "v3.0.7" + "url": "git://github.com/guzzle/http.git", + "reference": "v3.1.2" }, "dist": { "type": "zip", - "url": "https://github.com/guzzle/stream/archive/v3.0.7.zip", - "reference": "v3.0.7", + "url": "https://github.com/guzzle/http/archive/v3.1.2.zip", + "reference": "v3.1.2", "shasum": "" }, "require": { "guzzle/common": "self.version", + "guzzle/parser": "self.version", + "guzzle/stream": "self.version", "php": ">=5.3.2" }, - "time": "2012-12-07 16:45:11", + "suggest": { + "ext-curl": "*" + }, + "time": "2013-01-26 08:20:43", "type": "library", "extra": { "branch-alias": { @@ -925,7 +783,7 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Guzzle\\Stream": "" + "Guzzle\\Http": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -939,96 +797,249 @@ "homepage": "https://github.com/mtdowling" } ], - "description": "Guzzle stream wrapper component", + "description": "HTTP libraries used by Guzzle", "homepage": "http://guzzlephp.org/", "keywords": [ "Guzzle", - "component", - "stream" + "client", + "curl", + "http", + "http client" ] }, { - "name": "guzzle/parser", - "version": "v3.1.2", - "version_normalized": "3.1.2.0", - "target-dir": "Guzzle/Parser", + "name": "symfony/process", + "version": "v2.3.1", + "version_normalized": "2.3.1.0", + "target-dir": "Symfony/Component/Process", "source": { "type": "git", - "url": "git://github.com/guzzle/parser.git", - "reference": "v3.1.2" + "url": "https://github.com/symfony/Process.git", + "reference": "v2.3.1" }, "dist": { "type": "zip", - "url": "https://github.com/guzzle/parser/archive/v3.1.2.zip", - "reference": "v3.1.2", + "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.1", + "reference": "v2.3.1", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3.3" }, - "time": "2013-01-12 21:43:21", + "time": "2013-05-06 20:03:44", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { - "Guzzle\\Parser": "" + "Symfony\\Component\\Process\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Interchangeable parsers used by Guzzle", - "homepage": "http://guzzlephp.org/", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "http://symfony.com" + }, + { + "name": "kriswallsmith/assetic", + "version": "v1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/kriswallsmith/assetic.git", + "reference": "v1.1.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/v1.1.1", + "reference": "v1.1.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.1", + "symfony/process": ">=2.1,<3.0" + }, + "require-dev": { + "cssmin/cssmin": "*", + "joliclic/javascript-packer": "*", + "kamicane/packager": "*", + "leafo/lessphp": "*", + "leafo/scssphp": "*", + "leafo/scssphp-compass": "*", + "mrclay/minify": "*", + "phpunit/phpunit": ">=3.7,<4.0", + "ptachoire/cssembed": "*", + "twig/twig": ">=1.6,<2.0" + }, + "suggest": { + "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler", + "leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler", + "leafo/scssphp-compass": "Assetic provides the integration with the SCSS compass plugin", + "ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris", + "twig/twig": "Assetic provides the integration with the Twig templating engine" + }, + "time": "2013-06-01 22:13:43", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Assetic": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kris Wallsmith", + "email": "kris.wallsmith@gmail.com", + "homepage": "http://kriswallsmith.net/" + } + ], + "description": "Asset Management for PHP", + "homepage": "https://github.com/kriswallsmith/assetic", "keywords": [ - "URI Template", - "cookie", - "http", - "message", - "url" + "assets", + "compression", + "minification" ] }, { - "name": "guzzle/http", - "version": "v3.1.2", - "version_normalized": "3.1.2.0", - "target-dir": "Guzzle/Http", + "name": "symfony/debug", + "version": "v2.3.1", + "version_normalized": "2.3.1.0", + "target-dir": "Symfony/Component/Debug", + "source": { + "type": "git", + "url": "https://github.com/symfony/Debug.git", + "reference": "v2.3.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Debug/zipball/v2.3.1", + "reference": "v2.3.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/http-foundation": ">=2.1,<3.0", + "symfony/http-kernel": ">=2.1,<3.0" + }, + "suggest": { + "symfony/class-loader": "", + "symfony/http-foundation": "", + "symfony/http-kernel": "" + }, + "time": "2013-06-02 11:58:44", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\Debug\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "http://symfony.com" + }, + { + "name": "symfony/http-kernel", + "version": "v2.3.0", + "version_normalized": "2.3.0.0", + "target-dir": "Symfony/Component/HttpKernel", "source": { "type": "git", - "url": "git://github.com/guzzle/http.git", - "reference": "v3.1.2" + "url": "https://github.com/symfony/HttpKernel.git", + "reference": "v2.3.0" }, "dist": { "type": "zip", - "url": "https://github.com/guzzle/http/archive/v3.1.2.zip", - "reference": "v3.1.2", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.3.0", + "reference": "v2.3.0", "shasum": "" }, "require": { - "guzzle/common": "self.version", - "guzzle/parser": "self.version", - "guzzle/stream": "self.version", - "php": ">=5.3.2" + "php": ">=5.3.3", + "psr/log": ">=1.0,<2.0", + "symfony/debug": ">=2.3,<3.0", + "symfony/event-dispatcher": ">=2.1,<3.0", + "symfony/http-foundation": ">=2.2,<3.0" + }, + "require-dev": { + "symfony/browser-kit": "2.2.*", + "symfony/class-loader": ">=2.1,<3.0", + "symfony/config": ">=2.0,<3.0", + "symfony/console": "2.2.*", + "symfony/dependency-injection": ">=2.0,<3.0", + "symfony/finder": ">=2.0,<3.0", + "symfony/process": ">=2.0,<3.0", + "symfony/routing": ">=2.2,<3.0", + "symfony/stopwatch": ">=2.2,<3.0" }, "suggest": { - "ext-curl": "*" + "symfony/browser-kit": "", + "symfony/class-loader": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "" }, - "time": "2013-01-26 08:20:43", + "time": "2013-06-03 14:13:35", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { - "Guzzle\\Http": "" + "Symfony\\Component\\HttpKernel\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1037,41 +1048,48 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" } ], - "description": "HTTP libraries used by Guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "client", - "curl", - "http", - "http client" - ] + "description": "Symfony HttpKernel Component", + "homepage": "http://symfony.com" }, { - "name": "symfony/process", - "version": "v2.3.1", - "version_normalized": "2.3.1.0", - "target-dir": "Symfony/Component/Process", + "name": "symfony/routing", + "version": "v2.3.0", + "version_normalized": "2.3.0.0", + "target-dir": "Symfony/Component/Routing", "source": { "type": "git", - "url": "https://github.com/symfony/Process.git", - "reference": "v2.3.1" + "url": "https://github.com/symfony/Routing.git", + "reference": "v2.3.0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.1", - "reference": "v2.3.1", + "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.0", + "reference": "v2.3.0", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2013-05-06 20:03:44", + "require-dev": { + "doctrine/common": ">=2.2,<3.0", + "psr/log": ">=1.0,<2.0", + "symfony/config": ">=2.2,<3.0", + "symfony/yaml": ">=2.0,<3.0" + }, + "suggest": { + "doctrine/common": "", + "symfony/config": "", + "symfony/yaml": "" + }, + "time": "2013-05-20 08:57:26", "type": "library", "extra": { "branch-alias": { @@ -1081,7 +1099,7 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Component\\Routing\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1098,48 +1116,35 @@ "homepage": "http://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Symfony Routing Component", "homepage": "http://symfony.com" }, { - "name": "kriswallsmith/assetic", - "version": "v1.1.1", - "version_normalized": "1.1.1.0", + "name": "symfony-cmf/routing", + "version": "1.1.0-beta1", + "version_normalized": "1.1.0.0-beta1", + "target-dir": "Symfony/Cmf/Component/Routing", "source": { "type": "git", - "url": "https://github.com/kriswallsmith/assetic.git", - "reference": "v1.1.1" + "url": "https://github.com/symfony-cmf/Routing.git", + "reference": "1.1.0-beta1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kriswallsmith/assetic/zipball/v1.1.1", - "reference": "v1.1.1", + "url": "https://api.github.com/repos/symfony-cmf/Routing/zipball/1.1.0-beta1", + "reference": "1.1.0-beta1", "shasum": "" }, "require": { - "php": ">=5.3.1", - "symfony/process": ">=2.1,<3.0" - }, - "require-dev": { - "cssmin/cssmin": "*", - "joliclic/javascript-packer": "*", - "kamicane/packager": "*", - "leafo/lessphp": "*", - "leafo/scssphp": "*", - "leafo/scssphp-compass": "*", - "mrclay/minify": "*", - "phpunit/phpunit": ">=3.7,<4.0", - "ptachoire/cssembed": "*", - "twig/twig": ">=1.6,<2.0" + "php": ">=5.3.3", + "psr/log": ">=1.0,<2.0", + "symfony/http-kernel": ">=2.2,<3.0", + "symfony/routing": ">=2.2,<3.0" }, "suggest": { - "leafo/lessphp": "Assetic provides the integration with the lessphp LESS compiler", - "leafo/scssphp": "Assetic provides the integration with the scssphp SCSS compiler", - "leafo/scssphp-compass": "Assetic provides the integration with the SCSS compass plugin", - "ptachoire/cssembed": "Assetic provides the integration with phpcssembed to embed data uris", - "twig/twig": "Assetic provides the integration with the Twig templating engine" + "symfony/http-foundation": "ChainRouter/DynamicRouter have optional support for Request instances, several enhancers require a Request instances, ~2.2" }, - "time": "2013-06-01 22:13:43", + "time": "2013-06-03 17:23:01", "type": "library", "extra": { "branch-alias": { @@ -1149,11 +1154,8 @@ "installation-source": "dist", "autoload": { "psr-0": { - "Assetic": "src/" - }, - "files": [ - "src/functions.php" - ] + "Symfony\\Cmf\\Component\\Routing": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1161,33 +1163,31 @@ ], "authors": [ { - "name": "Kris Wallsmith", - "email": "kris.wallsmith@gmail.com", - "homepage": "http://kriswallsmith.net/" + "name": "Symfony CMF Community", + "homepage": "https://github.com/symfony-cmf/Routing/contributors" } ], - "description": "Asset Management for PHP", - "homepage": "https://github.com/kriswallsmith/assetic", + "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers", + "homepage": "http://cmf.symfony.com", "keywords": [ - "assets", - "compression", - "minification" + "database", + "routing" ] }, { "name": "symfony/yaml", - "version": "v2.3.0", - "version_normalized": "2.3.0.0", + "version": "v2.3.1", + "version_normalized": "2.3.1.0", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "v2.3.0-RC1" + "reference": "v2.3.1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.0-RC1", - "reference": "v2.3.0-RC1", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.1", + "reference": "v2.3.1", "shasum": "" }, "require": { @@ -1593,5 +1593,143 @@ "testing", "xunit" ] + }, + { + "name": "zendframework/zend-stdlib", + "version": "2.2.1", + "version_normalized": "2.2.1.0", + "target-dir": "Zend/Stdlib", + "source": { + "type": "git", + "url": "https://github.com/zendframework/Component_ZendStdlib.git", + "reference": "release-2.2.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/Component_ZendStdlib/zipball/release-2.2.1", + "reference": "release-2.2.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "zendframework/zend-eventmanager": "To support aggregate hydrator usage", + "zendframework/zend-servicemanager": "To support hydrator plugin manager usage" + }, + "time": "2013-06-12 19:46:58", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Zend\\Stdlib\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "keywords": [ + "stdlib", + "zf2" + ] + }, + { + "name": "zendframework/zend-escaper", + "version": "2.2.1", + "version_normalized": "2.2.1.0", + "target-dir": "Zend/Escaper", + "source": { + "type": "git", + "url": "https://github.com/zendframework/Component_ZendEscaper.git", + "reference": "release-2.2.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/Component_ZendEscaper/zipball/release-2.2.1", + "reference": "release-2.2.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2013-05-01 21:53:03", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Zend\\Escaper\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "keywords": [ + "escaper", + "zf2" + ] + }, + { + "name": "zendframework/zend-feed", + "version": "2.2.1", + "version_normalized": "2.2.1.0", + "target-dir": "Zend/Feed", + "source": { + "type": "git", + "url": "https://github.com/zendframework/Component_ZendFeed.git", + "reference": "release-2.2.1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/Component_ZendFeed/zipball/release-2.2.1", + "reference": "release-2.2.1", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "zendframework/zend-escaper": "self.version", + "zendframework/zend-stdlib": "self.version" + }, + "suggest": { + "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for default/recommended ExtensionManager implementations", + "zendframework/zend-validator": "Zend\\Validator component" + }, + "time": "2013-06-12 19:45:31", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Zend\\Feed\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides functionality for consuming RSS and Atom feeds", + "keywords": [ + "feed", + "zf2" + ] } ] diff --git a/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/.travis.yml b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/.travis.yml index 9c9cce938e40bf73710d8843fe0a25a630a2a391..494db9829aeae7f0cbc2c49237782c0a1ba35668 100644 --- a/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/.travis.yml +++ b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/.travis.yml @@ -6,6 +6,7 @@ php: env: - SYMFONY_VERSION=2.2.* + - SYMFONY_VERSION=2.3.* - SYMFONY_VERSION=dev-master before_script: diff --git a/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/CHANGELOG.md b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/CHANGELOG.md index a93a031d4dce3c8adb29e950d8d224d8ab1898d6..fe5dcfc79879586019287645cd142b8cf00eebfe 100644 --- a/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/CHANGELOG.md +++ b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/CHANGELOG.md @@ -1,6 +1,8 @@ -# Changelog +Changelog +========= -## 1.1 +1.1 +--- -* Dropped Symfony 2.1 support and got rid of ConfigurableUrlMatcher class -* Fix locale handling to always respect locale but never have unnecessary ?locale= \ No newline at end of file +* **2013-04-30**: Dropped Symfony 2.1 support and got rid of ConfigurableUrlMatcher class +* **2013-04-05**: [ContentAwareGenerator] Fix locale handling to always respect locale but never have unnecessary ?locale= diff --git a/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/composer.json b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/composer.json index 8559c1aa7616e3ddd4ef1a52294c5e5fac7c2dee..63cfa9b29386fcd5a51b2bd058615eb1dc69850e 100644 --- a/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/composer.json +++ b/core/vendor/symfony-cmf/routing/Symfony/Cmf/Component/Routing/composer.json @@ -13,13 +13,13 @@ ], "minimum-stability": "dev", "require": { - "php": ">=5.3.2", - "symfony/routing": ">=2.2,<2.4-dev", - "symfony/http-kernel": ">=2.2,<2.4-dev", + "php": ">=5.3.3", + "symfony/routing": "~2.2", + "symfony/http-kernel": "~2.2", "psr/log": "~1.0" }, "suggest": { - "symfony/http-foundation": "ChainRouter/DynamicRouter have optional support for Request instances, several enhancers require a Request instances, >=2.2,<2.3-dev" + "symfony/http-foundation": "ChainRouter/DynamicRouter have optional support for Request instances, several enhancers require a Request instances, ~2.2" }, "autoload": { "psr-0": { "Symfony\\Cmf\\Component\\Routing": "" } diff --git a/core/vendor/zendframework/zend-escaper/Zend/Escaper/Escaper.php b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Escaper.php new file mode 100644 index 0000000000000000000000000000000000000000..38ab113e9db5c32164c76b347e8a9465fb9fa49d --- /dev/null +++ b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Escaper.php @@ -0,0 +1,390 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Escaper; + +use Zend\Escaper\Exception; + +/** + * Context specific methods for use in secure output escaping + */ +class Escaper +{ + /** + * Entity Map mapping Unicode codepoints to any available named HTML entities. + * + * While HTML supports far more named entities, the lowest common denominator + * has become HTML5's XML Serialisation which is restricted to the those named + * entities that XML supports. Using HTML entities would result in this error: + * XML Parsing Error: undefined entity + * + * @var array + */ + protected static $htmlNamedEntityMap = array( + 34 => 'quot', // quotation mark + 38 => 'amp', // ampersand + 60 => 'lt', // less-than sign + 62 => 'gt', // greater-than sign + ); + + /** + * Current encoding for escaping. If not UTF-8, we convert strings from this encoding + * pre-escaping and back to this encoding post-escaping. + * + * @var string + */ + protected $encoding = 'utf-8'; + + /** + * Holds the value of the special flags passed as second parameter to + * htmlspecialchars(). We modify these for PHP 5.4 to take advantage + * of the new ENT_SUBSTITUTE flag for correctly dealing with invalid + * UTF-8 sequences. + * + * @var string + */ + protected $htmlSpecialCharsFlags = ENT_QUOTES; + + /** + * Static Matcher which escapes characters for HTML Attribute contexts + * + * @var callable + */ + protected $htmlAttrMatcher; + + /** + * Static Matcher which escapes characters for Javascript contexts + * + * @var callable + */ + protected $jsMatcher; + + /** + * Static Matcher which escapes characters for CSS Attribute contexts + * + * @var callable + */ + protected $cssMatcher; + + /** + * List of all encoding supported by this class + * + * @var array + */ + protected $supportedEncodings = array( + 'iso-8859-1', 'iso8859-1', 'iso-8859-5', 'iso8859-5', + 'iso-8859-15', 'iso8859-15', 'utf-8', 'cp866', + 'ibm866', '866', 'cp1251', 'windows-1251', + 'win-1251', '1251', 'cp1252', 'windows-1252', + '1252', 'koi8-r', 'koi8-ru', 'koi8r', + 'big5', '950', 'gb2312', '936', + 'big5-hkscs', 'shift_jis', 'sjis', 'sjis-win', + 'cp932', '932', 'euc-jp', 'eucjp', + 'eucjp-win', 'macroman' + ); + + /** + * Constructor: Single parameter allows setting of global encoding for use by + * the current object. If PHP 5.4 is detected, additional ENT_SUBSTITUTE flag + * is set for htmlspecialchars() calls. + * + * @param string $encoding + * @throws Exception\InvalidArgumentException + */ + public function __construct($encoding = null) + { + if ($encoding !== null) { + $encoding = (string) $encoding; + if ($encoding === '') { + throw new Exception\InvalidArgumentException( + get_class($this) . ' constructor parameter does not allow a blank value' + ); + } + + $encoding = strtolower($encoding); + if (!in_array($encoding, $this->supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Value of \'' . $encoding . '\' passed to ' . get_class($this) + . ' constructor parameter is invalid. Provide an encoding supported by htmlspecialchars()' + ); + } + + $this->encoding = $encoding; + } + + if (defined('ENT_SUBSTITUTE')) { + $this->htmlSpecialCharsFlags|= ENT_SUBSTITUTE; + } + + // set matcher callbacks + $this->htmlAttrMatcher = array($this, 'htmlAttrMatcher'); + $this->jsMatcher = array($this, 'jsMatcher'); + $this->cssMatcher = array($this, 'cssMatcher'); + } + + /** + * Return the encoding that all output/input is expected to be encoded in. + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Escape a string for the HTML Body context where there are very few characters + * of special meaning. Internally this will use htmlspecialchars(). + * + * @param string $string + * @return string + */ + public function escapeHtml($string) + { + $result = htmlspecialchars($string, $this->htmlSpecialCharsFlags, $this->encoding); + return $result; + } + + /** + * Escape a string for the HTML Attribute context. We use an extended set of characters + * to escape that are not covered by htmlspecialchars() to cover cases where an attribute + * might be unquoted or quoted illegally (e.g. backticks are valid quotes for IE). + * + * @param string $string + * @return string + */ + public function escapeHtmlAttr($string) + { + $string = $this->toUtf8($string); + if ($string === '' || ctype_digit($string)) { + return $string; + } + + $result = preg_replace_callback('/[^a-z0-9,\.\-_]/iSu', $this->htmlAttrMatcher, $string); + return $this->fromUtf8($result); + } + + /** + * Escape a string for the Javascript context. This does not use json_encode(). An extended + * set of characters are escaped beyond ECMAScript's rules for Javascript literal string + * escaping in order to prevent misinterpretation of Javascript as HTML leading to the + * injection of special characters and entities. The escaping used should be tolerant + * of cases where HTML escaping was not applied on top of Javascript escaping correctly. + * Backslash escaping is not used as it still leaves the escaped character as-is and so + * is not useful in a HTML context. + * + * @param string $string + * @return string + */ + public function escapeJs($string) + { + $string = $this->toUtf8($string); + if ($string === '' || ctype_digit($string)) { + return $string; + } + + $result = preg_replace_callback('/[^a-z0-9,\._]/iSu', $this->jsMatcher, $string); + return $this->fromUtf8($result); + } + + /** + * Escape a string for the URI or Parameter contexts. This should not be used to escape + * an entire URI - only a subcomponent being inserted. The function is a simple proxy + * to rawurlencode() which now implements RFC 3986 since PHP 5.3 completely. + * + * @param string $string + * @return string + */ + public function escapeUrl($string) + { + return rawurlencode($string); + } + + /** + * Escape a string for the CSS context. CSS escaping can be applied to any string being + * inserted into CSS and escapes everything except alphanumerics. + * + * @param string $string + * @return string + */ + public function escapeCss($string) + { + $string = $this->toUtf8($string); + if ($string === '' || ctype_digit($string)) { + return $string; + } + + $result = preg_replace_callback('/[^a-z0-9]/iSu', $this->cssMatcher, $string); + return $this->fromUtf8($result); + } + + /** + * Callback function for preg_replace_callback that applies HTML Attribute + * escaping to all matches. + * + * @param array $matches + * @return string + */ + protected function htmlAttrMatcher($matches) + { + $chr = $matches[0]; + $ord = ord($chr); + + /** + * The following replaces characters undefined in HTML with the + * hex entity for the Unicode replacement character. + */ + if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") + || ($ord >= 0x7f && $ord <= 0x9f) + ) { + return '�'; + } + + /** + * Check if the current character to escape has a name entity we should + * replace it with while grabbing the integer value of the character. + */ + if (strlen($chr) > 1) { + $chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8'); + } + + $hex = bin2hex($chr); + $ord = hexdec($hex); + if (isset(static::$htmlNamedEntityMap[$ord])) { + return '&' . static::$htmlNamedEntityMap[$ord] . ';'; + } + + /** + * Per OWASP recommendations, we'll use upper hex entities + * for any other characters where a named entity does not exist. + */ + if ($ord > 255) { + return sprintf('&#x%04X;', $ord); + } + return sprintf('&#x%02X;', $ord); + } + + /** + * Callback function for preg_replace_callback that applies Javascript + * escaping to all matches. + * + * @param array $matches + * @return string + */ + protected function jsMatcher($matches) + { + $chr = $matches[0]; + if (strlen($chr) == 1) { + return sprintf('\\x%02X', ord($chr)); + } + $chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8'); + return sprintf('\\u%04s', strtoupper(bin2hex($chr))); + } + + /** + * Callback function for preg_replace_callback that applies CSS + * escaping to all matches. + * + * @param array $matches + * @return string + */ + protected function cssMatcher($matches) + { + $chr = $matches[0]; + if (strlen($chr) == 1) { + $ord = ord($chr); + } else { + $chr = $this->convertEncoding($chr, 'UTF-16BE', 'UTF-8'); + $ord = hexdec(bin2hex($chr)); + } + return sprintf('\\%X ', $ord); + } + + /** + * Converts a string to UTF-8 from the base encoding. The base encoding is set via this + * class' constructor. + * + * @param string $string + * @throws Exception\RuntimeException + * @return string + */ + protected function toUtf8($string) + { + if ($this->getEncoding() === 'utf-8') { + $result = $string; + } else { + $result = $this->convertEncoding($string, 'UTF-8', $this->getEncoding()); + } + + if (!$this->isUtf8($result)) { + throw new Exception\RuntimeException(sprintf( + 'String to be escaped was not valid UTF-8 or could not be converted: %s', $result + )); + } + + return $result; + } + + /** + * Converts a string from UTF-8 to the base encoding. The base encoding is set via this + * class' constructor. + * @param string $string + * @return string + */ + protected function fromUtf8($string) + { + if ($this->getEncoding() === 'utf-8') { + return $string; + } + + return $this->convertEncoding($string, $this->getEncoding(), 'UTF-8'); + } + + /** + * Checks if a given string appears to be valid UTF-8 or not. + * + * @param string $string + * @return bool + */ + protected function isUtf8($string) + { + return ($string === '' || preg_match('/^./su', $string)); + } + + /** + * Encoding conversion helper which wraps iconv and mbstring where they exist or throws + * and exception where neither is available. + * + * @param string $string + * @param string $to + * @param array|string $from + * @throws Exception\RuntimeException + * @return string + */ + protected function convertEncoding($string, $to, $from) + { + $result = ''; + if (function_exists('iconv')) { + $result = iconv($from, $to, $string); + } elseif (function_exists('mb_convert_encoding')) { + $result = mb_convert_encoding($string, $to, $from); + } else { + throw new Exception\RuntimeException( + get_class($this) + . ' requires either the iconv or mbstring extension to be installed' + . ' when escaping for non UTF-8 strings.' + ); + } + + if ($result === false) { + return ''; // return non-fatal blank string on encoding errors from users + } + return $result; + } +} diff --git a/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/ExceptionInterface.php b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..364dd67e939ec1a2bccfb8d7af39f357c984d1e0 --- /dev/null +++ b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/ExceptionInterface.php @@ -0,0 +1,13 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Escaper\Exception; + +interface ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/InvalidArgumentException.php b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..78c4da7993c85d905976371b690213979a8cfc35 --- /dev/null +++ b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/InvalidArgumentException.php @@ -0,0 +1,18 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Escaper\Exception; + +/** + * Invalid argument exception + */ +class InvalidArgumentException extends \InvalidArgumentException implements + ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/RuntimeException.php b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..dec2501d2982a9c6b6b6cbc489072f251cd17fde --- /dev/null +++ b/core/vendor/zendframework/zend-escaper/Zend/Escaper/Exception/RuntimeException.php @@ -0,0 +1,18 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Escaper\Exception; + +/** + * Invalid argument exception + */ +class RuntimeException extends \RuntimeException implements + ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-escaper/Zend/Escaper/README.md b/core/vendor/zendframework/zend-escaper/Zend/Escaper/README.md new file mode 100644 index 0000000000000000000000000000000000000000..83bd91628059eb6d34d7eb4828269d5ee769d7c2 --- /dev/null +++ b/core/vendor/zendframework/zend-escaper/Zend/Escaper/README.md @@ -0,0 +1,15 @@ +Escaper Component from ZF2 +========================== + +This is the Escaper component for ZF2. + +- File issues at https://github.com/zendframework/zf2/issues +- Create pull requests against https://github.com/zendframework/zf2 +- Documentation is at http://framework.zend.com/docs + +LICENSE +------- + +The files in this archive are released under the [Zend Framework +license](http://framework.zend.com/license), which is a 3-clause BSD license. + diff --git a/core/vendor/zendframework/zend-escaper/Zend/Escaper/composer.json b/core/vendor/zendframework/zend-escaper/Zend/Escaper/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..3b2f2b602d4f490938dea11dd065c99bc3216268 --- /dev/null +++ b/core/vendor/zendframework/zend-escaper/Zend/Escaper/composer.json @@ -0,0 +1,24 @@ +{ + "name": "zendframework/zend-escaper", + "description": " ", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "escaper" + ], + "autoload": { + "psr-0": { + "Zend\\Escaper\\": "" + } + }, + "target-dir": "Zend/Escaper", + "require": { + "php": ">=5.3.3" + }, + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/BadMethodCallException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..34ab71874bded73caf6e2a838a59981a0abf6af9 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/BadMethodCallException.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Exception; + +class BadMethodCallException + extends \BadMethodCallException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/ExceptionInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f4cf0a0ba5e06a9ca345eee5b61bc9fe006af34f --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/ExceptionInterface.php @@ -0,0 +1,13 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Exception; + +interface ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/InvalidArgumentException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..09930c9b5197b54e347010f3f0ef7af8e9eefc26 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/InvalidArgumentException.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Exception; + +class InvalidArgumentException + extends \InvalidArgumentException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/RuntimeException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..27a32c6bbf2dc6963314c738561f62e3ae2c47ff --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Exception/RuntimeException.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Exception; + +class RuntimeException + extends \RuntimeException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/AbstractCallback.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/AbstractCallback.php new file mode 100644 index 0000000000000000000000000000000000000000..b3ab1907465ad78faca673ca322bbb1bcb211182 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/AbstractCallback.php @@ -0,0 +1,291 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub; + +use Traversable; +use Zend\Http\PhpEnvironment\Response as PhpResponse; +use Zend\Stdlib\ArrayUtils; + +abstract class AbstractCallback implements CallbackInterface +{ + /** + * An instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistenceInterface + * used to background save any verification tokens associated with a subscription + * or other. + * + * @var Model\SubscriptionPersistenceInterface + */ + protected $storage = null; + + /** + * An instance of a class handling Http Responses. This is implemented in + * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with + * (i.e. not inherited from) Zend\Controller\Response\Http. + * + * @var HttpResponse|PhpResponse + */ + protected $httpResponse = null; + + /** + * The number of Subscribers for which any updates are on behalf of. + * + * @var int + */ + protected $subscriberCount = 1; + + /** + * Constructor; accepts an array or Traversable object to preset + * options for the Subscriber without calling all supported setter + * methods in turn. + * + * @param array|Traversable $options Options array or Traversable object + */ + public function __construct($options = null) + { + if ($options !== null) { + $this->setOptions($options); + } + } + + /** + * Process any injected configuration options + * + * @param array|Traversable $options Options array or Traversable object + * @return AbstractCallback + * @throws Exception\InvalidArgumentException + */ + public function setOptions($options) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (!is_array($options)) { + throw new Exception\InvalidArgumentException('Array or Traversable object' + . 'expected, got ' . gettype($options)); + } + + if (is_array($options)) { + $this->setOptions($options); + } + + if (array_key_exists('storage', $options)) { + $this->setStorage($options['storage']); + } + return $this; + } + + /** + * Send the response, including all headers. + * If you wish to handle this via Zend\Http, use the getter methods + * to retrieve any data needed to be set on your HTTP Response object, or + * simply give this object the HTTP Response instance to work with for you! + * + * @return void + */ + public function sendResponse() + { + $this->getHttpResponse()->send(); + } + + /** + * Sets an instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used + * to background save any verification tokens associated with a subscription + * or other. + * + * @param Model\SubscriptionPersistenceInterface $storage + * @return AbstractCallback + */ + public function setStorage(Model\SubscriptionPersistenceInterface $storage) + { + $this->storage = $storage; + return $this; + } + + /** + * Gets an instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used + * to background save any verification tokens associated with a subscription + * or other. + * + * @return Model\SubscriptionPersistenceInterface + * @throws Exception\RuntimeException + */ + public function getStorage() + { + if ($this->storage === null) { + throw new Exception\RuntimeException('No storage object has been' + . ' set that subclasses Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence'); + } + return $this->storage; + } + + /** + * An instance of a class handling Http Responses. This is implemented in + * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with + * (i.e. not inherited from) Zend\Controller\Response\Http. + * + * @param HttpResponse|PhpResponse $httpResponse + * @return AbstractCallback + * @throws Exception\InvalidArgumentException + */ + public function setHttpResponse($httpResponse) + { + if (!$httpResponse instanceof HttpResponse && !$httpResponse instanceof PhpResponse) { + throw new Exception\InvalidArgumentException('HTTP Response object must' + . ' implement one of Zend\Feed\Pubsubhubbub\HttpResponse or' + . ' Zend\Http\PhpEnvironment\Response'); + } + $this->httpResponse = $httpResponse; + return $this; + } + + /** + * An instance of a class handling Http Responses. This is implemented in + * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with + * (i.e. not inherited from) Zend\Controller\Response\Http. + * + * @return HttpResponse|PhpResponse + */ + public function getHttpResponse() + { + if ($this->httpResponse === null) { + $this->httpResponse = new HttpResponse; + } + return $this->httpResponse; + } + + /** + * Sets the number of Subscribers for which any updates are on behalf of. + * In other words, is this class serving one or more subscribers? How many? + * Defaults to 1 if left unchanged. + * + * @param string|int $count + * @return AbstractCallback + * @throws Exception\InvalidArgumentException + */ + public function setSubscriberCount($count) + { + $count = intval($count); + if ($count <= 0) { + throw new Exception\InvalidArgumentException('Subscriber count must be' + . ' greater than zero'); + } + $this->subscriberCount = $count; + return $this; + } + + /** + * Gets the number of Subscribers for which any updates are on behalf of. + * In other words, is this class serving one or more subscribers? How many? + * + * @return int + */ + public function getSubscriberCount() + { + return $this->subscriberCount; + } + + /** + * Attempt to detect the callback URL (specifically the path forward) + * @return string + */ + protected function _detectCallbackUrl() + { + $callbackUrl = ''; + if (isset($_SERVER['HTTP_X_ORIGINAL_URL'])) { + $callbackUrl = $_SERVER['HTTP_X_ORIGINAL_URL']; + } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { + $callbackUrl = $_SERVER['HTTP_X_REWRITE_URL']; + } elseif (isset($_SERVER['REQUEST_URI'])) { + $callbackUrl = $_SERVER['REQUEST_URI']; + $scheme = 'http'; + if ($_SERVER['HTTPS'] == 'on') { + $scheme = 'https'; + } + $schemeAndHttpHost = $scheme . '://' . $this->_getHttpHost(); + if (strpos($callbackUrl, $schemeAndHttpHost) === 0) { + $callbackUrl = substr($callbackUrl, strlen($schemeAndHttpHost)); + } + } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { + $callbackUrl= $_SERVER['ORIG_PATH_INFO']; + if (!empty($_SERVER['QUERY_STRING'])) { + $callbackUrl .= '?' . $_SERVER['QUERY_STRING']; + } + } + return $callbackUrl; + } + + /** + * Get the HTTP host + * + * @return string + */ + protected function _getHttpHost() + { + if (!empty($_SERVER['HTTP_HOST'])) { + return $_SERVER['HTTP_HOST']; + } + $scheme = 'http'; + if ($_SERVER['HTTPS'] == 'on') { + $scheme = 'https'; + } + $name = $_SERVER['SERVER_NAME']; + $port = $_SERVER['SERVER_PORT']; + if (($scheme == 'http' && $port == 80) + || ($scheme == 'https' && $port == 443) + ) { + return $name; + } + + return $name . ':' . $port; + } + + /** + * Retrieve a Header value from either $_SERVER or Apache + * + * @param string $header + * @return bool|string + */ + protected function _getHeader($header) + { + $temp = strtoupper(str_replace('-', '_', $header)); + if (!empty($_SERVER[$temp])) { + return $_SERVER[$temp]; + } + $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header)); + if (!empty($_SERVER[$temp])) { + return $_SERVER[$temp]; + } + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + if (!empty($headers[$header])) { + return $headers[$header]; + } + } + return false; + } + + /** + * Return the raw body of the request + * + * @return string|false Raw body, or false if not present + */ + protected function _getRawBody() + { + $body = file_get_contents('php://input'); + if (strlen(trim($body)) == 0 && isset($GLOBALS['HTTP_RAW_POST_DATA'])) { + $body = $GLOBALS['HTTP_RAW_POST_DATA']; + } + if (strlen(trim($body)) > 0) { + return $body; + } + return false; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/CallbackInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/CallbackInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..9bcc6e2f900acdaec4ed52f8a54976161db0dbaf --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/CallbackInterface.php @@ -0,0 +1,51 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub; + +interface CallbackInterface +{ + /** + * Handle any callback from a Hub Server responding to a subscription or + * unsubscription request. This should be the Hub Server confirming the + * the request prior to taking action on it. + * + * @param array $httpData GET/POST data if available and not in $_GET/POST + * @param bool $sendResponseNow Whether to send response now or when asked + */ + public function handle(array $httpData = null, $sendResponseNow = false); + + /** + * Send the response, including all headers. + * If you wish to handle this via Controller, use the getter methods + * to retrieve any data needed to be set on your HTTP Response object, or + * simply give this object the HTTP Response instance to work with for you! + * + * @return void + */ + public function sendResponse(); + + /** + * An instance of a class handling Http Responses. This is implemented in + * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with + * (i.e. not inherited from) Zend\Feed\Pubsubhubbub\AbstractCallback. + * + * @param HttpResponse|\Zend\Http\PhpEnvironment\Response $httpResponse + */ + public function setHttpResponse($httpResponse); + + /** + * An instance of a class handling Http Responses. This is implemented in + * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with + * (i.e. not inherited from) Zend\Feed\Pubsubhubbub\AbstractCallback. + * + * @return HttpResponse|\Zend\Http\PhpEnvironment\Response + */ + public function getHttpResponse(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/ExceptionInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..75d710cd7093f0fe50ba08613497fa41e73a72bc --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/ExceptionInterface.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub\Exception; + +use Zend\Feed\Exception\ExceptionInterface as Exception; + +interface ExceptionInterface extends Exception +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/InvalidArgumentException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..0b2339f13103409da16e4f42e4432b06e7374a5f --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/InvalidArgumentException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub\Exception; + +use Zend\Feed\Exception; + +class InvalidArgumentException + extends Exception\InvalidArgumentException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/RuntimeException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..23e154411b7f17e38b8049b539a8b33d6a394253 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Exception/RuntimeException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub\Exception; + +use Zend\Feed\Exception; + +class RuntimeException + extends Exception\RuntimeException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/HttpResponse.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/HttpResponse.php new file mode 100644 index 0000000000000000000000000000000000000000..d820cf9f1436d9b6872b496ed1d1b06b9ca8c906 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/HttpResponse.php @@ -0,0 +1,211 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub; + +class HttpResponse +{ + /** + * The body of any response to the current callback request + * + * @var string + */ + protected $content = ''; + + /** + * Array of headers. Each header is an array with keys 'name' and 'value' + * + * @var array + */ + protected $headers = array(); + + /** + * HTTP response code to use in headers + * + * @var int + */ + protected $statusCode = 200; + + /** + * Send the response, including all headers + * + * @return void + */ + public function send() + { + $this->sendHeaders(); + echo $this->getContent(); + } + + /** + * Send all headers + * + * Sends any headers specified. If an {@link setHttpResponseCode() HTTP response code} + * has been specified, it is sent with the first header. + * + * @return void + */ + public function sendHeaders() + { + if (count($this->headers) || (200 != $this->statusCode)) { + $this->canSendHeaders(true); + } elseif (200 == $this->statusCode) { + return; + } + $httpCodeSent = false; + foreach ($this->headers as $header) { + if (!$httpCodeSent && $this->statusCode) { + header($header['name'] . ': ' . $header['value'], $header['replace'], $this->statusCode); + $httpCodeSent = true; + } else { + header($header['name'] . ': ' . $header['value'], $header['replace']); + } + } + if (!$httpCodeSent) { + header('HTTP/1.1 ' . $this->statusCode); + } + } + + /** + * Set a header + * + * If $replace is true, replaces any headers already defined with that + * $name. + * + * @param string $name + * @param string $value + * @param bool $replace + * @return \Zend\Feed\PubSubHubbub\HttpResponse + */ + public function setHeader($name, $value, $replace = false) + { + $name = $this->_normalizeHeader($name); + $value = (string) $value; + if ($replace) { + foreach ($this->headers as $key => $header) { + if ($name == $header['name']) { + unset($this->headers[$key]); + } + } + } + $this->headers[] = array( + 'name' => $name, + 'value' => $value, + 'replace' => $replace, + ); + + return $this; + } + + /** + * Check if a specific Header is set and return its value + * + * @param string $name + * @return string|null + */ + public function getHeader($name) + { + $name = $this->_normalizeHeader($name); + foreach ($this->headers as $header) { + if ($header['name'] == $name) { + return $header['value']; + } + } + } + + /** + * Return array of headers; see {@link $headers} for format + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Can we send headers? + * + * @param bool $throw Whether or not to throw an exception if headers have been sent; defaults to false + * @return HttpResponse + * @throws Exception\RuntimeException + */ + public function canSendHeaders($throw = false) + { + $ok = headers_sent($file, $line); + if ($ok && $throw) { + throw new Exception\RuntimeException('Cannot send headers; headers already sent in ' . $file . ', line ' . $line); + } + return !$ok; + } + + /** + * Set HTTP response code to use with headers + * + * @param int $code + * @return HttpResponse + * @throws Exception\InvalidArgumentException + */ + public function setStatusCode($code) + { + if (!is_int($code) || (100 > $code) || (599 < $code)) { + throw new Exception\InvalidArgumentException('Invalid HTTP response' + . ' code:' . $code); + } + $this->statusCode = $code; + return $this; + } + + /** + * Retrieve HTTP response code + * + * @return int + */ + public function getStatusCode() + { + return $this->statusCode; + } + + /** + * Set body content + * + * @param string $content + * @return \Zend\Feed\PubSubHubbub\HttpResponse + */ + public function setContent($content) + { + $this->content = (string) $content; + $this->setHeader('content-length', strlen($content)); + return $this; + } + + /** + * Return the body content + * + * @return string + */ + public function getContent() + { + return $this->content; + } + + /** + * Normalizes a header name to X-Capitalized-Names + * + * @param string $name + * @return string + */ + protected function _normalizeHeader($name) + { + $filtered = str_replace(array('-', '_'), ' ', (string) $name); + $filtered = ucwords(strtolower($filtered)); + $filtered = str_replace(' ', '-', $filtered); + return $filtered; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/AbstractModel.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/AbstractModel.php new file mode 100644 index 0000000000000000000000000000000000000000..023fe8ed67d317ae3c0232e8451eb3458e9ed5e0 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/AbstractModel.php @@ -0,0 +1,39 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub\Model; + +use Zend\Db\TableGateway\TableGateway; +use Zend\Db\TableGateway\TableGatewayInterface; + +class AbstractModel +{ + /** + * Zend\Db\TableGateway\TableGatewayInterface instance to host database methods + * + * @var TableGatewayInterface + */ + protected $db = null; + + /** + * Constructor + * + * @param null|TableGatewayInterface $tableGateway + */ + public function __construct(TableGatewayInterface $tableGateway = null) + { + if ($tableGateway === null) { + $parts = explode('\\', get_class($this)); + $table = strtolower(array_pop($parts)); + $this->db = new TableGateway($table, null); + } else { + $this->db = $tableGateway; + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/Subscription.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/Subscription.php new file mode 100644 index 0000000000000000000000000000000000000000..a7a4596b36b213e8fee403d4590d091e62a5e1b6 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/Subscription.php @@ -0,0 +1,142 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub\Model; + +use DateInterval; +use DateTime; +use Zend\Feed\PubSubHubbub; + +class Subscription extends AbstractModel implements SubscriptionPersistenceInterface +{ + /** + * Common DateTime object to assist with unit testing + * + * @var DateTime + */ + protected $now; + + /** + * Save subscription to RDMBS + * + * @param array $data + * @return bool + * @throws PubSubHubbub\Exception\InvalidArgumentException + */ + public function setSubscription(array $data) + { + if (!isset($data['id'])) { + throw new PubSubHubbub\Exception\InvalidArgumentException( + 'ID must be set before attempting a save' + ); + } + $result = $this->db->select(array('id' => $data['id'])); + if ($result && (0 < count($result))) { + $data['created_time'] = $result->current()->created_time; + $now = $this->getNow(); + if (array_key_exists('lease_seconds', $data) + && $data['lease_seconds'] + ) { + $data['expiration_time'] = $now->add(new DateInterval('PT' . $data['lease_seconds'] . 'S')) + ->format('Y-m-d H:i:s'); + } + $this->db->update( + $data, + array('id' => $data['id']) + ); + return false; + } + + $this->db->insert($data); + return true; + } + + /** + * Get subscription by ID/key + * + * @param string $key + * @return array + * @throws PubSubHubbub\Exception\InvalidArgumentException + */ + public function getSubscription($key) + { + if (empty($key) || !is_string($key)) { + throw new PubSubHubbub\Exception\InvalidArgumentException('Invalid parameter "key"' + .' of "' . $key . '" must be a non-empty string'); + } + $result = $this->db->select(array('id' => $key)); + if (count($result)) { + return $result->current()->getArrayCopy(); + } + return false; + } + + /** + * Determine if a subscription matching the key exists + * + * @param string $key + * @return bool + * @throws PubSubHubbub\Exception\InvalidArgumentException + */ + public function hasSubscription($key) + { + if (empty($key) || !is_string($key)) { + throw new PubSubHubbub\Exception\InvalidArgumentException('Invalid parameter "key"' + .' of "' . $key . '" must be a non-empty string'); + } + $result = $this->db->select(array('id' => $key)); + if (count($result)) { + return true; + } + return false; + } + + /** + * Delete a subscription + * + * @param string $key + * @return bool + */ + public function deleteSubscription($key) + { + $result = $this->db->select(array('id' => $key)); + if (count($result)) { + $this->db->delete( + array('id' => $key) + ); + return true; + } + return false; + } + + /** + * Get a new DateTime or the one injected for testing + * + * @return DateTime + */ + public function getNow() + { + if (null === $this->now) { + return new DateTime(); + } + return $this->now; + } + + /** + * Set a DateTime instance for assisting with unit testing + * + * @param DateTime $now + * @return Subscription + */ + public function setNow(DateTime $now) + { + $this->now = $now; + return $this; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/SubscriptionPersistenceInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/SubscriptionPersistenceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..717591b0fc1a4f909c0ce096ef6f2535b20ef57a --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Model/SubscriptionPersistenceInterface.php @@ -0,0 +1,47 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub\Model; + +interface SubscriptionPersistenceInterface +{ + + /** + * Save subscription to RDMBS + * + * @param array $data The key must be stored here as a $data['id'] entry + * @return bool + */ + public function setSubscription(array $data); + + /** + * Get subscription by ID/key + * + * @param string $key + * @return array + */ + public function getSubscription($key); + + /** + * Determine if a subscription matching the key exists + * + * @param string $key + * @return bool + */ + public function hasSubscription($key); + + /** + * Delete a subscription + * + * @param string $key + * @return bool + */ + public function deleteSubscription($key); + +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/PubSubHubbub.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/PubSubHubbub.php new file mode 100644 index 0000000000000000000000000000000000000000..ee009801e1f6a5befc65274c52a16a2d8c82736b --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/PubSubHubbub.php @@ -0,0 +1,147 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub; + +use Zend\Escaper\Escaper; +use Zend\Feed\Reader; +use Zend\Http; + +class PubSubHubbub +{ + /** + * Verification Modes + */ + const VERIFICATION_MODE_SYNC = 'sync'; + const VERIFICATION_MODE_ASYNC = 'async'; + + /** + * Subscription States + */ + const SUBSCRIPTION_VERIFIED = 'verified'; + const SUBSCRIPTION_NOTVERIFIED = 'not_verified'; + const SUBSCRIPTION_TODELETE = 'to_delete'; + + /** + * @var Escaper + */ + protected static $escaper; + + /** + * Singleton instance if required of the HTTP client + * + * @var Http\Client + */ + protected static $httpClient = null; + + /** + * Simple utility function which imports any feed URL and + * determines the existence of Hub Server endpoints. This works + * best if directly given an instance of Zend\Feed\Reader\Atom|Rss + * to leverage off. + * + * @param \Zend\Feed\Reader\Feed\AbstractFeed|string $source + * @return array + * @throws Exception\InvalidArgumentException + */ + public static function detectHubs($source) + { + if (is_string($source)) { + $feed = Reader\Reader::import($source); + } elseif ($source instanceof Reader\Feed\AbstractFeed) { + $feed = $source; + } else { + throw new Exception\InvalidArgumentException('The source parameter was' + . ' invalid, i.e. not a URL string or an instance of type' + . ' Zend\Feed\Reader\Feed\AbstractFeed'); + } + return $feed->getHubs(); + } + + /** + * Allows the external environment to make Oauth use a specific + * Client instance. + * + * @param Http\Client $httpClient + * @return void + */ + public static function setHttpClient(Http\Client $httpClient) + { + static::$httpClient = $httpClient; + } + + /** + * Return the singleton instance of the HTTP Client. Note that + * the instance is reset and cleared of previous parameters GET/POST. + * Headers are NOT reset but handled by this component if applicable. + * + * @return Http\Client + */ + public static function getHttpClient() + { + if (!isset(static::$httpClient)) { + static::$httpClient = new Http\Client; + } else { + static::$httpClient->resetParameters(); + } + return static::$httpClient; + } + + /** + * Simple mechanism to delete the entire singleton HTTP Client instance + * which forces an new instantiation for subsequent requests. + * + * @return void + */ + public static function clearHttpClient() + { + static::$httpClient = null; + } + + /** + * Set the Escaper instance + * + * If null, resets the instance + * + * @param null|Escaper $escaper + */ + public static function setEscaper(Escaper $escaper = null) + { + static::$escaper = $escaper; + } + + /** + * Get the Escaper instance + * + * If none registered, lazy-loads an instance. + * + * @return Escaper + */ + public static function getEscaper() + { + if (null === static::$escaper) { + static::setEscaper(new Escaper()); + } + return static::$escaper; + } + + /** + * RFC 3986 safe url encoding method + * + * @param string $string + * @return string + */ + public static function urlencode($string) + { + $escaper = static::getEscaper(); + $rawencoded = $escaper->escapeUrl($string); + $rfcencoded = str_replace('%7E', '~', $rawencoded); + return $rfcencoded; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Publisher.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Publisher.php new file mode 100644 index 0000000000000000000000000000000000000000..ec9c4e1ea8fb96a13d4489721d34614316ce9cc7 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Publisher.php @@ -0,0 +1,397 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub; + +use Traversable; +use Zend\Feed\Uri; +use Zend\Http\Request as HttpRequest; +use Zend\Stdlib\ArrayUtils; + +class Publisher +{ + /** + * An array of URLs for all Hub Servers used by the Publisher, and to + * which all topic update notifications will be sent. + * + * @var array + */ + protected $hubUrls = array(); + + /** + * An array of topic (Atom or RSS feed) URLs which have been updated and + * whose updated status will be notified to all Hub Servers. + * + * @var array + */ + protected $updatedTopicUrls = array(); + + /** + * An array of any errors including keys for 'response', 'hubUrl'. + * The response is the actual Zend\Http\Response object. + * + * @var array + */ + protected $errors = array(); + + /** + * An array of topic (Atom or RSS feed) URLs which have been updated and + * whose updated status will be notified to all Hub Servers. + * + * @var array + */ + protected $parameters = array(); + + /** + * Constructor; accepts an array or Zend\Config instance to preset + * options for the Publisher without calling all supported setter + * methods in turn. + * + * @param array|Traversable $options + */ + public function __construct($options = null) + { + if ($options !== null) { + $this->setOptions($options); + } + } + + /** + * Process any injected configuration options + * + * @param array|Traversable $options Options array or Traversable object + * @return Publisher + * @throws Exception\InvalidArgumentException + */ + public function setOptions($options) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (!is_array($options)) { + throw new Exception\InvalidArgumentException('Array or Traversable object' + . 'expected, got ' . gettype($options)); + } + if (array_key_exists('hubUrls', $options)) { + $this->addHubUrls($options['hubUrls']); + } + if (array_key_exists('updatedTopicUrls', $options)) { + $this->addUpdatedTopicUrls($options['updatedTopicUrls']); + } + if (array_key_exists('parameters', $options)) { + $this->setParameters($options['parameters']); + } + return $this; + } + + /** + * Add a Hub Server URL supported by Publisher + * + * @param string $url + * @return Publisher + * @throws Exception\InvalidArgumentException + */ + public function addHubUrl($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter "url"' + . ' of "' . $url . '" must be a non-empty string and a valid' + . 'URL'); + } + $this->hubUrls[] = $url; + return $this; + } + + /** + * Add an array of Hub Server URLs supported by Publisher + * + * @param array $urls + * @return Publisher + */ + public function addHubUrls(array $urls) + { + foreach ($urls as $url) { + $this->addHubUrl($url); + } + return $this; + } + + /** + * Remove a Hub Server URL + * + * @param string $url + * @return Publisher + */ + public function removeHubUrl($url) + { + if (!in_array($url, $this->getHubUrls())) { + return $this; + } + $key = array_search($url, $this->hubUrls); + unset($this->hubUrls[$key]); + return $this; + } + + /** + * Return an array of unique Hub Server URLs currently available + * + * @return array + */ + public function getHubUrls() + { + $this->hubUrls = array_unique($this->hubUrls); + return $this->hubUrls; + } + + /** + * Add a URL to a topic (Atom or RSS feed) which has been updated + * + * @param string $url + * @return Publisher + * @throws Exception\InvalidArgumentException + */ + public function addUpdatedTopicUrl($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter "url"' + . ' of "' . $url . '" must be a non-empty string and a valid' + . 'URL'); + } + $this->updatedTopicUrls[] = $url; + return $this; + } + + /** + * Add an array of Topic URLs which have been updated + * + * @param array $urls + * @return Publisher + */ + public function addUpdatedTopicUrls(array $urls) + { + foreach ($urls as $url) { + $this->addUpdatedTopicUrl($url); + } + return $this; + } + + /** + * Remove an updated topic URL + * + * @param string $url + * @return Publisher + */ + public function removeUpdatedTopicUrl($url) + { + if (!in_array($url, $this->getUpdatedTopicUrls())) { + return $this; + } + $key = array_search($url, $this->updatedTopicUrls); + unset($this->updatedTopicUrls[$key]); + return $this; + } + + /** + * Return an array of unique updated topic URLs currently available + * + * @return array + */ + public function getUpdatedTopicUrls() + { + $this->updatedTopicUrls = array_unique($this->updatedTopicUrls); + return $this->updatedTopicUrls; + } + + /** + * Notifies a single Hub Server URL of changes + * + * @param string $url The Hub Server's URL + * @return void + * @throws Exception\InvalidArgumentException + * @throws Exception\RuntimeException + */ + public function notifyHub($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter "url"' + . ' of "' . $url . '" must be a non-empty string and a valid' + . 'URL'); + } + $client = $this->_getHttpClient(); + $client->setUri($url); + $response = $client->getResponse(); + if ($response->getStatusCode() !== 204) { + throw new Exception\RuntimeException('Notification to Hub Server ' + . 'at "' . $url . '" appears to have failed with a status code of "' + . $response->getStatusCode() . '" and message "' + . $response->getContent() . '"'); + } + } + + /** + * Notifies all Hub Server URLs of changes + * + * If a Hub notification fails, certain data will be retained in an + * an array retrieved using getErrors(), if a failure occurs for any Hubs + * the isSuccess() check will return FALSE. This method is designed not + * to needlessly fail with an Exception/Error unless from Zend\Http\Client. + * + * @return void + * @throws Exception\RuntimeException + */ + public function notifyAll() + { + $client = $this->_getHttpClient(); + $hubs = $this->getHubUrls(); + if (empty($hubs)) { + throw new Exception\RuntimeException('No Hub Server URLs' + . ' have been set so no notifications can be sent'); + } + $this->errors = array(); + foreach ($hubs as $url) { + $client->setUri($url); + $response = $client->getResponse(); + if ($response->getStatusCode() !== 204) { + $this->errors[] = array( + 'response' => $response, + 'hubUrl' => $url + ); + } + } + } + + /** + * Add an optional parameter to the update notification requests + * + * @param string $name + * @param string|null $value + * @return Publisher + * @throws Exception\InvalidArgumentException + */ + public function setParameter($name, $value = null) + { + if (is_array($name)) { + $this->setParameters($name); + return $this; + } + if (empty($name) || !is_string($name)) { + throw new Exception\InvalidArgumentException('Invalid parameter "name"' + . ' of "' . $name . '" must be a non-empty string'); + } + if ($value === null) { + $this->removeParameter($name); + return $this; + } + if (empty($value) || (!is_string($value) && $value !== null)) { + throw new Exception\InvalidArgumentException('Invalid parameter "value"' + . ' of "' . $value . '" must be a non-empty string'); + } + $this->parameters[$name] = $value; + return $this; + } + + /** + * Add an optional parameter to the update notification requests + * + * @param array $parameters + * @return Publisher + */ + public function setParameters(array $parameters) + { + foreach ($parameters as $name => $value) { + $this->setParameter($name, $value); + } + return $this; + } + + /** + * Remove an optional parameter for the notification requests + * + * @param string $name + * @return Publisher + * @throws Exception\InvalidArgumentException + */ + public function removeParameter($name) + { + if (empty($name) || !is_string($name)) { + throw new Exception\InvalidArgumentException('Invalid parameter "name"' + . ' of "' . $name . '" must be a non-empty string'); + } + if (array_key_exists($name, $this->parameters)) { + unset($this->parameters[$name]); + } + return $this; + } + + /** + * Return an array of optional parameters for notification requests + * + * @return array + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * Returns a boolean indicator of whether the notifications to Hub + * Servers were ALL successful. If even one failed, FALSE is returned. + * + * @return bool + */ + public function isSuccess() + { + return !(count($this->errors) != 0); + } + + /** + * Return an array of errors met from any failures, including keys: + * 'response' => the Zend\Http\Response object from the failure + * 'hubUrl' => the URL of the Hub Server whose notification failed + * + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + /** + * Get a basic prepared HTTP client for use + * + * @return \Zend\Http\Client + * @throws Exception\RuntimeException + */ + protected function _getHttpClient() + { + $client = PubSubHubbub::getHttpClient(); + $client->setMethod(HttpRequest::METHOD_POST); + $client->setOptions(array( + 'useragent' => 'Zend_Feed_Pubsubhubbub_Publisher/' . Version::VERSION, + )); + $params = array(); + $params[] = 'hub.mode=publish'; + $topics = $this->getUpdatedTopicUrls(); + if (empty($topics)) { + throw new Exception\RuntimeException('No updated topic URLs' + . ' have been set'); + } + foreach ($topics as $topicUrl) { + $params[] = 'hub.url=' . urlencode($topicUrl); + } + $optParams = $this->getParameters(); + foreach ($optParams as $name => $value) { + $params[] = urlencode($name) . '=' . urlencode($value); + } + $paramString = implode('&', $params); + $client->setRawBody($paramString); + return $client; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Subscriber.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Subscriber.php new file mode 100644 index 0000000000000000000000000000000000000000..7171694d20a45910fc2be25829f2605f8f55b584 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Subscriber.php @@ -0,0 +1,837 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub; + +use DateInterval; +use DateTime; +use Traversable; +use Zend\Feed\Uri; +use Zend\Http\Request as HttpRequest; +use Zend\Stdlib\ArrayUtils; + +class Subscriber +{ + /** + * An array of URLs for all Hub Servers to subscribe/unsubscribe. + * + * @var array + */ + protected $hubUrls = array(); + + /** + * An array of optional parameters to be included in any + * (un)subscribe requests. + * + * @var array + */ + protected $parameters = array(); + + /** + * The URL of the topic (Rss or Atom feed) which is the subject of + * our current intent to subscribe to/unsubscribe from updates from + * the currently configured Hub Servers. + * + * @var string + */ + protected $topicUrl = ''; + + /** + * The URL Hub Servers must use when communicating with this Subscriber + * + * @var string + */ + protected $callbackUrl = ''; + + /** + * The number of seconds for which the subscriber would like to have the + * subscription active. Defaults to null, i.e. not sent, to setup a + * permanent subscription if possible. + * + * @var int + */ + protected $leaseSeconds = null; + + /** + * The preferred verification mode (sync or async). By default, this + * Subscriber prefers synchronous verification, but is considered + * desirable to support asynchronous verification if possible. + * + * Zend\Feed\Pubsubhubbub\Subscriber will always send both modes, whose + * order of occurrence in the parameter list determines this preference. + * + * @var string + */ + protected $preferredVerificationMode = PubSubHubbub::VERIFICATION_MODE_SYNC; + + /** + * An array of any errors including keys for 'response', 'hubUrl'. + * The response is the actual Zend\Http\Response object. + * + * @var array + */ + protected $errors = array(); + + /** + * An array of Hub Server URLs for Hubs operating at this time in + * asynchronous verification mode. + * + * @var array + */ + protected $asyncHubs = array(); + + /** + * An instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used to background + * save any verification tokens associated with a subscription or other. + * + * @var \Zend\Feed\PubSubHubbub\Model\SubscriptionPersistenceInterface + */ + protected $storage = null; + + /** + * An array of authentication credentials for HTTP Basic Authentication + * if required by specific Hubs. The array is indexed by Hub Endpoint URI + * and the value is a simple array of the username and password to apply. + * + * @var array + */ + protected $authentications = array(); + + /** + * Tells the Subscriber to append any subscription identifier to the path + * of the base Callback URL. E.g. an identifier "subkey1" would be added + * to the callback URL "http://www.example.com/callback" to create a subscription + * specific Callback URL of "http://www.example.com/callback/subkey1". + * + * This is required for all Hubs using the Pubsubhubbub 0.1 Specification. + * It should be manually intercepted and passed to the Callback class using + * Zend\Feed\Pubsubhubbub\Subscriber\Callback::setSubscriptionKey(). Will + * require a route in the form "callback/:subkey" to allow the parameter be + * retrieved from an action using the Zend\Controller\Action::\getParam() + * method. + * + * @var string + */ + protected $usePathParameter = false; + + /** + * Constructor; accepts an array or Traversable instance to preset + * options for the Subscriber without calling all supported setter + * methods in turn. + * + * @param array|Traversable $options + */ + public function __construct($options = null) + { + if ($options !== null) { + $this->setOptions($options); + } + } + + /** + * Process any injected configuration options + * + * @param array|Traversable $options + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function setOptions($options) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (!is_array($options)) { + throw new Exception\InvalidArgumentException('Array or Traversable object' + . 'expected, got ' . gettype($options)); + } + if (array_key_exists('hubUrls', $options)) { + $this->addHubUrls($options['hubUrls']); + } + if (array_key_exists('callbackUrl', $options)) { + $this->setCallbackUrl($options['callbackUrl']); + } + if (array_key_exists('topicUrl', $options)) { + $this->setTopicUrl($options['topicUrl']); + } + if (array_key_exists('storage', $options)) { + $this->setStorage($options['storage']); + } + if (array_key_exists('leaseSeconds', $options)) { + $this->setLeaseSeconds($options['leaseSeconds']); + } + if (array_key_exists('parameters', $options)) { + $this->setParameters($options['parameters']); + } + if (array_key_exists('authentications', $options)) { + $this->addAuthentications($options['authentications']); + } + if (array_key_exists('usePathParameter', $options)) { + $this->usePathParameter($options['usePathParameter']); + } + if (array_key_exists('preferredVerificationMode', $options)) { + $this->setPreferredVerificationMode( + $options['preferredVerificationMode'] + ); + } + return $this; + } + + /** + * Set the topic URL (RSS or Atom feed) to which the intended (un)subscribe + * event will relate + * + * @param string $url + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function setTopicUrl($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter "url"' + .' of "' . $url . '" must be a non-empty string and a valid' + .' URL'); + } + $this->topicUrl = $url; + return $this; + } + + /** + * Set the topic URL (RSS or Atom feed) to which the intended (un)subscribe + * event will relate + * + * @return string + * @throws Exception\RuntimeException + */ + public function getTopicUrl() + { + if (empty($this->topicUrl)) { + throw new Exception\RuntimeException('A valid Topic (RSS or Atom' + . ' feed) URL MUST be set before attempting any operation'); + } + return $this->topicUrl; + } + + /** + * Set the number of seconds for which any subscription will remain valid + * + * @param int $seconds + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function setLeaseSeconds($seconds) + { + $seconds = intval($seconds); + if ($seconds <= 0) { + throw new Exception\InvalidArgumentException('Expected lease seconds' + . ' must be an integer greater than zero'); + } + $this->leaseSeconds = $seconds; + return $this; + } + + /** + * Get the number of lease seconds on subscriptions + * + * @return int + */ + public function getLeaseSeconds() + { + return $this->leaseSeconds; + } + + /** + * Set the callback URL to be used by Hub Servers when communicating with + * this Subscriber + * + * @param string $url + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function setCallbackUrl($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter "url"' + . ' of "' . $url . '" must be a non-empty string and a valid' + . ' URL'); + } + $this->callbackUrl = $url; + return $this; + } + + /** + * Get the callback URL to be used by Hub Servers when communicating with + * this Subscriber + * + * @return string + * @throws Exception\RuntimeException + */ + public function getCallbackUrl() + { + if (empty($this->callbackUrl)) { + throw new Exception\RuntimeException('A valid Callback URL MUST be' + . ' set before attempting any operation'); + } + return $this->callbackUrl; + } + + /** + * Set preferred verification mode (sync or async). By default, this + * Subscriber prefers synchronous verification, but does support + * asynchronous if that's the Hub Server's utilised mode. + * + * Zend\Feed\Pubsubhubbub\Subscriber will always send both modes, whose + * order of occurrence in the parameter list determines this preference. + * + * @param string $mode Should be 'sync' or 'async' + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function setPreferredVerificationMode($mode) + { + if ($mode !== PubSubHubbub::VERIFICATION_MODE_SYNC + && $mode !== PubSubHubbub::VERIFICATION_MODE_ASYNC + ) { + throw new Exception\InvalidArgumentException('Invalid preferred' + . ' mode specified: "' . $mode . '" but should be one of' + . ' Zend\Feed\Pubsubhubbub::VERIFICATION_MODE_SYNC or' + . ' Zend\Feed\Pubsubhubbub::VERIFICATION_MODE_ASYNC'); + } + $this->preferredVerificationMode = $mode; + return $this; + } + + /** + * Get preferred verification mode (sync or async). + * + * @return string + */ + public function getPreferredVerificationMode() + { + return $this->preferredVerificationMode; + } + + /** + * Add a Hub Server URL supported by Publisher + * + * @param string $url + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function addHubUrl($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter "url"' + . ' of "' . $url . '" must be a non-empty string and a valid' + . ' URL'); + } + $this->hubUrls[] = $url; + return $this; + } + + /** + * Add an array of Hub Server URLs supported by Publisher + * + * @param array $urls + * @return Subscriber + */ + public function addHubUrls(array $urls) + { + foreach ($urls as $url) { + $this->addHubUrl($url); + } + return $this; + } + + /** + * Remove a Hub Server URL + * + * @param string $url + * @return Subscriber + */ + public function removeHubUrl($url) + { + if (!in_array($url, $this->getHubUrls())) { + return $this; + } + $key = array_search($url, $this->hubUrls); + unset($this->hubUrls[$key]); + return $this; + } + + /** + * Return an array of unique Hub Server URLs currently available + * + * @return array + */ + public function getHubUrls() + { + $this->hubUrls = array_unique($this->hubUrls); + return $this->hubUrls; + } + + /** + * Add authentication credentials for a given URL + * + * @param string $url + * @param array $authentication + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function addAuthentication($url, array $authentication) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter "url"' + . ' of "' . $url . '" must be a non-empty string and a valid' + . ' URL'); + } + $this->authentications[$url] = $authentication; + return $this; + } + + /** + * Add authentication credentials for hub URLs + * + * @param array $authentications + * @return Subscriber + */ + public function addAuthentications(array $authentications) + { + foreach ($authentications as $url => $authentication) { + $this->addAuthentication($url, $authentication); + } + return $this; + } + + /** + * Get all hub URL authentication credentials + * + * @return array + */ + public function getAuthentications() + { + return $this->authentications; + } + + /** + * Set flag indicating whether or not to use a path parameter + * + * @param bool $bool + * @return Subscriber + */ + public function usePathParameter($bool = true) + { + $this->usePathParameter = $bool; + return $this; + } + + /** + * Add an optional parameter to the (un)subscribe requests + * + * @param string $name + * @param string|null $value + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function setParameter($name, $value = null) + { + if (is_array($name)) { + $this->setParameters($name); + return $this; + } + if (empty($name) || !is_string($name)) { + throw new Exception\InvalidArgumentException('Invalid parameter "name"' + . ' of "' . $name . '" must be a non-empty string'); + } + if ($value === null) { + $this->removeParameter($name); + return $this; + } + if (empty($value) || (!is_string($value) && $value !== null)) { + throw new Exception\InvalidArgumentException('Invalid parameter "value"' + . ' of "' . $value . '" must be a non-empty string'); + } + $this->parameters[$name] = $value; + return $this; + } + + /** + * Add an optional parameter to the (un)subscribe requests + * + * @param array $parameters + * @return Subscriber + */ + public function setParameters(array $parameters) + { + foreach ($parameters as $name => $value) { + $this->setParameter($name, $value); + } + return $this; + } + + /** + * Remove an optional parameter for the (un)subscribe requests + * + * @param string $name + * @return Subscriber + * @throws Exception\InvalidArgumentException + */ + public function removeParameter($name) + { + if (empty($name) || !is_string($name)) { + throw new Exception\InvalidArgumentException('Invalid parameter "name"' + . ' of "' . $name . '" must be a non-empty string'); + } + if (array_key_exists($name, $this->parameters)) { + unset($this->parameters[$name]); + } + return $this; + } + + /** + * Return an array of optional parameters for (un)subscribe requests + * + * @return array + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * Sets an instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used to background + * save any verification tokens associated with a subscription or other. + * + * @param Model\SubscriptionPersistenceInterface $storage + * @return Subscriber + */ + public function setStorage(Model\SubscriptionPersistenceInterface $storage) + { + $this->storage = $storage; + return $this; + } + + /** + * Gets an instance of Zend\Feed\Pubsubhubbub\Storage\StoragePersistence used + * to background save any verification tokens associated with a subscription + * or other. + * + * @return Model\SubscriptionPersistenceInterface + * @throws Exception\RuntimeException + */ + public function getStorage() + { + if ($this->storage === null) { + throw new Exception\RuntimeException('No storage vehicle ' + . 'has been set.'); + } + return $this->storage; + } + + /** + * Subscribe to one or more Hub Servers using the stored Hub URLs + * for the given Topic URL (RSS or Atom feed) + * + * @return void + */ + public function subscribeAll() + { + $this->_doRequest('subscribe'); + } + + /** + * Unsubscribe from one or more Hub Servers using the stored Hub URLs + * for the given Topic URL (RSS or Atom feed) + * + * @return void + */ + public function unsubscribeAll() + { + $this->_doRequest('unsubscribe'); + } + + /** + * Returns a boolean indicator of whether the notifications to Hub + * Servers were ALL successful. If even one failed, FALSE is returned. + * + * @return bool + */ + public function isSuccess() + { + if (count($this->errors) > 0) { + return false; + } + return true; + } + + /** + * Return an array of errors met from any failures, including keys: + * 'response' => the Zend\Http\Response object from the failure + * 'hubUrl' => the URL of the Hub Server whose notification failed + * + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + /** + * Return an array of Hub Server URLs who returned a response indicating + * operation in Asynchronous Verification Mode, i.e. they will not confirm + * any (un)subscription immediately but at a later time (Hubs may be + * doing this as a batch process when load balancing) + * + * @return array + */ + public function getAsyncHubs() + { + return $this->asyncHubs; + } + + /** + * Executes an (un)subscribe request + * + * @param string $mode + * @return void + * @throws Exception\RuntimeException + */ + protected function _doRequest($mode) + { + $client = $this->_getHttpClient(); + $hubs = $this->getHubUrls(); + if (empty($hubs)) { + throw new Exception\RuntimeException('No Hub Server URLs' + . ' have been set so no subscriptions can be attempted'); + } + $this->errors = array(); + $this->asyncHubs = array(); + foreach ($hubs as $url) { + if (array_key_exists($url, $this->authentications)) { + $auth = $this->authentications[$url]; + $client->setAuth($auth[0], $auth[1]); + } + $client->setUri($url); + $client->setRawBody($params = $this->_getRequestParameters($url, $mode)); + $response = $client->send(); + if ($response->getStatusCode() !== 204 + && $response->getStatusCode() !== 202 + ) { + $this->errors[] = array( + 'response' => $response, + 'hubUrl' => $url, + ); + /** + * At first I thought it was needed, but the backend storage will + * allow tracking async without any user interference. It's left + * here in case the user is interested in knowing what Hubs + * are using async verification modes so they may update Models and + * move these to asynchronous processes. + */ + } elseif ($response->getStatusCode() == 202) { + $this->asyncHubs[] = array( + 'response' => $response, + 'hubUrl' => $url, + ); + } + } + } + + /** + * Get a basic prepared HTTP client for use + * + * @return \Zend\Http\Client + */ + protected function _getHttpClient() + { + $client = PubSubHubbub::getHttpClient(); + $client->setMethod(HttpRequest::METHOD_POST); + $client->setOptions(array('useragent' => 'Zend_Feed_Pubsubhubbub_Subscriber/' + . Version::VERSION)); + return $client; + } + + /** + * Return a list of standard protocol/optional parameters for addition to + * client's POST body that are specific to the current Hub Server URL + * + * @param string $hubUrl + * @param string $mode + * @return string + * @throws Exception\InvalidArgumentException + */ + protected function _getRequestParameters($hubUrl, $mode) + { + if (!in_array($mode, array('subscribe', 'unsubscribe'))) { + throw new Exception\InvalidArgumentException('Invalid mode specified: "' + . $mode . '" which should have been "subscribe" or "unsubscribe"'); + } + + $params = array( + 'hub.mode' => $mode, + 'hub.topic' => $this->getTopicUrl(), + ); + + if ($this->getPreferredVerificationMode() + == PubSubHubbub::VERIFICATION_MODE_SYNC + ) { + $vmodes = array( + PubSubHubbub::VERIFICATION_MODE_SYNC, + PubSubHubbub::VERIFICATION_MODE_ASYNC, + ); + } else { + $vmodes = array( + PubSubHubbub::VERIFICATION_MODE_ASYNC, + PubSubHubbub::VERIFICATION_MODE_SYNC, + ); + } + $params['hub.verify'] = array(); + foreach ($vmodes as $vmode) { + $params['hub.verify'][] = $vmode; + } + + /** + * Establish a persistent verify_token and attach key to callback + * URL's path/query_string + */ + $key = $this->_generateSubscriptionKey($params, $hubUrl); + $token = $this->_generateVerifyToken(); + $params['hub.verify_token'] = $token; + + // Note: query string only usable with PuSH 0.2 Hubs + if (!$this->usePathParameter) { + $params['hub.callback'] = $this->getCallbackUrl() + . '?xhub.subscription=' . PubSubHubbub::urlencode($key); + } else { + $params['hub.callback'] = rtrim($this->getCallbackUrl(), '/') + . '/' . PubSubHubbub::urlencode($key); + } + if ($mode == 'subscribe' && $this->getLeaseSeconds() !== null) { + $params['hub.lease_seconds'] = $this->getLeaseSeconds(); + } + + // hub.secret not currently supported + $optParams = $this->getParameters(); + foreach ($optParams as $name => $value) { + $params[$name] = $value; + } + + // store subscription to storage + $now = new DateTime(); + $expires = null; + if (isset($params['hub.lease_seconds'])) { + $expires = $now->add(new DateInterval('PT' . $params['hub.lease_seconds'] . 'S')) + ->format('Y-m-d H:i:s'); + } + $data = array( + 'id' => $key, + 'topic_url' => $params['hub.topic'], + 'hub_url' => $hubUrl, + 'created_time' => $now->format('Y-m-d H:i:s'), + 'lease_seconds' => $params['hub.lease_seconds'], + 'verify_token' => hash('sha256', $params['hub.verify_token']), + 'secret' => null, + 'expiration_time' => $expires, + 'subscription_state' => ($mode == 'unsubscribe')? PubSubHubbub::SUBSCRIPTION_TODELETE : PubSubHubbub::SUBSCRIPTION_NOTVERIFIED, + ); + $this->getStorage()->setSubscription($data); + + return $this->_toByteValueOrderedString( + $this->_urlEncode($params) + ); + } + + /** + * Simple helper to generate a verification token used in (un)subscribe + * requests to a Hub Server. Follows no particular method, which means + * it might be improved/changed in future. + * + * @return string + */ + protected function _generateVerifyToken() + { + if (!empty($this->testStaticToken)) { + return $this->testStaticToken; + } + return uniqid(rand(), true) . time(); + } + + /** + * Simple helper to generate a verification token used in (un)subscribe + * requests to a Hub Server. + * + * @param array $params + * @param string $hubUrl The Hub Server URL for which this token will apply + * @return string + */ + protected function _generateSubscriptionKey(array $params, $hubUrl) + { + $keyBase = $params['hub.topic'] . $hubUrl; + $key = md5($keyBase); + + return $key; + } + + /** + * URL Encode an array of parameters + * + * @param array $params + * @return array + */ + protected function _urlEncode(array $params) + { + $encoded = array(); + foreach ($params as $key => $value) { + if (is_array($value)) { + $ekey = PubSubHubbub::urlencode($key); + $encoded[$ekey] = array(); + foreach ($value as $duplicateKey) { + $encoded[$ekey][] + = PubSubHubbub::urlencode($duplicateKey); + } + } else { + $encoded[PubSubHubbub::urlencode($key)] + = PubSubHubbub::urlencode($value); + } + } + return $encoded; + } + + /** + * Order outgoing parameters + * + * @param array $params + * @return array + */ + protected function _toByteValueOrderedString(array $params) + { + $return = array(); + uksort($params, 'strnatcmp'); + foreach ($params as $key => $value) { + if (is_array($value)) { + foreach ($value as $keyduplicate) { + $return[] = $key . '=' . $keyduplicate; + } + } else { + $return[] = $key . '=' . $value; + } + } + return implode('&', $return); + } + + /** + * This is STRICTLY for testing purposes only... + */ + protected $testStaticToken = null; + + final public function setTestStaticToken($token) + { + $this->testStaticToken = (string) $token; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Subscriber/Callback.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Subscriber/Callback.php new file mode 100644 index 0000000000000000000000000000000000000000..4e15e58dbaed66bceaa86a20964d65b2f4dcea50 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Subscriber/Callback.php @@ -0,0 +1,316 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub\Subscriber; + +use Zend\Feed\PubSubHubbub; +use Zend\Feed\PubSubHubbub\Exception; +use Zend\Feed\Uri; + +class Callback extends PubSubHubbub\AbstractCallback +{ + /** + * Contains the content of any feeds sent as updates to the Callback URL + * + * @var string + */ + protected $feedUpdate = null; + + /** + * Holds a manually set subscription key (i.e. identifies a unique + * subscription) which is typical when it is not passed in the query string + * but is part of the Callback URL path, requiring manual retrieval e.g. + * using a route and the \Zend\Mvc\Router\RouteMatch::getParam() method. + * + * @var string + */ + protected $subscriptionKey = null; + + /** + * After verification, this is set to the verified subscription's data. + * + * @var array + */ + protected $currentSubscriptionData = null; + + /** + * Set a subscription key to use for the current callback request manually. + * Required if usePathParameter is enabled for the Subscriber. + * + * @param string $key + * @return \Zend\Feed\PubSubHubbub\Subscriber\Callback + */ + public function setSubscriptionKey($key) + { + $this->subscriptionKey = $key; + return $this; + } + + /** + * Handle any callback from a Hub Server responding to a subscription or + * unsubscription request. This should be the Hub Server confirming the + * the request prior to taking action on it. + * + * @param array $httpGetData GET data if available and not in $_GET + * @param bool $sendResponseNow Whether to send response now or when asked + * @return void + */ + public function handle(array $httpGetData = null, $sendResponseNow = false) + { + if ($httpGetData === null) { + $httpGetData = $_GET; + } + + /** + * Handle any feed updates (sorry for the mess :P) + * + * This DOES NOT attempt to process a feed update. Feed updates + * SHOULD be validated/processed by an asynchronous process so as + * to avoid holding up responses to the Hub. + */ + $contentType = $this->_getHeader('Content-Type'); + if (strtolower($_SERVER['REQUEST_METHOD']) == 'post' + && $this->_hasValidVerifyToken(null, false) + && (stripos($contentType, 'application/atom+xml') === 0 + || stripos($contentType, 'application/rss+xml') === 0 + || stripos($contentType, 'application/xml') === 0 + || stripos($contentType, 'text/xml') === 0 + || stripos($contentType, 'application/rdf+xml') === 0) + ) { + $this->setFeedUpdate($this->_getRawBody()); + $this->getHttpResponse()->setHeader('X-Hub-On-Behalf-Of', $this->getSubscriberCount()); + /** + * Handle any (un)subscribe confirmation requests + */ + } elseif ($this->isValidHubVerification($httpGetData)) { + $this->getHttpResponse()->setContent($httpGetData['hub_challenge']); + + switch (strtolower($httpGetData['hub_mode'])) { + case 'subscribe': + $data = $this->currentSubscriptionData; + $data['subscription_state'] = PubSubHubbub\PubSubHubbub::SUBSCRIPTION_VERIFIED; + if (isset($httpGetData['hub_lease_seconds'])) { + $data['lease_seconds'] = $httpGetData['hub_lease_seconds']; + } + $this->getStorage()->setSubscription($data); + break; + case 'unsubscribe': + $verifyTokenKey = $this->_detectVerifyTokenKey($httpGetData); + $this->getStorage()->deleteSubscription($verifyTokenKey); + break; + default: + throw new Exception\RuntimeException(sprintf( + 'Invalid hub_mode ("%s") provided', + $httpGetData['hub_mode'] + )); + } + /** + * Hey, C'mon! We tried everything else! + */ + } else { + $this->getHttpResponse()->setStatusCode(404); + } + + if ($sendResponseNow) { + $this->sendResponse(); + } + } + + /** + * Checks validity of the request simply by making a quick pass and + * confirming the presence of all REQUIRED parameters. + * + * @param array $httpGetData + * @return bool + */ + public function isValidHubVerification(array $httpGetData) + { + /** + * As per the specification, the hub.verify_token is OPTIONAL. This + * implementation of Pubsubhubbub considers it REQUIRED and will + * always send a hub.verify_token parameter to be echoed back + * by the Hub Server. Therefore, its absence is considered invalid. + */ + if (strtolower($_SERVER['REQUEST_METHOD']) !== 'get') { + return false; + } + $required = array( + 'hub_mode', + 'hub_topic', + 'hub_challenge', + 'hub_verify_token', + ); + foreach ($required as $key) { + if (!array_key_exists($key, $httpGetData)) { + return false; + } + } + if ($httpGetData['hub_mode'] !== 'subscribe' + && $httpGetData['hub_mode'] !== 'unsubscribe' + ) { + return false; + } + if ($httpGetData['hub_mode'] == 'subscribe' + && !array_key_exists('hub_lease_seconds', $httpGetData) + ) { + return false; + } + if (!Uri::factory($httpGetData['hub_topic'])->isValid()) { + return false; + } + + /** + * Attempt to retrieve any Verification Token Key attached to Callback + * URL's path by our Subscriber implementation + */ + if (!$this->_hasValidVerifyToken($httpGetData)) { + return false; + } + return true; + } + + /** + * Sets a newly received feed (Atom/RSS) sent by a Hub as an update to a + * Topic we've subscribed to. + * + * @param string $feed + * @return \Zend\Feed\PubSubHubbub\Subscriber\Callback + */ + public function setFeedUpdate($feed) + { + $this->feedUpdate = $feed; + return $this; + } + + /** + * Check if any newly received feed (Atom/RSS) update was received + * + * @return bool + */ + public function hasFeedUpdate() + { + if ($this->feedUpdate === null) { + return false; + } + return true; + } + + /** + * Gets a newly received feed (Atom/RSS) sent by a Hub as an update to a + * Topic we've subscribed to. + * + * @return string + */ + public function getFeedUpdate() + { + return $this->feedUpdate; + } + + /** + * Check for a valid verify_token. By default attempts to compare values + * with that sent from Hub, otherwise merely ascertains its existence. + * + * @param array $httpGetData + * @param bool $checkValue + * @return bool + */ + protected function _hasValidVerifyToken(array $httpGetData = null, $checkValue = true) + { + $verifyTokenKey = $this->_detectVerifyTokenKey($httpGetData); + if (empty($verifyTokenKey)) { + return false; + } + $verifyTokenExists = $this->getStorage()->hasSubscription($verifyTokenKey); + if (!$verifyTokenExists) { + return false; + } + if ($checkValue) { + $data = $this->getStorage()->getSubscription($verifyTokenKey); + $verifyToken = $data['verify_token']; + if ($verifyToken !== hash('sha256', $httpGetData['hub_verify_token'])) { + return false; + } + $this->currentSubscriptionData = $data; + return true; + } + return true; + } + + /** + * Attempt to detect the verification token key. This would be passed in + * the Callback URL (which we are handling with this class!) as a URI + * path part (the last part by convention). + * + * @param null|array $httpGetData + * @return false|string + */ + protected function _detectVerifyTokenKey(array $httpGetData = null) + { + /** + * Available when sub keys encoding in Callback URL path + */ + if (isset($this->subscriptionKey)) { + return $this->subscriptionKey; + } + + /** + * Available only if allowed by PuSH 0.2 Hubs + */ + if (is_array($httpGetData) + && isset($httpGetData['xhub_subscription']) + ) { + return $httpGetData['xhub_subscription']; + } + + /** + * Available (possibly) if corrupted in transit and not part of $_GET + */ + $params = $this->_parseQueryString(); + if (isset($params['xhub.subscription'])) { + return rawurldecode($params['xhub.subscription']); + } + + return false; + } + + /** + * Build an array of Query String parameters. + * This bypasses $_GET which munges parameter names and cannot accept + * multiple parameters with the same key. + * + * @return array|void + */ + protected function _parseQueryString() + { + $params = array(); + $queryString = ''; + if (isset($_SERVER['QUERY_STRING'])) { + $queryString = $_SERVER['QUERY_STRING']; + } + if (empty($queryString)) { + return array(); + } + $parts = explode('&', $queryString); + foreach ($parts as $kvpair) { + $pair = explode('=', $kvpair); + $key = rawurldecode($pair[0]); + $value = rawurldecode($pair[1]); + if (isset($params[$key])) { + if (is_array($params[$key])) { + $params[$key][] = $value; + } else { + $params[$key] = array($params[$key], $value); + } + } else { + $params[$key] = $value; + } + } + return $params; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Version.php b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Version.php new file mode 100644 index 0000000000000000000000000000000000000000..026fe3b9a25695e2bc467d926a672fecf999a0ce --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/PubSubHubbub/Version.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\PubSubHubbub; + +abstract class Version +{ + const VERSION = '2'; +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/README.md b/core/vendor/zendframework/zend-feed/Zend/Feed/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ffc73a9c262e2137aa7f0b307de8aae31af45e58 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/README.md @@ -0,0 +1,15 @@ +Feed Component from ZF2 +======================= + +This is the Feed component for ZF2. + +- File issues at https://github.com/zendframework/zf2/issues +- Create pull requests against https://github.com/zendframework/zf2 +- Documentation is at http://framework.zend.com/docs + +LICENSE +------- + +The files in this archive are released under the [Zend Framework +license](http://framework.zend.com/license), which is a 3-clause BSD license. + diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/AbstractEntry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/AbstractEntry.php new file mode 100644 index 0000000000000000000000000000000000000000..797562eaa03a0f41e8a3fe6428f0787eea84a354 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/AbstractEntry.php @@ -0,0 +1,224 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +use DOMDocument; +use DOMElement; +use DOMXPath; + +abstract class AbstractEntry +{ + /** + * Feed entry data + * + * @var array + */ + protected $data = array(); + + /** + * DOM document object + * + * @var DOMDocument + */ + protected $domDocument = null; + + /** + * Entry instance + * + * @var DOMElement + */ + protected $entry = null; + + /** + * Pointer to the current entry + * + * @var int + */ + protected $entryKey = 0; + + /** + * XPath object + * + * @var DOMXPath + */ + protected $xpath = null; + + /** + * Registered extensions + * + * @var array + */ + protected $extensions = array(); + + /** + * Constructor + * + * @param DOMElement $entry + * @param int $entryKey + * @param null|string $type + */ + public function __construct(DOMElement $entry, $entryKey, $type = null) + { + $this->entry = $entry; + $this->entryKey = $entryKey; + $this->domDocument = $entry->ownerDocument; + if ($type !== null) { + $this->data['type'] = $type; + } else { + $this->data['type'] = Reader::detectType($entry); + } + $this->_loadExtensions(); + } + + /** + * Get the DOM + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->domDocument; + } + + /** + * Get the entry element + * + * @return DOMElement + */ + public function getElement() + { + return $this->entry; + } + + /** + * Get the Entry's encoding + * + * @return string + */ + public function getEncoding() + { + $assumed = $this->getDomDocument()->encoding; + if (empty($assumed)) { + $assumed = 'UTF-8'; + } + return $assumed; + } + + /** + * Get entry as xml + * + * @return string + */ + public function saveXml() + { + $dom = new DOMDocument('1.0', $this->getEncoding()); + $entry = $dom->importNode($this->getElement(), true); + $dom->appendChild($entry); + return $dom->saveXml(); + } + + /** + * Get the entry type + * + * @return string + */ + public function getType() + { + return $this->data['type']; + } + + /** + * Get the XPath query object + * + * @return DOMXPath + */ + public function getXpath() + { + if (!$this->xpath) { + $this->setXpath(new DOMXPath($this->getDomDocument())); + } + return $this->xpath; + } + + /** + * Set the XPath query + * + * @param DOMXPath $xpath + * @return \Zend\Feed\Reader\AbstractEntry + */ + public function setXpath(DOMXPath $xpath) + { + $this->xpath = $xpath; + return $this; + } + + /** + * Get registered extensions + * + * @return array + */ + public function getExtensions() + { + return $this->extensions; + } + + /** + * Return an Extension object with the matching name (postfixed with _Entry) + * + * @param string $name + * @return \Zend\Feed\Reader\Extension\AbstractEntry + */ + public function getExtension($name) + { + if (array_key_exists($name . '\Entry', $this->extensions)) { + return $this->extensions[$name . '\Entry']; + } + return null; + } + + /** + * Method overloading: call given method on first extension implementing it + * + * @param string $method + * @param array $args + * @return mixed + * @throws Exception\BadMethodCallException if no extensions implements the method + */ + public function __call($method, $args) + { + foreach ($this->extensions as $extension) { + if (method_exists($extension, $method)) { + return call_user_func_array(array($extension, $method), $args); + } + } + throw new Exception\BadMethodCallException('Method: ' . $method + . 'does not exist and could not be located on a registered Extension'); + } + + /** + * Load extensions from Zend\Feed\Reader\Reader + * + * @return void + */ + protected function _loadExtensions() + { + $all = Reader::getExtensions(); + $feed = $all['entry']; + foreach ($feed as $extension) { + if (in_array($extension, $all['core'])) { + continue; + } + $className = Reader::getPluginLoader()->getClassName($extension); + $this->extensions[$extension] = new $className( + $this->getElement(), $this->entryKey, $this->data['type'] + ); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/AbstractFeed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/AbstractFeed.php new file mode 100644 index 0000000000000000000000000000000000000000..6a5cee33a56d8f2fb4d1cc9b585a0c3725a41c76 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/AbstractFeed.php @@ -0,0 +1,300 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +use DOMDocument; +use DOMElement; +use DOMXPath; + +abstract class AbstractFeed implements Feed\FeedInterface +{ + /** + * Parsed feed data + * + * @var array + */ + protected $data = array(); + + /** + * Parsed feed data in the shape of a DOMDocument + * + * @var DOMDocument + */ + protected $domDocument = null; + + /** + * An array of parsed feed entries + * + * @var array + */ + protected $entries = array(); + + /** + * A pointer for the iterator to keep track of the entries array + * + * @var int + */ + protected $entriesKey = 0; + + /** + * The base XPath query used to retrieve feed data + * + * @var DOMXPath + */ + protected $xpath = null; + + /** + * Array of loaded extensions + * + * @var array + */ + protected $extensions = array(); + + /** + * Original Source URI (set if imported from a URI) + * + * @var string + */ + protected $originalSourceUri = null; + + /** + * Constructor + * + * @param DomDocument $domDocument The DOM object for the feed's XML + * @param string $type Feed type + */ + public function __construct(DOMDocument $domDocument, $type = null) + { + $this->domDocument = $domDocument; + $this->xpath = new DOMXPath($this->domDocument); + + if ($type !== null) { + $this->data['type'] = $type; + } else { + $this->data['type'] = Reader::detectType($this->domDocument); + } + $this->registerNamespaces(); + $this->indexEntries(); + $this->loadExtensions(); + } + + /** + * Set an original source URI for the feed being parsed. This value + * is returned from getFeedLink() method if the feed does not carry + * a self-referencing URI. + * + * @param string $uri + */ + public function setOriginalSourceUri($uri) + { + $this->originalSourceUri = $uri; + } + + /** + * Get an original source URI for the feed being parsed. Returns null if + * unset or the feed was not imported from a URI. + * + * @return string|null + */ + public function getOriginalSourceUri() + { + return $this->originalSourceUri; + } + + /** + * Get the number of feed entries. + * Required by the Iterator interface. + * + * @return int + */ + public function count() + { + return count($this->entries); + } + + /** + * Return the current entry + * + * @return \Zend\Feed\Reader\AbstractEntry + */ + public function current() + { + if (substr($this->getType(), 0, 3) == 'rss') { + $reader = new Entry\RSS($this->entries[$this->key()], $this->key(), $this->getType()); + } else { + $reader = new Entry\Atom($this->entries[$this->key()], $this->key(), $this->getType()); + } + + $reader->setXpath($this->xpath); + + return $reader; + } + + /** + * Get the DOM + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->domDocument; + } + + /** + * Get the Feed's encoding + * + * @return string + */ + public function getEncoding() + { + $assumed = $this->getDomDocument()->encoding; + if (empty($assumed)) { + $assumed = 'UTF-8'; + } + return $assumed; + } + + /** + * Get feed as xml + * + * @return string + */ + public function saveXml() + { + return $this->getDomDocument()->saveXml(); + } + + /** + * Get the DOMElement representing the items/feed element + * + * @return DOMElement + */ + public function getElement() + { + return $this->getDomDocument()->documentElement; + } + + /** + * Get the DOMXPath object for this feed + * + * @return DOMXPath + */ + public function getXpath() + { + return $this->xpath; + } + + /** + * Get the feed type + * + * @return string + */ + public function getType() + { + return $this->data['type']; + } + + /** + * Return the current feed key + * + * @return int + */ + public function key() + { + return $this->entriesKey; + } + + /** + * Move the feed pointer forward + * + */ + public function next() + { + ++$this->entriesKey; + } + + /** + * Reset the pointer in the feed object + * + */ + public function rewind() + { + $this->entriesKey = 0; + } + + /** + * Check to see if the iterator is still valid + * + * @return bool + */ + public function valid() + { + return 0 <= $this->entriesKey && $this->entriesKey < $this->count(); + } + + public function getExtensions() + { + return $this->extensions; + } + + public function __call($method, $args) + { + foreach ($this->extensions as $extension) { + if (method_exists($extension, $method)) { + return call_user_func_array(array($extension, $method), $args); + } + } + throw new Exception\BadMethodCallException('Method: ' . $method + . 'does not exist and could not be located on a registered Extension'); + } + + /** + * Return an Extension object with the matching name (postfixed with _Feed) + * + * @param string $name + * @return \Zend\Feed\Reader\Extension\AbstractFeed + */ + public function getExtension($name) + { + if (array_key_exists($name . '\Feed', $this->extensions)) { + return $this->extensions[$name . '\Feed']; + } + return null; + } + + protected function loadExtensions() + { + $all = Reader::getExtensions(); + $manager = Reader::getExtensionManager(); + $feed = $all['feed']; + foreach ($feed as $extension) { + if (in_array($extension, $all['core'])) { + continue; + } + $plugin = $manager->get($extension); + $plugin->setDomDocument($this->getDomDocument()); + $plugin->setType($this->data['type']); + $plugin->setXpath($this->xpath); + $this->extensions[$extension] = $plugin; + } + } + + /** + * Read all entries to the internal entries array + * + */ + abstract protected function indexEntries(); + + /** + * Register the default namespaces for the current feed format + * + */ + abstract protected function registerNamespaces(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..32144dfa23c594e7456fbcecf1f0911895263f03 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +class Collection extends \ArrayObject +{ + + + +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/AbstractCollection.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/AbstractCollection.php new file mode 100644 index 0000000000000000000000000000000000000000..8c64ec99cc21b9da14ded6ba6f3e48030dd159f0 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/AbstractCollection.php @@ -0,0 +1,25 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Collection; + +abstract class AbstractCollection extends \ArrayObject +{ + + /** + * Return a simple array of the most relevant slice of + * the collection values. For example, feed categories contain + * the category name, domain/URI, and other data. This method would + * merely return the most useful data - i.e. the category names. + * + * @return array + */ + abstract public function getValues(); + +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Author.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Author.php new file mode 100644 index 0000000000000000000000000000000000000000..15aa32834be8ee60b4fa7c301596ef068a86801d --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Author.php @@ -0,0 +1,29 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Collection; + +class Author extends AbstractCollection +{ + + /** + * Return a simple array of the most relevant slice of + * the author values, i.e. all author names. + * + * @return array + */ + public function getValues() + { + $authors = array(); + foreach ($this->getIterator() as $element) { + $authors[] = $element['name']; + } + return array_unique($authors); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Category.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Category.php new file mode 100644 index 0000000000000000000000000000000000000000..2739bc8339418baa21d3f49e5a4ea3e27a2264c6 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Category.php @@ -0,0 +1,35 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Collection; + +class Category extends AbstractCollection +{ + + /** + * Return a simple array of the most relevant slice of + * the collection values. For example, feed categories contain + * the category name, domain/URI, and other data. This method would + * merely return the most useful data - i.e. the category names. + * + * @return array + */ + public function getValues() + { + $categories = array(); + foreach ($this->getIterator() as $element) { + if (isset($element['label']) && !empty($element['label'])) { + $categories[] = $element['label']; + } else { + $categories[] = $element['term']; + } + } + return array_unique($categories); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Collection.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..820a695ab9263fb6d7d87c15245895ccd7776866 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Collection/Collection.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Collection; + +class Collection extends \ArrayObject +{ + + + +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/AbstractEntry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/AbstractEntry.php new file mode 100644 index 0000000000000000000000000000000000000000..68ff4f9485925cbfa1e0e1dd77e6dca4a36ac8ba --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/AbstractEntry.php @@ -0,0 +1,230 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Entry; + +use DOMDocument; +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Exception; + +abstract class AbstractEntry +{ + /** + * Feed entry data + * + * @var array + */ + protected $data = array(); + + /** + * DOM document object + * + * @var DOMDocument + */ + protected $domDocument = null; + + /** + * Entry instance + * + * @var DOMElement + */ + protected $entry = null; + + /** + * Pointer to the current entry + * + * @var int + */ + protected $entryKey = 0; + + /** + * XPath object + * + * @var DOMXPath + */ + protected $xpath = null; + + /** + * Registered extensions + * + * @var array + */ + protected $extensions = array(); + + /** + * Constructor + * + * @param DOMElement $entry + * @param int $entryKey + * @param string $type + */ + public function __construct(DOMElement $entry, $entryKey, $type = null) + { + $this->entry = $entry; + $this->entryKey = $entryKey; + $this->domDocument = $entry->ownerDocument; + if ($type !== null) { + $this->data['type'] = $type; + } elseif ($this->domDocument !== null) { + $this->data['type'] = Reader\Reader::detectType($this->domDocument); + } else { + $this->data['type'] = Reader\Reader::TYPE_ANY; + } + $this->loadExtensions(); + } + + /** + * Get the DOM + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->domDocument; + } + + /** + * Get the entry element + * + * @return DOMElement + */ + public function getElement() + { + return $this->entry; + } + + /** + * Get the Entry's encoding + * + * @return string + */ + public function getEncoding() + { + $assumed = $this->getDomDocument()->encoding; + if (empty($assumed)) { + $assumed = 'UTF-8'; + } + return $assumed; + } + + /** + * Get entry as xml + * + * @return string + */ + public function saveXml() + { + $dom = new DOMDocument('1.0', $this->getEncoding()); + $entry = $dom->importNode($this->getElement(), true); + $dom->appendChild($entry); + return $dom->saveXml(); + } + + /** + * Get the entry type + * + * @return string + */ + public function getType() + { + return $this->data['type']; + } + + /** + * Get the XPath query object + * + * @return DOMXPath + */ + public function getXpath() + { + if (!$this->xpath) { + $this->setXpath(new DOMXPath($this->getDomDocument())); + } + return $this->xpath; + } + + /** + * Set the XPath query + * + * @param DOMXPath $xpath + * @return AbstractEntry + */ + public function setXpath(DOMXPath $xpath) + { + $this->xpath = $xpath; + return $this; + } + + /** + * Get registered extensions + * + * @return array + */ + public function getExtensions() + { + return $this->extensions; + } + + /** + * Return an Extension object with the matching name (postfixed with _Entry) + * + * @param string $name + * @return Reader\Extension\AbstractEntry + */ + public function getExtension($name) + { + if (array_key_exists($name . '\\Entry', $this->extensions)) { + return $this->extensions[$name . '\\Entry']; + } + return null; + } + + /** + * Method overloading: call given method on first extension implementing it + * + * @param string $method + * @param array $args + * @return mixed + * @throws Exception\RuntimeException if no extensions implements the method + */ + public function __call($method, $args) + { + foreach ($this->extensions as $extension) { + if (method_exists($extension, $method)) { + return call_user_func_array(array($extension, $method), $args); + } + } + throw new Exception\RuntimeException('Method: ' . $method + . ' does not exist and could not be located on a registered Extension'); + } + + /** + * Load extensions from Zend\Feed\Reader\Reader + * + * @return void + */ + protected function loadExtensions() + { + $all = Reader\Reader::getExtensions(); + $manager = Reader\Reader::getExtensionManager(); + $feed = $all['entry']; + foreach ($feed as $extension) { + if (in_array($extension, $all['core'])) { + continue; + } + $plugin = $manager->get($extension); + $plugin->setEntryElement($this->getElement()); + $plugin->setEntryKey($this->entryKey); + $plugin->setType($this->data['type']); + $this->extensions[$extension] = $plugin; + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/Atom.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/Atom.php new file mode 100644 index 0000000000000000000000000000000000000000..fcd5f60f90f8c4022ea510e61a09e073afb12cd2 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/Atom.php @@ -0,0 +1,370 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Entry; + +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; + +class Atom extends AbstractEntry implements EntryInterface +{ + /** + * XPath query + * + * @var string + */ + protected $xpathQuery = ''; + + /** + * Constructor + * + * @param DOMElement $entry + * @param int $entryKey + * @param string $type + */ + public function __construct(DOMElement $entry, $entryKey, $type = null) + { + parent::__construct($entry, $entryKey, $type); + + // Everyone by now should know XPath indices start from 1 not 0 + $this->xpathQuery = '//atom:entry[' . ($this->entryKey + 1) . ']'; + + $manager = Reader\Reader::getExtensionManager(); + $extensions = array('Atom\Entry', 'Thread\Entry', 'DublinCore\Entry'); + + foreach ($extensions as $name) { + $extension = $manager->get($name); + $extension->setEntryElement($entry); + $extension->setEntryKey($entryKey); + $extension->setType($type); + $this->extensions[$name] = $extension; + } + } + + /** + * Get the specified author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $people = $this->getExtension('Atom')->getAuthors(); + + $this->data['authors'] = $people; + + return $this->data['authors']; + } + + /** + * Get the entry content + * + * @return string + */ + public function getContent() + { + if (array_key_exists('content', $this->data)) { + return $this->data['content']; + } + + $content = $this->getExtension('Atom')->getContent(); + + $this->data['content'] = $content; + + return $this->data['content']; + } + + /** + * Get the entry creation date + * + * @return string + */ + public function getDateCreated() + { + if (array_key_exists('datecreated', $this->data)) { + return $this->data['datecreated']; + } + + $dateCreated = $this->getExtension('Atom')->getDateCreated(); + + $this->data['datecreated'] = $dateCreated; + + return $this->data['datecreated']; + } + + /** + * Get the entry modification date + * + * @return string + */ + public function getDateModified() + { + if (array_key_exists('datemodified', $this->data)) { + return $this->data['datemodified']; + } + + $dateModified = $this->getExtension('Atom')->getDateModified(); + + $this->data['datemodified'] = $dateModified; + + return $this->data['datemodified']; + } + + /** + * Get the entry description + * + * @return string + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = $this->getExtension('Atom')->getDescription(); + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the entry enclosure + * + * @return string + */ + public function getEnclosure() + { + if (array_key_exists('enclosure', $this->data)) { + return $this->data['enclosure']; + } + + $enclosure = $this->getExtension('Atom')->getEnclosure(); + + $this->data['enclosure'] = $enclosure; + + return $this->data['enclosure']; + } + + /** + * Get the entry ID + * + * @return string + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = $this->getExtension('Atom')->getId(); + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get a specific link + * + * @param int $index + * @return string + */ + public function getLink($index = 0) + { + if (!array_key_exists('links', $this->data)) { + $this->getLinks(); + } + + if (isset($this->data['links'][$index])) { + return $this->data['links'][$index]; + } + + return null; + } + + /** + * Get all links + * + * @return array + */ + public function getLinks() + { + if (array_key_exists('links', $this->data)) { + return $this->data['links']; + } + + $links = $this->getExtension('Atom')->getLinks(); + + $this->data['links'] = $links; + + return $this->data['links']; + } + + /** + * Get a permalink to the entry + * + * @return string + */ + public function getPermalink() + { + return $this->getLink(0); + } + + /** + * Get the entry title + * + * @return string + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = $this->getExtension('Atom')->getTitle(); + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * Get the number of comments/replies for current entry + * + * @return int + */ + public function getCommentCount() + { + if (array_key_exists('commentcount', $this->data)) { + return $this->data['commentcount']; + } + + $commentcount = $this->getExtension('Thread')->getCommentCount(); + + if (!$commentcount) { + $commentcount = $this->getExtension('Atom')->getCommentCount(); + } + + $this->data['commentcount'] = $commentcount; + + return $this->data['commentcount']; + } + + /** + * Returns a URI pointing to the HTML page where comments can be made on this entry + * + * @return string + */ + public function getCommentLink() + { + if (array_key_exists('commentlink', $this->data)) { + return $this->data['commentlink']; + } + + $commentlink = $this->getExtension('Atom')->getCommentLink(); + + $this->data['commentlink'] = $commentlink; + + return $this->data['commentlink']; + } + + /** + * Returns a URI pointing to a feed of all comments for this entry + * + * @return string + */ + public function getCommentFeedLink() + { + if (array_key_exists('commentfeedlink', $this->data)) { + return $this->data['commentfeedlink']; + } + + $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink(); + + $this->data['commentfeedlink'] = $commentfeedlink; + + return $this->data['commentfeedlink']; + } + + /** + * Get category data as a Reader\Reader_Collection_Category object + * + * @return Reader\Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + $categoryCollection = $this->getExtension('Atom')->getCategories(); + + if (count($categoryCollection) == 0) { + $categoryCollection = $this->getExtension('DublinCore')->getCategories(); + } + + $this->data['categories'] = $categoryCollection; + + return $this->data['categories']; + } + + /** + * Get source feed metadata from the entry + * + * @return Reader\Feed\Atom\Source|null + */ + public function getSource() + { + if (array_key_exists('source', $this->data)) { + return $this->data['source']; + } + + $source = $this->getExtension('Atom')->getSource(); + + $this->data['source'] = $source; + + return $this->data['source']; + } + + /** + * Set the XPath query (incl. on all Extensions) + * + * @param DOMXPath $xpath + * @return void + */ + public function setXpath(DOMXPath $xpath) + { + parent::setXpath($xpath); + foreach ($this->extensions as $extension) { + $extension->setXpath($this->xpath); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/EntryInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/EntryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..29b437a2ca231401e84b70a46396019c084dc013 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/EntryInterface.php @@ -0,0 +1,129 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Entry; + +use Zend\Feed\Reader\Collection\Category; + +interface EntryInterface +{ + /** + * Get the specified author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0); + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors(); + + /** + * Get the entry content + * + * @return string + */ + public function getContent(); + + /** + * Get the entry creation date + * + * @return string + */ + public function getDateCreated(); + + /** + * Get the entry modification date + * + * @return string + */ + public function getDateModified(); + + /** + * Get the entry description + * + * @return string + */ + public function getDescription(); + + /** + * Get the entry enclosure + * + * @return \stdClass + */ + public function getEnclosure(); + + /** + * Get the entry ID + * + * @return string + */ + public function getId(); + + /** + * Get a specific link + * + * @param int $index + * @return string + */ + public function getLink($index = 0); + + /** + * Get all links + * + * @return array + */ + public function getLinks(); + + /** + * Get a permalink to the entry + * + * @return string + */ + public function getPermalink(); + + /** + * Get the entry title + * + * @return string + */ + public function getTitle(); + + /** + * Get the number of comments/replies for current entry + * + * @return int + */ + public function getCommentCount(); + + /** + * Returns a URI pointing to the HTML page where comments can be made on this entry + * + * @return string + */ + public function getCommentLink(); + + /** + * Returns a URI pointing to a feed of all comments for this entry + * + * @return string + */ + public function getCommentFeedLink(); + + /** + * Get all categories + * + * @return Category + */ + public function getCategories(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/Rss.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/Rss.php new file mode 100644 index 0000000000000000000000000000000000000000..274d0d5865bd5ff385978fa71ee1653fcea6e8ad --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Entry/Rss.php @@ -0,0 +1,599 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Entry; + +use DateTime; +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Exception; + +class Rss extends AbstractEntry implements EntryInterface +{ + + /** + * XPath query for RDF + * + * @var string + */ + protected $xpathQueryRdf = ''; + + /** + * XPath query for RSS + * + * @var string + */ + protected $xpathQueryRss = ''; + + /** + * Constructor + * + * @param DOMElement $entry + * @param string $entryKey + * @param string $type + */ + public function __construct(DOMElement $entry, $entryKey, $type = null) + { + parent::__construct($entry, $entryKey, $type); + $this->xpathQueryRss = '//item[' . ($this->entryKey+1) . ']'; + $this->xpathQueryRdf = '//rss:item[' . ($this->entryKey+1) . ']'; + + $manager = Reader\Reader::getExtensionManager(); + $extensions = array( + 'DublinCore\Entry', + 'Content\Entry', + 'Atom\Entry', + 'WellFormedWeb\Entry', + 'Slash\Entry', + 'Thread\Entry', + ); + foreach ($extensions as $name) { + $extension = $manager->get($name); + $extension->setEntryElement($entry); + $extension->setEntryKey($entryKey); + $extension->setType($type); + $this->extensions[$name] = $extension; + } + } + + /** + * Get an author entry + * + * @param int $index + * @return string + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = array(); + $authorsDc = $this->getExtension('DublinCore')->getAuthors(); + if (!empty($authorsDc)) { + foreach ($authorsDc as $author) { + $authors[] = array( + 'name' => $author['name'] + ); + } + } + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $list = $this->xpath->query($this->xpathQueryRss . '//author'); + } else { + $list = $this->xpath->query($this->xpathQueryRdf . '//rss:author'); + } + if ($list->length) { + foreach ($list as $author) { + $string = trim($author->nodeValue); + $email = null; + $name = null; + $data = array(); + // Pretty rough parsing - but it's a catchall + if (preg_match("/^.*@[^ ]*/", $string, $matches)) { + $data['email'] = trim($matches[0]); + if (preg_match("/\((.*)\)$/", $string, $matches)) { + $data['name'] = $matches[1]; + } + $authors[] = $data; + } + } + } + + if (count($authors) == 0) { + $authors = $this->getExtension('Atom')->getAuthors(); + } else { + $authors = new Reader\Collection\Author( + Reader\Reader::arrayUnique($authors) + ); + } + + if (count($authors) == 0) { + $authors = null; + } + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get the entry content + * + * @return string + */ + public function getContent() + { + if (array_key_exists('content', $this->data)) { + return $this->data['content']; + } + + $content = $this->getExtension('Content')->getContent(); + + if (!$content) { + $content = $this->getDescription(); + } + + if (empty($content)) { + $content = $this->getExtension('Atom')->getContent(); + } + + $this->data['content'] = $content; + + return $this->data['content']; + } + + /** + * Get the entry's date of creation + * + * @return string + */ + public function getDateCreated() + { + return $this->getDateModified(); + } + + /** + * Get the entry's date of modification + * + * @throws Exception\RuntimeException + * @return string + */ + public function getDateModified() + { + if (array_key_exists('datemodified', $this->data)) { + return $this->data['datemodified']; + } + + $dateModified = null; + $date = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $dateModified = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/pubDate)'); + if ($dateModified) { + $dateModifiedParsed = strtotime($dateModified); + if ($dateModifiedParsed) { + $date = new DateTime('@' . $dateModifiedParsed); + } else { + $dateStandards = array(DateTime::RSS, DateTime::RFC822, + DateTime::RFC2822, null); + foreach ($dateStandards as $standard) { + try { + $date = date_create_from_format($standard, $dateModified); + break; + } catch (\Exception $e) { + if ($standard == null) { + throw new Exception\RuntimeException( + 'Could not load date due to unrecognised' + .' format (should follow RFC 822 or 2822):' + . $e->getMessage(), + 0, $e + ); + } + } + } + } + } + } + + if (!$date) { + $date = $this->getExtension('DublinCore')->getDate(); + } + + if (!$date) { + $date = $this->getExtension('Atom')->getDateModified(); + } + + if (!$date) { + $date = null; + } + + $this->data['datemodified'] = $date; + + return $this->data['datemodified']; + } + + /** + * Get the entry description + * + * @return string + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $description = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/description)'); + } else { + $description = $this->xpath->evaluate('string(' . $this->xpathQueryRdf . '/rss:description)'); + } + + if (!$description) { + $description = $this->getExtension('DublinCore')->getDescription(); + } + + if (empty($description)) { + $description = $this->getExtension('Atom')->getDescription(); + } + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the entry enclosure + * @return string + */ + public function getEnclosure() + { + if (array_key_exists('enclosure', $this->data)) { + return $this->data['enclosure']; + } + + $enclosure = null; + + if ($this->getType() == Reader\Reader::TYPE_RSS_20) { + $nodeList = $this->xpath->query($this->xpathQueryRss . '/enclosure'); + + if ($nodeList->length > 0) { + $enclosure = new \stdClass(); + $enclosure->url = $nodeList->item(0)->getAttribute('url'); + $enclosure->length = $nodeList->item(0)->getAttribute('length'); + $enclosure->type = $nodeList->item(0)->getAttribute('type'); + } + } + + if (!$enclosure) { + $enclosure = $this->getExtension('Atom')->getEnclosure(); + } + + $this->data['enclosure'] = $enclosure; + + return $this->data['enclosure']; + } + + /** + * Get the entry ID + * + * @return string + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $id = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/guid)'); + } + + if (!$id) { + $id = $this->getExtension('DublinCore')->getId(); + } + + if (empty($id)) { + $id = $this->getExtension('Atom')->getId(); + } + + if (!$id) { + if ($this->getPermalink()) { + $id = $this->getPermalink(); + } elseif ($this->getTitle()) { + $id = $this->getTitle(); + } else { + $id = null; + } + } + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get a specific link + * + * @param int $index + * @return string + */ + public function getLink($index = 0) + { + if (!array_key_exists('links', $this->data)) { + $this->getLinks(); + } + + if (isset($this->data['links'][$index])) { + return $this->data['links'][$index]; + } + + return null; + } + + /** + * Get all links + * + * @return array + */ + public function getLinks() + { + if (array_key_exists('links', $this->data)) { + return $this->data['links']; + } + + $links = array(); + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $list = $this->xpath->query($this->xpathQueryRss . '//link'); + } else { + $list = $this->xpath->query($this->xpathQueryRdf . '//rss:link'); + } + + if (!$list->length) { + $links = $this->getExtension('Atom')->getLinks(); + } else { + foreach ($list as $link) { + $links[] = $link->nodeValue; + } + } + + $this->data['links'] = $links; + + return $this->data['links']; + } + + /** + * Get all categories + * + * @return Reader\Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $list = $this->xpath->query($this->xpathQueryRss . '//category'); + } else { + $list = $this->xpath->query($this->xpathQueryRdf . '//rss:category'); + } + + if ($list->length) { + $categoryCollection = new Reader\Collection\Category; + foreach ($list as $category) { + $categoryCollection[] = array( + 'term' => $category->nodeValue, + 'scheme' => $category->getAttribute('domain'), + 'label' => $category->nodeValue, + ); + } + } else { + $categoryCollection = $this->getExtension('DublinCore')->getCategories(); + } + + if (count($categoryCollection) == 0) { + $categoryCollection = $this->getExtension('Atom')->getCategories(); + } + + $this->data['categories'] = $categoryCollection; + + return $this->data['categories']; + } + + /** + * Get a permalink to the entry + * + * @return string + */ + public function getPermalink() + { + return $this->getLink(0); + } + + /** + * Get the entry title + * + * @return string + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $title = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/title)'); + } else { + $title = $this->xpath->evaluate('string(' . $this->xpathQueryRdf . '/rss:title)'); + } + + if (!$title) { + $title = $this->getExtension('DublinCore')->getTitle(); + } + + if (!$title) { + $title = $this->getExtension('Atom')->getTitle(); + } + + if (!$title) { + $title = null; + } + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * Get the number of comments/replies for current entry + * + * @return string|null + */ + public function getCommentCount() + { + if (array_key_exists('commentcount', $this->data)) { + return $this->data['commentcount']; + } + + $commentcount = $this->getExtension('Slash')->getCommentCount(); + + if (!$commentcount) { + $commentcount = $this->getExtension('Thread')->getCommentCount(); + } + + if (!$commentcount) { + $commentcount = $this->getExtension('Atom')->getCommentCount(); + } + + if (!$commentcount) { + $commentcount = null; + } + + $this->data['commentcount'] = $commentcount; + + return $this->data['commentcount']; + } + + /** + * Returns a URI pointing to the HTML page where comments can be made on this entry + * + * @return string + */ + public function getCommentLink() + { + if (array_key_exists('commentlink', $this->data)) { + return $this->data['commentlink']; + } + + $commentlink = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $commentlink = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/comments)'); + } + + if (!$commentlink) { + $commentlink = $this->getExtension('Atom')->getCommentLink(); + } + + if (!$commentlink) { + $commentlink = null; + } + + $this->data['commentlink'] = $commentlink; + + return $this->data['commentlink']; + } + + /** + * Returns a URI pointing to a feed of all comments for this entry + * + * @return string + */ + public function getCommentFeedLink() + { + if (array_key_exists('commentfeedlink', $this->data)) { + return $this->data['commentfeedlink']; + } + + $commentfeedlink = $this->getExtension('WellFormedWeb')->getCommentFeedLink(); + + if (!$commentfeedlink) { + $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rss'); + } + + if (!$commentfeedlink) { + $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rdf'); + } + + if (!$commentfeedlink) { + $commentfeedlink = null; + } + + $this->data['commentfeedlink'] = $commentfeedlink; + + return $this->data['commentfeedlink']; + } + + /** + * Set the XPath query (incl. on all Extensions) + * + * @param DOMXPath $xpath + * @return void + */ + public function setXpath(DOMXPath $xpath) + { + parent::setXpath($xpath); + foreach ($this->extensions as $extension) { + $extension->setXpath($this->xpath); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/BadMethodCallException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..3994b0ceb692c76a8dfede5e527739bcc2504cc6 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/BadMethodCallException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Exception; + +use Zend\Feed\Exception; + +class BadMethodCallException + extends Exception\BadMethodCallException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/ExceptionInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..09abac6d308d9fd928042a7883d9b8c78630350e --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/ExceptionInterface.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Exception; + +use Zend\Feed\Exception\ExceptionInterface as Exception; + +interface ExceptionInterface extends Exception +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/InvalidArgumentException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..5860322ab528083094d0a327c849ae97fa5a7457 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/InvalidArgumentException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Exception; + +use Zend\Feed\Exception; + +class InvalidArgumentException + extends Exception\InvalidArgumentException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/RuntimeException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..f0590fb43c8f08a5055147339a6e6e545c4f84df --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Exception/RuntimeException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Exception; + +use Zend\Feed\Exception; + +class RuntimeException + extends Exception\RuntimeException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/AbstractEntry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/AbstractEntry.php new file mode 100644 index 0000000000000000000000000000000000000000..0f0333b9f5205a6acc8119ed6b21741828322269 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/AbstractEntry.php @@ -0,0 +1,233 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension; + +use DOMDocument; +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; + +abstract class AbstractEntry +{ + /** + * Feed entry data + * + * @var array + */ + protected $data = array(); + + /** + * DOM document object + * + * @var DOMDocument + */ + protected $domDocument = null; + + /** + * Entry instance + * + * @var DOMElement + */ + protected $entry = null; + + /** + * Pointer to the current entry + * + * @var int + */ + protected $entryKey = 0; + + /** + * XPath object + * + * @var DOMXPath + */ + protected $xpath = null; + + /** + * XPath query + * + * @var string + */ + protected $xpathPrefix = ''; + + /** + * Set the entry DOMElement + * + * Has side effect of setting the DOMDocument for the entry. + * + * @param DOMElement $entry + * @return AbstractEntry + */ + public function setEntryElement(DOMElement $entry) + { + $this->entry = $entry; + $this->domDocument = $entry->ownerDocument; + return $this; + } + + /** + * Get the entry DOMElement + * + * @return DOMElement + */ + public function getEntryElement() + { + return $this->entry; + } + + /** + * Set the entry key + * + * @param string $entryKey + * @return AbstractEntry + */ + public function setEntryKey($entryKey) + { + $this->entryKey = $entryKey; + return $this; + } + + /** + * Get the DOM + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->domDocument; + } + + /** + * Get the Entry's encoding + * + * @return string + */ + public function getEncoding() + { + $assumed = $this->getDomDocument()->encoding; + return $assumed; + } + + /** + * Set the entry type + * + * Has side effect of setting xpath prefix + * + * @param string $type + * @return AbstractEntry + */ + public function setType($type) + { + if (null === $type) { + $this->data['type'] = null; + return $this; + } + + $this->data['type'] = $type; + if ($type === Reader\Reader::TYPE_RSS_10 + || $type === Reader\Reader::TYPE_RSS_090 + ) { + $this->setXpathPrefix('//rss:item[' . ($this->entryKey + 1) . ']'); + return $this; + } + + if ($type === Reader\Reader::TYPE_ATOM_10 + || $type === Reader\Reader::TYPE_ATOM_03 + ) { + $this->setXpathPrefix('//atom:entry[' . ($this->entryKey + 1) . ']'); + return $this; + } + + $this->setXpathPrefix('//item[' . ($this->entryKey + 1) . ']'); + return $this; + } + + /** + * Get the entry type + * + * @return string + */ + public function getType() + { + $type = $this->data['type']; + if ($type === null) { + $type = Reader\Reader::detectType($this->getEntryElement(), true); + $this->setType($type); + } + + return $type; + } + + /** + * Set the XPath query + * + * @param DOMXPath $xpath + * @return AbstractEntry + */ + public function setXpath(DOMXPath $xpath) + { + $this->xpath = $xpath; + $this->registerNamespaces(); + return $this; + } + + /** + * Get the XPath query object + * + * @return DOMXPath + */ + public function getXpath() + { + if (!$this->xpath) { + $this->setXpath(new DOMXPath($this->getDomDocument())); + } + return $this->xpath; + } + + /** + * Serialize the entry to an array + * + * @return array + */ + public function toArray() + { + return $this->data; + } + + /** + * Get the XPath prefix + * + * @return string + */ + public function getXpathPrefix() + { + return $this->xpathPrefix; + } + + /** + * Set the XPath prefix + * + * @param string $prefix + * @return AbstractEntry + */ + public function setXpathPrefix($prefix) + { + $this->xpathPrefix = $prefix; + return $this; + } + + /** + * Register XML namespaces + * + * @return void + */ + abstract protected function registerNamespaces(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/AbstractFeed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/AbstractFeed.php new file mode 100644 index 0000000000000000000000000000000000000000..75089253602d95f9a52ed7c8abec17d8ff393448 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/AbstractFeed.php @@ -0,0 +1,176 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension; + +use DOMDocument; +use DOMXPath; +use Zend\Feed\Reader; + +abstract class AbstractFeed +{ + /** + * Parsed feed data + * + * @var array + */ + protected $data = array(); + + /** + * Parsed feed data in the shape of a DOMDocument + * + * @var DOMDocument + */ + protected $domDocument = null; + + /** + * The base XPath query used to retrieve feed data + * + * @var DOMXPath + */ + protected $xpath = null; + + /** + * The XPath prefix + * + * @var string + */ + protected $xpathPrefix = ''; + + /** + * Set the DOM document + * + * @param DOMDocument $dom + * @return AbstractFeed + */ + public function setDomDocument(DOMDocument $dom) + { + $this->domDocument = $dom; + return $this; + } + + /** + * Get the DOM + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->domDocument; + } + + /** + * Get the Feed's encoding + * + * @return string + */ + public function getEncoding() + { + $assumed = $this->getDomDocument()->encoding; + return $assumed; + } + + /** + * Set the feed type + * + * @param string $type + * @return AbstractFeed + */ + public function setType($type) + { + $this->data['type'] = $type; + return $this; + } + + /** + * Get the feed type + * + * If null, it will attempt to autodetect the type. + * + * @return string + */ + public function getType() + { + $type = $this->data['type']; + if (null === $type) { + $type = Reader\Reader::detectType($this->getDomDocument()); + $this->setType($type); + } + return $type; + } + + + /** + * Return the feed as an array + * + * @return array + */ + public function toArray() // untested + { + return $this->data; + } + + /** + * Set the XPath query + * + * @param DOMXPath $xpath + * @return AbstractEntry + */ + public function setXpath(DOMXPath $xpath = null) + { + if (null === $xpath) { + $this->xpath = null; + return $this; + } + + $this->xpath = $xpath; + $this->registerNamespaces(); + return $this; + } + + /** + * Get the DOMXPath object + * + * @return string + */ + public function getXpath() + { + if (null === $this->xpath) { + $this->setXpath(new DOMXPath($this->getDomDocument())); + } + + return $this->xpath; + } + + /** + * Get the XPath prefix + * + * @return string + */ + public function getXpathPrefix() + { + return $this->xpathPrefix; + } + + /** + * Set the XPath prefix + * + * @param string $prefix + * @return void + */ + public function setXpathPrefix($prefix) + { + $this->xpathPrefix = $prefix; + } + + /** + * Register the default namespaces for the current feed format + */ + abstract protected function registerNamespaces(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Atom/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Atom/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..d68577cdf72d8810264a3477bf6ee7f2b9fce3be --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Atom/Entry.php @@ -0,0 +1,628 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Atom; + +use DateTime; +use DOMDocument; +use DOMElement; +use stdClass; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Collection; +use Zend\Feed\Reader\Extension; +use Zend\Feed\Uri; + +class Entry extends Extension\AbstractEntry +{ + /** + * Get the specified author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return Collection\Author + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = array(); + $list = $this->getXpath()->query($this->getXpathPrefix() . '//atom:author'); + + if (!$list->length) { + /** + * TODO: Limit query to feed level els only! + */ + $list = $this->getXpath()->query('//atom:author'); + } + + if ($list->length) { + foreach ($list as $author) { + $author = $this->getAuthorFromElement($author); + if (!empty($author)) { + $authors[] = $author; + } + } + } + + if (count($authors) == 0) { + $authors = new Collection\Author(); + } else { + $authors = new Collection\Author( + Reader\Reader::arrayUnique($authors) + ); + } + + $this->data['authors'] = $authors; + return $this->data['authors']; + } + + /** + * Get the entry content + * + * @return string + */ + public function getContent() + { + if (array_key_exists('content', $this->data)) { + return $this->data['content']; + } + + $content = null; + + $el = $this->getXpath()->query($this->getXpathPrefix() . '/atom:content'); + if ($el->length > 0) { + $el = $el->item(0); + $type = $el->getAttribute('type'); + switch ($type) { + case '': + case 'text': + case 'text/plain': + case 'html': + case 'text/html': + $content = $el->nodeValue; + break; + case 'xhtml': + $this->getXpath()->registerNamespace('xhtml', 'http://www.w3.org/1999/xhtml'); + $xhtml = $this->getXpath()->query( + $this->getXpathPrefix() . '/atom:content/xhtml:div' + )->item(0); + $d = new DOMDocument('1.0', $this->getEncoding()); + $xhtmls = $d->importNode($xhtml, true); + $d->appendChild($xhtmls); + $content = $this->collectXhtml( + $d->saveXML(), + $d->lookupPrefix('http://www.w3.org/1999/xhtml') + ); + break; + } + } + + if (!$content) { + $content = $this->getDescription(); + } + + $this->data['content'] = trim($content); + + return $this->data['content']; + } + + /** + * Parse out XHTML to remove the namespacing + * + * @param $xhtml + * @param $prefix + * @return mixed + */ + protected function collectXhtml($xhtml, $prefix) + { + if (!empty($prefix)) $prefix = $prefix . ':'; + $matches = array( + "/<\?xml[^<]*>[^<]*<" . $prefix . "div[^<]*/", + "/<\/" . $prefix . "div>\s*$/" + ); + $xhtml = preg_replace($matches, '', $xhtml); + if (!empty($prefix)) { + $xhtml = preg_replace("/(<[\/]?)" . $prefix . "([a-zA-Z]+)/", '$1$2', $xhtml); + } + return $xhtml; + } + + /** + * Get the entry creation date + * + * @return string + */ + public function getDateCreated() + { + if (array_key_exists('datecreated', $this->data)) { + return $this->data['datecreated']; + } + + $date = null; + + if ($this->getAtomType() === Reader\Reader::TYPE_ATOM_03) { + $dateCreated = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:created)'); + } else { + $dateCreated = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:published)'); + } + + if ($dateCreated) { + $date = new DateTime($dateCreated); + } + + $this->data['datecreated'] = $date; + + return $this->data['datecreated']; + } + + /** + * Get the entry modification date + * + * @return string + */ + public function getDateModified() + { + if (array_key_exists('datemodified', $this->data)) { + return $this->data['datemodified']; + } + + $date = null; + + if ($this->getAtomType() === Reader\Reader::TYPE_ATOM_03) { + $dateModified = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:modified)'); + } else { + $dateModified = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:updated)'); + } + + if ($dateModified) { + $date = new DateTime($dateModified); + } + + $this->data['datemodified'] = $date; + + return $this->data['datemodified']; + } + + /** + * Get the entry description + * + * @return string + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:summary)'); + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the entry enclosure + * + * @return string + */ + public function getEnclosure() + { + if (array_key_exists('enclosure', $this->data)) { + return $this->data['enclosure']; + } + + $enclosure = null; + + $nodeList = $this->getXpath()->query($this->getXpathPrefix() . '/atom:link[@rel="enclosure"]'); + + if ($nodeList->length > 0) { + $enclosure = new stdClass(); + $enclosure->url = $nodeList->item(0)->getAttribute('href'); + $enclosure->length = $nodeList->item(0)->getAttribute('length'); + $enclosure->type = $nodeList->item(0)->getAttribute('type'); + } + + $this->data['enclosure'] = $enclosure; + + return $this->data['enclosure']; + } + + /** + * Get the entry ID + * + * @return string + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:id)'); + + if (!$id) { + if ($this->getPermalink()) { + $id = $this->getPermalink(); + } elseif ($this->getTitle()) { + $id = $this->getTitle(); + } else { + $id = null; + } + } + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get the base URI of the feed (if set). + * + * @return string|null + */ + public function getBaseUrl() + { + if (array_key_exists('baseUrl', $this->data)) { + return $this->data['baseUrl']; + } + + $baseUrl = $this->getXpath()->evaluate('string(' + . $this->getXpathPrefix() . '/@xml:base[1]' + . ')'); + + if (!$baseUrl) { + $baseUrl = $this->getXpath()->evaluate('string(//@xml:base[1])'); + } + + if (!$baseUrl) { + $baseUrl = null; + } + + $this->data['baseUrl'] = $baseUrl; + + return $this->data['baseUrl']; + } + + /** + * Get a specific link + * + * @param int $index + * @return string + */ + public function getLink($index = 0) + { + if (!array_key_exists('links', $this->data)) { + $this->getLinks(); + } + + if (isset($this->data['links'][$index])) { + return $this->data['links'][$index]; + } + + return null; + } + + /** + * Get all links + * + * @return array + */ + public function getLinks() + { + if (array_key_exists('links', $this->data)) { + return $this->data['links']; + } + + $links = array(); + + $list = $this->getXpath()->query( + $this->getXpathPrefix() . '//atom:link[@rel="alternate"]/@href' . '|' . + $this->getXpathPrefix() . '//atom:link[not(@rel)]/@href' + ); + + if ($list->length) { + foreach ($list as $link) { + $links[] = $this->absolutiseUri($link->value); + } + } + + $this->data['links'] = $links; + + return $this->data['links']; + } + + /** + * Get a permalink to the entry + * + * @return string + */ + public function getPermalink() + { + return $this->getLink(0); + } + + /** + * Get the entry title + * + * @return string + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:title)'); + + if (!$title) { + $title = null; + } + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * Get the number of comments/replies for current entry + * + * @return int + */ + public function getCommentCount() + { + if (array_key_exists('commentcount', $this->data)) { + return $this->data['commentcount']; + } + + $count = null; + + $this->getXpath()->registerNamespace('thread10', 'http://purl.org/syndication/thread/1.0'); + $list = $this->getXpath()->query( + $this->getXpathPrefix() . '//atom:link[@rel="replies"]/@thread10:count' + ); + + if ($list->length) { + $count = $list->item(0)->value; + } + + $this->data['commentcount'] = $count; + + return $this->data['commentcount']; + } + + /** + * Returns a URI pointing to the HTML page where comments can be made on this entry + * + * @return string + */ + public function getCommentLink() + { + if (array_key_exists('commentlink', $this->data)) { + return $this->data['commentlink']; + } + + $link = null; + + $list = $this->getXpath()->query( + $this->getXpathPrefix() . '//atom:link[@rel="replies" and @type="text/html"]/@href' + ); + + if ($list->length) { + $link = $list->item(0)->value; + $link = $this->absolutiseUri($link); + } + + $this->data['commentlink'] = $link; + + return $this->data['commentlink']; + } + + /** + * Returns a URI pointing to a feed of all comments for this entry + * + * @param string $type + * @return string + */ + public function getCommentFeedLink($type = 'atom') + { + if (array_key_exists('commentfeedlink', $this->data)) { + return $this->data['commentfeedlink']; + } + + $link = null; + + $list = $this->getXpath()->query( + $this->getXpathPrefix() . '//atom:link[@rel="replies" and @type="application/' . $type.'+xml"]/@href' + ); + + if ($list->length) { + $link = $list->item(0)->value; + $link = $this->absolutiseUri($link); + } + + $this->data['commentfeedlink'] = $link; + + return $this->data['commentfeedlink']; + } + + /** + * Get all categories + * + * @return Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + if ($this->getAtomType() == Reader\Reader::TYPE_ATOM_10) { + $list = $this->getXpath()->query($this->getXpathPrefix() . '//atom:category'); + } else { + /** + * Since Atom 0.3 did not support categories, it would have used the + * Dublin Core extension. However there is a small possibility Atom 0.3 + * may have been retrofitted to use Atom 1.0 instead. + */ + $this->getXpath()->registerNamespace('atom10', Reader\Reader::NAMESPACE_ATOM_10); + $list = $this->getXpath()->query($this->getXpathPrefix() . '//atom10:category'); + } + + if ($list->length) { + $categoryCollection = new Collection\Category; + foreach ($list as $category) { + $categoryCollection[] = array( + 'term' => $category->getAttribute('term'), + 'scheme' => $category->getAttribute('scheme'), + 'label' => $category->getAttribute('label') + ); + } + } else { + return new Collection\Category; + } + + $this->data['categories'] = $categoryCollection; + + return $this->data['categories']; + } + + /** + * Get source feed metadata from the entry + * + * @return Reader\Feed\Atom\Source|null + */ + public function getSource() + { + if (array_key_exists('source', $this->data)) { + return $this->data['source']; + } + + $source = null; + // TODO: Investigate why _getAtomType() fails here. Is it even needed? + if ($this->getType() == Reader\Reader::TYPE_ATOM_10) { + $list = $this->getXpath()->query($this->getXpathPrefix() . '/atom:source[1]'); + if ($list->length) { + $element = $list->item(0); + $source = new Reader\Feed\Atom\Source($element, $this->getXpathPrefix()); + } + } + + $this->data['source'] = $source; + return $this->data['source']; + } + + /** + * Attempt to absolutise the URI, i.e. if a relative URI apply the + * xml:base value as a prefix to turn into an absolute URI. + * + * @param $link + * @return string + */ + protected function absolutiseUri($link) + { + if (!Uri::factory($link)->isAbsolute()) { + if ($this->getBaseUrl() !== null) { + $link = $this->getBaseUrl() . $link; + if (!Uri::factory($link)->isValid()) { + $link = null; + } + } + } + return $link; + } + + /** + * Get an author entry + * + * @param DOMElement $element + * @return string + */ + protected function getAuthorFromElement(DOMElement $element) + { + $author = array(); + + $emailNode = $element->getElementsByTagName('email'); + $nameNode = $element->getElementsByTagName('name'); + $uriNode = $element->getElementsByTagName('uri'); + + if ($emailNode->length && strlen($emailNode->item(0)->nodeValue) > 0) { + $author['email'] = $emailNode->item(0)->nodeValue; + } + + if ($nameNode->length && strlen($nameNode->item(0)->nodeValue) > 0) { + $author['name'] = $nameNode->item(0)->nodeValue; + } + + if ($uriNode->length && strlen($uriNode->item(0)->nodeValue) > 0) { + $author['uri'] = $uriNode->item(0)->nodeValue; + } + + if (empty($author)) { + return null; + } + return $author; + } + + /** + * Register the default namespaces for the current feed format + */ + protected function registerNamespaces() + { + switch ($this->getAtomType()) { + case Reader\Reader::TYPE_ATOM_03: + $this->getXpath()->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_03); + break; + default: + $this->getXpath()->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_10); + break; + } + } + + /** + * Detect the presence of any Atom namespaces in use + * + * @return string + */ + protected function getAtomType() + { + $dom = $this->getDomDocument(); + $prefixAtom03 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_03); + $prefixAtom10 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_10); + if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_03) + || !empty($prefixAtom03)) { + return Reader\Reader::TYPE_ATOM_03; + } + if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_10) + || !empty($prefixAtom10)) { + return Reader\Reader::TYPE_ATOM_10; + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Atom/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Atom/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..83e9ccae7c894a9be9be9079716c9408cf9c2a37 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Atom/Feed.php @@ -0,0 +1,536 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Atom; + +use DateTime; +use DOMElement; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Collection; +use Zend\Feed\Reader\Extension; +use Zend\Feed\Uri; + +class Feed extends Extension\AbstractFeed +{ + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return Collection\Author + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $list = $this->xpath->query('//atom:author'); + + $authors = array(); + + if ($list->length) { + foreach ($list as $author) { + $author = $this->getAuthorFromElement($author); + if (!empty($author)) { + $authors[] = $author; + } + } + } + + if (count($authors) == 0) { + $authors = new Collection\Author(); + } else { + $authors = new Collection\Author( + Reader\Reader::arrayUnique($authors) + ); + } + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright() + { + if (array_key_exists('copyright', $this->data)) { + return $this->data['copyright']; + } + + $copyright = null; + + if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { + $copyright = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:copyright)'); + } else { + $copyright = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:rights)'); + } + + if (!$copyright) { + $copyright = null; + } + + $this->data['copyright'] = $copyright; + + return $this->data['copyright']; + } + + /** + * Get the feed creation date + * + * @return DateTime|null + */ + public function getDateCreated() + { + if (array_key_exists('datecreated', $this->data)) { + return $this->data['datecreated']; + } + + $date = null; + + if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { + $dateCreated = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:created)'); + } else { + $dateCreated = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:published)'); + } + + if ($dateCreated) { + $date = new DateTime($dateCreated); + } + + $this->data['datecreated'] = $date; + + return $this->data['datecreated']; + } + + /** + * Get the feed modification date + * + * @return DateTime|null + */ + public function getDateModified() + { + if (array_key_exists('datemodified', $this->data)) { + return $this->data['datemodified']; + } + + $date = null; + + if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { + $dateModified = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:modified)'); + } else { + $dateModified = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:updated)'); + } + + if ($dateModified) { + $date = new DateTime($dateModified); + } + + $this->data['datemodified'] = $date; + + return $this->data['datemodified']; + } + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = null; + + if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { + $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:tagline)'); + } else { + $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:subtitle)'); + } + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the feed generator entry + * + * @return string|null + */ + public function getGenerator() + { + if (array_key_exists('generator', $this->data)) { + return $this->data['generator']; + } + // TODO: Add uri support + $generator = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:generator)'); + + if (!$generator) { + $generator = null; + } + + $this->data['generator'] = $generator; + + return $this->data['generator']; + } + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:id)'); + + if (!$id) { + if ($this->getLink()) { + $id = $this->getLink(); + } elseif ($this->getTitle()) { + $id = $this->getTitle(); + } else { + $id = null; + } + } + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage() + { + if (array_key_exists('language', $this->data)) { + return $this->data['language']; + } + + $language = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:lang)'); + + if (!$language) { + $language = $this->xpath->evaluate('string(//@xml:lang[1])'); + } + + if (!$language) { + $language = null; + } + + $this->data['language'] = $language; + + return $this->data['language']; + } + + /** + * Get the feed image + * + * @return array|null + */ + public function getImage() + { + if (array_key_exists('image', $this->data)) { + return $this->data['image']; + } + + $imageUrl = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:logo)'); + + if (!$imageUrl) { + $image = null; + } else { + $image = array('uri' => $imageUrl); + } + + $this->data['image'] = $image; + + return $this->data['image']; + } + + /** + * Get the base URI of the feed (if set). + * + * @return string|null + */ + public function getBaseUrl() + { + if (array_key_exists('baseUrl', $this->data)) { + return $this->data['baseUrl']; + } + + $baseUrl = $this->xpath->evaluate('string(//@xml:base[1])'); + + if (!$baseUrl) { + $baseUrl = null; + } + $this->data['baseUrl'] = $baseUrl; + + return $this->data['baseUrl']; + } + + /** + * Get a link to the source website + * + * @return string|null + */ + public function getLink() + { + if (array_key_exists('link', $this->data)) { + return $this->data['link']; + } + + $link = null; + + $list = $this->xpath->query( + $this->getXpathPrefix() . '/atom:link[@rel="alternate"]/@href' . '|' . + $this->getXpathPrefix() . '/atom:link[not(@rel)]/@href' + ); + + if ($list->length) { + $link = $list->item(0)->nodeValue; + $link = $this->absolutiseUri($link); + } + + $this->data['link'] = $link; + + return $this->data['link']; + } + + /** + * Get a link to the feed's XML Url + * + * @return string|null + */ + public function getFeedLink() + { + if (array_key_exists('feedlink', $this->data)) { + return $this->data['feedlink']; + } + + $link = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:link[@rel="self"]/@href)'); + + $link = $this->absolutiseUri($link); + + $this->data['feedlink'] = $link; + + return $this->data['feedlink']; + } + + /** + * Get an array of any supported Pusubhubbub endpoints + * + * @return array|null + */ + public function getHubs() + { + if (array_key_exists('hubs', $this->data)) { + return $this->data['hubs']; + } + $hubs = array(); + + $list = $this->xpath->query($this->getXpathPrefix() + . '//atom:link[@rel="hub"]/@href'); + + if ($list->length) { + foreach ($list as $uri) { + $hubs[] = $this->absolutiseUri($uri->nodeValue); + } + } else { + $hubs = null; + } + + $this->data['hubs'] = $hubs; + + return $this->data['hubs']; + } + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:title)'); + + if (!$title) { + $title = null; + } + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * Get all categories + * + * @return Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + if ($this->getType() == Reader\Reader::TYPE_ATOM_10) { + $list = $this->xpath->query($this->getXpathPrefix() . '/atom:category'); + } else { + /** + * Since Atom 0.3 did not support categories, it would have used the + * Dublin Core extension. However there is a small possibility Atom 0.3 + * may have been retrofittied to use Atom 1.0 instead. + */ + $this->xpath->registerNamespace('atom10', Reader\Reader::NAMESPACE_ATOM_10); + $list = $this->xpath->query($this->getXpathPrefix() . '/atom10:category'); + } + + if ($list->length) { + $categoryCollection = new Collection\Category; + foreach ($list as $category) { + $categoryCollection[] = array( + 'term' => $category->getAttribute('term'), + 'scheme' => $category->getAttribute('scheme'), + 'label' => $category->getAttribute('label') + ); + } + } else { + return new Collection\Category; + } + + $this->data['categories'] = $categoryCollection; + + return $this->data['categories']; + } + + /** + * Get an author entry in RSS format + * + * @param DOMElement $element + * @return string + */ + protected function getAuthorFromElement(DOMElement $element) + { + $author = array(); + + $emailNode = $element->getElementsByTagName('email'); + $nameNode = $element->getElementsByTagName('name'); + $uriNode = $element->getElementsByTagName('uri'); + + if ($emailNode->length && strlen($emailNode->item(0)->nodeValue) > 0) { + $author['email'] = $emailNode->item(0)->nodeValue; + } + + if ($nameNode->length && strlen($nameNode->item(0)->nodeValue) > 0) { + $author['name'] = $nameNode->item(0)->nodeValue; + } + + if ($uriNode->length && strlen($uriNode->item(0)->nodeValue) > 0) { + $author['uri'] = $uriNode->item(0)->nodeValue; + } + + if (empty($author)) { + return null; + } + return $author; + } + + /** + * Attempt to absolutise the URI, i.e. if a relative URI apply the + * xml:base value as a prefix to turn into an absolute URI. + */ + protected function absolutiseUri($link) + { + if (!Uri::factory($link)->isAbsolute()) { + if ($this->getBaseUrl() !== null) { + $link = $this->getBaseUrl() . $link; + if (!Uri::factory($link)->isValid()) { + $link = null; + } + } + } + return $link; + } + + /** + * Register the default namespaces for the current feed format + */ + protected function registerNamespaces() + { + if ($this->getType() == Reader\Reader::TYPE_ATOM_10 + || $this->getType() == Reader\Reader::TYPE_ATOM_03 + ) { + return; // pre-registered at Feed level + } + $atomDetected = $this->getAtomType(); + switch ($atomDetected) { + case Reader\Reader::TYPE_ATOM_03: + $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_03); + break; + default: + $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_10); + break; + } + } + + /** + * Detect the presence of any Atom namespaces in use + */ + protected function getAtomType() + { + $dom = $this->getDomDocument(); + $prefixAtom03 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_03); + $prefixAtom10 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_10); + if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_10) + || !empty($prefixAtom10) + ) { + return Reader\Reader::TYPE_ATOM_10; + } + if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_03) + || !empty($prefixAtom03) + ) { + return Reader\Reader::TYPE_ATOM_03; + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Content/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Content/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..88fd850b25abf019c3874c93e50ccad2bb3b0f40 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Content/Entry.php @@ -0,0 +1,37 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Content; + +use Zend\Feed\Reader; +use Zend\Feed\Reader\Extension; + +class Entry extends Extension\AbstractEntry +{ + + public function getContent() + { + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $content = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/content:encoded)'); + } else { + $content = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/content:encoded)'); + } + return $content; + } + + /** + * Register RSS Content Module namespace + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..0352102c634d8f96e2857410260bcbb803578f20 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php @@ -0,0 +1,73 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\CreativeCommons; + +use Zend\Feed\Reader; +use Zend\Feed\Reader\Extension; + +class Entry extends Extension\AbstractEntry +{ + /** + * Get the entry license + * + * @param int $index + * @return string|null + */ + public function getLicense($index = 0) + { + $licenses = $this->getLicenses(); + + if (isset($licenses[$index])) { + return $licenses[$index]; + } + + return null; + } + + /** + * Get the entry licenses + * + * @return array + */ + public function getLicenses() + { + $name = 'licenses'; + if (array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + + $licenses = array(); + $list = $this->xpath->evaluate($this->getXpathPrefix() . '//cc:license'); + + if ($list->length) { + foreach ($list as $license) { + $licenses[] = $license->nodeValue; + } + + $licenses = array_unique($licenses); + } else { + $cc = new Feed(); + $licenses = $cc->getLicenses(); + } + + $this->data[$name] = $licenses; + + return $this->data[$name]; + } + + /** + * Register Creative Commons namespaces + * + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('cc', 'http://backend.userland.com/creativeCommonsRssModule'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..d2a50496078d959341f6315b7046ed5ce3e99a00 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php @@ -0,0 +1,71 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\CreativeCommons; + +use Zend\Feed\Reader; +use Zend\Feed\Reader\Extension; + +class Feed extends Extension\AbstractFeed +{ + /** + * Get the entry license + * + * @param int $index + * @return string|null + */ + public function getLicense($index = 0) + { + $licenses = $this->getLicenses(); + + if (isset($licenses[$index])) { + return $licenses[$index]; + } + + return null; + } + + /** + * Get the entry licenses + * + * @return array + */ + public function getLicenses() + { + $name = 'licenses'; + if (array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + + $licenses = array(); + $list = $this->xpath->evaluate('channel/cc:license'); + + if ($list->length) { + foreach ($list as $license) { + $licenses[] = $license->nodeValue; + } + + $licenses = array_unique($licenses); + } + + $this->data[$name] = $licenses; + + return $this->data[$name]; + } + + /** + * Register Creative Commons namespaces + * + * @return void + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('cc', 'http://backend.userland.com/creativeCommonsRssModule'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/DublinCore/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/DublinCore/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..7ec5304e953c83de628c1341a07f9dc34c1e3113 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/DublinCore/Entry.php @@ -0,0 +1,238 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\DublinCore; + +use DateTime; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Collection; +use Zend\Feed\Reader\Extension; + +class Entry extends Extension\AbstractEntry +{ + /** + * Get an author entry + * + * @param int $index + * @return string + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = array(); + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc11:creator'); + + if (!$list->length) { + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc10:creator'); + } + if (!$list->length) { + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc11:publisher'); + + if (!$list->length) { + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc10:publisher'); + } + } + + if ($list->length) { + foreach ($list as $author) { + $authors[] = array( + 'name' => $author->nodeValue + ); + } + $authors = new Collection\Author( + Reader\Reader::arrayUnique($authors) + ); + } else { + $authors = null; + } + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get categories (subjects under DC) + * + * @return Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc11:subject'); + + if (!$list->length) { + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc10:subject'); + } + + if ($list->length) { + $categoryCollection = new Collection\Category; + foreach ($list as $category) { + $categoryCollection[] = array( + 'term' => $category->nodeValue, + 'scheme' => null, + 'label' => $category->nodeValue, + ); + } + } else { + $categoryCollection = new Collection\Category; + } + + $this->data['categories'] = $categoryCollection; + return $this->data['categories']; + } + + + /** + * Get the entry content + * + * @return string + */ + public function getContent() + { + return $this->getDescription(); + } + + /** + * Get the entry description + * + * @return string + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = null; + $description = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:description)'); + + if (!$description) { + $description = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:description)'); + } + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the entry ID + * + * @return string + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = null; + $id = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:identifier)'); + + if (!$id) { + $id = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:identifier)'); + } + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get the entry title + * + * @return string + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = null; + $title = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:title)'); + + if (!$title) { + $title = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:title)'); + } + + if (!$title) { + $title = null; + } + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * + * + * @return DateTime|null + */ + public function getDate() + { + if (array_key_exists('date', $this->data)) { + return $this->data['date']; + } + + $d = null; + $date = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:date)'); + + if (!$date) { + $date = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:date)'); + } + + if ($date) { + $d = new DateTime($date); + } + + $this->data['date'] = $d; + + return $this->data['date']; + } + + /** + * Register DC namespaces + * + * @return void + */ + protected function registerNamespaces() + { + $this->getXpath()->registerNamespace('dc10', 'http://purl.org/dc/elements/1.0/'); + $this->getXpath()->registerNamespace('dc11', 'http://purl.org/dc/elements/1.1/'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/DublinCore/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/DublinCore/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..61959c4a06d83ff02be40d2821cbac1410c7cb97 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/DublinCore/Feed.php @@ -0,0 +1,281 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\DublinCore; + +use DateTime; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Collection; +use Zend\Feed\Reader\Extension; + +class Feed extends Extension\AbstractFeed +{ + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = array(); + $list = $this->getXpath()->query('//dc11:creator'); + + if (!$list->length) { + $list = $this->getXpath()->query('//dc10:creator'); + } + if (!$list->length) { + $list = $this->getXpath()->query('//dc11:publisher'); + + if (!$list->length) { + $list = $this->getXpath()->query('//dc10:publisher'); + } + } + + if ($list->length) { + foreach ($list as $author) { + $authors[] = array( + 'name' => $author->nodeValue + ); + } + $authors = new Collection\Author( + Reader\Reader::arrayUnique($authors) + ); + } else { + $authors = null; + } + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright() + { + if (array_key_exists('copyright', $this->data)) { + return $this->data['copyright']; + } + + $copyright = null; + $copyright = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:rights)'); + + if (!$copyright) { + $copyright = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:rights)'); + } + + if (!$copyright) { + $copyright = null; + } + + $this->data['copyright'] = $copyright; + + return $this->data['copyright']; + } + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = null; + $description = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:description)'); + + if (!$description) { + $description = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:description)'); + } + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = null; + $id = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:identifier)'); + + if (!$id) { + $id = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:identifier)'); + } + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage() + { + if (array_key_exists('language', $this->data)) { + return $this->data['language']; + } + + $language = null; + $language = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:language)'); + + if (!$language) { + $language = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:language)'); + } + + if (!$language) { + $language = null; + } + + $this->data['language'] = $language; + + return $this->data['language']; + } + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = null; + $title = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:title)'); + + if (!$title) { + $title = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:title)'); + } + + if (!$title) { + $title = null; + } + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * + * + * @return DateTime|null + */ + public function getDate() + { + if (array_key_exists('date', $this->data)) { + return $this->data['date']; + } + + $d = null; + $date = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc11:date)'); + + if (!$date) { + $date = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/dc10:date)'); + } + + if ($date) { + $d = new DateTime($date); + } + + $this->data['date'] = $d; + + return $this->data['date']; + } + + /** + * Get categories (subjects under DC) + * + * @return Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc11:subject'); + + if (!$list->length) { + $list = $this->getXpath()->evaluate($this->getXpathPrefix() . '//dc10:subject'); + } + + if ($list->length) { + $categoryCollection = new Collection\Category; + foreach ($list as $category) { + $categoryCollection[] = array( + 'term' => $category->nodeValue, + 'scheme' => null, + 'label' => $category->nodeValue, + ); + } + } else { + $categoryCollection = new Collection\Category; + } + + $this->data['categories'] = $categoryCollection; + return $this->data['categories']; + } + + /** + * Register the default namespaces for the current feed format + * + * @return void + */ + protected function registerNamespaces() + { + $this->getXpath()->registerNamespace('dc10', 'http://purl.org/dc/elements/1.0/'); + $this->getXpath()->registerNamespace('dc11', 'http://purl.org/dc/elements/1.1/'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Podcast/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Podcast/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..584fd375d2c96c9685f0ef5fe0327ea114813c47 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Podcast/Entry.php @@ -0,0 +1,180 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Podcast; + +use Zend\Feed\Reader\Extension; + +/** +*/ +class Entry extends Extension\AbstractEntry +{ + /** + * Get the entry author + * + * @return string + */ + public function getCastAuthor() + { + if (isset($this->data['author'])) { + return $this->data['author']; + } + + $author = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:author)'); + + if (!$author) { + $author = null; + } + + $this->data['author'] = $author; + + return $this->data['author']; + } + + /** + * Get the entry block + * + * @return string + */ + public function getBlock() + { + if (isset($this->data['block'])) { + return $this->data['block']; + } + + $block = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:block)'); + + if (!$block) { + $block = null; + } + + $this->data['block'] = $block; + + return $this->data['block']; + } + + /** + * Get the entry duration + * + * @return string + */ + public function getDuration() + { + if (isset($this->data['duration'])) { + return $this->data['duration']; + } + + $duration = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:duration)'); + + if (!$duration) { + $duration = null; + } + + $this->data['duration'] = $duration; + + return $this->data['duration']; + } + + /** + * Get the entry explicit + * + * @return string + */ + public function getExplicit() + { + if (isset($this->data['explicit'])) { + return $this->data['explicit']; + } + + $explicit = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:explicit)'); + + if (!$explicit) { + $explicit = null; + } + + $this->data['explicit'] = $explicit; + + return $this->data['explicit']; + } + + /** + * Get the entry keywords + * + * @return string + */ + public function getKeywords() + { + if (isset($this->data['keywords'])) { + return $this->data['keywords']; + } + + $keywords = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:keywords)'); + + if (!$keywords) { + $keywords = null; + } + + $this->data['keywords'] = $keywords; + + return $this->data['keywords']; + } + + /** + * Get the entry subtitle + * + * @return string + */ + public function getSubtitle() + { + if (isset($this->data['subtitle'])) { + return $this->data['subtitle']; + } + + $subtitle = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:subtitle)'); + + if (!$subtitle) { + $subtitle = null; + } + + $this->data['subtitle'] = $subtitle; + + return $this->data['subtitle']; + } + + /** + * Get the entry summary + * + * @return string + */ + public function getSummary() + { + if (isset($this->data['summary'])) { + return $this->data['summary']; + } + + $summary = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:summary)'); + + if (!$summary) { + $summary = null; + } + + $this->data['summary'] = $summary; + + return $this->data['summary']; + } + + /** + * Register iTunes namespace + * + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('itunes', 'http://www.itunes.com/dtds/podcast-1.0.dtd'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Podcast/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Podcast/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..b80bec9c31c22903de97100fbc4ed0cf7f1a86c7 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Podcast/Feed.php @@ -0,0 +1,277 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Podcast; + +use DOMText; +use Zend\Feed\Reader\Extension; + +/** +*/ +class Feed extends Extension\AbstractFeed +{ + /** + * Get the entry author + * + * @return string + */ + public function getCastAuthor() + { + if (isset($this->data['author'])) { + return $this->data['author']; + } + + $author = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:author)'); + + if (!$author) { + $author = null; + } + + $this->data['author'] = $author; + + return $this->data['author']; + } + + /** + * Get the entry block + * + * @return string + */ + public function getBlock() + { + if (isset($this->data['block'])) { + return $this->data['block']; + } + + $block = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:block)'); + + if (!$block) { + $block = null; + } + + $this->data['block'] = $block; + + return $this->data['block']; + } + + /** + * Get the entry category + * + * @return string + */ + public function getItunesCategories() + { + if (isset($this->data['categories'])) { + return $this->data['categories']; + } + + $categoryList = $this->xpath->query($this->getXpathPrefix() . '/itunes:category'); + + $categories = array(); + + if ($categoryList->length > 0) { + foreach ($categoryList as $node) { + $children = null; + + if ($node->childNodes->length > 0) { + $children = array(); + + foreach ($node->childNodes as $childNode) { + if (!($childNode instanceof DOMText)) { + $children[$childNode->getAttribute('text')] = null; + } + } + } + + $categories[$node->getAttribute('text')] = $children; + } + } + + + if (!$categories) { + $categories = null; + } + + $this->data['categories'] = $categories; + + return $this->data['categories']; + } + + /** + * Get the entry explicit + * + * @return string + */ + public function getExplicit() + { + if (isset($this->data['explicit'])) { + return $this->data['explicit']; + } + + $explicit = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:explicit)'); + + if (!$explicit) { + $explicit = null; + } + + $this->data['explicit'] = $explicit; + + return $this->data['explicit']; + } + + /** + * Get the entry image + * + * @return string + */ + public function getItunesImage() + { + if (isset($this->data['image'])) { + return $this->data['image']; + } + + $image = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:image/@href)'); + + if (!$image) { + $image = null; + } + + $this->data['image'] = $image; + + return $this->data['image']; + } + + /** + * Get the entry keywords + * + * @return string + */ + public function getKeywords() + { + if (isset($this->data['keywords'])) { + return $this->data['keywords']; + } + + $keywords = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:keywords)'); + + if (!$keywords) { + $keywords = null; + } + + $this->data['keywords'] = $keywords; + + return $this->data['keywords']; + } + + /** + * Get the entry's new feed url + * + * @return string + */ + public function getNewFeedUrl() + { + if (isset($this->data['new-feed-url'])) { + return $this->data['new-feed-url']; + } + + $newFeedUrl = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:new-feed-url)'); + + if (!$newFeedUrl) { + $newFeedUrl = null; + } + + $this->data['new-feed-url'] = $newFeedUrl; + + return $this->data['new-feed-url']; + } + + /** + * Get the entry owner + * + * @return string + */ + public function getOwner() + { + if (isset($this->data['owner'])) { + return $this->data['owner']; + } + + $owner = null; + + $email = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:owner/itunes:email)'); + $name = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:owner/itunes:name)'); + + if (!empty($email)) { + $owner = $email . (empty($name) ? '' : ' (' . $name . ')'); + } elseif (!empty($name)) { + $owner = $name; + } + + if (!$owner) { + $owner = null; + } + + $this->data['owner'] = $owner; + + return $this->data['owner']; + } + + /** + * Get the entry subtitle + * + * @return string + */ + public function getSubtitle() + { + if (isset($this->data['subtitle'])) { + return $this->data['subtitle']; + } + + $subtitle = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:subtitle)'); + + if (!$subtitle) { + $subtitle = null; + } + + $this->data['subtitle'] = $subtitle; + + return $this->data['subtitle']; + } + + /** + * Get the entry summary + * + * @return string + */ + public function getSummary() + { + if (isset($this->data['summary'])) { + return $this->data['summary']; + } + + $summary = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:summary)'); + + if (!$summary) { + $summary = null; + } + + $this->data['summary'] = $summary; + + return $this->data['summary']; + } + + /** + * Register iTunes namespace + * + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('itunes', 'http://www.itunes.com/dtds/podcast-1.0.dtd'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Slash/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Slash/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..abd7eda905af475e6cc8fe0d4b66ecb0f43b493a --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Slash/Entry.php @@ -0,0 +1,121 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Slash; + +use Zend\Feed\Reader\Extension; + +/** +*/ +class Entry extends Extension\AbstractEntry +{ + /** + * Get the entry section + * + * @return string|null + */ + public function getSection() + { + return $this->getData('section'); + } + + /** + * Get the entry department + * + * @return string|null + */ + public function getDepartment() + { + return $this->getData('department'); + } + + /** + * Get the entry hit_parade + * + * @return array + */ + public function getHitParade() + { + $name = 'hit_parade'; + + if (isset($this->data[$name])) { + return $this->data[$name]; + } + + $stringParade = $this->getData($name); + $hitParade = array(); + + if (!empty($stringParade)) { + $stringParade = explode(',', $stringParade); + + foreach ($stringParade as $hit) + $hitParade[] = $hit + 0; //cast to integer + } + + $this->data[$name] = $hitParade; + return $hitParade; + } + + /** + * Get the entry comments + * + * @return int + */ + public function getCommentCount() + { + $name = 'comments'; + + if (isset($this->data[$name])) { + return $this->data[$name]; + } + + $comments = $this->getData($name, 'string'); + + if (!$comments) { + $this->data[$name] = null; + return $this->data[$name]; + } + + return $comments; + } + + /** + * Get the entry data specified by name + * @param string $name + * @param string $type + * + * @return mixed|null + */ + protected function getData($name, $type = 'string') + { + if (array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + + $data = $this->xpath->evaluate($type . '(' . $this->getXpathPrefix() . '/slash10:' . $name . ')'); + + if (!$data) { + $data = null; + } + + $this->data[$name] = $data; + + return $data; + } + + /** + * Register Slash namespaces + * + * @return void + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('slash10', 'http://purl.org/rss/1.0/modules/slash/'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Syndication/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Syndication/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..75f031b2899ada37d4f62bd41faa9348eb5f8ed0 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Syndication/Feed.php @@ -0,0 +1,149 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Syndication; + +use DateTime; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Extension; + +class Feed extends \Zend\Feed\Reader\Extension\AbstractFeed +{ + /** + * Get update period + * + * @return string + * @throws Reader\Exception\InvalidArgumentException + */ + public function getUpdatePeriod() + { + $name = 'updatePeriod'; + $period = $this->_getData($name); + + if ($period === null) { + $this->data[$name] = 'daily'; + return 'daily'; //Default specified by spec + } + + switch ($period) { + case 'hourly': + case 'daily': + case 'weekly': + case 'yearly': + return $period; + default: + throw new Reader\Exception\InvalidArgumentException("Feed specified invalid update period: '$period'." + . " Must be one of hourly, daily, weekly or yearly" + ); + } + } + + /** + * Get update frequency + * @return int + */ + public function getUpdateFrequency() + { + $name = 'updateFrequency'; + $freq = $this->_getData($name, 'number'); + + if (!$freq || $freq < 1) { + $this->data[$name] = 1; + return 1; + } + + return $freq; + } + + /** + * Get update frequency as ticks + * @return int + */ + public function getUpdateFrequencyAsTicks() + { + $name = 'updateFrequency'; + $freq = $this->_getData($name, 'number'); + + if (!$freq || $freq < 1) { + $this->data[$name] = 1; + $freq = 1; + } + + $period = $this->getUpdatePeriod(); + $ticks = 1; + + switch ($period) { + case 'yearly': + $ticks *= 52; //TODO: fix generalisation, how? + // no break + case 'weekly': + $ticks *= 7; + // no break + case 'daily': + $ticks *= 24; + // no break + case 'hourly': + $ticks *= 3600; + break; + default: //Never arrive here, exception thrown in getPeriod() + break; + } + + return $ticks / $freq; + } + + /** + * Get update base + * + * @return DateTime|null + */ + public function getUpdateBase() + { + $updateBase = $this->_getData('updateBase'); + $date = null; + if ($updateBase) { + $date = DateTime::createFromFormat(DateTime::W3C, $updateBase); + } + return $date; + } + + /** + * Get the entry data specified by name + * + * @param string $name + * @param string $type + * @return mixed|null + */ + private function _getData($name, $type = 'string') + { + if (array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + + $data = $this->xpath->evaluate($type . '(' . $this->getXpathPrefix() . '/syn10:' . $name . ')'); + + if (!$data) { + $data = null; + } + + $this->data[$name] = $data; + + return $data; + } + + /** + * Register Syndication namespaces + * + * @return void + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('syn10', 'http://purl.org/rss/1.0/modules/syndication/'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Thread/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Thread/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..ceaee85bd573a608fbef486a30aeae76fd401f92 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/Thread/Entry.php @@ -0,0 +1,72 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\Thread; + +use Zend\Feed\Reader\Extension; + +/** +*/ +class Entry extends Extension\AbstractEntry +{ + /** + * Get the "in-reply-to" value + * + * @return string + */ + public function getInReplyTo() + { + // TODO: to be implemented + } + + // TODO: Implement "replies" and "updated" constructs from standard + + /** + * Get the total number of threaded responses (i.e comments) + * + * @return int|null + */ + public function getCommentCount() + { + return $this->getData('total'); + } + + /** + * Get the entry data specified by name + * + * @param string $name + * @return mixed|null + */ + protected function getData($name) + { + if (array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + + $data = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/thread10:' . $name . ')'); + + if (!$data) { + $data = null; + } + + $this->data[$name] = $data; + + return $data; + } + + /** + * Register Atom Thread Extension 1.0 namespace + * + * @return void + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('thread10', 'http://purl.org/syndication/thread/1.0'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..cc52bc9088cf8b75db29a728f62f961cdf5c58ef --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php @@ -0,0 +1,50 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Extension\WellFormedWeb; + +use Zend\Feed\Reader\Extension; + +/** +*/ +class Entry extends Extension\AbstractEntry +{ + /** + * Get the entry comment Uri + * + * @return string|null + */ + public function getCommentFeedLink() + { + $name = 'commentRss'; + if (array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + + $data = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/wfw:' . $name . ')'); + + if (!$data) { + $data = null; + } + + $this->data[$name] = $data; + + return $data; + } + + /** + * Register Slash namespaces + * + * @return void + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('wfw', 'http://wellformedweb.org/CommentAPI/'); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionManager.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionManager.php new file mode 100644 index 0000000000000000000000000000000000000000..b6fa68db51096ac3d3611964205ea1590ddd5603 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionManager.php @@ -0,0 +1,80 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +/** + * Default implementation of ExtensionManagerInterface + * + * Decorator of ExtensionPluginManager. + */ +class ExtensionManager implements ExtensionManagerInterface +{ + protected $pluginManager; + + /** + * Constructor + * + * Seeds the extension manager with a plugin manager; if none provided, + * creates an instance. + * + * @param null|ExtensionPluginManager $pluginManager + */ + public function __construct(ExtensionPluginManager $pluginManager = null) + { + if (null === $pluginManager) { + $pluginManager = new ExtensionPluginManager(); + } + $this->pluginManager = $pluginManager; + } + + /** + * Method overloading + * + * Proxy to composed ExtensionPluginManager instance. + * + * @param string $method + * @param array $args + * @return mixed + * @throws Exception\BadMethodCallException + */ + public function __call($method, $args) + { + if (!method_exists($this->pluginManager, $method)) { + throw new Exception\BadMethodCallException(sprintf( + 'Method by name of %s does not exist in %s', + $method, + __CLASS__ + )); + } + return call_user_func_array(array($this->pluginManager, $method), $args); + } + + /** + * Get the named extension + * + * @param string $name + * @return Extension\AbstractEntry|Extension\AbstractFeed + */ + public function get($name) + { + return $this->pluginManager->get($name); + } + + /** + * Do we have the named extension? + * + * @param string $name + * @return bool + */ + public function has($name) + { + return $this->pluginManager->has($name); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionManagerInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6ae9b6798e1f2e94c2f135c9069281e5b92d3479 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionManagerInterface.php @@ -0,0 +1,29 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +interface ExtensionManagerInterface +{ + /** + * Do we have the extension? + * + * @param string $extension + * @return bool + */ + public function has($extension); + + /** + * Retrieve the extension + * + * @param string $extension + * @return mixed + */ + public function get($extension); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionPluginManager.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionPluginManager.php new file mode 100644 index 0000000000000000000000000000000000000000..8222ee2c1c6c578733e125b86a8dd92e68ad4e74 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/ExtensionPluginManager.php @@ -0,0 +1,77 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +use Zend\ServiceManager\AbstractPluginManager; + +/** + * Plugin manager implementation for feed reader extensions based on the + * AbstractPluginManager. + * + * Validation checks that we have an Extension\AbstractEntry or + * Extension\AbstractFeed. + */ +class ExtensionPluginManager extends AbstractPluginManager +{ + /** + * Default set of extension classes + * + * @var array + */ + protected $invokableClasses = array( + 'atomentry' => 'Zend\Feed\Reader\Extension\Atom\Entry', + 'atomfeed' => 'Zend\Feed\Reader\Extension\Atom\Feed', + 'contententry' => 'Zend\Feed\Reader\Extension\Content\Entry', + 'creativecommonsentry' => 'Zend\Feed\Reader\Extension\CreativeCommons\Entry', + 'creativecommonsfeed' => 'Zend\Feed\Reader\Extension\CreativeCommons\Feed', + 'dublincoreentry' => 'Zend\Feed\Reader\Extension\DublinCore\Entry', + 'dublincorefeed' => 'Zend\Feed\Reader\Extension\DublinCore\Feed', + 'podcastentry' => 'Zend\Feed\Reader\Extension\Podcast\Entry', + 'podcastfeed' => 'Zend\Feed\Reader\Extension\Podcast\Feed', + 'slashentry' => 'Zend\Feed\Reader\Extension\Slash\Entry', + 'syndicationfeed' => 'Zend\Feed\Reader\Extension\Syndication\Feed', + 'threadentry' => 'Zend\Feed\Reader\Extension\Thread\Entry', + 'wellformedwebentry' => 'Zend\Feed\Reader\Extension\WellFormedWeb\Entry', + ); + + /** + * Do not share instances + * + * @var bool + */ + protected $shareByDefault = false; + + /** + * Validate the plugin + * + * Checks that the extension loaded is of a valid type. + * + * @param mixed $plugin + * @return void + * @throws Exception\InvalidArgumentException if invalid + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof Extension\AbstractEntry + || $plugin instanceof Extension\AbstractFeed + ) { + // we're okay + return; + } + + throw new Exception\InvalidArgumentException(sprintf( + 'Plugin of type %s is invalid; must implement %s\Extension\AbstractFeed ' + . 'or %s\Extension\AbstractEntry', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + __NAMESPACE__, + __NAMESPACE__ + )); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/AbstractFeed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/AbstractFeed.php new file mode 100644 index 0000000000000000000000000000000000000000..643818405c279ceaf9304f6a411fa3d3dbba964e --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/AbstractFeed.php @@ -0,0 +1,307 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use DOMDocument; +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Exception; + +/** +*/ +abstract class AbstractFeed implements FeedInterface +{ + /** + * Parsed feed data + * + * @var array + */ + protected $data = array(); + + /** + * Parsed feed data in the shape of a DOMDocument + * + * @var DOMDocument + */ + protected $domDocument = null; + + /** + * An array of parsed feed entries + * + * @var array + */ + protected $entries = array(); + + /** + * A pointer for the iterator to keep track of the entries array + * + * @var int + */ + protected $entriesKey = 0; + + /** + * The base XPath query used to retrieve feed data + * + * @var DOMXPath + */ + protected $xpath = null; + + /** + * Array of loaded extensions + * + * @var array + */ + protected $extensions = array(); + + /** + * Original Source URI (set if imported from a URI) + * + * @var string + */ + protected $originalSourceUri = null; + + /** + * Constructor + * + * @param DOMDocument $domDocument The DOM object for the feed's XML + * @param string $type Feed type + */ + public function __construct(DOMDocument $domDocument, $type = null) + { + $this->domDocument = $domDocument; + $this->xpath = new DOMXPath($this->domDocument); + + if ($type !== null) { + $this->data['type'] = $type; + } else { + $this->data['type'] = Reader\Reader::detectType($this->domDocument); + } + $this->registerNamespaces(); + $this->indexEntries(); + $this->loadExtensions(); + } + + /** + * Set an original source URI for the feed being parsed. This value + * is returned from getFeedLink() method if the feed does not carry + * a self-referencing URI. + * + * @param string $uri + */ + public function setOriginalSourceUri($uri) + { + $this->originalSourceUri = $uri; + } + + /** + * Get an original source URI for the feed being parsed. Returns null if + * unset or the feed was not imported from a URI. + * + * @return string|null + */ + public function getOriginalSourceUri() + { + return $this->originalSourceUri; + } + + /** + * Get the number of feed entries. + * Required by the Iterator interface. + * + * @return int + */ + public function count() + { + return count($this->entries); + } + + /** + * Return the current entry + * + * @return \Zend\Feed\Reader\Entry\EntryInterface + */ + public function current() + { + if (substr($this->getType(), 0, 3) == 'rss') { + $reader = new Reader\Entry\Rss($this->entries[$this->key()], $this->key(), $this->getType()); + } else { + $reader = new Reader\Entry\Atom($this->entries[$this->key()], $this->key(), $this->getType()); + } + + $reader->setXpath($this->xpath); + + return $reader; + } + + /** + * Get the DOM + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->domDocument; + } + + /** + * Get the Feed's encoding + * + * @return string + */ + public function getEncoding() + { + $assumed = $this->getDomDocument()->encoding; + if (empty($assumed)) { + $assumed = 'UTF-8'; + } + return $assumed; + } + + /** + * Get feed as xml + * + * @return string + */ + public function saveXml() + { + return $this->getDomDocument()->saveXml(); + } + + /** + * Get the DOMElement representing the items/feed element + * + * @return DOMElement + */ + public function getElement() + { + return $this->getDomDocument()->documentElement; + } + + /** + * Get the DOMXPath object for this feed + * + * @return DOMXPath + */ + public function getXpath() + { + return $this->xpath; + } + + /** + * Get the feed type + * + * @return string + */ + public function getType() + { + return $this->data['type']; + } + + /** + * Return the current feed key + * + * @return int + */ + public function key() + { + return $this->entriesKey; + } + + /** + * Move the feed pointer forward + * + */ + public function next() + { + ++$this->entriesKey; + } + + /** + * Reset the pointer in the feed object + * + */ + public function rewind() + { + $this->entriesKey = 0; + } + + /** + * Check to see if the iterator is still valid + * + * @return bool + */ + public function valid() + { + return 0 <= $this->entriesKey && $this->entriesKey < $this->count(); + } + + public function getExtensions() + { + return $this->extensions; + } + + public function __call($method, $args) + { + foreach ($this->extensions as $extension) { + if (method_exists($extension, $method)) { + return call_user_func_array(array($extension, $method), $args); + } + } + throw new Exception\BadMethodCallException('Method: ' . $method + . 'does not exist and could not be located on a registered Extension'); + } + + /** + * Return an Extension object with the matching name (postfixed with _Feed) + * + * @param string $name + * @return \Zend\Feed\Reader\Extension\AbstractFeed + */ + public function getExtension($name) + { + if (array_key_exists($name . '\\Feed', $this->extensions)) { + return $this->extensions[$name . '\\Feed']; + } + return null; + } + + protected function loadExtensions() + { + $all = Reader\Reader::getExtensions(); + $manager = Reader\Reader::getExtensionManager(); + $feed = $all['feed']; + foreach ($feed as $extension) { + if (in_array($extension, $all['core'])) { + continue; + } + if (!$manager->has($extension)) { + throw new Exception\RuntimeException(sprintf('Unable to load extension "%s"; cannot find class', $extension)); + } + $plugin = $manager->get($extension); + $plugin->setDomDocument($this->getDomDocument()); + $plugin->setType($this->data['type']); + $plugin->setXpath($this->xpath); + $this->extensions[$extension] = $plugin; + } + } + + /** + * Read all entries to the internal entries array + * + */ + abstract protected function indexEntries(); + + /** + * Register the default namespaces for the current feed format + * + */ + abstract protected function registerNamespaces(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Atom.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Atom.php new file mode 100644 index 0000000000000000000000000000000000000000..cc3943854111abeaec0575da50727d25f85568b2 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Atom.php @@ -0,0 +1,410 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use DOMDocument; +use Zend\Feed\Reader; + +/** +*/ +class Atom extends AbstractFeed +{ + + /** + * Constructor + * + * @param DOMDocument $dom + * @param string $type + */ + public function __construct(DOMDocument $dom, $type = null) + { + parent::__construct($dom, $type); + $manager = Reader\Reader::getExtensionManager(); + + $atomFeed = $manager->get('Atom\Feed'); + $atomFeed->setDomDocument($dom); + $atomFeed->setType($this->data['type']); + $atomFeed->setXpath($this->xpath); + $this->extensions['Atom\\Feed'] = $atomFeed; + + $atomFeed = $manager->get('DublinCore\Feed'); + $atomFeed->setDomDocument($dom); + $atomFeed->setType($this->data['type']); + $atomFeed->setXpath($this->xpath); + $this->extensions['DublinCore\\Feed'] = $atomFeed; + + foreach ($this->extensions as $extension) { + $extension->setXpathPrefix('/atom:feed'); + } + } + + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = $this->getExtension('Atom')->getAuthors(); + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright() + { + if (array_key_exists('copyright', $this->data)) { + return $this->data['copyright']; + } + + $copyright = $this->getExtension('Atom')->getCopyright(); + + if (!$copyright) { + $copyright = null; + } + + $this->data['copyright'] = $copyright; + + return $this->data['copyright']; + } + + /** + * Get the feed creation date + * + * @return string|null + */ + public function getDateCreated() + { + if (array_key_exists('datecreated', $this->data)) { + return $this->data['datecreated']; + } + + $dateCreated = $this->getExtension('Atom')->getDateCreated(); + + if (!$dateCreated) { + $dateCreated = null; + } + + $this->data['datecreated'] = $dateCreated; + + return $this->data['datecreated']; + } + + /** + * Get the feed modification date + * + * @return string|null + */ + public function getDateModified() + { + if (array_key_exists('datemodified', $this->data)) { + return $this->data['datemodified']; + } + + $dateModified = $this->getExtension('Atom')->getDateModified(); + + if (!$dateModified) { + $dateModified = null; + } + + $this->data['datemodified'] = $dateModified; + + return $this->data['datemodified']; + } + + /** + * Get the feed lastBuild date. This is not implemented in Atom. + * + * @return string|null + */ + public function getLastBuildDate() + { + return null; + } + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = $this->getExtension('Atom')->getDescription(); + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the feed generator entry + * + * @return string|null + */ + public function getGenerator() + { + if (array_key_exists('generator', $this->data)) { + return $this->data['generator']; + } + + $generator = $this->getExtension('Atom')->getGenerator(); + + $this->data['generator'] = $generator; + + return $this->data['generator']; + } + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = $this->getExtension('Atom')->getId(); + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage() + { + if (array_key_exists('language', $this->data)) { + return $this->data['language']; + } + + $language = $this->getExtension('Atom')->getLanguage(); + + if (!$language) { + $language = $this->xpath->evaluate('string(//@xml:lang[1])'); + } + + if (!$language) { + $language = null; + } + + $this->data['language'] = $language; + + return $this->data['language']; + } + + /** + * Get a link to the source website + * + * @return string|null + */ + public function getBaseUrl() + { + if (array_key_exists('baseUrl', $this->data)) { + return $this->data['baseUrl']; + } + + $baseUrl = $this->getExtension('Atom')->getBaseUrl(); + + $this->data['baseUrl'] = $baseUrl; + + return $this->data['baseUrl']; + } + + /** + * Get a link to the source website + * + * @return string|null + */ + public function getLink() + { + if (array_key_exists('link', $this->data)) { + return $this->data['link']; + } + + $link = $this->getExtension('Atom')->getLink(); + + $this->data['link'] = $link; + + return $this->data['link']; + } + + /** + * Get feed image data + * + * @return array|null + */ + public function getImage() + { + if (array_key_exists('image', $this->data)) { + return $this->data['image']; + } + + $link = $this->getExtension('Atom')->getImage(); + + $this->data['image'] = $link; + + return $this->data['image']; + } + + /** + * Get a link to the feed's XML Url + * + * @return string|null + */ + public function getFeedLink() + { + if (array_key_exists('feedlink', $this->data)) { + return $this->data['feedlink']; + } + + $link = $this->getExtension('Atom')->getFeedLink(); + + if ($link === null || empty($link)) { + $link = $this->getOriginalSourceUri(); + } + + $this->data['feedlink'] = $link; + + return $this->data['feedlink']; + } + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = $this->getExtension('Atom')->getTitle(); + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * Get an array of any supported Pusubhubbub endpoints + * + * @return array|null + */ + public function getHubs() + { + if (array_key_exists('hubs', $this->data)) { + return $this->data['hubs']; + } + + $hubs = $this->getExtension('Atom')->getHubs(); + + $this->data['hubs'] = $hubs; + + return $this->data['hubs']; + } + + /** + * Get all categories + * + * @return Reader\Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + $categoryCollection = $this->getExtension('Atom')->getCategories(); + + if (count($categoryCollection) == 0) { + $categoryCollection = $this->getExtension('DublinCore')->getCategories(); + } + + $this->data['categories'] = $categoryCollection; + + return $this->data['categories']; + } + + /** + * Read all entries to the internal entries array + * + * @return void + */ + protected function indexEntries() + { + if ($this->getType() == Reader\Reader::TYPE_ATOM_10 || + $this->getType() == Reader\Reader::TYPE_ATOM_03) { + $entries = array(); + $entries = $this->xpath->evaluate('//atom:entry'); + + foreach ($entries as $index => $entry) { + $this->entries[$index] = $entry; + } + } + } + + /** + * Register the default namespaces for the current feed format + * + */ + protected function registerNamespaces() + { + switch ($this->data['type']) { + case Reader\Reader::TYPE_ATOM_03: + $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_03); + break; + case Reader\Reader::TYPE_ATOM_10: + default: + $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_10); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Atom/Source.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Atom/Source.php new file mode 100644 index 0000000000000000000000000000000000000000..3055dc3215f7575c084fdbc5402e6a91a715e223 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Atom/Source.php @@ -0,0 +1,94 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed\Atom; + +use DOMElement; +use DOMXPath; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Feed; + +/** +*/ +class Source extends Feed\Atom +{ + + /** + * Constructor: Create a Source object which is largely just a normal + * Zend\Feed\Reader\AbstractFeed object only designed to retrieve feed level + * metadata from an Atom entry's source element. + * + * @param DOMElement $source + * @param string $xpathPrefix Passed from parent Entry object + * @param string $type Nearly always Atom 1.0 + */ + public function __construct(DOMElement $source, $xpathPrefix, $type = Reader\Reader::TYPE_ATOM_10) + { + $this->domDocument = $source->ownerDocument; + $this->xpath = new DOMXPath($this->domDocument); + $this->data['type'] = $type; + $this->registerNamespaces(); + $this->loadExtensions(); + + $manager = Reader\Reader::getExtensionManager(); + $extensions = array('Atom\Feed', 'DublinCore\Feed'); + + foreach ($extensions as $name) { + $extension = $manager->get($name); + $extension->setDomDocument($this->domDocument); + $extension->setType($this->data['type']); + $extension->setXpath($this->xpath); + $this->extensions[$name] = $extension; + } + + foreach ($this->extensions as $extension) { + $extension->setXpathPrefix(rtrim($xpathPrefix, '/') . '/atom:source'); + } + } + + /** + * Since this is not an Entry carrier but a vehicle for Feed metadata, any + * applicable Entry methods are stubbed out and do nothing. + */ + + /** + * @return void + */ + public function count() {} + + /** + * @return void + */ + public function current() {} + + /** + * @return void + */ + public function key() {} + + /** + * @return void + */ + public function next() {} + + /** + * @return void + */ + public function rewind() {} + + /** + * @return void + */ + public function valid() {} + + /** + * @return void + */ + protected function indexEntries() {} +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/FeedInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/FeedInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c66bb7bff2729032dc6390f7f825c1a2c73a1872 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/FeedInterface.php @@ -0,0 +1,111 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use Countable; +use Iterator; + +/** +*/ +interface FeedInterface extends Iterator, Countable +{ + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0); + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors(); + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright(); + + /** + * Get the feed creation date + * + * @return string|null + */ + public function getDateCreated(); + + /** + * Get the feed modification date + * + * @return string|null + */ + public function getDateModified(); + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription(); + + /** + * Get the feed generator entry + * + * @return string|null + */ + public function getGenerator(); + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId(); + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage(); + + /** + * Get a link to the HTML source + * + * @return string|null + */ + public function getLink(); + + /** + * Get a link to the XML feed + * + * @return string|null + */ + public function getFeedLink(); + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle(); + + /** + * Get all categories + * + * @return \Zend\Feed\Reader\Collection\Category + */ + public function getCategories(); + +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Rss.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Rss.php new file mode 100644 index 0000000000000000000000000000000000000000..61ce229ba442b322fe41db83579367595bc3f400 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Feed/Rss.php @@ -0,0 +1,709 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Feed; + +use DateTime; +use DOMDocument; +use Zend\Feed\Reader; +use Zend\Feed\Reader\Collection; +use Zend\Feed\Reader\Exception; + +/** +*/ +class Rss extends AbstractFeed +{ + + /** + * Constructor + * + * @param DOMDocument $dom + * @param string $type + */ + public function __construct(DOMDocument $dom, $type = null) + { + parent::__construct($dom, $type); + + $manager = Reader\Reader::getExtensionManager(); + + $feed = $manager->get('DublinCore\Feed'); + $feed->setDomDocument($dom); + $feed->setType($this->data['type']); + $feed->setXpath($this->xpath); + $this->extensions['DublinCore\Feed'] = $feed; + + $feed = $manager->get('Atom\Feed'); + $feed->setDomDocument($dom); + $feed->setType($this->data['type']); + $feed->setXpath($this->xpath); + $this->extensions['Atom\Feed'] = $feed; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090 + ) { + $xpathPrefix = '/rss/channel'; + } else { + $xpathPrefix = '/rdf:RDF/rss:channel'; + } + foreach ($this->extensions as $extension) { + $extension->setXpathPrefix($xpathPrefix); + } + } + + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + $authors = $this->getAuthors(); + + if (isset($authors[$index])) { + return $authors[$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (array_key_exists('authors', $this->data)) { + return $this->data['authors']; + } + + $authors = array(); + $authorsDc = $this->getExtension('DublinCore')->getAuthors(); + if (!empty($authorsDc)) { + foreach ($authorsDc as $author) { + $authors[] = array( + 'name' => $author['name'] + ); + } + } + + /** + * Technically RSS doesn't specific author element use at the feed level + * but it's supported on a "just in case" basis. + */ + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 + && $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $list = $this->xpath->query('//author'); + } else { + $list = $this->xpath->query('//rss:author'); + } + if ($list->length) { + foreach ($list as $author) { + $string = trim($author->nodeValue); + $email = null; + $name = null; + $data = array(); + // Pretty rough parsing - but it's a catchall + if (preg_match("/^.*@[^ ]*/", $string, $matches)) { + $data['email'] = trim($matches[0]); + if (preg_match("/\((.*)\)$/", $string, $matches)) { + $data['name'] = $matches[1]; + } + $authors[] = $data; + } + } + } + + if (count($authors) == 0) { + $authors = $this->getExtension('Atom')->getAuthors(); + } else { + $authors = new Reader\Collection\Author( + Reader\Reader::arrayUnique($authors) + ); + } + + if (count($authors) == 0) { + $authors = null; + } + + $this->data['authors'] = $authors; + + return $this->data['authors']; + } + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright() + { + if (array_key_exists('copyright', $this->data)) { + return $this->data['copyright']; + } + + $copyright = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $copyright = $this->xpath->evaluate('string(/rss/channel/copyright)'); + } + + if (!$copyright && $this->getExtension('DublinCore') !== null) { + $copyright = $this->getExtension('DublinCore')->getCopyright(); + } + + if (empty($copyright)) { + $copyright = $this->getExtension('Atom')->getCopyright(); + } + + if (!$copyright) { + $copyright = null; + } + + $this->data['copyright'] = $copyright; + + return $this->data['copyright']; + } + + /** + * Get the feed creation date + * + * @return string|null + */ + public function getDateCreated() + { + return $this->getDateModified(); + } + + /** + * Get the feed modification date + * + * @return DateTime + * @throws Exception\RuntimeException + */ + public function getDateModified() + { + if (array_key_exists('datemodified', $this->data)) { + return $this->data['datemodified']; + } + + $dateModified = null; + $date = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $dateModified = $this->xpath->evaluate('string(/rss/channel/pubDate)'); + if (!$dateModified) { + $dateModified = $this->xpath->evaluate('string(/rss/channel/lastBuildDate)'); + } + if ($dateModified) { + $dateModifiedParsed = strtotime($dateModified); + if ($dateModifiedParsed) { + $date = new DateTime('@' . $dateModifiedParsed); + } else { + $dateStandards = array(DateTime::RSS, DateTime::RFC822, + DateTime::RFC2822, null); + foreach ($dateStandards as $standard) { + try { + $date = DateTime::createFromFormat($standard, $dateModified); + break; + } catch (\Exception $e) { + if ($standard == null) { + throw new Exception\RuntimeException( + 'Could not load date due to unrecognised' + .' format (should follow RFC 822 or 2822):' + . $e->getMessage(), + 0, $e + ); + } + } + } + } + } + } + + if (!$date) { + $date = $this->getExtension('DublinCore')->getDate(); + } + + if (!$date) { + $date = $this->getExtension('Atom')->getDateModified(); + } + + if (!$date) { + $date = null; + } + + $this->data['datemodified'] = $date; + + return $this->data['datemodified']; + } + + /** + * Get the feed lastBuild date + * + * @throws Exception\RuntimeException + * @return DateTime + */ + public function getLastBuildDate() + { + if (array_key_exists('lastBuildDate', $this->data)) { + return $this->data['lastBuildDate']; + } + + $lastBuildDate = null; + $date = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $lastBuildDate = $this->xpath->evaluate('string(/rss/channel/lastBuildDate)'); + if ($lastBuildDate) { + $lastBuildDateParsed = strtotime($lastBuildDate); + if ($lastBuildDateParsed) { + $date = new DateTime('@' . $lastBuildDateParsed); + } else { + $dateStandards = array(DateTime::RSS, DateTime::RFC822, + DateTime::RFC2822, null); + foreach ($dateStandards as $standard) { + try { + $date = DateTime::createFromFormat($standard, $lastBuildDateParsed); + break; + } catch (\Exception $e) { + if ($standard == null) { + throw new Exception\RuntimeException( + 'Could not load date due to unrecognised' + .' format (should follow RFC 822 or 2822):' + . $e->getMessage(), + 0, $e + ); + } + } + } + } + } + } + + if (!$date) { + $date = null; + } + + $this->data['lastBuildDate'] = $date; + + return $this->data['lastBuildDate']; + } + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription() + { + if (array_key_exists('description', $this->data)) { + return $this->data['description']; + } + + $description = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $description = $this->xpath->evaluate('string(/rss/channel/description)'); + } else { + $description = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/rss:description)'); + } + + if (!$description && $this->getExtension('DublinCore') !== null) { + $description = $this->getExtension('DublinCore')->getDescription(); + } + + if (empty($description)) { + $description = $this->getExtension('Atom')->getDescription(); + } + + if (!$description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId() + { + if (array_key_exists('id', $this->data)) { + return $this->data['id']; + } + + $id = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $id = $this->xpath->evaluate('string(/rss/channel/guid)'); + } + + if (!$id && $this->getExtension('DublinCore') !== null) { + $id = $this->getExtension('DublinCore')->getId(); + } + + if (empty($id)) { + $id = $this->getExtension('Atom')->getId(); + } + + if (!$id) { + if ($this->getLink()) { + $id = $this->getLink(); + } elseif ($this->getTitle()) { + $id = $this->getTitle(); + } else { + $id = null; + } + } + + $this->data['id'] = $id; + + return $this->data['id']; + } + + /** + * Get the feed image data + * + * @return array|null + */ + public function getImage() + { + if (array_key_exists('image', $this->data)) { + return $this->data['image']; + } + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $list = $this->xpath->query('/rss/channel/image'); + $prefix = '/rss/channel/image[1]'; + } else { + $list = $this->xpath->query('/rdf:RDF/rss:channel/rss:image'); + $prefix = '/rdf:RDF/rss:channel/rss:image[1]'; + } + if ($list->length > 0) { + $image = array(); + $value = $this->xpath->evaluate('string(' . $prefix . '/url)'); + if ($value) { + $image['uri'] = $value; + } + $value = $this->xpath->evaluate('string(' . $prefix . '/link)'); + if ($value) { + $image['link'] = $value; + } + $value = $this->xpath->evaluate('string(' . $prefix . '/title)'); + if ($value) { + $image['title'] = $value; + } + $value = $this->xpath->evaluate('string(' . $prefix . '/height)'); + if ($value) { + $image['height'] = $value; + } + $value = $this->xpath->evaluate('string(' . $prefix . '/width)'); + if ($value) { + $image['width'] = $value; + } + $value = $this->xpath->evaluate('string(' . $prefix . '/description)'); + if ($value) { + $image['description'] = $value; + } + } else { + $image = null; + } + + $this->data['image'] = $image; + + return $this->data['image']; + } + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage() + { + if (array_key_exists('language', $this->data)) { + return $this->data['language']; + } + + $language = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $language = $this->xpath->evaluate('string(/rss/channel/language)'); + } + + if (!$language && $this->getExtension('DublinCore') !== null) { + $language = $this->getExtension('DublinCore')->getLanguage(); + } + + if (empty($language)) { + $language = $this->getExtension('Atom')->getLanguage(); + } + + if (!$language) { + $language = $this->xpath->evaluate('string(//@xml:lang[1])'); + } + + if (!$language) { + $language = null; + } + + $this->data['language'] = $language; + + return $this->data['language']; + } + + /** + * Get a link to the feed + * + * @return string|null + */ + public function getLink() + { + if (array_key_exists('link', $this->data)) { + return $this->data['link']; + } + + $link = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $link = $this->xpath->evaluate('string(/rss/channel/link)'); + } else { + $link = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/rss:link)'); + } + + if (empty($link)) { + $link = $this->getExtension('Atom')->getLink(); + } + + if (!$link) { + $link = null; + } + + $this->data['link'] = $link; + + return $this->data['link']; + } + + /** + * Get a link to the feed XML + * + * @return string|null + */ + public function getFeedLink() + { + if (array_key_exists('feedlink', $this->data)) { + return $this->data['feedlink']; + } + + $link = null; + + $link = $this->getExtension('Atom')->getFeedLink(); + + if ($link === null || empty($link)) { + $link = $this->getOriginalSourceUri(); + } + + $this->data['feedlink'] = $link; + + return $this->data['feedlink']; + } + + /** + * Get the feed generator entry + * + * @return string|null + */ + public function getGenerator() + { + if (array_key_exists('generator', $this->data)) { + return $this->data['generator']; + } + + $generator = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $generator = $this->xpath->evaluate('string(/rss/channel/generator)'); + } + + if (!$generator) { + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $generator = $this->xpath->evaluate('string(/rss/channel/atom:generator)'); + } else { + $generator = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/atom:generator)'); + } + } + + if (empty($generator)) { + $generator = $this->getExtension('Atom')->getGenerator(); + } + + if (!$generator) { + $generator = null; + } + + $this->data['generator'] = $generator; + + return $this->data['generator']; + } + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle() + { + if (array_key_exists('title', $this->data)) { + return $this->data['title']; + } + + $title = null; + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $title = $this->xpath->evaluate('string(/rss/channel/title)'); + } else { + $title = $this->xpath->evaluate('string(/rdf:RDF/rss:channel/rss:title)'); + } + + if (!$title && $this->getExtension('DublinCore') !== null) { + $title = $this->getExtension('DublinCore')->getTitle(); + } + + if (!$title) { + $title = $this->getExtension('Atom')->getTitle(); + } + + if (!$title) { + $title = null; + } + + $this->data['title'] = $title; + + return $this->data['title']; + } + + /** + * Get an array of any supported Pusubhubbub endpoints + * + * @return array|null + */ + public function getHubs() + { + if (array_key_exists('hubs', $this->data)) { + return $this->data['hubs']; + } + + $hubs = $this->getExtension('Atom')->getHubs(); + + if (empty($hubs)) { + $hubs = null; + } else { + $hubs = array_unique($hubs); + } + + $this->data['hubs'] = $hubs; + + return $this->data['hubs']; + } + + /** + * Get all categories + * + * @return Reader\Collection\Category + */ + public function getCategories() + { + if (array_key_exists('categories', $this->data)) { + return $this->data['categories']; + } + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && + $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $list = $this->xpath->query('/rss/channel//category'); + } else { + $list = $this->xpath->query('/rdf:RDF/rss:channel//rss:category'); + } + + if ($list->length) { + $categoryCollection = new Collection\Category; + foreach ($list as $category) { + $categoryCollection[] = array( + 'term' => $category->nodeValue, + 'scheme' => $category->getAttribute('domain'), + 'label' => $category->nodeValue, + ); + } + } else { + $categoryCollection = $this->getExtension('DublinCore')->getCategories(); + } + + if (count($categoryCollection) == 0) { + $categoryCollection = $this->getExtension('Atom')->getCategories(); + } + + $this->data['categories'] = $categoryCollection; + + return $this->data['categories']; + } + + /** + * Read all entries to the internal entries array + * + */ + protected function indexEntries() + { + $entries = array(); + + if ($this->getType() !== Reader\Reader::TYPE_RSS_10 && $this->getType() !== Reader\Reader::TYPE_RSS_090) { + $entries = $this->xpath->evaluate('//item'); + } else { + $entries = $this->xpath->evaluate('//rss:item'); + } + + foreach ($entries as $index => $entry) { + $this->entries[$index] = $entry; + } + } + + /** + * Register the default namespaces for the current feed format + * + */ + protected function registerNamespaces() + { + switch ($this->data['type']) { + case Reader\Reader::TYPE_RSS_10: + $this->xpath->registerNamespace('rdf', Reader\Reader::NAMESPACE_RDF); + $this->xpath->registerNamespace('rss', Reader\Reader::NAMESPACE_RSS_10); + break; + + case Reader\Reader::TYPE_RSS_090: + $this->xpath->registerNamespace('rdf', Reader\Reader::NAMESPACE_RDF); + $this->xpath->registerNamespace('rss', Reader\Reader::NAMESPACE_RSS_090); + break; + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/FeedSet.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/FeedSet.php new file mode 100644 index 0000000000000000000000000000000000000000..c9476208d28cdc02744c485c67a9b68ba47a8a64 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/FeedSet.php @@ -0,0 +1,127 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +use ArrayObject; +use DOMNodeList; +use Zend\Feed\Uri; + +/** +*/ +class FeedSet extends ArrayObject +{ + + public $rss = null; + + public $rdf = null; + + public $atom = null; + + /** + * Import a DOMNodeList from any document containing a set of links + * for alternate versions of a document, which will normally refer to + * RSS/RDF/Atom feeds for the current document. + * + * All such links are stored internally, however the first instance of + * each RSS, RDF or Atom type has its URI stored as a public property + * as a shortcut where the use case is simply to get a quick feed ref. + * + * Note that feeds are not loaded at this point, but will be lazy + * loaded automatically when each links 'feed' array key is accessed. + * + * @param DOMNodeList $links + * @param string $uri + * @return void + */ + public function addLinks(DOMNodeList $links, $uri) + { + foreach ($links as $link) { + if (strtolower($link->getAttribute('rel')) !== 'alternate' + || !$link->getAttribute('type') || !$link->getAttribute('href')) { + continue; + } + if (!isset($this->rss) && $link->getAttribute('type') == 'application/rss+xml') { + $this->rss = $this->absolutiseUri(trim($link->getAttribute('href')), $uri); + } elseif (!isset($this->atom) && $link->getAttribute('type') == 'application/atom+xml') { + $this->atom = $this->absolutiseUri(trim($link->getAttribute('href')), $uri); + } elseif (!isset($this->rdf) && $link->getAttribute('type') == 'application/rdf+xml') { + $this->rdf = $this->absolutiseUri(trim($link->getAttribute('href')), $uri); + } + $this[] = new static(array( + 'rel' => 'alternate', + 'type' => $link->getAttribute('type'), + 'href' => $this->absolutiseUri(trim($link->getAttribute('href')), $uri), + )); + } + } + + /** + * Attempt to turn a relative URI into an absolute URI + */ + protected function absolutiseUri($link, $uri = null) + { + $linkUri = Uri::factory($link); + if (!$linkUri->isAbsolute() or !$linkUri->isValid()) { + if ($uri !== null) { + $uri = Uri::factory($uri); + + if ($link[0] !== '/') { + $link = $uri->getPath() . '/' . $link; + } + + $link = $uri->getScheme() . '://' . $uri->getHost() . '/' . $this->canonicalizePath($link); + if (!Uri::factory($link)->isValid()) { + $link = null; + } + } + } + return $link; + } + + /** + * Canonicalize relative path + */ + protected function canonicalizePath($path) + { + $parts = array_filter(explode('/', $path)); + $absolutes = array(); + foreach ($parts as $part) { + if ('.' == $part) { + continue; + } + if ('..' == $part) { + array_pop($absolutes); + } else { + $absolutes[] = $part; + } + } + return implode('/', $absolutes); + } + + /** + * Supports lazy loading of feeds using Reader::import() but + * delegates any other operations to the parent class. + * + * @param string $offset + * @return mixed + */ + public function offsetGet($offset) + { + if ($offset == 'feed' && !$this->offsetExists('feed')) { + if (!$this->offsetExists('href')) { + return null; + } + $feed = Reader::import($this->offsetGet('href')); + $this->offsetSet('feed', $feed); + return $feed; + } + return parent::offsetGet($offset); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Http/ClientInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Http/ClientInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..dc0f5f694da2380e869e4a725cde5b537061a87f --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Http/ClientInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Http; + +interface ClientInterface +{ + /** + * Make a GET request to a given URI + * + * @param string $uri + * @return ResponseInterface + */ + public function get($uri); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Http/ResponseInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Http/ResponseInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..5027f200545920e5fe14923a833213e554985651 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Http/ResponseInterface.php @@ -0,0 +1,27 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader\Http; + +interface ResponseInterface +{ + /** + * Retrieve the response body + * + * @return string + */ + public function getBody(); + + /** + * Retrieve the HTTP response status code + * + * @return int + */ + public function getStatusCode(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Reader.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Reader.php new file mode 100644 index 0000000000000000000000000000000000000000..7f8a25c20d891f3796005b744d6e7ff82e63d99e --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Reader/Reader.php @@ -0,0 +1,674 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Reader; + +use DOMDocument; +use DOMXPath; +use Zend\Cache\Storage\StorageInterface as CacheStorage; +use Zend\Http as ZendHttp; +use Zend\Stdlib\ErrorHandler; + +/** +*/ +class Reader +{ + /** + * Namespace constants + */ + const NAMESPACE_ATOM_03 = 'http://purl.org/atom/ns#'; + const NAMESPACE_ATOM_10 = 'http://www.w3.org/2005/Atom'; + const NAMESPACE_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; + const NAMESPACE_RSS_090 = 'http://my.netscape.com/rdf/simple/0.9/'; + const NAMESPACE_RSS_10 = 'http://purl.org/rss/1.0/'; + + /** + * Feed type constants + */ + const TYPE_ANY = 'any'; + const TYPE_ATOM_03 = 'atom-03'; + const TYPE_ATOM_10 = 'atom-10'; + const TYPE_ATOM_10_ENTRY = 'atom-10-entry'; + const TYPE_ATOM_ANY = 'atom'; + const TYPE_RSS_090 = 'rss-090'; + const TYPE_RSS_091 = 'rss-091'; + const TYPE_RSS_091_NETSCAPE = 'rss-091n'; + const TYPE_RSS_091_USERLAND = 'rss-091u'; + const TYPE_RSS_092 = 'rss-092'; + const TYPE_RSS_093 = 'rss-093'; + const TYPE_RSS_094 = 'rss-094'; + const TYPE_RSS_10 = 'rss-10'; + const TYPE_RSS_20 = 'rss-20'; + const TYPE_RSS_ANY = 'rss'; + + /** + * Cache instance + * + * @var CacheStorage + */ + protected static $cache = null; + + /** + * HTTP client object to use for retrieving feeds + * + * @var ZendHttp\Client + */ + protected static $httpClient = null; + + /** + * Override HTTP PUT and DELETE request methods? + * + * @var bool + */ + protected static $httpMethodOverride = false; + + protected static $httpConditionalGet = false; + + protected static $extensionManager = null; + + protected static $extensions = array( + 'feed' => array( + 'DublinCore\Feed', + 'Atom\Feed' + ), + 'entry' => array( + 'Content\Entry', + 'DublinCore\Entry', + 'Atom\Entry' + ), + 'core' => array( + 'DublinCore\Feed', + 'Atom\Feed', + 'Content\Entry', + 'DublinCore\Entry', + 'Atom\Entry' + ) + ); + + /** + * Get the Feed cache + * + * @return CacheStorage + */ + public static function getCache() + { + return static::$cache; + } + + /** + * Set the feed cache + * + * @param CacheStorage $cache + * @return void + */ + public static function setCache(CacheStorage $cache) + { + static::$cache = $cache; + } + + /** + * Set the HTTP client instance + * + * Sets the HTTP client object to use for retrieving the feeds. + * + * @param ZendHttp\Client $httpClient + * @return void + */ + public static function setHttpClient(ZendHttp\Client $httpClient) + { + static::$httpClient = $httpClient; + } + + + /** + * Gets the HTTP client object. If none is set, a new ZendHttp\Client will be used. + * + * @return ZendHttp\Client + */ + public static function getHttpClient() + { + if (!static::$httpClient instanceof ZendHttp\Client) { + static::$httpClient = new ZendHttp\Client(); + } + + return static::$httpClient; + } + + /** + * Toggle using POST instead of PUT and DELETE HTTP methods + * + * Some feed implementations do not accept PUT and DELETE HTTP + * methods, or they can't be used because of proxies or other + * measures. This allows turning on using POST where PUT and + * DELETE would normally be used; in addition, an + * X-Method-Override header will be sent with a value of PUT or + * DELETE as appropriate. + * + * @param bool $override Whether to override PUT and DELETE. + * @return void + */ + public static function setHttpMethodOverride($override = true) + { + static::$httpMethodOverride = $override; + } + + /** + * Get the HTTP override state + * + * @return bool + */ + public static function getHttpMethodOverride() + { + return static::$httpMethodOverride; + } + + /** + * Set the flag indicating whether or not to use HTTP conditional GET + * + * @param bool $bool + * @return void + */ + public static function useHttpConditionalGet($bool = true) + { + static::$httpConditionalGet = $bool; + } + + /** + * Import a feed by providing a URI + * + * @param string $uri The URI to the feed + * @param string $etag OPTIONAL Last received ETag for this resource + * @param string $lastModified OPTIONAL Last-Modified value for this resource + * @return Feed\FeedInterface + * @throws Exception\RuntimeException + */ + public static function import($uri, $etag = null, $lastModified = null) + { + $cache = self::getCache(); + $feed = null; + $responseXml = ''; + $client = self::getHttpClient(); + $client->resetParameters(); + $headers = new ZendHttp\Headers(); + $client->setHeaders($headers); + $client->setUri($uri); + $cacheId = 'Zend_Feed_Reader_' . md5($uri); + + if (static::$httpConditionalGet && $cache) { + $data = $cache->getItem($cacheId); + if ($data) { + if ($etag === null) { + $etag = $cache->getItem($cacheId . '_etag'); + } + if ($lastModified === null) { + $lastModified = $cache->getItem($cacheId . '_lastmodified'); + } + if ($etag) { + $headers->addHeaderLine('If-None-Match', $etag); + } + if ($lastModified) { + $headers->addHeaderLine('If-Modified-Since', $lastModified); + } + } + $response = $client->send(); + if ($response->getStatusCode() !== 200 && $response->getStatusCode() !== 304) { + throw new Exception\RuntimeException('Feed failed to load, got response code ' . $response->getStatusCode()); + } + if ($response->getStatusCode() == 304) { + $responseXml = $data; + } else { + $responseXml = $response->getBody(); + $cache->setItem($cacheId, $responseXml); + if ($response->getHeaders()->get('ETag')) { + $cache->setItem($cacheId . '_etag', $response->getHeaders()->get('ETag')->getFieldValue()); + } + if ($response->getHeaders()->get('Last-Modified')) { + $cache->setItem($cacheId . '_lastmodified', $response->getHeaders()->get('Last-Modified')->getFieldValue()); + } + } + return static::importString($responseXml); + } elseif ($cache) { + $data = $cache->getItem($cacheId); + if ($data) { + return static::importString($data); + } + $response = $client->send(); + if ((int) $response->getStatusCode() !== 200) { + throw new Exception\RuntimeException('Feed failed to load, got response code ' . $response->getStatusCode()); + } + $responseXml = $response->getBody(); + $cache->setItem($cacheId, $responseXml); + return static::importString($responseXml); + } else { + $response = $client->send(); + if ((int) $response->getStatusCode() !== 200) { + throw new Exception\RuntimeException('Feed failed to load, got response code ' . $response->getStatusCode()); + } + $reader = static::importString($response->getBody()); + $reader->setOriginalSourceUri($uri); + return $reader; + } + } + + /** + * Import a feed from a remote URI + * + * Performs similarly to import(), except it uses the HTTP client passed to + * the method, and does not take into account cached data. + * + * Primary purpose is to make it possible to use the Reader with alternate + * HTTP client implementations. + * + * @param string $uri + * @param Http\Client $client + * @return self + * @throws Exception\RuntimeException if response is not an Http\ResponseInterface + */ + public static function importRemoteFeed($uri, Http\ClientInterface $client) + { + $response = $client->get($uri); + if (!$response instanceof Http\ResponseInterface) { + throw new Exception\RuntimeException(sprintf( + 'Did not receive a %s\Http\ResponseInterface from the provided HTTP client; received "%s"', + __NAMESPACE__, + (is_object($response) ? get_class($response) : gettype($response)) + )); + } + + if ((int) $response->getStatusCode() !== 200) { + throw new Exception\RuntimeException('Feed failed to load, got response code ' . $response->getStatusCode()); + } + $reader = static::importString($response->getBody()); + $reader->setOriginalSourceUri($uri); + return $reader; + } + + /** + * Import a feed from a string + * + * @param string $string + * @return Feed\FeedInterface + * @throws Exception\InvalidArgumentException + * @throws Exception\RuntimeException + */ + public static function importString($string) + { + $libxmlErrflag = libxml_use_internal_errors(true); + $oldValue = libxml_disable_entity_loader(true); + $dom = new DOMDocument; + $status = $dom->loadXML(trim($string)); + foreach ($dom->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + throw new Exception\InvalidArgumentException( + 'Invalid XML: Detected use of illegal DOCTYPE' + ); + } + } + libxml_disable_entity_loader($oldValue); + libxml_use_internal_errors($libxmlErrflag); + + if (!$status) { + // Build error message + $error = libxml_get_last_error(); + if ($error && $error->message) { + $error->message = trim($error->message); + $errormsg = "DOMDocument cannot parse XML: {$error->message}"; + } else { + $errormsg = "DOMDocument cannot parse XML: Please check the XML document's validity"; + } + throw new Exception\RuntimeException($errormsg); + } + + $type = static::detectType($dom); + + static::registerCoreExtensions(); + + if (substr($type, 0, 3) == 'rss') { + $reader = new Feed\Rss($dom, $type); + } elseif (substr($type, 8, 5) == 'entry') { + $reader = new Entry\Atom($dom->documentElement, 0, self::TYPE_ATOM_10); + } elseif (substr($type, 0, 4) == 'atom') { + $reader = new Feed\Atom($dom, $type); + } else { + throw new Exception\RuntimeException('The URI used does not point to a ' + . 'valid Atom, RSS or RDF feed that Zend\Feed\Reader can parse.'); + } + return $reader; + } + + /** + * Imports a feed from a file located at $filename. + * + * @param string $filename + * @throws Exception\RuntimeException + * @return Feed\FeedInterface + */ + public static function importFile($filename) + { + ErrorHandler::start(); + $feed = file_get_contents($filename); + $err = ErrorHandler::stop(); + if ($feed === false) { + throw new Exception\RuntimeException("File '{$filename}' could not be loaded", 0, $err); + } + return static::importString($feed); + } + + /** + * Find feed links + * + * @param $uri + * @return FeedSet + * @throws Exception\RuntimeException + */ + public static function findFeedLinks($uri) + { + $client = static::getHttpClient(); + $client->setUri($uri); + $response = $client->send(); + if ($response->getStatusCode() !== 200) { + throw new Exception\RuntimeException("Failed to access $uri, got response code " . $response->getStatusCode()); + } + $responseHtml = $response->getBody(); + $libxmlErrflag = libxml_use_internal_errors(true); + $oldValue = libxml_disable_entity_loader(true); + $dom = new DOMDocument; + $status = $dom->loadHTML(trim($responseHtml)); + libxml_disable_entity_loader($oldValue); + libxml_use_internal_errors($libxmlErrflag); + if (!$status) { + // Build error message + $error = libxml_get_last_error(); + if ($error && $error->message) { + $error->message = trim($error->message); + $errormsg = "DOMDocument cannot parse HTML: {$error->message}"; + } else { + $errormsg = "DOMDocument cannot parse HTML: Please check the XML document's validity"; + } + throw new Exception\RuntimeException($errormsg); + } + $feedSet = new FeedSet; + $links = $dom->getElementsByTagName('link'); + $feedSet->addLinks($links, $uri); + return $feedSet; + } + + /** + * Detect the feed type of the provided feed + * + * @param Feed\AbstractFeed|DOMDocument|string $feed + * @param bool $specOnly + * @return string + * @throws Exception\InvalidArgumentException + * @throws Exception\RuntimeException + */ + public static function detectType($feed, $specOnly = false) + { + if ($feed instanceof Feed\AbstractFeed) { + $dom = $feed->getDomDocument(); + } elseif ($feed instanceof DOMDocument) { + $dom = $feed; + } elseif (is_string($feed) && !empty($feed)) { + ErrorHandler::start(E_NOTICE|E_WARNING); + ini_set('track_errors', 1); + $oldValue = libxml_disable_entity_loader(true); + $dom = new DOMDocument; + $status = $dom->loadXML($feed); + foreach ($dom->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + throw new Exception\InvalidArgumentException( + 'Invalid XML: Detected use of illegal DOCTYPE' + ); + } + } + libxml_disable_entity_loader($oldValue); + ini_restore('track_errors'); + ErrorHandler::stop(); + if (!$status) { + if (!isset($phpErrormsg)) { + if (function_exists('xdebug_is_enabled')) { + $phpErrormsg = '(error message not available, when XDebug is running)'; + } else { + $phpErrormsg = '(error message not available)'; + } + } + throw new Exception\RuntimeException("DOMDocument cannot parse XML: $phpErrormsg"); + } + } else { + throw new Exception\InvalidArgumentException('Invalid object/scalar provided: must' + . ' be of type Zend\Feed\Reader\Feed, DomDocument or string'); + } + $xpath = new DOMXPath($dom); + + if ($xpath->query('/rss')->length) { + $type = self::TYPE_RSS_ANY; + $version = $xpath->evaluate('string(/rss/@version)'); + + if (strlen($version) > 0) { + switch ($version) { + case '2.0': + $type = self::TYPE_RSS_20; + break; + + case '0.94': + $type = self::TYPE_RSS_094; + break; + + case '0.93': + $type = self::TYPE_RSS_093; + break; + + case '0.92': + $type = self::TYPE_RSS_092; + break; + + case '0.91': + $type = self::TYPE_RSS_091; + break; + } + } + + return $type; + } + + $xpath->registerNamespace('rdf', self::NAMESPACE_RDF); + + if ($xpath->query('/rdf:RDF')->length) { + $xpath->registerNamespace('rss', self::NAMESPACE_RSS_10); + + if ($xpath->query('/rdf:RDF/rss:channel')->length + || $xpath->query('/rdf:RDF/rss:image')->length + || $xpath->query('/rdf:RDF/rss:item')->length + || $xpath->query('/rdf:RDF/rss:textinput')->length + ) { + return self::TYPE_RSS_10; + } + + $xpath->registerNamespace('rss', self::NAMESPACE_RSS_090); + + if ($xpath->query('/rdf:RDF/rss:channel')->length + || $xpath->query('/rdf:RDF/rss:image')->length + || $xpath->query('/rdf:RDF/rss:item')->length + || $xpath->query('/rdf:RDF/rss:textinput')->length + ) { + return self::TYPE_RSS_090; + } + } + + $xpath->registerNamespace('atom', self::NAMESPACE_ATOM_10); + + if ($xpath->query('//atom:feed')->length) { + return self::TYPE_ATOM_10; + } + + if ($xpath->query('//atom:entry')->length) { + if ($specOnly == true) { + return self::TYPE_ATOM_10; + } else { + return self::TYPE_ATOM_10_ENTRY; + } + } + + $xpath->registerNamespace('atom', self::NAMESPACE_ATOM_03); + + if ($xpath->query('//atom:feed')->length) { + return self::TYPE_ATOM_03; + } + + return self::TYPE_ANY; + } + + /** + * Set plugin manager for use with Extensions + * + * @param ExtensionManagerInterface $extensionManager + */ + public static function setExtensionManager(ExtensionManagerInterface $extensionManager) + { + static::$extensionManager = $extensionManager; + } + + /** + * Get plugin manager for use with Extensions + * + * @return ExtensionManagerInterface + */ + public static function getExtensionManager() + { + if (!isset(static::$extensionManager)) { + static::setExtensionManager(new ExtensionManager()); + } + return static::$extensionManager; + } + + /** + * Register an Extension by name + * + * @param string $name + * @return void + * @throws Exception\RuntimeException if unable to resolve Extension class + */ + public static function registerExtension($name) + { + $feedName = $name . '\Feed'; + $entryName = $name . '\Entry'; + $manager = static::getExtensionManager(); + if (static::isRegistered($name)) { + if ($manager->has($feedName) || $manager->has($entryName)) { + return; + } + } + + if (!$manager->has($feedName) && !$manager->has($entryName)) { + throw new Exception\RuntimeException('Could not load extension: ' . $name + . ' using Plugin Loader. Check prefix paths are configured and extension exists.'); + } + if ($manager->has($feedName)) { + static::$extensions['feed'][] = $feedName; + } + if ($manager->has($entryName)) { + static::$extensions['entry'][] = $entryName; + } + } + + /** + * Is a given named Extension registered? + * + * @param string $extensionName + * @return bool + */ + public static function isRegistered($extensionName) + { + $feedName = $extensionName . '\Feed'; + $entryName = $extensionName . '\Entry'; + if (in_array($feedName, static::$extensions['feed']) + || in_array($entryName, static::$extensions['entry']) + ) { + return true; + } + return false; + } + + /** + * Get a list of extensions + * + * @return array + */ + public static function getExtensions() + { + return static::$extensions; + } + + /** + * Reset class state to defaults + * + * @return void + */ + public static function reset() + { + static::$cache = null; + static::$httpClient = null; + static::$httpMethodOverride = false; + static::$httpConditionalGet = false; + static::$extensionManager = null; + static::$extensions = array( + 'feed' => array( + 'DublinCore\Feed', + 'Atom\Feed' + ), + 'entry' => array( + 'Content\Entry', + 'DublinCore\Entry', + 'Atom\Entry' + ), + 'core' => array( + 'DublinCore\Feed', + 'Atom\Feed', + 'Content\Entry', + 'DublinCore\Entry', + 'Atom\Entry' + ) + ); + } + + /** + * Register core (default) extensions + * + * @return void + */ + protected static function registerCoreExtensions() + { + static::registerExtension('DublinCore'); + static::registerExtension('Content'); + static::registerExtension('Atom'); + static::registerExtension('Slash'); + static::registerExtension('WellFormedWeb'); + static::registerExtension('Thread'); + static::registerExtension('Podcast'); + } + + /** + * Utility method to apply array_unique operation to a multidimensional + * array. + * + * @param array + * @return array + */ + public static function arrayUnique(array $array) + { + foreach ($array as &$value) { + $value = serialize($value); + } + $array = array_unique($array); + foreach ($array as &$value) { + $value = unserialize($value); + } + return $array; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Uri.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Uri.php new file mode 100644 index 0000000000000000000000000000000000000000..c2403c5b75ac17446c0f11b412ca1586cad9048b --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Uri.php @@ -0,0 +1,184 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed; + +class Uri +{ + /** + * @var string + */ + protected $fragment; + + /** + * @var string + */ + protected $host; + + /** + * @var string + */ + protected $pass; + + /** + * @var string + */ + protected $path; + + /** + * @var int + */ + protected $port; + + /** + * @var string + */ + protected $query; + + /** + * @var string + */ + protected $scheme; + + /** + * @var string + */ + protected $user; + + /** + * @var bool + */ + protected $valid; + + /** + * Valid schemes + */ + protected $validSchemes = array( + 'http', + 'https', + 'file', + ); + + /** + * @param string $uri + */ + public function __construct($uri) + { + $parsed = parse_url($uri); + if (false === $parsed) { + $this->valid = false; + return; + } + + $this->scheme = isset($parsed['scheme']) ? $parsed['scheme'] : null; + $this->host = isset($parsed['host']) ? $parsed['host'] : null; + $this->port = isset($parsed['port']) ? $parsed['port'] : null; + $this->user = isset($parsed['user']) ? $parsed['user'] : null; + $this->pass = isset($parsed['pass']) ? $parsed['pass'] : null; + $this->path = isset($parsed['path']) ? $parsed['path'] : null; + $this->query = isset($parsed['query']) ? $parsed['query'] : null; + $this->fragment = isset($parsed['fragment']) ? $parsed['fragment'] : null; + } + + /** + * Create an instance + * + * Useful for chained validations + * + * @param string $uri + * @return self + */ + public static function factory($uri) + { + return new static($uri); + } + + /** + * Retrieve the host + * + * @return string + */ + public function getHost() + { + return $this->host; + } + + /** + * Retrieve the URI path + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Retrieve the scheme + * + * @return string + */ + public function getScheme() + { + return $this->scheme; + } + + /** + * Is the URI valid? + * + * @return bool + */ + public function isValid() + { + if (false === $this->valid) { + return false; + } + + if ($this->scheme && !in_array($this->scheme, $this->validSchemes)) { + return false; + } + + if ($this->host) { + if ($this->path && substr($this->path, 0, 1) != '/') { + return false; + } + return true; + } + + // no host, but user and/or port... what? + if ($this->user || $this->port) { + return false; + } + + if ($this->path) { + // Check path-only (no host) URI + if (substr($this->path, 0, 2) == '//') { + return false; + } + return true; + } + + if (! ($this->query || $this->fragment)) { + // No host, path, query or fragment - this is not a valid URI + return false; + } + + return true; + } + + /** + * Is the URI absolute? + * + * @return bool + */ + public function isAbsolute() + { + return ($this->scheme !== null); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/AbstractFeed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/AbstractFeed.php new file mode 100644 index 0000000000000000000000000000000000000000..389a987d2fec556d701c8a21fb4b78ea47d4f01b --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/AbstractFeed.php @@ -0,0 +1,848 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +use DateTime; +use Zend\Feed\Uri; +use Zend\Validator; + +class AbstractFeed +{ + /** + * Contains all Feed level date to append in feed output + * + * @var array + */ + protected $data = array(); + + /** + * Holds the value "atom" or "rss" depending on the feed type set when + * when last exported. + * + * @var string + */ + protected $type = null; + + /** + * @var $extensions + */ + protected $extensions; + + /** + * Constructor: Primarily triggers the registration of core extensions and + * loads those appropriate to this data container. + * + */ + public function __construct() + { + Writer::registerCoreExtensions(); + $this->_loadExtensions(); + } + + /** + * Set a single author + * + * The following option keys are supported: + * 'name' => (string) The name + * 'email' => (string) An optional email + * 'uri' => (string) An optional and valid URI + * + * @param array $author + * @throws Exception\InvalidArgumentException If any value of $author not follow the format. + * @return AbstractFeed + */ + public function addAuthor(array $author) + { + // Check array values + if (!array_key_exists('name', $author) + || empty($author['name']) + || !is_string($author['name']) + ) { + throw new Exception\InvalidArgumentException( + 'Invalid parameter: author array must include a "name" key with a non-empty string value'); + } + + if (isset($author['email'])) { + if (empty($author['email']) || !is_string($author['email'])) { + throw new Exception\InvalidArgumentException( + 'Invalid parameter: "email" array value must be a non-empty string'); + } + } + if (isset($author['uri'])) { + if (empty($author['uri']) || !is_string($author['uri']) || + !Uri::factory($author['uri'])->isValid() + ) { + throw new Exception\InvalidArgumentException( + 'Invalid parameter: "uri" array value must be a non-empty string and valid URI/IRI'); + } + } + + $this->data['authors'][] = $author; + + return $this; + } + + /** + * Set an array with feed authors + * + * @see addAuthor + * @param array $authors + * @return AbstractFeed + */ + public function addAuthors(array $authors) + { + foreach ($authors as $author) { + $this->addAuthor($author); + } + + return $this; + } + + /** + * Set the copyright entry + * + * @param string $copyright + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setCopyright($copyright) + { + if (empty($copyright) || !is_string($copyright)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['copyright'] = $copyright; + + return $this; + } + + /** + * Set the feed creation date + * + * @param null|int|DateTime + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setDateCreated($date = null) + { + if ($date === null) { + $date = new DateTime(); + } elseif (is_int($date)) { + $date = new DateTime('@' . $date); + } elseif (!$date instanceof DateTime) { + throw new Exception\InvalidArgumentException('Invalid DateTime object or UNIX Timestamp' + . ' passed as parameter'); + } + $this->data['dateCreated'] = $date; + + return $this; + } + + /** + * Set the feed modification date + * + * @param null|int|DateTime + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setDateModified($date = null) + { + if ($date === null) { + $date = new DateTime(); + } elseif (is_int($date)) { + $date = new DateTime('@' . $date); + } elseif (!$date instanceof DateTime) { + throw new Exception\InvalidArgumentException('Invalid DateTime object or UNIX Timestamp' + . ' passed as parameter'); + } + $this->data['dateModified'] = $date; + + return $this; + } + + /** + * Set the feed last-build date. Ignored for Atom 1.0. + * + * @param null|int|DateTime + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setLastBuildDate($date = null) + { + if ($date === null) { + $date = new DateTime(); + } elseif (is_int($date)) { + $date = new DateTime('@' . $date); + } elseif (!$date instanceof DateTime) { + throw new Exception\InvalidArgumentException('Invalid DateTime object or UNIX Timestamp' + . ' passed as parameter'); + } + $this->data['lastBuildDate'] = $date; + + return $this; + } + + /** + * Set the feed description + * + * @param string $description + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setDescription($description) + { + if (empty($description) || !is_string($description)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['description'] = $description; + + return $this; + } + + /** + * Set the feed generator entry + * + * @param array|string $name + * @param null|string $version + * @param null|string $uri + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setGenerator($name, $version = null, $uri = null) + { + if (is_array($name)) { + $data = $name; + if (empty($data['name']) || !is_string($data['name'])) { + throw new Exception\InvalidArgumentException('Invalid parameter: "name" must be a non-empty string'); + } + $generator = array('name' => $data['name']); + if (isset($data['version'])) { + if (empty($data['version']) || !is_string($data['version'])) { + throw new Exception\InvalidArgumentException('Invalid parameter: "version" must be a non-empty string'); + } + $generator['version'] = $data['version']; + } + if (isset($data['uri'])) { + if (empty($data['uri']) || !is_string($data['uri']) || !Uri::factory($data['uri'])->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: "uri" must be a non-empty string and a valid URI/IRI'); + } + $generator['uri'] = $data['uri']; + } + } else { + if (empty($name) || !is_string($name)) { + throw new Exception\InvalidArgumentException('Invalid parameter: "name" must be a non-empty string'); + } + $generator = array('name' => $name); + if (isset($version)) { + if (empty($version) || !is_string($version)) { + throw new Exception\InvalidArgumentException('Invalid parameter: "version" must be a non-empty string'); + } + $generator['version'] = $version; + } + if (isset($uri)) { + if (empty($uri) || !is_string($uri) || !Uri::factory($uri)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: "uri" must be a non-empty string and a valid URI/IRI'); + } + $generator['uri'] = $uri; + } + } + $this->data['generator'] = $generator; + + return $this; + } + + /** + * Set the feed ID - URI or URN (via PCRE pattern) supported + * + * @param string $id + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setId($id) + { + if ((empty($id) || !is_string($id) || !Uri::factory($id)->isValid()) + && !preg_match("#^urn:[a-zA-Z0-9][a-zA-Z0-9\-]{1,31}:([a-zA-Z0-9\(\)\+\,\.\:\=\@\;\$\_\!\*\-]|%[0-9a-fA-F]{2})*#", $id) + && !$this->_validateTagUri($id) + ) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string and valid URI/IRI'); + } + $this->data['id'] = $id; + + return $this; + } + + /** + * Validate a URI using the tag scheme (RFC 4151) + * + * @param string $id + * @return bool + */ + protected function _validateTagUri($id) + { + if (preg_match('/^tag:(?P<name>.*),(?P<date>\d{4}-?\d{0,2}-?\d{0,2}):(?P<specific>.*)(.*:)*$/', $id, $matches)) { + $dvalid = false; + $nvalid = false; + $date = $matches['date']; + $d6 = strtotime($date); + if ((strlen($date) == 4) && $date <= date('Y')) { + $dvalid = true; + } elseif ((strlen($date) == 7) && ($d6 < strtotime("now"))) { + $dvalid = true; + } elseif ((strlen($date) == 10) && ($d6 < strtotime("now"))) { + $dvalid = true; + } + $validator = new Validator\EmailAddress; + if ($validator->isValid($matches['name'])) { + $nvalid = true; + } else { + $nvalid = $validator->isValid('info@' . $matches['name']); + } + return $dvalid && $nvalid; + + } + return false; + } + + /** + * Set a feed image (URI at minimum). Parameter is a single array with the + * required key 'uri'. When rendering as RSS, the required keys are 'uri', + * 'title' and 'link'. RSS also specifies three optional parameters 'width', + * 'height' and 'description'. Only 'uri' is required and used for Atom rendering. + * + * @param array $data + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setImage(array $data) + { + if (empty($data['uri']) || !is_string($data['uri']) + || !Uri::factory($data['uri'])->isValid() + ) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter \'uri\'' + . ' must be a non-empty string and valid URI/IRI'); + } + $this->data['image'] = $data; + + return $this; + } + + /** + * Set the feed language + * + * @param string $language + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setLanguage($language) + { + if (empty($language) || !is_string($language)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['language'] = $language; + + return $this; + } + + /** + * Set a link to the HTML source + * + * @param string $link + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setLink($link) + { + if (empty($link) || !is_string($link) || !Uri::factory($link)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string and valid URI/IRI'); + } + $this->data['link'] = $link; + + return $this; + } + + /** + * Set a link to an XML feed for any feed type/version + * + * @param string $link + * @param string $type + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setFeedLink($link, $type) + { + if (empty($link) || !is_string($link) || !Uri::factory($link)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: "link"" must be a non-empty string and valid URI/IRI'); + } + if (!in_array(strtolower($type), array('rss', 'rdf', 'atom'))) { + throw new Exception\InvalidArgumentException('Invalid parameter: "type"; You must declare the type of feed the link points to, i.e. RSS, RDF or Atom'); + } + $this->data['feedLinks'][strtolower($type)] = $link; + + return $this; + } + + /** + * Set the feed title + * + * @param string $title + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setTitle($title) + { + if (empty($title) || !is_string($title)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['title'] = $title; + + return $this; + } + + /** + * Set the feed character encoding + * + * @param string $encoding + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setEncoding($encoding) + { + if (empty($encoding) || !is_string($encoding)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['encoding'] = $encoding; + + return $this; + } + + /** + * Set the feed's base URL + * + * @param string $url + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function setBaseUrl($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: "url" array value' + . ' must be a non-empty string and valid URI/IRI'); + } + $this->data['baseUrl'] = $url; + + return $this; + } + + /** + * Add a Pubsubhubbub hub endpoint URL + * + * @param string $url + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function addHub($url) + { + if (empty($url) || !is_string($url) || !Uri::factory($url)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: "url" array value' + . ' must be a non-empty string and valid URI/IRI'); + } + if (!isset($this->data['hubs'])) { + $this->data['hubs'] = array(); + } + $this->data['hubs'][] = $url; + + return $this; + } + + /** + * Add Pubsubhubbub hub endpoint URLs + * + * @param array $urls + * @return AbstractFeed + */ + public function addHubs(array $urls) + { + foreach ($urls as $url) { + $this->addHub($url); + } + + return $this; + } + + /** + * Add a feed category + * + * @param array $category + * @throws Exception\InvalidArgumentException + * @return AbstractFeed + */ + public function addCategory(array $category) + { + if (!isset($category['term'])) { + throw new Exception\InvalidArgumentException('Each category must be an array and ' + . 'contain at least a "term" element containing the machine ' + . ' readable category name'); + } + if (isset($category['scheme'])) { + if (empty($category['scheme']) + || !is_string($category['scheme']) + || !Uri::factory($category['scheme'])->isValid() + ) { + throw new Exception\InvalidArgumentException('The Atom scheme or RSS domain of' + . ' a category must be a valid URI'); + } + } + if (!isset($this->data['categories'])) { + $this->data['categories'] = array(); + } + $this->data['categories'][] = $category; + + return $this; + } + + /** + * Set an array of feed categories + * + * @param array $categories + * @return AbstractFeed + */ + public function addCategories(array $categories) + { + foreach ($categories as $category) { + $this->addCategory($category); + } + + return $this; + } + + /** + * Get a single author + * + * @param int $index + * @return string|null + */ + public function getAuthor($index = 0) + { + if (isset($this->data['authors'][$index])) { + return $this->data['authors'][$index]; + } + + return null; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (!array_key_exists('authors', $this->data)) { + return null; + } + return $this->data['authors']; + } + + /** + * Get the copyright entry + * + * @return string|null + */ + public function getCopyright() + { + if (!array_key_exists('copyright', $this->data)) { + return null; + } + return $this->data['copyright']; + } + + /** + * Get the feed creation date + * + * @return string|null + */ + public function getDateCreated() + { + if (!array_key_exists('dateCreated', $this->data)) { + return null; + } + return $this->data['dateCreated']; + } + + /** + * Get the feed modification date + * + * @return string|null + */ + public function getDateModified() + { + if (!array_key_exists('dateModified', $this->data)) { + return null; + } + return $this->data['dateModified']; + } + + /** + * Get the feed last-build date + * + * @return string|null + */ + public function getLastBuildDate() + { + if (!array_key_exists('lastBuildDate', $this->data)) { + return null; + } + return $this->data['lastBuildDate']; + } + + /** + * Get the feed description + * + * @return string|null + */ + public function getDescription() + { + if (!array_key_exists('description', $this->data)) { + return null; + } + return $this->data['description']; + } + + /** + * Get the feed generator entry + * + * @return string|null + */ + public function getGenerator() + { + if (!array_key_exists('generator', $this->data)) { + return null; + } + return $this->data['generator']; + } + + /** + * Get the feed ID + * + * @return string|null + */ + public function getId() + { + if (!array_key_exists('id', $this->data)) { + return null; + } + return $this->data['id']; + } + + /** + * Get the feed image URI + * + * @return array + */ + public function getImage() + { + if (!array_key_exists('image', $this->data)) { + return null; + } + return $this->data['image']; + } + + /** + * Get the feed language + * + * @return string|null + */ + public function getLanguage() + { + if (!array_key_exists('language', $this->data)) { + return null; + } + return $this->data['language']; + } + + /** + * Get a link to the HTML source + * + * @return string|null + */ + public function getLink() + { + if (!array_key_exists('link', $this->data)) { + return null; + } + return $this->data['link']; + } + + /** + * Get a link to the XML feed + * + * @return string|null + */ + public function getFeedLinks() + { + if (!array_key_exists('feedLinks', $this->data)) { + return null; + } + return $this->data['feedLinks']; + } + + /** + * Get the feed title + * + * @return string|null + */ + public function getTitle() + { + if (!array_key_exists('title', $this->data)) { + return null; + } + return $this->data['title']; + } + + /** + * Get the feed character encoding + * + * @return string|null + */ + public function getEncoding() + { + if (!array_key_exists('encoding', $this->data)) { + return 'UTF-8'; + } + return $this->data['encoding']; + } + + /** + * Get the feed's base url + * + * @return string|null + */ + public function getBaseUrl() + { + if (!array_key_exists('baseUrl', $this->data)) { + return null; + } + return $this->data['baseUrl']; + } + + /** + * Get the URLs used as Pubsubhubbub hubs endpoints + * + * @return string|null + */ + public function getHubs() + { + if (!array_key_exists('hubs', $this->data)) { + return null; + } + return $this->data['hubs']; + } + + /** + * Get the feed categories + * + * @return string|null + */ + public function getCategories() + { + if (!array_key_exists('categories', $this->data)) { + return null; + } + return $this->data['categories']; + } + + /** + * Resets the instance and deletes all data + * + * @return void + */ + public function reset() + { + $this->data = array(); + } + + /** + * Set the current feed type being exported to "rss" or "atom". This allows + * other objects to gracefully choose whether to execute or not, depending + * on their appropriateness for the current type, e.g. renderers. + * + * @param string $type + * @return AbstractFeed + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * Retrieve the current or last feed type exported. + * + * @return string Value will be "rss" or "atom" + */ + public function getType() + { + return $this->type; + } + + /** + * Unset a specific data point + * + * @param string $name + * @return AbstractFeed + */ + public function remove($name) + { + if (isset($this->data[$name])) { + unset($this->data[$name]); + } + return $this; + } + + /** + * Method overloading: call given method on first extension implementing it + * + * @param string $method + * @param array $args + * @return mixed + * @throws Exception\BadMethodCallException if no extensions implements the method + */ + public function __call($method, $args) + { + foreach ($this->extensions as $extension) { + try { + return call_user_func_array(array($extension, $method), $args); + } catch (Exception\BadMethodCallException $e) { + } + } + throw new Exception\BadMethodCallException( + 'Method: ' . $method . ' does not exist and could not be located on a registered Extension' + ); + } + + /** + * Load extensions from Zend\Feed\Writer\Writer + * + * @throws Exception\RuntimeException + * @return void + */ + protected function _loadExtensions() + { + $all = Writer::getExtensions(); + $manager = Writer::getExtensionManager(); + $exts = $all['feed']; + foreach ($exts as $ext) { + if (!$manager->has($ext)) { + throw new Exception\RuntimeException(sprintf('Unable to load extension "%s"; could not resolve to class', $ext)); + } + $this->extensions[$ext] = $manager->get($ext); + $this->extensions[$ext]->setEncoding($this->getEncoding()); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Deleted.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Deleted.php new file mode 100644 index 0000000000000000000000000000000000000000..b9ff321210da79bd76f4f87c569a18882e793d61 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Deleted.php @@ -0,0 +1,237 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +use DateTime; +use Zend\Feed\Uri; + +/** +*/ +class Deleted +{ + + /** + * Internal array containing all data associated with this entry or item. + * + * @var array + */ + protected $data = array(); + + /** + * Holds the value "atom" or "rss" depending on the feed type set when + * when last exported. + * + * @var string + */ + protected $type = null; + + /** + * Set the feed character encoding + * + * @param $encoding + * @throws Exception\InvalidArgumentException + * @return string|null + * @return Deleted + */ + public function setEncoding($encoding) + { + if (empty($encoding) || !is_string($encoding)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['encoding'] = $encoding; + + return $this; + } + + /** + * Get the feed character encoding + * + * @return string|null + */ + public function getEncoding() + { + if (!array_key_exists('encoding', $this->data)) { + return 'UTF-8'; + } + return $this->data['encoding']; + } + + /** + * Unset a specific data point + * + * @param string $name + * @return Deleted + */ + public function remove($name) + { + if (isset($this->data[$name])) { + unset($this->data[$name]); + } + + return $this; + } + + /** + * Set the current feed type being exported to "rss" or "atom". This allows + * other objects to gracefully choose whether to execute or not, depending + * on their appropriateness for the current type, e.g. renderers. + * + * @param string $type + * @return Deleted + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * Retrieve the current or last feed type exported. + * + * @return string Value will be "rss" or "atom" + */ + public function getType() + { + return $this->type; + } + + /** + * Set reference + * + * @param $reference + * @throws Exception\InvalidArgumentException + * @return Deleted + */ + public function setReference($reference) + { + if (empty($reference) || !is_string($reference)) { + throw new Exception\InvalidArgumentException('Invalid parameter: reference must be a non-empty string'); + } + $this->data['reference'] = $reference; + + return $this; + } + + /** + * @return string + */ + public function getReference() + { + if (!array_key_exists('reference', $this->data)) { + return null; + } + return $this->data['reference']; + } + + /** + * Set when + * + * @param null|string|DateTime $date + * @throws Exception\InvalidArgumentException + * @return Deleted + */ + public function setWhen($date = null) + { + if ($date === null) { + $date = new DateTime(); + } elseif (is_int($date)) { + $date = new DateTime('@' . $date); + } elseif (!$date instanceof DateTime) { + throw new Exception\InvalidArgumentException('Invalid DateTime object or UNIX Timestamp' + . ' passed as parameter'); + } + $this->data['when'] = $date; + + return $this; + } + + /** + * @return DateTime + */ + public function getWhen() + { + if (!array_key_exists('when', $this->data)) { + return null; + } + return $this->data['when']; + } + + /** + * Set by + * + * @param array $by + * @throws Exception\InvalidArgumentException + * @return Deleted + */ + public function setBy(array $by) + { + $author = array(); + if (!array_key_exists('name', $by) + || empty($by['name']) + || !is_string($by['name']) + ) { + throw new Exception\InvalidArgumentException('Invalid parameter: author array must include a' + . ' "name" key with a non-empty string value'); + } + $author['name'] = $by['name']; + if (isset($by['email'])) { + if (empty($by['email']) || !is_string($by['email'])) { + throw new Exception\InvalidArgumentException('Invalid parameter: "email" array' + . ' value must be a non-empty string'); + } + $author['email'] = $by['email']; + } + if (isset($by['uri'])) { + if (empty($by['uri']) + || !is_string($by['uri']) + || !Uri::factory($by['uri'])->isValid() + ) { + throw new Exception\InvalidArgumentException('Invalid parameter: "uri" array value must' + . ' be a non-empty string and valid URI/IRI'); + } + $author['uri'] = $by['uri']; + } + $this->data['by'] = $author; + + return $this; + } + + /** + * @return string + */ + public function getBy() + { + if (!array_key_exists('by', $this->data)) { + return null; + } + return $this->data['by']; + } + + /** + * @param string $comment + * @return Deleted + */ + public function setComment($comment) + { + $this->data['comment'] = $comment; + return $this; + } + + /** + * @return string + */ + public function getComment() + { + if (!array_key_exists('comment', $this->data)) { + return null; + } + return $this->data['comment']; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..88a6fea320e28a16cb6418657e04060e676a9eff --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Entry.php @@ -0,0 +1,767 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +use DateTime; +use Zend\Feed\Uri; +use Zend\Feed\Writer\Exception; + +/** +*/ +class Entry +{ + + /** + * Internal array containing all data associated with this entry or item. + * + * @var array + */ + protected $data = array(); + + /** + * Registered extensions + * + * @var array + */ + protected $extensions = array(); + + /** + * Holds the value "atom" or "rss" depending on the feed type set when + * when last exported. + * + * @var string + */ + protected $type = null; + + /** + * Constructor: Primarily triggers the registration of core extensions and + * loads those appropriate to this data container. + * + */ + public function __construct() + { + Writer::registerCoreExtensions(); + $this->_loadExtensions(); + } + + /** + * Set a single author + * + * The following option keys are supported: + * 'name' => (string) The name + * 'email' => (string) An optional email + * 'uri' => (string) An optional and valid URI + * + * @param array $author + * @throws Exception\InvalidArgumentException If any value of $author not follow the format. + * @return Entry + */ + public function addAuthor(array $author) + { + // Check array values + if (!array_key_exists('name', $author) + || empty($author['name']) + || !is_string($author['name']) + ) { + throw new Exception\InvalidArgumentException( + 'Invalid parameter: author array must include a "name" key with a non-empty string value'); + } + + if (isset($author['email'])) { + if (empty($author['email']) || !is_string($author['email'])) { + throw new Exception\InvalidArgumentException( + 'Invalid parameter: "email" array value must be a non-empty string'); + } + } + if (isset($author['uri'])) { + if (empty($author['uri']) || !is_string($author['uri']) || + !Uri::factory($author['uri'])->isValid() + ) { + throw new Exception\InvalidArgumentException( + 'Invalid parameter: "uri" array value must be a non-empty string and valid URI/IRI'); + } + } + + $this->data['authors'][] = $author; + + return $this; + } + + /** + * Set an array with feed authors + * + * @see addAuthor + * @param array $authors + * @return Entry + */ + public function addAuthors(array $authors) + { + foreach ($authors as $author) { + $this->addAuthor($author); + } + + return $this; + } + + /** + * Set the feed character encoding + * + * @param string $encoding + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setEncoding($encoding) + { + if (empty($encoding) || !is_string($encoding)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['encoding'] = $encoding; + + return $this; + } + + /** + * Get the feed character encoding + * + * @return string|null + */ + public function getEncoding() + { + if (!array_key_exists('encoding', $this->data)) { + return 'UTF-8'; + } + return $this->data['encoding']; + } + + /** + * Set the copyright entry + * + * @param string $copyright + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setCopyright($copyright) + { + if (empty($copyright) || !is_string($copyright)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['copyright'] = $copyright; + + return $this; + } + + /** + * Set the entry's content + * + * @param string $content + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setContent($content) + { + if (empty($content) || !is_string($content)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['content'] = $content; + + return $this; + } + + /** + * Set the feed creation date + * + * @param null|int|DateTime $date + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setDateCreated($date = null) + { + if ($date === null) { + $date = new DateTime(); + } elseif (is_int($date)) { + $date = new DateTime('@' . $date); + } elseif (!$date instanceof DateTime) { + throw new Exception\InvalidArgumentException('Invalid DateTime object or UNIX Timestamp passed as parameter'); + } + $this->data['dateCreated'] = $date; + + return $this; + } + + /** + * Set the feed modification date + * + * @param null|int|DateTime $date + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setDateModified($date = null) + { + if ($date === null) { + $date = new DateTime(); + } elseif (is_int($date)) { + $date = new DateTime('@' . $date); + } elseif (!$date instanceof DateTime) { + throw new Exception\InvalidArgumentException('Invalid DateTime object or UNIX Timestamp passed as parameter'); + } + $this->data['dateModified'] = $date; + + return $this; + } + + /** + * Set the feed description + * + * @param string $description + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setDescription($description) + { + if (empty($description) || !is_string($description)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['description'] = $description; + + return $this; + } + + /** + * Set the feed ID + * + * @param string $id + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setId($id) + { + if (empty($id) || !is_string($id)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['id'] = $id; + + return $this; + } + + /** + * Set a link to the HTML source of this entry + * + * @param string $link + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setLink($link) + { + if (empty($link) || !is_string($link) || !Uri::factory($link)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string and valid URI/IRI'); + } + $this->data['link'] = $link; + + return $this; + } + + /** + * Set the number of comments associated with this entry + * + * @param int $count + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setCommentCount($count) + { + if (!is_numeric($count) || (int) $count != $count || (int) $count < 0) { + throw new Exception\InvalidArgumentException('Invalid parameter: "count" must be a positive integer number or zero'); + } + $this->data['commentCount'] = (int) $count; + + return $this; + } + + /** + * Set a link to a HTML page containing comments associated with this entry + * + * @param string $link + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setCommentLink($link) + { + if (empty($link) || !is_string($link) || !Uri::factory($link)->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: "link" must be a non-empty string and valid URI/IRI'); + } + $this->data['commentLink'] = $link; + + return $this; + } + + /** + * Set a link to an XML feed for any comments associated with this entry + * + * @param array $link + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setCommentFeedLink(array $link) + { + if (!isset($link['uri']) || !is_string($link['uri']) || !Uri::factory($link['uri'])->isValid()) { + throw new Exception\InvalidArgumentException('Invalid parameter: "link" must be a non-empty string and valid URI/IRI'); + } + if (!isset($link['type']) || !in_array($link['type'], array('atom', 'rss', 'rdf'))) { + throw new Exception\InvalidArgumentException('Invalid parameter: "type" must be one' + . ' of "atom", "rss" or "rdf"'); + } + if (!isset($this->data['commentFeedLinks'])) { + $this->data['commentFeedLinks'] = array(); + } + $this->data['commentFeedLinks'][] = $link; + + return $this; + } + + /** + * Set a links to an XML feed for any comments associated with this entry. + * Each link is an array with keys "uri" and "type", where type is one of: + * "atom", "rss" or "rdf". + * + * @param array $links + * @return Entry + */ + public function setCommentFeedLinks(array $links) + { + foreach ($links as $link) { + $this->setCommentFeedLink($link); + } + + return $this; + } + + /** + * Set the feed title + * + * @param string $title + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setTitle($title) + { + if (empty($title) || !is_string($title)) { + throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); + } + $this->data['title'] = $title; + + return $this; + } + + /** + * Get an array with feed authors + * + * @return array + */ + public function getAuthors() + { + if (!array_key_exists('authors', $this->data)) { + return null; + } + return $this->data['authors']; + } + + /** + * Get the entry content + * + * @return string + */ + public function getContent() + { + if (!array_key_exists('content', $this->data)) { + return null; + } + return $this->data['content']; + } + + /** + * Get the entry copyright information + * + * @return string + */ + public function getCopyright() + { + if (!array_key_exists('copyright', $this->data)) { + return null; + } + return $this->data['copyright']; + } + + /** + * Get the entry creation date + * + * @return string + */ + public function getDateCreated() + { + if (!array_key_exists('dateCreated', $this->data)) { + return null; + } + return $this->data['dateCreated']; + } + + /** + * Get the entry modification date + * + * @return string + */ + public function getDateModified() + { + if (!array_key_exists('dateModified', $this->data)) { + return null; + } + return $this->data['dateModified']; + } + + /** + * Get the entry description + * + * @return string + */ + public function getDescription() + { + if (!array_key_exists('description', $this->data)) { + return null; + } + return $this->data['description']; + } + + /** + * Get the entry ID + * + * @return string + */ + public function getId() + { + if (!array_key_exists('id', $this->data)) { + return null; + } + return $this->data['id']; + } + + /** + * Get a link to the HTML source + * + * @return string|null + */ + public function getLink() + { + if (!array_key_exists('link', $this->data)) { + return null; + } + return $this->data['link']; + } + + + /** + * Get all links + * + * @return array + */ + public function getLinks() + { + if (!array_key_exists('links', $this->data)) { + return null; + } + return $this->data['links']; + } + + /** + * Get the entry title + * + * @return string + */ + public function getTitle() + { + if (!array_key_exists('title', $this->data)) { + return null; + } + return $this->data['title']; + } + + /** + * Get the number of comments/replies for current entry + * + * @return int + */ + public function getCommentCount() + { + if (!array_key_exists('commentCount', $this->data)) { + return null; + } + return $this->data['commentCount']; + } + + /** + * Returns a URI pointing to the HTML page where comments can be made on this entry + * + * @return string + */ + public function getCommentLink() + { + if (!array_key_exists('commentLink', $this->data)) { + return null; + } + return $this->data['commentLink']; + } + + /** + * Returns an array of URIs pointing to a feed of all comments for this entry + * where the array keys indicate the feed type (atom, rss or rdf). + * + * @return string + */ + public function getCommentFeedLinks() + { + if (!array_key_exists('commentFeedLinks', $this->data)) { + return null; + } + return $this->data['commentFeedLinks']; + } + + /** + * Add a entry category + * + * @param array $category + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function addCategory(array $category) + { + if (!isset($category['term'])) { + throw new Exception\InvalidArgumentException('Each category must be an array and ' + . 'contain at least a "term" element containing the machine ' + . ' readable category name'); + } + if (isset($category['scheme'])) { + if (empty($category['scheme']) + || !is_string($category['scheme']) + || !Uri::factory($category['scheme'])->isValid() + ) { + throw new Exception\InvalidArgumentException('The Atom scheme or RSS domain of' + . ' a category must be a valid URI'); + } + } + if (!isset($this->data['categories'])) { + $this->data['categories'] = array(); + } + $this->data['categories'][] = $category; + + return $this; + } + + /** + * Set an array of entry categories + * + * @param array $categories + * @return Entry + */ + public function addCategories(array $categories) + { + foreach ($categories as $category) { + $this->addCategory($category); + } + + return $this; + } + + /** + * Get the entry categories + * + * @return string|null + */ + public function getCategories() + { + if (!array_key_exists('categories', $this->data)) { + return null; + } + return $this->data['categories']; + } + + /** + * Adds an enclosure to the entry. The array parameter may contain the + * keys 'uri', 'type' and 'length'. Only 'uri' is required for Atom, though the + * others must also be provided or RSS rendering (where they are required) + * will throw an Exception. + * + * @param array $enclosure + * @throws Exception\InvalidArgumentException + * @return Entry + */ + public function setEnclosure(array $enclosure) + { + if (!isset($enclosure['uri'])) { + throw new Exception\InvalidArgumentException('Enclosure "uri" is not set'); + } + if (!Uri::factory($enclosure['uri'])->isValid()) { + throw new Exception\InvalidArgumentException('Enclosure "uri" is not a valid URI/IRI'); + } + $this->data['enclosure'] = $enclosure; + + return $this; + } + + /** + * Retrieve an array of all enclosures to be added to entry. + * + * @return array + */ + public function getEnclosure() + { + if (!array_key_exists('enclosure', $this->data)) { + return null; + } + return $this->data['enclosure']; + } + + /** + * Unset a specific data point + * + * @param string $name + * @return Entry + */ + public function remove($name) + { + if (isset($this->data[$name])) { + unset($this->data[$name]); + } + + return $this; + } + + /** + * Get registered extensions + * + * @return array + */ + public function getExtensions() + { + return $this->extensions; + } + + /** + * Return an Extension object with the matching name (postfixed with _Entry) + * + * @param string $name + * @return object + */ + public function getExtension($name) + { + if (array_key_exists($name . '\\Entry', $this->extensions)) { + return $this->extensions[$name . '\\Entry']; + } + return null; + } + + /** + * Set the current feed type being exported to "rss" or "atom". This allows + * other objects to gracefully choose whether to execute or not, depending + * on their appropriateness for the current type, e.g. renderers. + * + * @param string $type + * @return Entry + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * Retrieve the current or last feed type exported. + * + * @return string Value will be "rss" or "atom" + */ + public function getType() + { + return $this->type; + } + + /** + * Method overloading: call given method on first extension implementing it + * + * @param string $method + * @param array $args + * @return mixed + * @throws Exception\BadMethodCallException if no extensions implements the method + */ + public function __call($method, $args) + { + foreach ($this->extensions as $extension) { + try { + return call_user_func_array(array($extension, $method), $args); + } catch (\BadMethodCallException $e) { + } + } + throw new Exception\BadMethodCallException('Method: ' . $method + . ' does not exist and could not be located on a registered Extension'); + } + + /** + * Creates a new Zend\Feed\Writer\Source data container for use. This is NOT + * added to the current feed automatically, but is necessary to create a + * container with some initial values preset based on the current feed data. + * + * @return Source + */ + public function createSource() + { + $source = new Source; + if ($this->getEncoding()) { + $source->setEncoding($this->getEncoding()); + } + $source->setType($this->getType()); + return $source; + } + + /** + * Appends a Zend\Feed\Writer\Entry object representing a new entry/item + * the feed data container's internal group of entries. + * + * @param Source $source + * @return Entry + */ + public function setSource(Source $source) + { + $this->data['source'] = $source; + return $this; + } + + /** + * @return Source + */ + public function getSource() + { + if (isset($this->data['source'])) { + return $this->data['source']; + } + return null; + } + + /** + * Load extensions from Zend\Feed\Writer\Writer + * + * @return void + */ + protected function _loadExtensions() + { + $all = Writer::getExtensions(); + $manager = Writer::getExtensionManager(); + $exts = $all['entry']; + foreach ($exts as $ext) { + $this->extensions[$ext] = $manager->get($ext); + $this->extensions[$ext]->setEncoding($this->getEncoding()); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/BadMethodCallException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..e969d219e09bc03afd6817bf866042012896e8b0 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/BadMethodCallException.php @@ -0,0 +1,22 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Exception; + +use Zend\Feed\Exception; + +/** + * Feed exceptions + * + * Class to represent exceptions that occur during Feed operations. + */ +class BadMethodCallException + extends Exception\BadMethodCallException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/ExceptionInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..dbcd27964b2f976eb828a2a2cb9c312d24f5860e --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/ExceptionInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Exception; + +/** + * Feed exceptions + * + * Interface to represent exceptions that occur during Feed operations. + */ +interface ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/InvalidArgumentException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..971eead3862dfbbbd976c305ebd49be7a88b05b0 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/InvalidArgumentException.php @@ -0,0 +1,22 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Exception; + +use Zend\Feed\Exception; + +/** + * Feed exceptions + * + * Class to represent exceptions that occur during Feed operations. + */ +class InvalidArgumentException + extends Exception\InvalidArgumentException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/RuntimeException.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..2c37bdaf68bb547f00f8cd8e9d3e46286ba10a19 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Exception/RuntimeException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Exception; + +use Zend\Feed\Exception; + +class RuntimeException + extends Exception\RuntimeException + implements ExceptionInterface +{} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/AbstractRenderer.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/AbstractRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..7927e735ea070797dc40f3014bfa52e5a40e4f85 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/AbstractRenderer.php @@ -0,0 +1,164 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension; + +use DOMDocument; +use DOMElement; + +/** +*/ +abstract class AbstractRenderer implements RendererInterface +{ + /** + * @var DOMDocument + */ + protected $dom = null; + + /** + * @var mixed + */ + protected $entry = null; + + /** + * @var DOMElement + */ + protected $base = null; + + /** + * @var mixed + */ + protected $container = null; + + /** + * @var string + */ + protected $type = null; + + /** + * @var DOMElement + */ + protected $rootElement = null; + + /** + * Encoding of all text values + * + * @var string + */ + protected $encoding = 'UTF-8'; + + /** + * Set the data container + * + * @param mixed $container + * @return AbstractRenderer + */ + public function setDataContainer($container) + { + $this->container = $container; + return $this; + } + + /** + * Set feed encoding + * + * @param string $enc + * @return AbstractRenderer + */ + public function setEncoding($enc) + { + $this->encoding = $enc; + return $this; + } + + /** + * Get feed encoding + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Set DOMDocument and DOMElement on which to operate + * + * @param DOMDocument $dom + * @param DOMElement $base + * @return AbstractRenderer + */ + public function setDomDocument(DOMDocument $dom, DOMElement $base) + { + $this->dom = $dom; + $this->base = $base; + return $this; + } + + /** + * Get data container being rendered + * + * @return mixed + */ + public function getDataContainer() + { + return $this->container; + } + + /** + * Set feed type + * + * @param string $type + * @return AbstractRenderer + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * Get feedtype + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set root element of document + * + * @param DOMElement $root + * @return AbstractRenderer + */ + public function setRootElement(DOMElement $root) + { + $this->rootElement = $root; + return $this; + } + + /** + * Get root element + * + * @return DOMElement + */ + public function getRootElement() + { + return $this->rootElement; + } + + /** + * Append namespaces to feed + * + * @return void + */ + abstract protected function _appendNamespaces(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Atom/Renderer/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Atom/Renderer/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..1d7023e311d35de656b7f933d062d5ed6c522b18 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Atom/Renderer/Feed.php @@ -0,0 +1,109 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\Atom\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Feed extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render feed + * + * @return void + */ + public function render() + { + /** + * RSS 2.0 only. Used mainly to include Atom links and + * Pubsubhubbub Hub endpoint URIs under the Atom namespace + */ + if (strtolower($this->getType()) == 'atom') { + return; + } + $this->_setFeedLinks($this->dom, $this->base); + $this->_setHubs($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append namespaces to root element of feed + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:atom', + 'http://www.w3.org/2005/Atom'); + } + + /** + * Set feed link elements + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setFeedLinks(DOMDocument $dom, DOMElement $root) + { + $flinks = $this->getDataContainer()->getFeedLinks(); + if (!$flinks || empty($flinks)) { + return; + } + foreach ($flinks as $type => $href) { + if (strtolower($type) == $this->getType()) { // issue 2605 + $mime = 'application/' . strtolower($type) . '+xml'; + $flink = $dom->createElement('atom:link'); + $root->appendChild($flink); + $flink->setAttribute('rel', 'self'); + $flink->setAttribute('type', $mime); + $flink->setAttribute('href', $href); + } + } + $this->called = true; + } + + /** + * Set PuSH hubs + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setHubs(DOMDocument $dom, DOMElement $root) + { + $hubs = $this->getDataContainer()->getHubs(); + if (!$hubs || empty($hubs)) { + return; + } + foreach ($hubs as $hubUrl) { + $hub = $dom->createElement('atom:link'); + $hub->setAttribute('rel', 'hub'); + $hub->setAttribute('href', $hubUrl); + $root->appendChild($hub); + } + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Content/Renderer/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Content/Renderer/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..8785fb7320ba86c94ee3b80fd440c707535263e9 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Content/Renderer/Entry.php @@ -0,0 +1,76 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\Content\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Entry extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render entry + * + * @return void + */ + public function render() + { + if (strtolower($this->getType()) == 'atom') { + return; + } + $this->_setContent($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append namespaces to root element + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:content', + 'http://purl.org/rss/1.0/modules/content/'); + } + + /** + * Set entry content + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setContent(DOMDocument $dom, DOMElement $root) + { + $content = $this->getDataContainer()->getContent(); + if (!$content) { + return; + } + $element = $dom->createElement('content:encoded'); + $root->appendChild($element); + $cdata = $dom->createCDATASection($content); + $element->appendChild($cdata); + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/DublinCore/Renderer/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/DublinCore/Renderer/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..fffefd54f28a77667b54bb7ad03e664a93a81081 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/DublinCore/Renderer/Entry.php @@ -0,0 +1,80 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\DublinCore\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Entry extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render entry + * + * @return void + */ + public function render() + { + if (strtolower($this->getType()) == 'atom') { + return; + } + $this->_setAuthors($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append namespaces to entry + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:dc', + 'http://purl.org/dc/elements/1.1/'); + } + + /** + * Set entry author elements + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->getDataContainer()->getAuthors(); + if (!$authors || empty($authors)) { + return; + } + foreach ($authors as $data) { + $author = $this->dom->createElement('dc:creator'); + if (array_key_exists('name', $data)) { + $text = $dom->createTextNode($data['name']); + $author->appendChild($text); + $root->appendChild($author); + } + } + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/DublinCore/Renderer/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/DublinCore/Renderer/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..ceb3fac3f3d3e7c311e641539996973e65f1e31e --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/DublinCore/Renderer/Feed.php @@ -0,0 +1,80 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\DublinCore\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Feed extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render feed + * + * @return void + */ + public function render() + { + if (strtolower($this->getType()) == 'atom') { + return; + } + $this->_setAuthors($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append namespaces to feed element + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:dc', + 'http://purl.org/dc/elements/1.1/'); + } + + /** + * Set feed authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->getDataContainer()->getAuthors(); + if (!$authors || empty($authors)) { + return; + } + foreach ($authors as $data) { + $author = $this->dom->createElement('dc:creator'); + if (array_key_exists('name', $data)) { + $text = $dom->createTextNode($data['name']); + $author->appendChild($text); + $root->appendChild($author); + } + } + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..f136293e87381e815f051765b934a2b5bd2a2985 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Entry.php @@ -0,0 +1,246 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\ITunes; + +use Zend\Feed\Writer; +use Zend\Feed\Writer\Extension; +use Zend\Stdlib\StringUtils; +use Zend\Stdlib\StringWrapper\StringWrapperInterface; + +/** +*/ +class Entry +{ + /** + * Array of Feed data for rendering by Extension's renderers + * + * @var array + */ + protected $data = array(); + + /** + * Encoding of all text values + * + * @var string + */ + protected $encoding = 'UTF-8'; + + /** + * The used string wrapper supporting encoding + * + * @var StringWrapperInterface + */ + protected $stringWrapper; + + public function __construct() + { + $this->stringWrapper = StringUtils::getWrapper($this->encoding); + } + + /** + * Set feed encoding + * + * @param string $enc + * @return Entry + */ + public function setEncoding($enc) + { + $this->stringWrapper = StringUtils::getWrapper($enc); + $this->encoding = $enc; + return $this; + } + + /** + * Get feed encoding + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Set a block value of "yes" or "no". You may also set an empty string. + * + * @param string + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesBlock($value) + { + if (!ctype_alpha($value) && strlen($value) > 0) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "block" may only' + . ' contain alphabetic characters'); + } + + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "block" may only' + . ' contain a maximum of 255 characters'); + } + $this->data['block'] = $value; + } + + /** + * Add authors to itunes entry + * + * @param array $values + * @return Entry + */ + public function addItunesAuthors(array $values) + { + foreach ($values as $value) { + $this->addItunesAuthor($value); + } + return $this; + } + + /** + * Add author to itunes entry + * + * @param string $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function addItunesAuthor($value) + { + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "author" may only' + . ' contain a maximum of 255 characters each'); + } + if (!isset($this->data['authors'])) { + $this->data['authors'] = array(); + } + $this->data['authors'][] = $value; + return $this; + } + + /** + * Set duration + * + * @param int $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesDuration($value) + { + $value = (string) $value; + if (!ctype_digit($value) + && !preg_match("/^\d+:[0-5]{1}[0-9]{1}$/", $value) + && !preg_match("/^\d+:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}$/", $value) + ) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "duration" may only' + . ' be of a specified [[HH:]MM:]SS format'); + } + $this->data['duration'] = $value; + return $this; + } + + /** + * Set "explicit" flag + * + * @param bool $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesExplicit($value) + { + if (!in_array($value, array('yes', 'no', 'clean'))) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "explicit" may only' + . ' be one of "yes", "no" or "clean"'); + } + $this->data['explicit'] = $value; + return $this; + } + + /** + * Set keywords + * + * @param array $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesKeywords(array $value) + { + if (count($value) > 12) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only' + . ' contain a maximum of 12 terms'); + } + + $concat = implode(',', $value); + if ($this->stringWrapper->strlen($concat) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only' + . ' have a concatenated length of 255 chars where terms are delimited' + . ' by a comma'); + } + $this->data['keywords'] = $value; + return $this; + } + + /** + * Set subtitle + * + * @param string $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesSubtitle($value) + { + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "subtitle" may only' + . ' contain a maximum of 255 characters'); + } + $this->data['subtitle'] = $value; + return $this; + } + + /** + * Set summary + * + * @param string $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesSummary($value) + { + if ($this->stringWrapper->strlen($value) > 4000) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "summary" may only' + . ' contain a maximum of 4000 characters'); + } + $this->data['summary'] = $value; + return $this; + } + + /** + * Overloading to itunes specific setters + * + * @param string $method + * @param array $params + * @throws Writer\Exception\BadMethodCallException + * @return mixed + */ + public function __call($method, array $params) + { + $point = lcfirst(substr($method, 9)); + if (!method_exists($this, 'setItunes' . ucfirst($point)) + && !method_exists($this, 'addItunes' . ucfirst($point)) + ) { + throw new Writer\Exception\BadMethodCallException( + 'invalid method: ' . $method + ); + } + if (!array_key_exists($point, $this->data) + || empty($this->data[$point]) + ) { + return null; + } + return $this->data[$point]; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..7e6c5ac55e461928b3c45fd8f5246f1342ac3a6a --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Feed.php @@ -0,0 +1,362 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\ITunes; + +use Zend\Feed\Uri; +use Zend\Feed\Writer; +use Zend\Stdlib\StringUtils; +use Zend\Stdlib\StringWrapper\StringWrapperInterface; + +/** +*/ +class Feed +{ + /** + * Array of Feed data for rendering by Extension's renderers + * + * @var array + */ + protected $data = array(); + + /** + * Encoding of all text values + * + * @var string + */ + protected $encoding = 'UTF-8'; + + /** + * The used string wrapper supporting encoding + * + * @var StringWrapperInterface + */ + protected $stringWrapper; + + /** + * Constructor + */ + public function __construct() + { + $this->stringWrapper = StringUtils::getWrapper($this->encoding); + } + + /** + * Set feed encoding + * + * @param string $enc + * @return Feed + */ + public function setEncoding($enc) + { + $this->stringWrapper = StringUtils::getWrapper($enc); + $this->encoding = $enc; + return $this; + } + + /** + * Get feed encoding + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Set a block value of "yes" or "no". You may also set an empty string. + * + * @param string + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesBlock($value) + { + if (!ctype_alpha($value) && strlen($value) > 0) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "block" may only' + . ' contain alphabetic characters'); + } + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "block" may only' + . ' contain a maximum of 255 characters'); + } + $this->data['block'] = $value; + return $this; + } + + /** + * Add feed authors + * + * @param array $values + * @return Feed + */ + public function addItunesAuthors(array $values) + { + foreach ($values as $value) { + $this->addItunesAuthor($value); + } + return $this; + } + + /** + * Add feed author + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function addItunesAuthor($value) + { + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "author" may only' + . ' contain a maximum of 255 characters each'); + } + if (!isset($this->data['authors'])) { + $this->data['authors'] = array(); + } + $this->data['authors'][] = $value; + return $this; + } + + /** + * Set feed categories + * + * @param array $values + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesCategories(array $values) + { + if (!isset($this->data['categories'])) { + $this->data['categories'] = array(); + } + foreach ($values as $key => $value) { + if (!is_array($value)) { + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "category" may only' + . ' contain a maximum of 255 characters each'); + } + $this->data['categories'][] = $value; + } else { + if ($this->stringWrapper->strlen($key) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "category" may only' + . ' contain a maximum of 255 characters each'); + } + $this->data['categories'][$key] = array(); + foreach ($value as $val) { + if ($this->stringWrapper->strlen($val) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "category" may only' + . ' contain a maximum of 255 characters each'); + } + $this->data['categories'][$key][] = $val; + } + } + } + return $this; + } + + /** + * Set feed image (icon) + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesImage($value) + { + if (!Uri::factory($value)->isValid()) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "image" may only' + . ' be a valid URI/IRI'); + } + if (!in_array(substr($value, -3), array('jpg', 'png'))) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "image" may only' + . ' use file extension "jpg" or "png" which must be the last three' + . ' characters of the URI (i.e. no query string or fragment)'); + } + $this->data['image'] = $value; + return $this; + } + + /** + * Set feed cumulative duration + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesDuration($value) + { + $value = (string) $value; + if (!ctype_digit($value) + && !preg_match("/^\d+:[0-5]{1}[0-9]{1}$/", $value) + && !preg_match("/^\d+:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}$/", $value) + ) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "duration" may only' + . ' be of a specified [[HH:]MM:]SS format'); + } + $this->data['duration'] = $value; + return $this; + } + + /** + * Set "explicit" flag + * + * @param bool $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesExplicit($value) + { + if (!in_array($value, array('yes', 'no', 'clean'))) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "explicit" may only' + . ' be one of "yes", "no" or "clean"'); + } + $this->data['explicit'] = $value; + return $this; + } + + /** + * Set feed keywords + * + * @param array $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesKeywords(array $value) + { + if (count($value) > 12) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only' + . ' contain a maximum of 12 terms'); + } + $concat = implode(',', $value); + if ($this->stringWrapper->strlen($concat) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only' + . ' have a concatenated length of 255 chars where terms are delimited' + . ' by a comma'); + } + $this->data['keywords'] = $value; + return $this; + } + + /** + * Set new feed URL + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesNewFeedUrl($value) + { + if (!Uri::factory($value)->isValid()) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "newFeedUrl" may only' + . ' be a valid URI/IRI'); + } + $this->data['newFeedUrl'] = $value; + return $this; + } + + /** + * Add feed owners + * + * @param array $values + * @return Feed + */ + public function addItunesOwners(array $values) + { + foreach ($values as $value) { + $this->addItunesOwner($value); + } + return $this; + } + + /** + * Add feed owner + * + * @param array $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function addItunesOwner(array $value) + { + if (!isset($value['name']) || !isset($value['email'])) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "owner" must' + . ' be an array containing keys "name" and "email"'); + } + if ($this->stringWrapper->strlen($value['name']) > 255 + || $this->stringWrapper->strlen($value['email']) > 255 + ) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "owner" may only' + . ' contain a maximum of 255 characters each for "name" and "email"'); + } + if (!isset($this->data['owners'])) { + $this->data['owners'] = array(); + } + $this->data['owners'][] = $value; + return $this; + } + + /** + * Set feed subtitle + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesSubtitle($value) + { + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "subtitle" may only' + . ' contain a maximum of 255 characters'); + } + $this->data['subtitle'] = $value; + return $this; + } + + /** + * Set feed summary + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesSummary($value) + { + if ($this->stringWrapper->strlen($value) > 4000) { + throw new Writer\Exception\InvalidArgumentException('invalid parameter: "summary" may only' + . ' contain a maximum of 4000 characters'); + } + $this->data['summary'] = $value; + return $this; + } + + /** + * Overloading: proxy to internal setters + * + * @param string $method + * @param array $params + * @return mixed + * @throws Writer\Exception\BadMethodCallException + */ + public function __call($method, array $params) + { + $point = lcfirst(substr($method, 9)); + if (!method_exists($this, 'setItunes' . ucfirst($point)) + && !method_exists($this, 'addItunes' . ucfirst($point)) + ) { + throw new Writer\Exception\BadMethodCallException( + 'invalid method: ' . $method + ); + } + if (!array_key_exists($point, $this->data) || empty($this->data[$point])) { + return null; + } + return $this->data[$point]; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Renderer/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Renderer/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..b46d10c5373c57a4b4dad14cca62ceb51ec78a42 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Renderer/Entry.php @@ -0,0 +1,200 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\ITunes\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Entry extends Extension\AbstractRenderer +{ + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render entry + * + * @return void + */ + public function render() + { + $this->_setAuthors($this->dom, $this->base); + $this->_setBlock($this->dom, $this->base); + $this->_setDuration($this->dom, $this->base); + $this->_setExplicit($this->dom, $this->base); + $this->_setKeywords($this->dom, $this->base); + $this->_setSubtitle($this->dom, $this->base); + $this->_setSummary($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append namespaces to entry root + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:itunes', + 'http://www.itunes.com/dtds/podcast-1.0.dtd'); + } + + /** + * Set entry authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->getDataContainer()->getItunesAuthors(); + if (!$authors || empty($authors)) { + return; + } + foreach ($authors as $author) { + $el = $dom->createElement('itunes:author'); + $text = $dom->createTextNode($author); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + } + + /** + * Set itunes block + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setBlock(DOMDocument $dom, DOMElement $root) + { + $block = $this->getDataContainer()->getItunesBlock(); + if ($block === null) { + return; + } + $el = $dom->createElement('itunes:block'); + $text = $dom->createTextNode($block); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set entry duration + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDuration(DOMDocument $dom, DOMElement $root) + { + $duration = $this->getDataContainer()->getItunesDuration(); + if (!$duration) { + return; + } + $el = $dom->createElement('itunes:duration'); + $text = $dom->createTextNode($duration); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set explicit flag + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setExplicit(DOMDocument $dom, DOMElement $root) + { + $explicit = $this->getDataContainer()->getItunesExplicit(); + if ($explicit === null) { + return; + } + $el = $dom->createElement('itunes:explicit'); + $text = $dom->createTextNode($explicit); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set entry keywords + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setKeywords(DOMDocument $dom, DOMElement $root) + { + $keywords = $this->getDataContainer()->getItunesKeywords(); + if (!$keywords || empty($keywords)) { + return; + } + $el = $dom->createElement('itunes:keywords'); + $text = $dom->createTextNode(implode(',', $keywords)); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set entry subtitle + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setSubtitle(DOMDocument $dom, DOMElement $root) + { + $subtitle = $this->getDataContainer()->getItunesSubtitle(); + if (!$subtitle) { + return; + } + $el = $dom->createElement('itunes:subtitle'); + $text = $dom->createTextNode($subtitle); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set entry summary + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setSummary(DOMDocument $dom, DOMElement $root) + { + $summary = $this->getDataContainer()->getItunesSummary(); + if (!$summary) { + return; + } + $el = $dom->createElement('itunes:summary'); + $text = $dom->createTextNode($summary); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Renderer/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Renderer/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..9799681a0c3f99c1b65e1c41a67e30443ebf7fb6 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/ITunes/Renderer/Feed.php @@ -0,0 +1,304 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\ITunes\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Feed extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render feed + * + * @return void + */ + public function render() + { + $this->_setAuthors($this->dom, $this->base); + $this->_setBlock($this->dom, $this->base); + $this->_setCategories($this->dom, $this->base); + $this->_setImage($this->dom, $this->base); + $this->_setDuration($this->dom, $this->base); + $this->_setExplicit($this->dom, $this->base); + $this->_setKeywords($this->dom, $this->base); + $this->_setNewFeedUrl($this->dom, $this->base); + $this->_setOwners($this->dom, $this->base); + $this->_setSubtitle($this->dom, $this->base); + $this->_setSummary($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append feed namespaces + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:itunes', + 'http://www.itunes.com/dtds/podcast-1.0.dtd'); + } + + /** + * Set feed authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->getDataContainer()->getItunesAuthors(); + if (!$authors || empty($authors)) { + return; + } + foreach ($authors as $author) { + $el = $dom->createElement('itunes:author'); + $text = $dom->createTextNode($author); + $el->appendChild($text); + $root->appendChild($el); + } + $this->called = true; + } + + /** + * Set feed itunes block + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setBlock(DOMDocument $dom, DOMElement $root) + { + $block = $this->getDataContainer()->getItunesBlock(); + if ($block === null) { + return; + } + $el = $dom->createElement('itunes:block'); + $text = $dom->createTextNode($block); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set feed categories + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCategories(DOMDocument $dom, DOMElement $root) + { + $cats = $this->getDataContainer()->getItunesCategories(); + if (!$cats || empty($cats)) { + return; + } + foreach ($cats as $key => $cat) { + if (!is_array($cat)) { + $el = $dom->createElement('itunes:category'); + $el->setAttribute('text', $cat); + $root->appendChild($el); + } else { + $el = $dom->createElement('itunes:category'); + $el->setAttribute('text', $key); + $root->appendChild($el); + foreach ($cat as $subcat) { + $el2 = $dom->createElement('itunes:category'); + $el2->setAttribute('text', $subcat); + $el->appendChild($el2); + } + } + } + $this->called = true; + } + + /** + * Set feed image (icon) + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setImage(DOMDocument $dom, DOMElement $root) + { + $image = $this->getDataContainer()->getItunesImage(); + if (!$image) { + return; + } + $el = $dom->createElement('itunes:image'); + $el->setAttribute('href', $image); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set feed cumulative duration + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDuration(DOMDocument $dom, DOMElement $root) + { + $duration = $this->getDataContainer()->getItunesDuration(); + if (!$duration) { + return; + } + $el = $dom->createElement('itunes:duration'); + $text = $dom->createTextNode($duration); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set explicit flag + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setExplicit(DOMDocument $dom, DOMElement $root) + { + $explicit = $this->getDataContainer()->getItunesExplicit(); + if ($explicit === null) { + return; + } + $el = $dom->createElement('itunes:explicit'); + $text = $dom->createTextNode($explicit); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set feed keywords + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setKeywords(DOMDocument $dom, DOMElement $root) + { + $keywords = $this->getDataContainer()->getItunesKeywords(); + if (!$keywords || empty($keywords)) { + return; + } + $el = $dom->createElement('itunes:keywords'); + $text = $dom->createTextNode(implode(',', $keywords)); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set feed's new URL + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setNewFeedUrl(DOMDocument $dom, DOMElement $root) + { + $url = $this->getDataContainer()->getItunesNewFeedUrl(); + if (!$url) { + return; + } + $el = $dom->createElement('itunes:new-feed-url'); + $text = $dom->createTextNode($url); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set feed owners + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setOwners(DOMDocument $dom, DOMElement $root) + { + $owners = $this->getDataContainer()->getItunesOwners(); + if (!$owners || empty($owners)) { + return; + } + foreach ($owners as $owner) { + $el = $dom->createElement('itunes:owner'); + $name = $dom->createElement('itunes:name'); + $text = $dom->createTextNode($owner['name']); + $name->appendChild($text); + $email = $dom->createElement('itunes:email'); + $text = $dom->createTextNode($owner['email']); + $email->appendChild($text); + $root->appendChild($el); + $el->appendChild($name); + $el->appendChild($email); + } + $this->called = true; + } + + /** + * Set feed subtitle + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setSubtitle(DOMDocument $dom, DOMElement $root) + { + $subtitle = $this->getDataContainer()->getItunesSubtitle(); + if (!$subtitle) { + return; + } + $el = $dom->createElement('itunes:subtitle'); + $text = $dom->createTextNode($subtitle); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set feed summary + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setSummary(DOMDocument $dom, DOMElement $root) + { + $summary = $this->getDataContainer()->getItunesSummary(); + if (!$summary) { + return; + } + $el = $dom->createElement('itunes:summary'); + $text = $dom->createTextNode($summary); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/RendererInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/RendererInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..032313d6fd3f84ed85d599b302ac46506afbe296 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/RendererInterface.php @@ -0,0 +1,49 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension; + +use DOMDocument; +use DOMElement; + +/** +*/ +interface RendererInterface +{ + /** + * Set the data container + * + * @param mixed $container + * @return void + */ + public function setDataContainer($container); + + /** + * Retrieve container + * + * @return mixed + */ + public function getDataContainer(); + + /** + * Set DOMDocument and DOMElement on which to operate + * + * @param DOMDocument $dom + * @param DOMElement $base + * @return void + */ + public function setDomDocument(DOMDocument $dom, DOMElement $base); + + /** + * Render + * + * @return void + */ + public function render(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Slash/Renderer/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Slash/Renderer/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..80adb515a60153f54a197dbd8fa2ba6f119228d9 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Slash/Renderer/Entry.php @@ -0,0 +1,75 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\Slash\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Entry extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render entry + * + * @return void + */ + public function render() + { + if (strtolower($this->getType()) == 'atom') { + return; // RSS 2.0 only + } + $this->_setCommentCount($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append entry namespaces + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:slash', + 'http://purl.org/rss/1.0/modules/slash/'); + } + + /** + * Set entry comment count + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCommentCount(DOMDocument $dom, DOMElement $root) + { + $count = $this->getDataContainer()->getCommentCount(); + if (!$count) { + $count = 0; + } + $tcount = $this->dom->createElement('slash:comments'); + $tcount->nodeValue = $count; + $root->appendChild($tcount); + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Threading/Renderer/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Threading/Renderer/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..ee66b8f2635a58d4d4e96c820b5e56c5f6a8ce01 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/Threading/Renderer/Entry.php @@ -0,0 +1,129 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\Threading\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Entry extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render entry + * + * @return void + */ + public function render() + { + if (strtolower($this->getType()) == 'rss') { + return; // Atom 1.0 only + } + $this->_setCommentLink($this->dom, $this->base); + $this->_setCommentFeedLinks($this->dom, $this->base); + $this->_setCommentCount($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append entry namespaces + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:thr', + 'http://purl.org/syndication/thread/1.0'); + } + + /** + * Set comment link + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCommentLink(DOMDocument $dom, DOMElement $root) + { + $link = $this->getDataContainer()->getCommentLink(); + if (!$link) { + return; + } + $clink = $this->dom->createElement('link'); + $clink->setAttribute('rel', 'replies'); + $clink->setAttribute('type', 'text/html'); + $clink->setAttribute('href', $link); + $count = $this->getDataContainer()->getCommentCount(); + if ($count !== null) { + $clink->setAttribute('thr:count', $count); + } + $root->appendChild($clink); + $this->called = true; + } + + /** + * Set comment feed links + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCommentFeedLinks(DOMDocument $dom, DOMElement $root) + { + $links = $this->getDataContainer()->getCommentFeedLinks(); + if (!$links || empty($links)) { + return; + } + foreach ($links as $link) { + $flink = $this->dom->createElement('link'); + $flink->setAttribute('rel', 'replies'); + $flink->setAttribute('type', 'application/' . $link['type'] . '+xml'); + $flink->setAttribute('href', $link['uri']); + $count = $this->getDataContainer()->getCommentCount(); + if ($count !== null) { + $flink->setAttribute('thr:count', $count); + } + $root->appendChild($flink); + $this->called = true; + } + } + + /** + * Set entry comment count + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCommentCount(DOMDocument $dom, DOMElement $root) + { + $count = $this->getDataContainer()->getCommentCount(); + if ($count === null) { + return; + } + $tcount = $this->dom->createElement('thr:total'); + $tcount->nodeValue = $count; + $root->appendChild($tcount); + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/WellFormedWeb/Renderer/Entry.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/WellFormedWeb/Renderer/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..f5da0b0d27c6e168800ed36f2cbdaf22d9336707 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Extension/WellFormedWeb/Renderer/Entry.php @@ -0,0 +1,80 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Extension\WellFormedWeb\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer\Extension; + +/** +*/ +class Entry extends Extension\AbstractRenderer +{ + + /** + * Set to TRUE if a rendering method actually renders something. This + * is used to prevent premature appending of a XML namespace declaration + * until an element which requires it is actually appended. + * + * @var bool + */ + protected $called = false; + + /** + * Render entry + * + * @return void + */ + public function render() + { + if (strtolower($this->getType()) == 'atom') { + return; // RSS 2.0 only + } + $this->_setCommentFeedLinks($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append entry namespaces + * + * @return void + */ + protected function _appendNamespaces() + { + $this->getRootElement()->setAttribute('xmlns:wfw', + 'http://wellformedweb.org/CommentAPI/'); + } + + /** + * Set entry comment feed links + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCommentFeedLinks(DOMDocument $dom, DOMElement $root) + { + $links = $this->getDataContainer()->getCommentFeedLinks(); + if (!$links || empty($links)) { + return; + } + foreach ($links as $link) { + if ($link['type'] == 'rss') { + $flink = $this->dom->createElement('wfw:commentRss'); + $text = $dom->createTextNode($link['uri']); + $flink->appendChild($text); + $root->appendChild($flink); + } + } + $this->called = true; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionManager.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionManager.php new file mode 100644 index 0000000000000000000000000000000000000000..0bb4ce0ff03c660abb35a60b376bdf296a0bf40b --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionManager.php @@ -0,0 +1,80 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +/** + * Default implementation of ExtensionManagerInterface + * + * Decorator of ExtensionPluginManager. + */ +class ExtensionManager implements ExtensionManagerInterface +{ + protected $pluginManager; + + /** + * Constructor + * + * Seeds the extension manager with a plugin manager; if none provided, + * creates an instance. + * + * @param null|ExtensionPluginManager $pluginManager + */ + public function __construct(ExtensionPluginManager $pluginManager = null) + { + if (null === $pluginManager) { + $pluginManager = new ExtensionPluginManager(); + } + $this->pluginManager = $pluginManager; + } + + /** + * Method overloading + * + * Proxy to composed ExtensionPluginManager instance. + * + * @param string $method + * @param array $args + * @return mixed + * @throws Exception\BadMethodCallException + */ + public function __call($method, $args) + { + if (!method_exists($this->pluginManager, $method)) { + throw new Exception\BadMethodCallException(sprintf( + 'Method by name of %s does not exist in %s', + $method, + __CLASS__ + )); + } + return call_user_func_array(array($this->pluginManager, $method), $args); + } + + /** + * Get the named extension + * + * @param string $name + * @return Extension\AbstractEntry|Extension\AbstractFeed + */ + public function get($name) + { + return $this->pluginManager->get($name); + } + + /** + * Do we have the named extension? + * + * @param string $name + * @return bool + */ + public function has($name) + { + return $this->pluginManager->has($name); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionManagerInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..358e187a86ad6c780fcb140ad47df33f4dfda119 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionManagerInterface.php @@ -0,0 +1,29 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +interface ExtensionManagerInterface +{ + /** + * Do we have the extension? + * + * @param string $extension + * @return bool + */ + public function has($extension); + + /** + * Retrieve the extension + * + * @param string $extension + * @return mixed + */ + public function get($extension); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionPluginManager.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionPluginManager.php new file mode 100644 index 0000000000000000000000000000000000000000..575794eb3f5bb3bf02ab90f206b4ef76242324d7 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/ExtensionPluginManager.php @@ -0,0 +1,80 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +use Zend\ServiceManager\AbstractPluginManager; + +/** + * Plugin manager implementation for feed writer extensions + * + * Validation checks that we have an Entry, Feed, or Extension\AbstractRenderer. + */ +class ExtensionPluginManager extends AbstractPluginManager +{ + /** + * Default set of extension classes + * + * @var array + */ + protected $invokableClasses = array( + 'atomrendererfeed' => 'Zend\Feed\Writer\Extension\Atom\Renderer\Feed', + 'contentrendererentry' => 'Zend\Feed\Writer\Extension\Content\Renderer\Entry', + 'dublincorerendererentry' => 'Zend\Feed\Writer\Extension\DublinCore\Renderer\Entry', + 'dublincorerendererfeed' => 'Zend\Feed\Writer\Extension\DublinCore\Renderer\Feed', + 'itunesentry' => 'Zend\Feed\Writer\Extension\ITunes\Entry', + 'itunesfeed' => 'Zend\Feed\Writer\Extension\ITunes\Feed', + 'itunesrendererentry' => 'Zend\Feed\Writer\Extension\ITunes\Renderer\Entry', + 'itunesrendererfeed' => 'Zend\Feed\Writer\Extension\ITunes\Renderer\Feed', + 'slashrendererentry' => 'Zend\Feed\Writer\Extension\Slash\Renderer\Entry', + 'threadingrendererentry' => 'Zend\Feed\Writer\Extension\Threading\Renderer\Entry', + 'wellformedwebrendererentry' => 'Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry', + ); + + /** + * Do not share instances + * + * @var bool + */ + protected $shareByDefault = false; + + /** + * Validate the plugin + * + * Checks that the extension loaded is of a valid type. + * + * @param mixed $plugin + * @return void + * @throws Exception\InvalidArgumentException if invalid + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof Extension\AbstractRenderer) { + // we're okay + return; + } + + if ('Feed' == substr(get_class($plugin), -4)) { + // we're okay + return; + } + + if ('Entry' == substr(get_class($plugin), -5)) { + // we're okay + return; + } + + throw new Exception\InvalidArgumentException(sprintf( + 'Plugin of type %s is invalid; must implement %s\Extension\RendererInterface ' + . 'or the classname must end in "Feed" or "Entry"', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + __NAMESPACE__ + )); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Feed.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Feed.php new file mode 100644 index 0000000000000000000000000000000000000000..0922082c66cca6b8d6818e63da7609f50ae1c0aa --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Feed.php @@ -0,0 +1,241 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +use Countable; +use Iterator; +use Zend\Feed\Writer\Renderer; + +/** +*/ +class Feed extends AbstractFeed implements Iterator, Countable +{ + + /** + * Contains all entry objects + * + * @var array + */ + protected $entries = array(); + + /** + * A pointer for the iterator to keep track of the entries array + * + * @var int + */ + protected $entriesKey = 0; + + /** + * Creates a new Zend\Feed\Writer\Entry data container for use. This is NOT + * added to the current feed automatically, but is necessary to create a + * container with some initial values preset based on the current feed data. + * + * @return \Zend\Feed\Writer\Entry + */ + public function createEntry() + { + $entry = new Entry; + if ($this->getEncoding()) { + $entry->setEncoding($this->getEncoding()); + } + $entry->setType($this->getType()); + return $entry; + } + + /** + * Appends a Zend\Feed\Writer\Deleted object representing a new entry tombstone + * to the feed data container's internal group of entries. + * + * @param Deleted $deleted + * @return void + */ + public function addTombstone(Deleted $deleted) + { + $this->entries[] = $deleted; + } + + /** + * Creates a new Zend\Feed\Writer\Deleted data container for use. This is NOT + * added to the current feed automatically, but is necessary to create a + * container with some initial values preset based on the current feed data. + * + * @return Deleted + */ + public function createTombstone() + { + $deleted = new Deleted; + if ($this->getEncoding()) { + $deleted->setEncoding($this->getEncoding()); + } + $deleted->setType($this->getType()); + return $deleted; + } + + /** + * Appends a Zend\Feed\Writer\Entry object representing a new entry/item + * the feed data container's internal group of entries. + * + * @param Entry $entry + * @return Feed + */ + public function addEntry(Entry $entry) + { + $this->entries[] = $entry; + return $this; + } + + /** + * Removes a specific indexed entry from the internal queue. Entries must be + * added to a feed container in order to be indexed. + * + * @param int $index + * @throws Exception\InvalidArgumentException + * @return Feed + */ + public function removeEntry($index) + { + if (!isset($this->entries[$index])) { + throw new Exception\InvalidArgumentException('Undefined index: ' . $index . '. Entry does not exist.'); + } + unset($this->entries[$index]); + + return $this; + } + + /** + * Retrieve a specific indexed entry from the internal queue. Entries must be + * added to a feed container in order to be indexed. + * + * @param int $index + * @throws Exception\InvalidArgumentException + */ + public function getEntry($index = 0) + { + if (isset($this->entries[$index])) { + return $this->entries[$index]; + } + throw new Exception\InvalidArgumentException('Undefined index: ' . $index . '. Entry does not exist.'); + } + + /** + * Orders all indexed entries by date, thus offering date ordered readable + * content where a parser (or Homo Sapien) ignores the generic rule that + * XML element order is irrelevant and has no intrinsic meaning. + * + * Using this method will alter the original indexation. + * + * @return Feed + */ + public function orderByDate() + { + /** + * Could do with some improvement for performance perhaps + */ + $timestamp = time(); + $entries = array(); + foreach ($this->entries as $entry) { + if ($entry->getDateModified()) { + $timestamp = (int) $entry->getDateModified()->getTimestamp(); + } elseif ($entry->getDateCreated()) { + $timestamp = (int) $entry->getDateCreated()->getTimestamp(); + } + $entries[$timestamp] = $entry; + } + krsort($entries, SORT_NUMERIC); + $this->entries = array_values($entries); + + return $this; + } + + /** + * Get the number of feed entries. + * Required by the Iterator interface. + * + * @return int + */ + public function count() + { + return count($this->entries); + } + + /** + * Return the current entry + * + * @return Entry + */ + public function current() + { + return $this->entries[$this->key()]; + } + + /** + * Return the current feed key + * + * @return mixed + */ + public function key() + { + return $this->entriesKey; + } + + /** + * Move the feed pointer forward + * + * @return void + */ + public function next() + { + ++$this->entriesKey; + } + + /** + * Reset the pointer in the feed object + * + * @return void + */ + public function rewind() + { + $this->entriesKey = 0; + } + + /** + * Check to see if the iterator is still valid + * + * @return bool + */ + public function valid() + { + return 0 <= $this->entriesKey && $this->entriesKey < $this->count(); + } + + /** + * Attempt to build and return the feed resulting from the data set + * + * @param string $type The feed type "rss" or "atom" to export as + * @param bool $ignoreExceptions + * @throws Exception\InvalidArgumentException + * @return string + */ + public function export($type, $ignoreExceptions = false) + { + $this->setType(strtolower($type)); + $type = ucfirst($this->getType()); + if ($type !== 'Rss' && $type !== 'Atom') { + throw new Exception\InvalidArgumentException('Invalid feed type specified: ' . $type . '.' + . ' Should be one of "rss" or "atom".'); + } + $renderClass = 'Zend\\Feed\\Writer\\Renderer\\Feed\\' . $type; + $renderer = new $renderClass($this); + if ($ignoreExceptions) { + $renderer->ignoreExceptions(); + } + return $renderer->render()->saveXml(); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/FeedFactory.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/FeedFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..9cf8fbae6271a1a33c1a4d0aff83f6832d7de39a --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/FeedFactory.php @@ -0,0 +1,127 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +use Traversable; + +abstract class FeedFactory +{ + /** + * Create and return a Feed based on data provided. + * + * @param array|Traversable $data + * @throws Exception\InvalidArgumentException + * @return Feed + */ + public static function factory($data) + { + if (!is_array($data) && !$data instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + '%s expects an array or Traversable argument; received "%s"', + __METHOD__, + (is_object($data) ? get_class($data) : gettype($data)) + )); + } + + $feed = new Feed(); + + foreach ($data as $key => $value) { + // Setters + $key = static::convertKey($key); + $method = 'set' . $key; + if (method_exists($feed, $method)) { + switch ($method) { + case 'setfeedlink': + if (!is_array($value)) { + // Need an array + break; + } + if (!array_key_exists('link', $value) || !array_key_exists('type', $value)) { + // Need both keys to set this correctly + break; + } + $feed->setFeedLink($value['link'], $value['type']); + break; + default: + $feed->$method($value); + break; + } + continue; + } + + // Entries + if ('entries' == $key) { + static::createEntries($value, $feed); + continue; + } + } + + return $feed; + } + + /** + * Normalize a key + * + * @param string $key + * @return string + */ + protected static function convertKey($key) + { + $key = str_replace('_', '', strtolower($key)); + return $key; + } + + /** + * Create and attach entries to a feed + * + * @param array|Traversable $entries + * @param Feed $feed + * @throws Exception\InvalidArgumentException + * @return void + */ + protected static function createEntries($entries, Feed $feed) + { + if (!is_array($entries) && !$entries instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + '%s::factory expects the "entries" value to be an array or Traversable; received "%s"', + get_called_class(), + (is_object($entries) ? get_class($entries) : gettype($entries)) + )); + } + + foreach ($entries as $data) { + if (!is_array($data) && !$data instanceof Traversable && !$data instanceof Entry) { + throw new Exception\InvalidArgumentException(sprintf( + '%s expects an array, Traversable, or Zend\Feed\Writer\Entry argument; received "%s"', + __METHOD__, + (is_object($data) ? get_class($data) : gettype($data)) + )); + } + + // Use case 1: Entry item + if ($data instanceof Entry) { + $feed->addEntry($data); + continue; + } + + // Use case 2: iterate item and populate entry + $entry = $feed->createEntry(); + foreach ($data as $key => $value) { + $key = static::convertKey($key); + $method = 'set' . $key; + if (!method_exists($entry, $method)) { + continue; + } + $entry->$method($value); + } + $feed->addEntry($entry); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/AbstractRenderer.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/AbstractRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..f981f49a01365f8ff41c047238489027f2c28dea --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/AbstractRenderer.php @@ -0,0 +1,233 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer; + +/** +*/ +class AbstractRenderer +{ + /** + * Extensions + * @var array + */ + protected $extensions = array(); + + /** + * @var Writer\AbstractFeed + */ + protected $container = null; + + /** + * @var DOMDocument + */ + protected $dom = null; + + /** + * @var bool + */ + protected $ignoreExceptions = false; + + /** + * @var array + */ + protected $exceptions = array(); + + /** + * Encoding of all text values + * + * @var string + */ + protected $encoding = 'UTF-8'; + + /** + * Holds the value "atom" or "rss" depending on the feed type set when + * when last exported. + * + * @var string + */ + protected $type = null; + + /** + * @var DOMElement + */ + protected $rootElement = null; + + /** + * Constructor + * + * @param Writer\AbstractFeed $container + */ + public function __construct($container) + { + $this->container = $container; + $this->setType($container->getType()); + $this->_loadExtensions(); + } + + /** + * Save XML to string + * + * @return string + */ + public function saveXml() + { + return $this->getDomDocument()->saveXml(); + } + + /** + * Get DOM document + * + * @return DOMDocument + */ + public function getDomDocument() + { + return $this->dom; + } + + /** + * Get document element from DOM + * + * @return DOMElement + */ + public function getElement() + { + return $this->getDomDocument()->documentElement; + } + + /** + * Get data container of items being rendered + * + * @return Writer\AbstractFeed + */ + public function getDataContainer() + { + return $this->container; + } + + /** + * Set feed encoding + * + * @param string $enc + * @return AbstractRenderer + */ + public function setEncoding($enc) + { + $this->encoding = $enc; + return $this; + } + + /** + * Get feed encoding + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Indicate whether or not to ignore exceptions + * + * @param bool $bool + * @return AbstractRenderer + * @throws Writer\Exception\InvalidArgumentException + */ + public function ignoreExceptions($bool = true) + { + if (!is_bool($bool)) { + throw new Writer\Exception\InvalidArgumentException('Invalid parameter: $bool. Should be TRUE or FALSE (defaults to TRUE if null)'); + } + $this->ignoreExceptions = $bool; + return $this; + } + + /** + * Get exception list + * + * @return array + */ + public function getExceptions() + { + return $this->exceptions; + } + + /** + * Set the current feed type being exported to "rss" or "atom". This allows + * other objects to gracefully choose whether to execute or not, depending + * on their appropriateness for the current type, e.g. renderers. + * + * @param string $type + */ + public function setType($type) + { + $this->type = $type; + } + + /** + * Retrieve the current or last feed type exported. + * + * @return string Value will be "rss" or "atom" + */ + public function getType() + { + return $this->type; + } + + /** + * Sets the absolute root element for the XML feed being generated. This + * helps simplify the appending of namespace declarations, but also ensures + * namespaces are added to the root element - not scattered across the entire + * XML file - may assist namespace unsafe parsers and looks pretty ;). + * + * @param DOMElement $root + */ + public function setRootElement(DOMElement $root) + { + $this->rootElement = $root; + } + + /** + * Retrieve the absolute root element for the XML feed being generated. + * + * @return DOMElement + */ + public function getRootElement() + { + return $this->rootElement; + } + + /** + * Load extensions from Zend\Feed\Writer\Writer + * + * @return void + */ + protected function _loadExtensions() + { + Writer\Writer::registerCoreExtensions(); + $manager = Writer\Writer::getExtensionManager(); + $all = Writer\Writer::getExtensions(); + if (stripos(get_class($this), 'entry')) { + $exts = $all['entryRenderer']; + } else { + $exts = $all['feedRenderer']; + } + foreach ($exts as $extension) { + $plugin = $manager->get($extension); + $plugin->setDataContainer($this->getDataContainer()); + $plugin->setEncoding($this->getEncoding()); + $this->extensions[$extension] = $plugin; + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Atom.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Atom.php new file mode 100644 index 0000000000000000000000000000000000000000..1758f4ff68e7860f999c697cb2e85ec0f5f41ff8 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Atom.php @@ -0,0 +1,427 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Entry; + +use DateTime; +use DOMDocument; +use DOMElement; +use Zend\Feed\Uri; +use Zend\Feed\Writer; +use Zend\Feed\Writer\Renderer; +use Zend\Validator; + +class Atom extends Renderer\AbstractRenderer implements Renderer\RendererInterface +{ + /** + * Constructor + * + * @param Writer\Entry $container + */ + public function __construct (Writer\Entry $container) + { + parent::__construct($container); + } + + /** + * Render atom entry + * + * @return Atom + */ + public function render() + { + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $entry = $this->dom->createElementNS(Writer\Writer::NAMESPACE_ATOM_10, 'entry'); + $this->dom->appendChild($entry); + + $this->_setSource($this->dom, $entry); + $this->_setTitle($this->dom, $entry); + $this->_setDescription($this->dom, $entry); + $this->_setDateCreated($this->dom, $entry); + $this->_setDateModified($this->dom, $entry); + $this->_setLink($this->dom, $entry); + $this->_setId($this->dom, $entry); + $this->_setAuthors($this->dom, $entry); + $this->_setEnclosure($this->dom, $entry); + $this->_setContent($this->dom, $entry); + $this->_setCategories($this->dom, $entry); + + foreach ($this->extensions as $ext) { + $ext->setType($this->getType()); + $ext->setRootElement($this->getRootElement()); + $ext->setDOMDocument($this->getDOMDocument(), $entry); + $ext->render(); + } + + return $this; + } + + /** + * Set entry title + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setTitle(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getTitle()) { + $message = 'Atom 1.0 entry elements MUST contain exactly one' + . ' atom:title element but a title has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $title = $dom->createElement('title'); + $root->appendChild($title); + $title->setAttribute('type', 'html'); + $cdata = $dom->createCDATASection($this->getDataContainer()->getTitle()); + $title->appendChild($cdata); + } + + /** + * Set entry description + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDescription(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDescription()) { + return; // unless src content or base64 + } + $subtitle = $dom->createElement('summary'); + $root->appendChild($subtitle); + $subtitle->setAttribute('type', 'html'); + $cdata = $dom->createCDATASection( + $this->getDataContainer()->getDescription() + ); + $subtitle->appendChild($cdata); + } + + /** + * Set date entry was modified + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setDateModified(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateModified()) { + $message = 'Atom 1.0 entry elements MUST contain exactly one' + . ' atom:updated element but a modification date has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + $updated = $dom->createElement('updated'); + $root->appendChild($updated); + $text = $dom->createTextNode( + $this->getDataContainer()->getDateModified()->format(DateTime::ISO8601) + ); + $updated->appendChild($text); + } + + /** + * Set date entry was created + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDateCreated(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateCreated()) { + return; + } + $el = $dom->createElement('published'); + $root->appendChild($el); + $text = $dom->createTextNode( + $this->getDataContainer()->getDateCreated()->format(DateTime::ISO8601) + ); + $el->appendChild($text); + } + + /** + * Set entry authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->container->getAuthors(); + if ((!$authors || empty($authors))) { + /** + * This will actually trigger an Exception at the feed level if + * a feed level author is not set. + */ + return; + } + foreach ($authors as $data) { + $author = $this->dom->createElement('author'); + $name = $this->dom->createElement('name'); + $author->appendChild($name); + $root->appendChild($author); + $text = $dom->createTextNode($data['name']); + $name->appendChild($text); + if (array_key_exists('email', $data)) { + $email = $this->dom->createElement('email'); + $author->appendChild($email); + $text = $dom->createTextNode($data['email']); + $email->appendChild($text); + } + if (array_key_exists('uri', $data)) { + $uri = $this->dom->createElement('uri'); + $author->appendChild($uri); + $text = $dom->createTextNode($data['uri']); + $uri->appendChild($text); + } + } + } + + /** + * Set entry enclosure + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setEnclosure(DOMDocument $dom, DOMElement $root) + { + $data = $this->container->getEnclosure(); + if ((!$data || empty($data))) { + return; + } + $enclosure = $this->dom->createElement('link'); + $enclosure->setAttribute('rel', 'enclosure'); + if (isset($data['type'])) { + $enclosure->setAttribute('type', $data['type']); + } + if (isset($data['length'])) { + $enclosure->setAttribute('length', $data['length']); + } + $enclosure->setAttribute('href', $data['uri']); + $root->appendChild($enclosure); + } + + protected function _setLink(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getLink()) { + return; + } + $link = $dom->createElement('link'); + $root->appendChild($link); + $link->setAttribute('rel', 'alternate'); + $link->setAttribute('type', 'text/html'); + $link->setAttribute('href', $this->getDataContainer()->getLink()); + } + + /** + * Set entry identifier + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setId(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getId() + && !$this->getDataContainer()->getLink()) { + $message = 'Atom 1.0 entry elements MUST contain exactly one ' + . 'atom:id element, or as an alternative, we can use the same ' + . 'value as atom:link however neither a suitable link nor an ' + . 'id have been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + if (!$this->getDataContainer()->getId()) { + $this->getDataContainer()->setId( + $this->getDataContainer()->getLink()); + } + if (!Uri::factory($this->getDataContainer()->getId())->isValid() + && !preg_match( + "#^urn:[a-zA-Z0-9][a-zA-Z0-9\-]{1,31}:([a-zA-Z0-9\(\)\+\,\.\:\=\@\;\$\_\!\*\-]|%[0-9a-fA-F]{2})*#", + $this->getDataContainer()->getId()) + && !$this->_validateTagUri($this->getDataContainer()->getId()) + ) { + throw new Writer\Exception\InvalidArgumentException('Atom 1.0 IDs must be a valid URI/IRI'); + } + $id = $dom->createElement('id'); + $root->appendChild($id); + $text = $dom->createTextNode($this->getDataContainer()->getId()); + $id->appendChild($text); + } + + /** + * Validate a URI using the tag scheme (RFC 4151) + * + * @param string $id + * @return bool + */ + protected function _validateTagUri($id) + { + if (preg_match('/^tag:(?P<name>.*),(?P<date>\d{4}-?\d{0,2}-?\d{0,2}):(?P<specific>.*)(.*:)*$/', $id, $matches)) { + $dvalid = false; + $nvalid = false; + $date = $matches['date']; + $d6 = strtotime($date); + if ((strlen($date) == 4) && $date <= date('Y')) { + $dvalid = true; + } elseif ((strlen($date) == 7) && ($d6 < strtotime("now"))) { + $dvalid = true; + } elseif ((strlen($date) == 10) && ($d6 < strtotime("now"))) { + $dvalid = true; + } + $validator = new Validator\EmailAddress; + if ($validator->isValid($matches['name'])) { + $nvalid = true; + } else { + $nvalid = $validator->isValid('info@' . $matches['name']); + } + return $dvalid && $nvalid; + + } + return false; + } + + /** + * Set entry content + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setContent(DOMDocument $dom, DOMElement $root) + { + $content = $this->getDataContainer()->getContent(); + if (!$content && !$this->getDataContainer()->getLink()) { + $message = 'Atom 1.0 entry elements MUST contain exactly one ' + . 'atom:content element, or as an alternative, at least one link ' + . 'with a rel attribute of "alternate" to indicate an alternate ' + . 'method to consume the content.'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + if (!$content) { + return; + } + $element = $dom->createElement('content'); + $element->setAttribute('type', 'xhtml'); + $xhtmlElement = $this->_loadXhtml($content); + $xhtml = $dom->importNode($xhtmlElement, true); + $element->appendChild($xhtml); + $root->appendChild($element); + } + + /** + * Load a HTML string and attempt to normalise to XML + */ + protected function _loadXhtml($content) + { + $xhtml = ''; + if (class_exists('tidy', false)) { + $tidy = new \tidy; + $config = array( + 'output-xhtml' => true, + 'show-body-only' => true, + 'quote-nbsp' => false + ); + $encoding = str_replace('-', '', $this->getEncoding()); + $tidy->parseString($content, $config, $encoding); + $tidy->cleanRepair(); + $xhtml = (string) $tidy; + } else { + $xhtml = $content; + } + $xhtml = preg_replace(array( + "/(<[\/]?)([a-zA-Z]+)/" + ), '$1xhtml:$2', $xhtml); + $dom = new DOMDocument('1.0', $this->getEncoding()); + $dom->loadXML('<xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml">' + . $xhtml . '</xhtml:div>'); + return $dom->documentElement; + } + + /** + * Set entry categories + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCategories(DOMDocument $dom, DOMElement $root) + { + $categories = $this->getDataContainer()->getCategories(); + if (!$categories) { + return; + } + foreach ($categories as $cat) { + $category = $dom->createElement('category'); + $category->setAttribute('term', $cat['term']); + if (isset($cat['label'])) { + $category->setAttribute('label', $cat['label']); + } else { + $category->setAttribute('label', $cat['term']); + } + if (isset($cat['scheme'])) { + $category->setAttribute('scheme', $cat['scheme']); + } + $root->appendChild($category); + } + } + + /** + * Append Source element (Atom 1.0 Feed Metadata) + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setSource(DOMDocument $dom, DOMElement $root) + { + $source = $this->getDataContainer()->getSource(); + if (!$source) { + return; + } + $renderer = new Renderer\Feed\AtomSource($source); + $renderer->setType($this->getType()); + $element = $renderer->render()->getElement(); + $imported = $dom->importNode($element, true); + $root->appendChild($imported); + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php new file mode 100644 index 0000000000000000000000000000000000000000..679b6c48f42f8b9abc52e7e887ef37d96d144533 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php @@ -0,0 +1,102 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Entry\Atom; + +use DateTime; +use DOMDocument; +use DOMElement; + +class Deleted + extends \Zend\Feed\Writer\Renderer\AbstractRenderer + implements \Zend\Feed\Writer\Renderer\RendererInterface +{ + /** + * Constructor + * + * @param \Zend\Feed\Writer\Deleted $container + */ + public function __construct (\Zend\Feed\Writer\Deleted $container) + { + parent::__construct($container); + } + + /** + * Render atom entry + * + * @return \Zend\Feed\Writer\Renderer\Entry\Atom + */ + public function render() + { + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $entry = $this->dom->createElement('at:deleted-entry'); + $this->dom->appendChild($entry); + + $entry->setAttribute('ref', $this->container->getReference()); + $entry->setAttribute('when', $this->container->getWhen()->format(DateTime::ISO8601)); + + $this->_setBy($this->dom, $entry); + $this->_setComment($this->dom, $entry); + + return $this; + } + + /** + * Set tombstone comment + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setComment(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getComment()) { + return; + } + $c = $dom->createElement('at:comment'); + $root->appendChild($c); + $c->setAttribute('type', 'html'); + $cdata = $dom->createCDATASection($this->getDataContainer()->getComment()); + $c->appendChild($cdata); + } + + /** + * Set entry authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setBy(DOMDocument $dom, DOMElement $root) + { + $data = $this->container->getBy(); + if ((!$data || empty($data))) { + return; + } + $author = $this->dom->createElement('at:by'); + $name = $this->dom->createElement('name'); + $author->appendChild($name); + $root->appendChild($author); + $text = $dom->createTextNode($data['name']); + $name->appendChild($text); + if (array_key_exists('email', $data)) { + $email = $this->dom->createElement('email'); + $author->appendChild($email); + $text = $dom->createTextNode($data['email']); + $email->appendChild($text); + } + if (array_key_exists('uri', $data)) { + $uri = $this->dom->createElement('uri'); + $author->appendChild($uri); + $text = $dom->createTextNode($data['uri']); + $uri->appendChild($text); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/AtomDeleted.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/AtomDeleted.php new file mode 100644 index 0000000000000000000000000000000000000000..fd12eef586809fabd89930c1a980a2f995f773ba --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/AtomDeleted.php @@ -0,0 +1,104 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Entry; + +use DateTime; +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer; +use Zend\Feed\Writer\Renderer; + +/** +*/ +class AtomDeleted extends Renderer\AbstractRenderer implements Renderer\RendererInterface +{ + /** + * Constructor + * + * @param Writer\Deleted $container + */ + public function __construct (Writer\Deleted $container) + { + parent::__construct($container); + } + + /** + * Render atom entry + * + * @return \Zend\Feed\Writer\Renderer\Entry\Atom + */ + public function render() + { + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $entry = $this->dom->createElement('at:deleted-entry'); + $this->dom->appendChild($entry); + + $entry->setAttribute('ref', $this->container->getReference()); + $entry->setAttribute('when', $this->container->getWhen()->format(DateTime::ISO8601)); + + $this->_setBy($this->dom, $entry); + $this->_setComment($this->dom, $entry); + + return $this; + } + + /** + * Set tombstone comment + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setComment(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getComment()) { + return; + } + $c = $dom->createElement('at:comment'); + $root->appendChild($c); + $c->setAttribute('type', 'html'); + $cdata = $dom->createCDATASection($this->getDataContainer()->getComment()); + $c->appendChild($cdata); + } + + /** + * Set entry authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setBy(DOMDocument $dom, DOMElement $root) + { + $data = $this->container->getBy(); + if ((!$data || empty($data))) { + return; + } + $author = $this->dom->createElement('at:by'); + $name = $this->dom->createElement('name'); + $author->appendChild($name); + $root->appendChild($author); + $text = $dom->createTextNode($data['name']); + $name->appendChild($text); + if (array_key_exists('email', $data)) { + $email = $this->dom->createElement('email'); + $author->appendChild($email); + $text = $dom->createTextNode($data['email']); + $email->appendChild($text); + } + if (array_key_exists('uri', $data)) { + $uri = $this->dom->createElement('uri'); + $author->appendChild($uri); + $text = $dom->createTextNode($data['uri']); + $uri->appendChild($text); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Rss.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Rss.php new file mode 100644 index 0000000000000000000000000000000000000000..8d352c9c190edacbbfd07514b7164d8eab63e61e --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Entry/Rss.php @@ -0,0 +1,329 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Entry; + +use DateTime; +use DOMDocument; +use DOMElement; +use Zend\Feed\Uri; +use Zend\Feed\Writer; +use Zend\Feed\Writer\Renderer; + +/** +*/ +class Rss extends Renderer\AbstractRenderer implements Renderer\RendererInterface +{ + /** + * Constructor + * + * @param Writer\Entry $container + */ + public function __construct (Writer\Entry $container) + { + parent::__construct($container); + } + + /** + * Render RSS entry + * + * @return Rss + */ + public function render() + { + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $this->dom->substituteEntities = false; + $entry = $this->dom->createElement('item'); + $this->dom->appendChild($entry); + + $this->_setTitle($this->dom, $entry); + $this->_setDescription($this->dom, $entry); + $this->_setDateCreated($this->dom, $entry); + $this->_setDateModified($this->dom, $entry); + $this->_setLink($this->dom, $entry); + $this->_setId($this->dom, $entry); + $this->_setAuthors($this->dom, $entry); + $this->_setEnclosure($this->dom, $entry); + $this->_setCommentLink($this->dom, $entry); + $this->_setCategories($this->dom, $entry); + foreach ($this->extensions as $ext) { + $ext->setType($this->getType()); + $ext->setRootElement($this->getRootElement()); + $ext->setDOMDocument($this->getDOMDocument(), $entry); + $ext->render(); + } + + return $this; + } + + /** + * Set entry title + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setTitle(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDescription() + && !$this->getDataContainer()->getTitle()) { + $message = 'RSS 2.0 entry elements SHOULD contain exactly one' + . ' title element but a title has not been set. In addition, there' + . ' is no description as required in the absence of a title.'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $title = $dom->createElement('title'); + $root->appendChild($title); + $text = $dom->createTextNode($this->getDataContainer()->getTitle()); + $title->appendChild($text); + } + + /** + * Set entry description + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setDescription(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDescription() + && !$this->getDataContainer()->getTitle()) { + $message = 'RSS 2.0 entry elements SHOULD contain exactly one' + . ' description element but a description has not been set. In' + . ' addition, there is no title element as required in the absence' + . ' of a description.'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + if (!$this->getDataContainer()->getDescription()) { + return; + } + $subtitle = $dom->createElement('description'); + $root->appendChild($subtitle); + $text = $dom->createCDATASection($this->getDataContainer()->getDescription()); + $subtitle->appendChild($text); + } + + /** + * Set date entry was last modified + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDateModified(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateModified()) { + return; + } + + $updated = $dom->createElement('pubDate'); + $root->appendChild($updated); + $text = $dom->createTextNode( + $this->getDataContainer()->getDateModified()->format(DateTime::RSS) + ); + $updated->appendChild($text); + } + + /** + * Set date entry was created + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDateCreated(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateCreated()) { + return; + } + if (!$this->getDataContainer()->getDateModified()) { + $this->getDataContainer()->setDateModified( + $this->getDataContainer()->getDateCreated() + ); + } + } + + /** + * Set entry authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->container->getAuthors(); + if ((!$authors || empty($authors))) { + return; + } + foreach ($authors as $data) { + $author = $this->dom->createElement('author'); + $name = $data['name']; + if (array_key_exists('email', $data)) { + $name = $data['email'] . ' (' . $data['name'] . ')'; + } + $text = $dom->createTextNode($name); + $author->appendChild($text); + $root->appendChild($author); + } + } + + /** + * Set entry enclosure + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setEnclosure(DOMDocument $dom, DOMElement $root) + { + $data = $this->container->getEnclosure(); + if ((!$data || empty($data))) { + return; + } + if (!isset($data['type'])) { + $exception = new Writer\Exception\InvalidArgumentException('Enclosure "type" is not set'); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + if (!isset($data['length'])) { + $exception = new Writer\Exception\InvalidArgumentException('Enclosure "length" is not set'); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + if (isset($data['length']) && (int) $data['length'] <= 0) { + $exception = new Writer\Exception\InvalidArgumentException('Enclosure "length" must be an integer' + . ' indicating the content\'s length in bytes'); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $enclosure = $this->dom->createElement('enclosure'); + $enclosure->setAttribute('type', $data['type']); + $enclosure->setAttribute('length', $data['length']); + $enclosure->setAttribute('url', $data['uri']); + $root->appendChild($enclosure); + } + + /** + * Set link to entry + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setLink(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getLink()) { + return; + } + $link = $dom->createElement('link'); + $root->appendChild($link); + $text = $dom->createTextNode($this->getDataContainer()->getLink()); + $link->appendChild($text); + } + + /** + * Set entry identifier + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setId(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getId() + && !$this->getDataContainer()->getLink()) { + return; + } + + $id = $dom->createElement('guid'); + $root->appendChild($id); + if (!$this->getDataContainer()->getId()) { + $this->getDataContainer()->setId( + $this->getDataContainer()->getLink()); + } + $text = $dom->createTextNode($this->getDataContainer()->getId()); + $id->appendChild($text); + if (!Uri::factory($this->getDataContainer()->getId())->isValid()) { + $id->setAttribute('isPermaLink', 'false'); + } + } + + /** + * Set link to entry comments + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCommentLink(DOMDocument $dom, DOMElement $root) + { + $link = $this->getDataContainer()->getCommentLink(); + if (!$link) { + return; + } + $clink = $this->dom->createElement('comments'); + $text = $dom->createTextNode($link); + $clink->appendChild($text); + $root->appendChild($clink); + } + + /** + * Set entry categories + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCategories(DOMDocument $dom, DOMElement $root) + { + $categories = $this->getDataContainer()->getCategories(); + if (!$categories) { + return; + } + foreach ($categories as $cat) { + $category = $dom->createElement('category'); + if (isset($cat['scheme'])) { + $category->setAttribute('domain', $cat['scheme']); + } + $text = $dom->createCDATASection($cat['term']); + $category->appendChild($text); + $root->appendChild($category); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/AbstractAtom.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/AbstractAtom.php new file mode 100644 index 0000000000000000000000000000000000000000..2ff11129ac49849dafd8d4691aab8f09906b7044 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/AbstractAtom.php @@ -0,0 +1,403 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Feed; + +use DateTime; +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer; +use Zend\Feed\Writer\Renderer; +use Zend\Feed\Writer\Version; + +/** +*/ +class AbstractAtom extends Renderer\AbstractRenderer +{ + /** + * Constructor + * + * @param Writer\AbstractFeed $container + */ + public function __construct($container) + { + parent::__construct($container); + } + + /** + * Set feed language + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setLanguage(DOMDocument $dom, DOMElement $root) + { + if ($this->getDataContainer()->getLanguage()) { + $root->setAttribute('xml:lang', $this->getDataContainer() + ->getLanguage()); + } + } + + /** + * Set feed title + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setTitle(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getTitle()) { + $message = 'Atom 1.0 feed elements MUST contain exactly one' + . ' atom:title element but a title has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + $title = $dom->createElement('title'); + $root->appendChild($title); + $title->setAttribute('type', 'text'); + $text = $dom->createTextNode($this->getDataContainer()->getTitle()); + $title->appendChild($text); + } + + /** + * Set feed description + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDescription(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDescription()) { + return; + } + $subtitle = $dom->createElement('subtitle'); + $root->appendChild($subtitle); + $subtitle->setAttribute('type', 'text'); + $text = $dom->createTextNode($this->getDataContainer()->getDescription()); + $subtitle->appendChild($text); + } + + /** + * Set date feed was last modified + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setDateModified(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateModified()) { + $message = 'Atom 1.0 feed elements MUST contain exactly one' + . ' atom:updated element but a modification date has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + $updated = $dom->createElement('updated'); + $root->appendChild($updated); + $text = $dom->createTextNode( + $this->getDataContainer()->getDateModified()->format(DateTime::ISO8601) + ); + $updated->appendChild($text); + } + + /** + * Set feed generator string + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setGenerator(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getGenerator()) { + $this->getDataContainer()->setGenerator('Zend_Feed_Writer', + Version::VERSION, 'http://framework.zend.com'); + } + + $gdata = $this->getDataContainer()->getGenerator(); + $generator = $dom->createElement('generator'); + $root->appendChild($generator); + $text = $dom->createTextNode($gdata['name']); + $generator->appendChild($text); + if (array_key_exists('uri', $gdata)) { + $generator->setAttribute('uri', $gdata['uri']); + } + if (array_key_exists('version', $gdata)) { + $generator->setAttribute('version', $gdata['version']); + } + } + + /** + * Set link to feed + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setLink(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getLink()) { + return; + } + $link = $dom->createElement('link'); + $root->appendChild($link); + $link->setAttribute('rel', 'alternate'); + $link->setAttribute('type', 'text/html'); + $link->setAttribute('href', $this->getDataContainer()->getLink()); + } + + /** + * Set feed links + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setFeedLinks(DOMDocument $dom, DOMElement $root) + { + $flinks = $this->getDataContainer()->getFeedLinks(); + if (!$flinks || !array_key_exists('atom', $flinks)) { + $message = 'Atom 1.0 feed elements SHOULD contain one atom:link ' + . 'element with a rel attribute value of "self". This is the ' + . 'preferred URI for retrieving Atom Feed Documents representing ' + . 'this Atom feed but a feed link has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + foreach ($flinks as $type => $href) { + $mime = 'application/' . strtolower($type) . '+xml'; + $flink = $dom->createElement('link'); + $root->appendChild($flink); + $flink->setAttribute('rel', 'self'); + $flink->setAttribute('type', $mime); + $flink->setAttribute('href', $href); + } + } + + /** + * Set feed authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->container->getAuthors(); + if (!$authors || empty($authors)) { + /** + * Technically we should defer an exception until we can check + * that all entries contain an author. If any entry is missing + * an author, then a missing feed author element is invalid + */ + return; + } + foreach ($authors as $data) { + $author = $this->dom->createElement('author'); + $name = $this->dom->createElement('name'); + $author->appendChild($name); + $root->appendChild($author); + $text = $dom->createTextNode($data['name']); + $name->appendChild($text); + if (array_key_exists('email', $data)) { + $email = $this->dom->createElement('email'); + $author->appendChild($email); + $text = $dom->createTextNode($data['email']); + $email->appendChild($text); + } + if (array_key_exists('uri', $data)) { + $uri = $this->dom->createElement('uri'); + $author->appendChild($uri); + $text = $dom->createTextNode($data['uri']); + $uri->appendChild($text); + } + } + } + + /** + * Set feed identifier + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setId(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getId() + && !$this->getDataContainer()->getLink()) { + $message = 'Atom 1.0 feed elements MUST contain exactly one ' + . 'atom:id element, or as an alternative, we can use the same ' + . 'value as atom:link however neither a suitable link nor an ' + . 'id have been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + if (!$this->getDataContainer()->getId()) { + $this->getDataContainer()->setId( + $this->getDataContainer()->getLink()); + } + $id = $dom->createElement('id'); + $root->appendChild($id); + $text = $dom->createTextNode($this->getDataContainer()->getId()); + $id->appendChild($text); + } + + /** + * Set feed copyright + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCopyright(DOMDocument $dom, DOMElement $root) + { + $copyright = $this->getDataContainer()->getCopyright(); + if (!$copyright) { + return; + } + $copy = $dom->createElement('rights'); + $root->appendChild($copy); + $text = $dom->createTextNode($copyright); + $copy->appendChild($text); + } + + /** + * Set feed level logo (image) + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setImage(DOMDocument $dom, DOMElement $root) + { + $image = $this->getDataContainer()->getImage(); + if (!$image) { + return; + } + $img = $dom->createElement('logo'); + $root->appendChild($img); + $text = $dom->createTextNode($image['uri']); + $img->appendChild($text); + } + + /** + * Set date feed was created + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDateCreated(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateCreated()) { + return; + } + if (!$this->getDataContainer()->getDateModified()) { + $this->getDataContainer()->setDateModified( + $this->getDataContainer()->getDateCreated() + ); + } + } + + /** + * Set base URL to feed links + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setBaseUrl(DOMDocument $dom, DOMElement $root) + { + $baseUrl = $this->getDataContainer()->getBaseUrl(); + if (!$baseUrl) { + return; + } + $root->setAttribute('xml:base', $baseUrl); + } + + /** + * Set hubs to which this feed pushes + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setHubs(DOMDocument $dom, DOMElement $root) + { + $hubs = $this->getDataContainer()->getHubs(); + if (!$hubs) { + return; + } + foreach ($hubs as $hubUrl) { + $hub = $dom->createElement('link'); + $hub->setAttribute('rel', 'hub'); + $hub->setAttribute('href', $hubUrl); + $root->appendChild($hub); + } + } + + /** + * Set feed categories + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCategories(DOMDocument $dom, DOMElement $root) + { + $categories = $this->getDataContainer()->getCategories(); + if (!$categories) { + return; + } + foreach ($categories as $cat) { + $category = $dom->createElement('category'); + $category->setAttribute('term', $cat['term']); + if (isset($cat['label'])) { + $category->setAttribute('label', $cat['label']); + } else { + $category->setAttribute('label', $cat['term']); + } + if (isset($cat['scheme'])) { + $category->setAttribute('scheme', $cat['scheme']); + } + $root->appendChild($category); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom.php new file mode 100644 index 0000000000000000000000000000000000000000..78abdd55a17d1781dd6301e23675f1efde6e23da --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom.php @@ -0,0 +1,96 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Feed; + +use DOMDocument; +use Zend\Feed\Writer; +use Zend\Feed\Writer\Renderer; + +/** +*/ +class Atom extends AbstractAtom implements Renderer\RendererInterface +{ + /** + * Constructor + * + * @param Writer\Feed $container + */ + public function __construct (Writer\Feed $container) + { + parent::__construct($container); + } + + /** + * Render Atom feed + * + * @return Atom + */ + public function render() + { + if (!$this->container->getEncoding()) { + $this->container->setEncoding('UTF-8'); + } + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $root = $this->dom->createElementNS( + Writer\Writer::NAMESPACE_ATOM_10, 'feed' + ); + $this->setRootElement($root); + $this->dom->appendChild($root); + $this->_setLanguage($this->dom, $root); + $this->_setBaseUrl($this->dom, $root); + $this->_setTitle($this->dom, $root); + $this->_setDescription($this->dom, $root); + $this->_setImage($this->dom, $root); + $this->_setDateCreated($this->dom, $root); + $this->_setDateModified($this->dom, $root); + $this->_setGenerator($this->dom, $root); + $this->_setLink($this->dom, $root); + $this->_setFeedLinks($this->dom, $root); + $this->_setId($this->dom, $root); + $this->_setAuthors($this->dom, $root); + $this->_setCopyright($this->dom, $root); + $this->_setCategories($this->dom, $root); + $this->_setHubs($this->dom, $root); + + foreach ($this->extensions as $ext) { + $ext->setType($this->getType()); + $ext->setRootElement($this->getRootElement()); + $ext->setDOMDocument($this->getDOMDocument(), $root); + $ext->render(); + } + + foreach ($this->container as $entry) { + if ($this->getDataContainer()->getEncoding()) { + $entry->setEncoding($this->getDataContainer()->getEncoding()); + } + if ($entry instanceof Writer\Entry) { + $renderer = new Renderer\Entry\Atom($entry); + } else { + if (!$this->dom->documentElement->hasAttribute('xmlns:at')) { + $this->dom->documentElement->setAttribute( + 'xmlns:at', 'http://purl.org/atompub/tombstones/1.0' + ); + } + $renderer = new Renderer\Entry\AtomDeleted($entry); + } + if ($this->ignoreExceptions === true) { + $renderer->ignoreExceptions(); + } + $renderer->setType($this->getType()); + $renderer->setRootElement($this->dom->documentElement); + $renderer->render(); + $element = $renderer->getElement(); + $imported = $this->dom->importNode($element, true); + $root->appendChild($imported); + } + return $this; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom/AbstractAtom.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom/AbstractAtom.php new file mode 100644 index 0000000000000000000000000000000000000000..a36dab28eaf3ce2734d76e1cc5cfabd7b1f11a16 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom/AbstractAtom.php @@ -0,0 +1,400 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Feed\Atom; + +use Datetime; +use DOMDocument; +use DOMElement; +use Zend\Feed; +use Zend\Feed\Writer\Version; + +class AbstractAtom extends Feed\Writer\Renderer\AbstractRenderer +{ + /** + * Constructor + * + * @param \Zend\Feed\Writer\Feed $container + */ + public function __construct ($container) + { + parent::__construct($container); + } + + /** + * Set feed language + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setLanguage(DOMDocument $dom, DOMElement $root) + { + if ($this->getDataContainer()->getLanguage()) { + $root->setAttribute('xml:lang', $this->getDataContainer() + ->getLanguage()); + } + } + + /** + * Set feed title + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Feed\Exception\InvalidArgumentException + */ + protected function _setTitle(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getTitle()) { + $message = 'Atom 1.0 feed elements MUST contain exactly one' + . ' atom:title element but a title has not been set'; + $exception = new Feed\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + $title = $dom->createElement('title'); + $root->appendChild($title); + $title->setAttribute('type', 'text'); + $text = $dom->createTextNode($this->getDataContainer()->getTitle()); + $title->appendChild($text); + } + + /** + * Set feed description + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDescription(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDescription()) { + return; + } + $subtitle = $dom->createElement('subtitle'); + $root->appendChild($subtitle); + $subtitle->setAttribute('type', 'text'); + $text = $dom->createTextNode($this->getDataContainer()->getDescription()); + $subtitle->appendChild($text); + } + + /** + * Set date feed was last modified + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Feed\Exception\InvalidArgumentException + */ + protected function _setDateModified(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateModified()) { + $message = 'Atom 1.0 feed elements MUST contain exactly one' + . ' atom:updated element but a modification date has not been set'; + $exception = new Feed\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + $updated = $dom->createElement('updated'); + $root->appendChild($updated); + $text = $dom->createTextNode( + $this->getDataContainer()->getDateModified()->format(DateTime::ISO8601) + ); + $updated->appendChild($text); + } + + /** + * Set feed generator string + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setGenerator(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getGenerator()) { + $this->getDataContainer()->setGenerator('Zend_Feed_Writer', + Version::VERSION, 'http://framework.zend.com'); + } + + $gdata = $this->getDataContainer()->getGenerator(); + $generator = $dom->createElement('generator'); + $root->appendChild($generator); + $text = $dom->createTextNode($gdata['name']); + $generator->appendChild($text); + if (array_key_exists('uri', $gdata)) { + $generator->setAttribute('uri', $gdata['uri']); + } + if (array_key_exists('version', $gdata)) { + $generator->setAttribute('version', $gdata['version']); + } + } + + /** + * Set link to feed + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setLink(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getLink()) { + return; + } + $link = $dom->createElement('link'); + $root->appendChild($link); + $link->setAttribute('rel', 'alternate'); + $link->setAttribute('type', 'text/html'); + $link->setAttribute('href', $this->getDataContainer()->getLink()); + } + + /** + * Set feed links + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Feed\Exception\InvalidArgumentException + */ + protected function _setFeedLinks(DOMDocument $dom, DOMElement $root) + { + $flinks = $this->getDataContainer()->getFeedLinks(); + if (!$flinks || !array_key_exists('atom', $flinks)) { + $message = 'Atom 1.0 feed elements SHOULD contain one atom:link ' + . 'element with a rel attribute value of "self". This is the ' + . 'preferred URI for retrieving Atom Feed Documents representing ' + . 'this Atom feed but a feed link has not been set'; + $exception = new Feed\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + foreach ($flinks as $type => $href) { + $mime = 'application/' . strtolower($type) . '+xml'; + $flink = $dom->createElement('link'); + $root->appendChild($flink); + $flink->setAttribute('rel', 'self'); + $flink->setAttribute('type', $mime); + $flink->setAttribute('href', $href); + } + } + + /** + * Set feed authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->container->getAuthors(); + if (!$authors || empty($authors)) { + /** + * Technically we should defer an exception until we can check + * that all entries contain an author. If any entry is missing + * an author, then a missing feed author element is invalid + */ + return; + } + foreach ($authors as $data) { + $author = $this->dom->createElement('author'); + $name = $this->dom->createElement('name'); + $author->appendChild($name); + $root->appendChild($author); + $text = $dom->createTextNode($data['name']); + $name->appendChild($text); + if (array_key_exists('email', $data)) { + $email = $this->dom->createElement('email'); + $author->appendChild($email); + $text = $dom->createTextNode($data['email']); + $email->appendChild($text); + } + if (array_key_exists('uri', $data)) { + $uri = $this->dom->createElement('uri'); + $author->appendChild($uri); + $text = $dom->createTextNode($data['uri']); + $uri->appendChild($text); + } + } + } + + /** + * Set feed identifier + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Feed\Exception\InvalidArgumentException + */ + protected function _setId(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getId() + && !$this->getDataContainer()->getLink()) { + $message = 'Atom 1.0 feed elements MUST contain exactly one ' + . 'atom:id element, or as an alternative, we can use the same ' + . 'value as atom:link however neither a suitable link nor an ' + . 'id have been set'; + $exception = new Feed\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + if (!$this->getDataContainer()->getId()) { + $this->getDataContainer()->setId( + $this->getDataContainer()->getLink()); + } + $id = $dom->createElement('id'); + $root->appendChild($id); + $text = $dom->createTextNode($this->getDataContainer()->getId()); + $id->appendChild($text); + } + + /** + * Set feed copyright + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCopyright(DOMDocument $dom, DOMElement $root) + { + $copyright = $this->getDataContainer()->getCopyright(); + if (!$copyright) { + return; + } + $copy = $dom->createElement('rights'); + $root->appendChild($copy); + $text = $dom->createTextNode($copyright); + $copy->appendChild($text); + } + /** + * Set feed level logo (image) + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setImage(DOMDocument $dom, DOMElement $root) + { + $image = $this->getDataContainer()->getImage(); + if (!$image) { + return; + } + $img = $dom->createElement('logo'); + $root->appendChild($img); + $text = $dom->createTextNode($image['uri']); + $img->appendChild($text); + } + + + /** + * Set date feed was created + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDateCreated(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateCreated()) { + return; + } + if (!$this->getDataContainer()->getDateModified()) { + $this->getDataContainer()->setDateModified( + $this->getDataContainer()->getDateCreated() + ); + } + } + + /** + * Set base URL to feed links + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setBaseUrl(DOMDocument $dom, DOMElement $root) + { + $baseUrl = $this->getDataContainer()->getBaseUrl(); + if (!$baseUrl) { + return; + } + $root->setAttribute('xml:base', $baseUrl); + } + + /** + * Set hubs to which this feed pushes + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setHubs(DOMDocument $dom, DOMElement $root) + { + $hubs = $this->getDataContainer()->getHubs(); + if (!$hubs) { + return; + } + foreach ($hubs as $hubUrl) { + $hub = $dom->createElement('link'); + $hub->setAttribute('rel', 'hub'); + $hub->setAttribute('href', $hubUrl); + $root->appendChild($hub); + } + } + + /** + * Set feed categories + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCategories(DOMDocument $dom, DOMElement $root) + { + $categories = $this->getDataContainer()->getCategories(); + if (!$categories) { + return; + } + foreach ($categories as $cat) { + $category = $dom->createElement('category'); + $category->setAttribute('term', $cat['term']); + if (isset($cat['label'])) { + $category->setAttribute('label', $cat['label']); + } else { + $category->setAttribute('label', $cat['term']); + } + if (isset($cat['scheme'])) { + $category->setAttribute('scheme', $cat['scheme']); + } + $root->appendChild($category); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom/Source.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom/Source.php new file mode 100644 index 0000000000000000000000000000000000000000..f9fbf2d957f96c41c52638fb6024970f84fa1bb8 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Atom/Source.php @@ -0,0 +1,91 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Feed\Atom; + +use DOMDocument; +use DOMElement; + +class Source extends AbstractAtom implements \Zend\Feed\Writer\Renderer\RendererInterface +{ + + /** + * Constructor + * + * @param \Zend\Feed\Writer\Source $container + */ + public function __construct (\Zend\Feed\Writer\Source $container) + { + parent::__construct($container); + } + + /** + * Render Atom Feed Metadata (Source element) + * + * @return \Zend\Feed\Writer\Renderer\Feed\Atom + */ + public function render() + { + if (!$this->container->getEncoding()) { + $this->container->setEncoding('UTF-8'); + } + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $root = $this->dom->createElement('source'); + $this->setRootElement($root); + $this->dom->appendChild($root); + $this->_setLanguage($this->dom, $root); + $this->_setBaseUrl($this->dom, $root); + $this->_setTitle($this->dom, $root); + $this->_setDescription($this->dom, $root); + $this->_setDateCreated($this->dom, $root); + $this->_setDateModified($this->dom, $root); + $this->_setGenerator($this->dom, $root); + $this->_setLink($this->dom, $root); + $this->_setFeedLinks($this->dom, $root); + $this->_setId($this->dom, $root); + $this->_setAuthors($this->dom, $root); + $this->_setCopyright($this->dom, $root); + $this->_setCategories($this->dom, $root); + + foreach ($this->extensions as $ext) { + $ext->setType($this->getType()); + $ext->setRootElement($this->getRootElement()); + $ext->setDomDocument($this->getDomDocument(), $root); + $ext->render(); + } + return $this; + } + + /** + * Set feed generator string + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setGenerator(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getGenerator()) { + return; + } + + $gdata = $this->getDataContainer()->getGenerator(); + $generator = $dom->createElement('generator'); + $root->appendChild($generator); + $text = $dom->createTextNode($gdata['name']); + $generator->appendChild($text); + if (array_key_exists('uri', $gdata)) { + $generator->setAttribute('uri', $gdata['uri']); + } + if (array_key_exists('version', $gdata)) { + $generator->setAttribute('version', $gdata['version']); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/AtomSource.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/AtomSource.php new file mode 100644 index 0000000000000000000000000000000000000000..de9654c58e4cfdf0fb4a569a1ec4f19ed85ed0d4 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/AtomSource.php @@ -0,0 +1,95 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Feed; + +use DOMDocument; +use DOMElement; +use Zend\Feed\Writer; +use Zend\Feed\Writer\Renderer; + +/** +*/ +class AtomSource extends AbstractAtom implements Renderer\RendererInterface +{ + + /** + * Constructor + * + * @param Writer\Source $container + */ + public function __construct (Writer\Source $container) + { + parent::__construct($container); + } + + /** + * Render Atom Feed Metadata (Source element) + * + * @return \Zend\Feed\Writer\Renderer\Feed\Atom + */ + public function render() + { + if (!$this->container->getEncoding()) { + $this->container->setEncoding('UTF-8'); + } + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $root = $this->dom->createElement('source'); + $this->setRootElement($root); + $this->dom->appendChild($root); + $this->_setLanguage($this->dom, $root); + $this->_setBaseUrl($this->dom, $root); + $this->_setTitle($this->dom, $root); + $this->_setDescription($this->dom, $root); + $this->_setDateCreated($this->dom, $root); + $this->_setDateModified($this->dom, $root); + $this->_setGenerator($this->dom, $root); + $this->_setLink($this->dom, $root); + $this->_setFeedLinks($this->dom, $root); + $this->_setId($this->dom, $root); + $this->_setAuthors($this->dom, $root); + $this->_setCopyright($this->dom, $root); + $this->_setCategories($this->dom, $root); + + foreach ($this->extensions as $ext) { + $ext->setType($this->getType()); + $ext->setRootElement($this->getRootElement()); + $ext->setDOMDocument($this->getDOMDocument(), $root); + $ext->render(); + } + return $this; + } + + /** + * Set feed generator string + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setGenerator(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getGenerator()) { + return; + } + + $gdata = $this->getDataContainer()->getGenerator(); + $generator = $dom->createElement('generator'); + $root->appendChild($generator); + $text = $dom->createTextNode($gdata['name']); + $generator->appendChild($text); + if (array_key_exists('uri', $gdata)) { + $generator->setAttribute('uri', $gdata['uri']); + } + if (array_key_exists('version', $gdata)) { + $generator->setAttribute('version', $gdata['version']); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Rss.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Rss.php new file mode 100644 index 0000000000000000000000000000000000000000..84056a92286c5436a9b27145ff5409701e73b068 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/Feed/Rss.php @@ -0,0 +1,484 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer\Feed; + +use DateTime; +use DOMDocument; +use DOMElement; +use Zend\Feed\Uri; +use Zend\Feed\Writer; +use Zend\Feed\Writer\Renderer; +use Zend\Feed\Writer\Version; + +/** +*/ +class Rss extends Renderer\AbstractRenderer implements Renderer\RendererInterface +{ + /** + * Constructor + * + * @param Writer\Feed $container + */ + public function __construct (Writer\Feed $container) + { + parent::__construct($container); + } + + /** + * Render RSS feed + * + * @return self + */ + public function render() + { + $this->dom = new DOMDocument('1.0', $this->container->getEncoding()); + $this->dom->formatOutput = true; + $this->dom->substituteEntities = false; + $rss = $this->dom->createElement('rss'); + $this->setRootElement($rss); + $rss->setAttribute('version', '2.0'); + + $channel = $this->dom->createElement('channel'); + $rss->appendChild($channel); + $this->dom->appendChild($rss); + $this->_setLanguage($this->dom, $channel); + $this->_setBaseUrl($this->dom, $channel); + $this->_setTitle($this->dom, $channel); + $this->_setDescription($this->dom, $channel); + $this->_setImage($this->dom, $channel); + $this->_setDateCreated($this->dom, $channel); + $this->_setDateModified($this->dom, $channel); + $this->_setLastBuildDate($this->dom, $channel); + $this->_setGenerator($this->dom, $channel); + $this->_setLink($this->dom, $channel); + $this->_setAuthors($this->dom, $channel); + $this->_setCopyright($this->dom, $channel); + $this->_setCategories($this->dom, $channel); + + foreach ($this->extensions as $ext) { + $ext->setType($this->getType()); + $ext->setRootElement($this->getRootElement()); + $ext->setDOMDocument($this->getDOMDocument(), $channel); + $ext->render(); + } + + foreach ($this->container as $entry) { + if ($this->getDataContainer()->getEncoding()) { + $entry->setEncoding($this->getDataContainer()->getEncoding()); + } + if ($entry instanceof Writer\Entry) { + $renderer = new Renderer\Entry\Rss($entry); + } else { + continue; + } + if ($this->ignoreExceptions === true) { + $renderer->ignoreExceptions(); + } + $renderer->setType($this->getType()); + $renderer->setRootElement($this->dom->documentElement); + $renderer->render(); + $element = $renderer->getElement(); + $imported = $this->dom->importNode($element, true); + $channel->appendChild($imported); + } + return $this; + } + + /** + * Set feed language + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setLanguage(DOMDocument $dom, DOMElement $root) + { + $lang = $this->getDataContainer()->getLanguage(); + if (!$lang) { + return; + } + $language = $dom->createElement('language'); + $root->appendChild($language); + $language->nodeValue = $lang; + } + + /** + * Set feed title + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setTitle(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getTitle()) { + $message = 'RSS 2.0 feed elements MUST contain exactly one' + . ' title element but a title has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + $title = $dom->createElement('title'); + $root->appendChild($title); + $text = $dom->createTextNode($this->getDataContainer()->getTitle()); + $title->appendChild($text); + } + + /** + * Set feed description + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setDescription(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDescription()) { + $message = 'RSS 2.0 feed elements MUST contain exactly one' + . ' description element but one has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $subtitle = $dom->createElement('description'); + $root->appendChild($subtitle); + $text = $dom->createTextNode($this->getDataContainer()->getDescription()); + $subtitle->appendChild($text); + } + + /** + * Set date feed was last modified + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDateModified(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateModified()) { + return; + } + + $updated = $dom->createElement('pubDate'); + $root->appendChild($updated); + $text = $dom->createTextNode( + $this->getDataContainer()->getDateModified()->format(DateTime::RSS) + ); + $updated->appendChild($text); + } + + /** + * Set feed generator string + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setGenerator(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getGenerator()) { + $this->getDataContainer()->setGenerator('Zend_Feed_Writer', + Version::VERSION, 'http://framework.zend.com'); + } + + $gdata = $this->getDataContainer()->getGenerator(); + $generator = $dom->createElement('generator'); + $root->appendChild($generator); + $name = $gdata['name']; + if (array_key_exists('version', $gdata)) { + $name .= ' ' . $gdata['version']; + } + if (array_key_exists('uri', $gdata)) { + $name .= ' (' . $gdata['uri'] . ')'; + } + $text = $dom->createTextNode($name); + $generator->appendChild($text); + } + + /** + * Set link to feed + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setLink(DOMDocument $dom, DOMElement $root) + { + $value = $this->getDataContainer()->getLink(); + if (!$value) { + $message = 'RSS 2.0 feed elements MUST contain exactly one' + . ' link element but one has not been set'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $link = $dom->createElement('link'); + $root->appendChild($link); + $text = $dom->createTextNode($value); + $link->appendChild($text); + if (!Uri::factory($value)->isValid()) { + $link->setAttribute('isPermaLink', 'false'); + } + } + + /** + * Set feed authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + $authors = $this->getDataContainer()->getAuthors(); + if (!$authors || empty($authors)) { + return; + } + foreach ($authors as $data) { + $author = $this->dom->createElement('author'); + $name = $data['name']; + if (array_key_exists('email', $data)) { + $name = $data['email'] . ' (' . $data['name'] . ')'; + } + $text = $dom->createTextNode($name); + $author->appendChild($text); + $root->appendChild($author); + } + } + + /** + * Set feed copyright + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCopyright(DOMDocument $dom, DOMElement $root) + { + $copyright = $this->getDataContainer()->getCopyright(); + if (!$copyright) { + return; + } + $copy = $dom->createElement('copyright'); + $root->appendChild($copy); + $text = $dom->createTextNode($copyright); + $copy->appendChild($text); + } + + /** + * Set feed channel image + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + * @throws Writer\Exception\InvalidArgumentException + */ + protected function _setImage(DOMDocument $dom, DOMElement $root) + { + $image = $this->getDataContainer()->getImage(); + if (!$image) { + return; + } + + if (!isset($image['title']) || empty($image['title']) + || !is_string($image['title']) + ) { + $message = 'RSS 2.0 feed images must include a title'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + if (empty($image['link']) || !is_string($image['link']) + || !Uri::factory($image['link'])->isValid() + ) { + $message = 'Invalid parameter: parameter \'link\'' + . ' must be a non-empty string and valid URI/IRI'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + + $img = $dom->createElement('image'); + $root->appendChild($img); + + $url = $dom->createElement('url'); + $text = $dom->createTextNode($image['uri']); + $url->appendChild($text); + + $title = $dom->createElement('title'); + $text = $dom->createTextNode($image['title']); + $title->appendChild($text); + + $link = $dom->createElement('link'); + $text = $dom->createTextNode($image['link']); + $link->appendChild($text); + + $img->appendChild($url); + $img->appendChild($title); + $img->appendChild($link); + + if (isset($image['height'])) { + if (!ctype_digit((string) $image['height']) || $image['height'] > 400) { + $message = 'Invalid parameter: parameter \'height\'' + . ' must be an integer not exceeding 400'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $height = $dom->createElement('height'); + $text = $dom->createTextNode($image['height']); + $height->appendChild($text); + $img->appendChild($height); + } + if (isset($image['width'])) { + if (!ctype_digit((string) $image['width']) || $image['width'] > 144) { + $message = 'Invalid parameter: parameter \'width\'' + . ' must be an integer not exceeding 144'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $width = $dom->createElement('width'); + $text = $dom->createTextNode($image['width']); + $width->appendChild($text); + $img->appendChild($width); + } + if (isset($image['description'])) { + if (empty($image['description']) || !is_string($image['description'])) { + $message = 'Invalid parameter: parameter \'description\'' + . ' must be a non-empty string'; + $exception = new Writer\Exception\InvalidArgumentException($message); + if (!$this->ignoreExceptions) { + throw $exception; + } else { + $this->exceptions[] = $exception; + return; + } + } + $desc = $dom->createElement('description'); + $text = $dom->createTextNode($image['description']); + $desc->appendChild($text); + $img->appendChild($desc); + } + } + + /** + * Set date feed was created + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setDateCreated(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getDateCreated()) { + return; + } + if (!$this->getDataContainer()->getDateModified()) { + $this->getDataContainer()->setDateModified( + $this->getDataContainer()->getDateCreated() + ); + } + } + + /** + * Set date feed last build date + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setLastBuildDate(DOMDocument $dom, DOMElement $root) + { + if (!$this->getDataContainer()->getLastBuildDate()) { + return; + } + + $lastBuildDate = $dom->createElement('lastBuildDate'); + $root->appendChild($lastBuildDate); + $text = $dom->createTextNode( + $this->getDataContainer()->getLastBuildDate()->format(DateTime::RSS) + ); + $lastBuildDate->appendChild($text); + } + + /** + * Set base URL to feed links + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setBaseUrl(DOMDocument $dom, DOMElement $root) + { + $baseUrl = $this->getDataContainer()->getBaseUrl(); + if (!$baseUrl) { + return; + } + $root->setAttribute('xml:base', $baseUrl); + } + + /** + * Set feed categories + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + protected function _setCategories(DOMDocument $dom, DOMElement $root) + { + $categories = $this->getDataContainer()->getCategories(); + if (!$categories) { + return; + } + foreach ($categories as $cat) { + $category = $dom->createElement('category'); + if (isset($cat['scheme'])) { + $category->setAttribute('domain', $cat['scheme']); + } + $text = $dom->createTextNode($cat['term']); + $category->appendChild($text); + $root->appendChild($category); + } + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/RendererInterface.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/RendererInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b9d47c3f1025c77f83a6da08a2a25e60769b0608 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Renderer/RendererInterface.php @@ -0,0 +1,100 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer\Renderer; + +use DOMDocument; +use DOMElement; + +/** +*/ +interface RendererInterface +{ + /** + * Render feed/entry + * + * @return void + */ + public function render(); + + /** + * Save feed and/or entry to XML and return string + * + * @return string + */ + public function saveXml(); + + /** + * Get DOM document + * + * @return DOMDocument + */ + public function getDomDocument(); + + /** + * Get document element from DOM + * + * @return DOMElement + */ + public function getElement(); + + /** + * Get data container containing feed items + * + * @return mixed + */ + public function getDataContainer(); + + /** + * Should exceptions be ignored? + * + * @return mixed + */ + public function ignoreExceptions(); + + /** + * Get list of thrown exceptions + * + * @return array + */ + public function getExceptions(); + + /** + * Set the current feed type being exported to "rss" or "atom". This allows + * other objects to gracefully choose whether to execute or not, depending + * on their appropriateness for the current type, e.g. renderers. + * + * @param string $type + */ + public function setType($type); + + /** + * Retrieve the current or last feed type exported. + * + * @return string Value will be "rss" or "atom" + */ + public function getType(); + + /** + * Sets the absolute root element for the XML feed being generated. This + * helps simplify the appending of namespace declarations, but also ensures + * namespaces are added to the root element - not scattered across the entire + * XML file - may assist namespace unsafe parsers and looks pretty ;). + * + * @param DOMElement $root + */ + public function setRootElement(DOMElement $root); + + /** + * Retrieve the absolute root element for the XML feed being generated. + * + * @return DOMElement + */ + public function getRootElement(); +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Source.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Source.php new file mode 100644 index 0000000000000000000000000000000000000000..ff4534db16a397ab2f5ae83605317a1e9834d57c --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Source.php @@ -0,0 +1,16 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +/** +*/ +class Source extends AbstractFeed +{ +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Version.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Version.php new file mode 100644 index 0000000000000000000000000000000000000000..806d5906d4cb0a0a45322ce1407bd683a973e9a9 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Version.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +abstract class Version +{ + const VERSION = '2'; +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Writer.php b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Writer.php new file mode 100644 index 0000000000000000000000000000000000000000..ccd69d4d01d70e3c957b6a058e5b24f851c5ae2c --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/Writer/Writer.php @@ -0,0 +1,199 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Feed\Writer; + +/** +*/ +class Writer +{ + /** + * Namespace constants + */ + const NAMESPACE_ATOM_03 = 'http://purl.org/atom/ns#'; + const NAMESPACE_ATOM_10 = 'http://www.w3.org/2005/Atom'; + const NAMESPACE_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; + const NAMESPACE_RSS_090 = 'http://my.netscape.com/rdf/simple/0.9/'; + const NAMESPACE_RSS_10 = 'http://purl.org/rss/1.0/'; + + /** + * Feed type constants + */ + const TYPE_ANY = 'any'; + const TYPE_ATOM_03 = 'atom-03'; + const TYPE_ATOM_10 = 'atom-10'; + const TYPE_ATOM_ANY = 'atom'; + const TYPE_RSS_090 = 'rss-090'; + const TYPE_RSS_091 = 'rss-091'; + const TYPE_RSS_091_NETSCAPE = 'rss-091n'; + const TYPE_RSS_091_USERLAND = 'rss-091u'; + const TYPE_RSS_092 = 'rss-092'; + const TYPE_RSS_093 = 'rss-093'; + const TYPE_RSS_094 = 'rss-094'; + const TYPE_RSS_10 = 'rss-10'; + const TYPE_RSS_20 = 'rss-20'; + const TYPE_RSS_ANY = 'rss'; + + /** + * @var ExtensionManagerInterface + */ + protected static $extensionManager = null; + + /** + * Array of registered extensions by class postfix (after the base class + * name) across four categories - data containers and renderers for entry + * and feed levels. + * + * @var array + */ + protected static $extensions = array( + 'entry' => array(), + 'feed' => array(), + 'entryRenderer' => array(), + 'feedRenderer' => array(), + ); + + /** + * Set plugin loader for use with Extensions + * + * @param ExtensionManagerInterface + */ + public static function setExtensionManager(ExtensionManagerInterface $extensionManager) + { + static::$extensionManager = $extensionManager; + } + + /** + * Get plugin manager for use with Extensions + * + * @return ExtensionManagerInterface + */ + public static function getExtensionManager() + { + if (!isset(static::$extensionManager)) { + static::setExtensionManager(new ExtensionManager()); + } + return static::$extensionManager; + } + + /** + * Register an Extension by name + * + * @param string $name + * @return void + * @throws Exception\RuntimeException if unable to resolve Extension class + */ + public static function registerExtension($name) + { + $feedName = $name . '\Feed'; + $entryName = $name . '\Entry'; + $feedRendererName = $name . '\Renderer\Feed'; + $entryRendererName = $name . '\Renderer\Entry'; + $manager = static::getExtensionManager(); + if (static::isRegistered($name)) { + if ($manager->has($feedName) + || $manager->has($entryName) + || $manager->has($feedRendererName) + || $manager->has($entryRendererName) + ) { + return; + } + } + if (!$manager->has($feedName) + && !$manager->has($entryName) + && !$manager->has($feedRendererName) + && !$manager->has($entryRendererName) + ) { + throw new Exception\RuntimeException('Could not load extension: ' . $name + . 'using Plugin Loader. Check prefix paths are configured and extension exists.'); + } + if ($manager->has($feedName)) { + static::$extensions['feed'][] = $feedName; + } + if ($manager->has($entryName)) { + static::$extensions['entry'][] = $entryName; + } + if ($manager->has($feedRendererName)) { + static::$extensions['feedRenderer'][] = $feedRendererName; + } + if ($manager->has($entryRendererName)) { + static::$extensions['entryRenderer'][] = $entryRendererName; + } + } + + /** + * Is a given named Extension registered? + * + * @param string $extensionName + * @return bool + */ + public static function isRegistered($extensionName) + { + $feedName = $extensionName . '\Feed'; + $entryName = $extensionName . '\Entry'; + $feedRendererName = $extensionName . '\Renderer\Feed'; + $entryRendererName = $extensionName . '\Renderer\Entry'; + if (in_array($feedName, static::$extensions['feed']) + || in_array($entryName, static::$extensions['entry']) + || in_array($feedRendererName, static::$extensions['feedRenderer']) + || in_array($entryRendererName, static::$extensions['entryRenderer']) + ) { + return true; + } + return false; + } + + /** + * Get a list of extensions + * + * @return array + */ + public static function getExtensions() + { + return static::$extensions; + } + + /** + * Reset class state to defaults + * + * @return void + */ + public static function reset() + { + static::$extensionManager = null; + static::$extensions = array( + 'entry' => array(), + 'feed' => array(), + 'entryRenderer' => array(), + 'feedRenderer' => array(), + ); + } + + /** + * Register core (default) extensions + * + * @return void + */ + public static function registerCoreExtensions() + { + static::registerExtension('DublinCore'); + static::registerExtension('Content'); + static::registerExtension('Atom'); + static::registerExtension('Slash'); + static::registerExtension('WellFormedWeb'); + static::registerExtension('Threading'); + static::registerExtension('ITunes'); + } + + public static function lcfirst($str) + { + $str[0] = strtolower($str[0]); + return $str; + } +} diff --git a/core/vendor/zendframework/zend-feed/Zend/Feed/composer.json b/core/vendor/zendframework/zend-feed/Zend/Feed/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..d55068f011fd990e370dbceb6b939e3168a3fc20 --- /dev/null +++ b/core/vendor/zendframework/zend-feed/Zend/Feed/composer.json @@ -0,0 +1,31 @@ +{ + "name": "zendframework/zend-feed", + "description": "provides functionality for consuming RSS and Atom feeds", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "feed" + ], + "autoload": { + "psr-0": { + "Zend\\Feed\\": "" + } + }, + "target-dir": "Zend/Feed", + "require": { + "php": ">=5.3.3", + "zendframework/zend-escaper": "self.version", + "zendframework/zend-stdlib": "self.version" + }, + "suggest": { + "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for default/recommended ExtensionManager implementations", + "zendframework/zend-validator": "Zend\\Validator component" + }, + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/AbstractOptions.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/AbstractOptions.php new file mode 100644 index 0000000000000000000000000000000000000000..0e68c29e11c7c39ac5fa340d66d5fe0250c879dd --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/AbstractOptions.php @@ -0,0 +1,161 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Traversable; + +abstract class AbstractOptions implements ParameterObjectInterface +{ + /** + * We use the __ prefix to avoid collisions with properties in + * user-implementations. + * + * @var bool + */ + protected $__strictMode__ = true; + + /** + * Constructor + * + * @param array|Traversable|null $options + */ + public function __construct($options = null) + { + if (null !== $options) { + $this->setFromArray($options); + } + } + + /** + * Set one or more configuration properties + * + * @param array|Traversable|AbstractOptions $options + * @throws Exception\InvalidArgumentException + * @return AbstractOptions Provides fluent interface + */ + public function setFromArray($options) + { + if ($options instanceof self) { + $options = $options->toArray(); + } + + if (!is_array($options) && !$options instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + 'Parameter provided to %s must be an %s, %s or %s', + __METHOD__, 'array', 'Traversable', 'Zend\Stdlib\AbstractOptions' + )); + } + + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + + return $this; + } + + /** + * Cast to array + * + * @return array + */ + public function toArray() + { + $array = array(); + $transform = function ($letters) { + $letter = array_shift($letters); + return '_' . strtolower($letter); + }; + foreach ($this as $key => $value) { + if ($key === '__strictMode__') continue; + $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key); + $array[$normalizedKey] = $value; + } + return $array; + } + + /** + * Set a configuration property + * + * @see ParameterObject::__set() + * @param string $key + * @param mixed $value + * @throws Exception\BadMethodCallException + * @return void + */ + public function __set($key, $value) + { + $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); + if ($this->__strictMode__ && !method_exists($this, $setter)) { + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $setter . ' setter method ' + . 'which must be defined' + ); + } elseif (!$this->__strictMode__ && !method_exists($this, $setter)) { + return; + } + $this->{$setter}($value); + } + + /** + * Get a configuration property + * + * @see ParameterObject::__get() + * @param string $key + * @throws Exception\BadMethodCallException + * @return mixed + */ + public function __get($key) + { + $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); + if (!method_exists($this, $getter)) { + throw new Exception\BadMethodCallException( + 'The option "' . $key . '" does not ' + . 'have a matching ' . $getter . ' getter method ' + . 'which must be defined' + ); + } + + return $this->{$getter}(); + } + + /** + * Test if a configuration property is null + * @see ParameterObject::__isset() + * @param string $key + * @return bool + */ + public function __isset($key) + { + return null !== $this->__get($key); + } + + /** + * Set a configuration property to NULL + * + * @see ParameterObject::__unset() + * @param string $key + * @throws Exception\InvalidArgumentException + * @return void + */ + public function __unset($key) + { + try { + $this->__set($key, null); + } catch (Exception\BadMethodCallException $e) { + throw new Exception\InvalidArgumentException( + 'The class property $' . $key . ' cannot be unset as' + . ' NULL is an invalid value for it', + 0, + $e + ); + } + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject.php new file mode 100644 index 0000000000000000000000000000000000000000..806c128fc76f417b93ec5a152c316b1e6fab06fd --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject.php @@ -0,0 +1,34 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +/** + * If the version is less than 5.3.4, we'll use Zend\Stdlib\ArrayObject\PhpLegacyCompatibility + * which extends the native PHP ArrayObject implementation. For versions greater than or equal + * to 5.3.4, we'll use Zend\Stdlib\ArrayObject\PhpReferenceCompatibility, which corrects + * issues with how PHP handles references inside ArrayObject. + * + * class_alias is a global construct, so we can alias either one to Zend\Stdlib\ArrayObject, + * and from this point forward, that alias will be used. + */ +if (version_compare(PHP_VERSION, '5.3.4', 'lt')) { + class_alias('Zend\Stdlib\ArrayObject\PhpLegacyCompatibility', 'Zend\Stdlib\AbstractArrayObject'); +} else { + class_alias('Zend\Stdlib\ArrayObject\PhpReferenceCompatibility', 'Zend\Stdlib\AbstractArrayObject'); +} + +/** + * Custom framework ArrayObject implementation + * + * Extends version-specific "abstract" implementation. + */ +class ArrayObject extends AbstractArrayObject +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpLegacyCompatibility.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpLegacyCompatibility.php new file mode 100644 index 0000000000000000000000000000000000000000..9a71605e728e0c017ad2007733069ca4bd0ca489 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpLegacyCompatibility.php @@ -0,0 +1,35 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\ArrayObject; + +use ArrayObject as PhpArrayObject; + +/** + * ArrayObject + * + * Since we need to substitute an alternate ArrayObject implementation for + * versions > 5.3.3, we need to provide a stub for 5.3.3. This stub + * simply extends the PHP ArrayObject implementation, and provides default + * behavior in the constructor. + */ +abstract class PhpLegacyCompatibility extends PhpArrayObject +{ + /** + * Constructor + * + * @param array $input + * @param int $flags + * @param string $iteratorClass + */ + public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator') + { + parent::__construct($input, $flags, $iteratorClass); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpReferenceCompatibility.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpReferenceCompatibility.php new file mode 100644 index 0000000000000000000000000000000000000000..e25257c761b124c77d2b5f5bf60c27da5d7c7933 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpReferenceCompatibility.php @@ -0,0 +1,433 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\ArrayObject; + +use ArrayAccess; +use Countable; +use IteratorAggregate; +use Serializable; +use Zend\Stdlib\Exception; + +/** + * ArrayObject + * + * This ArrayObject is a rewrite of the implementation to fix + * issues with php's implementation of ArrayObject where you + * are unable to unset multi-dimensional arrays because you + * need to fetch the properties / lists as references. + */ +abstract class PhpReferenceCompatibility implements IteratorAggregate, ArrayAccess, Serializable, Countable +{ + /** + * Properties of the object have their normal functionality + * when accessed as list (var_dump, foreach, etc.). + */ + const STD_PROP_LIST = 1; + + /** + * Entries can be accessed as properties (read and write). + */ + const ARRAY_AS_PROPS = 2; + + /** + * @var array + */ + protected $storage; + + /** + * @var int + */ + protected $flag; + + /** + * @var string + */ + protected $iteratorClass; + + /** + * @var array + */ + protected $protectedProperties; + + /** + * Constructor + * + * @param array $input + * @param int $flags + * @param string $iteratorClass + */ + public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator') + { + $this->setFlags($flags); + $this->storage = $input; + $this->setIteratorClass($iteratorClass); + $this->protectedProperties = array_keys(get_object_vars($this)); + } + + /** + * Returns whether the requested key exists + * + * @param mixed $key + * @return bool + */ + public function __isset($key) + { + if ($this->flag == self::ARRAY_AS_PROPS) { + return $this->offsetExists($key); + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + + return isset($this->$key); + } + + /** + * Sets the value at the specified key to value + * + * @param mixed $key + * @param mixed $value + * @return void + */ + public function __set($key, $value) + { + if ($this->flag == self::ARRAY_AS_PROPS) { + return $this->offsetSet($key, $value); + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + $this->$key = $value; + } + + /** + * Unsets the value at the specified key + * + * @param mixed $key + * @return void + */ + public function __unset($key) + { + if ($this->flag == self::ARRAY_AS_PROPS) { + return $this->offsetUnset($key); + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + unset($this->$key); + } + + /** + * Returns the value at the specified key by reference + * + * @param mixed $key + * @return mixed + */ + public function &__get($key) + { + $ret = null; + if ($this->flag == self::ARRAY_AS_PROPS) { + $ret =& $this->offsetGet($key); + + return $ret; + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + + return $this->$key; + } + + /** + * Appends the value + * + * @param mixed $value + * @return void + */ + public function append($value) + { + $this->storage[] = $value; + } + + /** + * Sort the entries by value + * + * @return void + */ + public function asort() + { + asort($this->storage); + } + + /** + * Get the number of public properties in the ArrayObject + * + * @return int + */ + public function count() + { + return count($this->storage); + } + + /** + * Exchange the array for another one. + * + * @param array|ArrayObject $data + * @return array + */ + public function exchangeArray($data) + { + if (!is_array($data) && !is_object($data)) { + throw new Exception\InvalidArgumentException('Passed variable is not an array or object, using empty array instead'); + } + + if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) { + $data = $data->getArrayCopy(); + } + if (!is_array($data)) { + $data = (array) $data; + } + + $storage = $this->storage; + + $this->storage = $data; + + return $storage; + } + + /** + * Creates a copy of the ArrayObject. + * + * @return array + */ + public function getArrayCopy() + { + return $this->storage; + } + + /** + * Gets the behavior flags. + * + * @return int + */ + public function getFlags() + { + return $this->flag; + } + + /** + * Create a new iterator from an ArrayObject instance + * + * @return \Iterator + */ + public function getIterator() + { + $class = $this->iteratorClass; + + return new $class($this->storage); + } + + /** + * Gets the iterator classname for the ArrayObject. + * + * @return string + */ + public function getIteratorClass() + { + return $this->iteratorClass; + } + + /** + * Sort the entries by key + * + * @return void + */ + public function ksort() + { + ksort($this->storage); + } + + /** + * Sort an array using a case insensitive "natural order" algorithm + * + * @return void + */ + public function natcasesort() + { + natcasesort($this->storage); + } + + /** + * Sort entries using a "natural order" algorithm + * + * @return void + */ + public function natsort() + { + natsort($this->storage); + } + + /** + * Returns whether the requested key exists + * + * @param mixed $key + * @return bool + */ + public function offsetExists($key) + { + return isset($this->storage[$key]); + } + + /** + * Returns the value at the specified key + * + * @param mixed $key + * @return mixed + */ + public function &offsetGet($key) + { + $ret = null; + if (!$this->offsetExists($key)) { + return $ret; + } + $ret =& $this->storage[$key]; + + return $ret; + } + + /** + * Sets the value at the specified key to value + * + * @param mixed $key + * @param mixed $value + * @return void + */ + public function offsetSet($key, $value) + { + $this->storage[$key] = $value; + } + + /** + * Unsets the value at the specified key + * + * @param mixed $key + * @return void + */ + public function offsetUnset($key) + { + if ($this->offsetExists($key)) { + unset($this->storage[$key]); + } + } + + /** + * Serialize an ArrayObject + * + * @return string + */ + public function serialize() + { + return serialize(get_object_vars($this)); + } + + /** + * Sets the behavior flags + * + * @param int $flags + * @return void + */ + public function setFlags($flags) + { + $this->flag = $flags; + } + + /** + * Sets the iterator classname for the ArrayObject + * + * @param string $class + * @return void + */ + public function setIteratorClass($class) + { + if (class_exists($class)) { + $this->iteratorClass = $class; + + return ; + } + + if (strpos($class, '\\') === 0) { + $class = '\\' . $class; + if (class_exists($class)) { + $this->iteratorClass = $class; + + return ; + } + } + + throw new Exception\InvalidArgumentException('The iterator class does not exist'); + } + + /** + * Sort the entries with a user-defined comparison function and maintain key association + * + * @param callable $function + * @return void + */ + public function uasort($function) + { + if (is_callable($function)) { + uasort($this->storage, $function); + } + } + + /** + * Sort the entries by keys using a user-defined comparison function + * + * @param callable $function + * @return void + */ + public function uksort($function) + { + if (is_callable($function)) { + uksort($this->storage, $function); + } + } + + /** + * Unserialize an ArrayObject + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + $ar = unserialize($data); + $this->setFlags($ar['flag']); + $this->exchangeArray($ar['storage']); + $this->setIteratorClass($ar['iteratorClass']); + foreach ($ar as $k => $v) { + switch ($k) { + case 'flag': + $this->setFlags($v); + break; + case 'storage': + $this->exchangeArray($v); + break; + case 'iteratorClass': + $this->setIteratorClass($v); + break; + case 'protectedProperties': + continue; + default: + $this->__set($k, $v); + } + } + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArraySerializableInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArraySerializableInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..7bd6f6eddb54a1855c852cc0832845c17d880805 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArraySerializableInterface.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +interface ArraySerializableInterface +{ + /** + * Exchange internal values from provided array + * + * @param array $array + * @return void + */ + public function exchangeArray(array $array); + + /** + * Return an array representation of the object + * + * @return array + */ + public function getArrayCopy(); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayStack.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayStack.php new file mode 100644 index 0000000000000000000000000000000000000000..559d65e3f0a6956907ff1c100293bb6931957c3f --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayStack.php @@ -0,0 +1,33 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use ArrayIterator; +use ArrayObject as PhpArrayObject; + +/** + * ArrayObject that acts as a stack with regards to iteration + */ +class ArrayStack extends PhpArrayObject +{ + /** + * Retrieve iterator + * + * Retrieve an array copy of the object, reverse its order, and return an + * ArrayIterator with that reversed array. + * + * @return ArrayIterator + */ + public function getIterator() + { + $array = $this->getArrayCopy(); + return new ArrayIterator(array_reverse($array)); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayUtils.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayUtils.php new file mode 100644 index 0000000000000000000000000000000000000000..4261d2e65fa94c2f9ef204fee38f379ea10bdff2 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayUtils.php @@ -0,0 +1,275 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Traversable; + +/** + * Utility class for testing and manipulation of PHP arrays. + * + * Declared abstract, as we have no need for instantiation. + */ +abstract class ArrayUtils +{ + /** + * Test whether an array contains one or more string keys + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasStringKeys($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_string')) > 0; + } + + /** + * Test whether an array contains one or more integer keys + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasIntegerKeys($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_int')) > 0; + } + + /** + * Test whether an array contains one or more numeric keys. + * + * A numeric key can be one of the following: + * - an integer 1, + * - a string with a number '20' + * - a string with negative number: '-1000' + * - a float: 2.2120, -78.150999 + * - a string with float: '4000.99999', '-10.10' + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasNumericKeys($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_numeric')) > 0; + } + + /** + * Test whether an array is a list + * + * A list is a collection of values assigned to continuous integer keys + * starting at 0 and ending at count() - 1. + * + * For example: + * <code> + * $list = array('a', 'b', 'c', 'd'); + * $list = array( + * 0 => 'foo', + * 1 => 'bar', + * 2 => array('foo' => 'baz'), + * ); + * </code> + * + * @param mixed $value + * @param bool $allowEmpty Is an empty list a valid list? + * @return bool + */ + public static function isList($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return (array_values($value) === $value); + } + + /** + * Test whether an array is a hash table. + * + * An array is a hash table if: + * + * 1. Contains one or more non-integer keys, or + * 2. Integer keys are non-continuous or misaligned (not starting with 0) + * + * For example: + * <code> + * $hash = array( + * 'foo' => 15, + * 'bar' => false, + * ); + * $hash = array( + * 1995 => 'Birth of PHP', + * 2009 => 'PHP 5.3.0', + * 2012 => 'PHP 5.4.0', + * ); + * $hash = array( + * 'formElement, + * 'options' => array( 'debug' => true ), + * ); + * </code> + * + * @param mixed $value + * @param bool $allowEmpty Is an empty array() a valid hash table? + * @return bool + */ + public static function isHashTable($value, $allowEmpty = false) + { + if (!is_array($value)) { + return false; + } + + if (!$value) { + return $allowEmpty; + } + + return (array_values($value) !== $value); + } + + /** + * Checks if a value exists in an array. + * + * Due to "foo" == 0 === TRUE with in_array when strict = false, an option + * has been added to prevent this. When $strict = 0/false, the most secure + * non-strict check is implemented. if $strict = -1, the default in_array + * non-strict behaviour is used. + * + * @param mixed $needle + * @param array $haystack + * @param int|bool $strict + * @return bool + */ + public static function inArray($needle, array $haystack, $strict = false) + { + if (!$strict) { + if (is_int($needle) || is_float($needle)) { + $needle = (string) $needle; + } + if (is_string($needle)) { + foreach ($haystack as &$h) { + if (is_int($h) || is_float($h)) { + $h = (string) $h; + } + } + } + } + return in_array($needle, $haystack, $strict); + } + + /** + * Convert an iterator to an array. + * + * Converts an iterator to an array. The $recursive flag, on by default, + * hints whether or not you want to do so recursively. + * + * @param array|Traversable $iterator The array or Traversable object to convert + * @param bool $recursive Recursively check all nested structures + * @throws Exception\InvalidArgumentException if $iterator is not an array or a Traversable object + * @return array + */ + public static function iteratorToArray($iterator, $recursive = true) + { + if (!is_array($iterator) && !$iterator instanceof Traversable) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object'); + } + + if (!$recursive) { + if (is_array($iterator)) { + return $iterator; + } + + return iterator_to_array($iterator); + } + + if (method_exists($iterator, 'toArray')) { + return $iterator->toArray(); + } + + $array = array(); + foreach ($iterator as $key => $value) { + if (is_scalar($value)) { + $array[$key] = $value; + continue; + } + + if ($value instanceof Traversable) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + if (is_array($value)) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + $array[$key] = $value; + } + + return $array; + } + + /** + * Merge two arrays together. + * + * If an integer key exists in both arrays, the value from the second array + * will be appended the the first array. If both values are arrays, they + * are merged together, else the value of the second array overwrites the + * one of the first array. + * + * @param array $a + * @param array $b + * @return array + */ + public static function merge(array $a, array $b) + { + foreach ($b as $key => $value) { + if (array_key_exists($key, $a)) { + if (is_int($key)) { + $a[] = $value; + } elseif (is_array($value) && is_array($a[$key])) { + $a[$key] = static::merge($a[$key], $value); + } else { + $a[$key] = $value; + } + } else { + $a[$key] = $value; + } + } + + return $a; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/CallbackHandler.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/CallbackHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..f1ac4a65b36d9713f6295f3d2e2bf59e158e6866 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/CallbackHandler.php @@ -0,0 +1,218 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Closure; +use ReflectionClass; + +/** + * CallbackHandler + * + * A handler for a event, event, filterchain, etc. Abstracts PHP callbacks, + * primarily to allow for lazy-loading and ensuring availability of default + * arguments (currying). + */ +class CallbackHandler +{ + /** + * @var string|array|callable PHP callback to invoke + */ + protected $callback; + + /** + * Callback metadata, if any + * @var array + */ + protected $metadata; + + /** + * PHP version is greater as 5.4rc1? + * @var bool + */ + protected static $isPhp54; + + /** + * Constructor + * + * @param string|array|object|callable $callback PHP callback + * @param array $metadata Callback metadata + */ + public function __construct($callback, array $metadata = array()) + { + $this->metadata = $metadata; + $this->registerCallback($callback); + } + + /** + * Registers the callback provided in the constructor + * + * @param callable $callback + * @throws Exception\InvalidCallbackException + * @return void + */ + protected function registerCallback($callback) + { + if (!is_callable($callback)) { + throw new Exception\InvalidCallbackException('Invalid callback provided; not callable'); + } + + $this->callback = $callback; + } + + /** + * Retrieve registered callback + * + * @return callable + */ + public function getCallback() + { + return $this->callback; + } + + /** + * Invoke handler + * + * @param array $args Arguments to pass to callback + * @return mixed + */ + public function call(array $args = array()) + { + $callback = $this->getCallback(); + + // Minor performance tweak, if the callback gets called more than once + if (!isset(static::$isPhp54)) { + static::$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); + } + + $argCount = count($args); + + if (static::$isPhp54 && is_string($callback)) { + $result = $this->validateStringCallbackFor54($callback); + + if ($result !== true && $argCount <= 3) { + $callback = $result; + // Minor performance tweak, if the callback gets called more + // than once + $this->callback = $result; + } + } + + // Minor performance tweak; use call_user_func() until > 3 arguments + // reached + switch ($argCount) { + case 0: + if (static::$isPhp54) { + return $callback(); + } + return call_user_func($callback); + case 1: + if (static::$isPhp54) { + return $callback(array_shift($args)); + } + return call_user_func($callback, array_shift($args)); + case 2: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + if (static::$isPhp54) { + return $callback($arg1, $arg2); + } + return call_user_func($callback, $arg1, $arg2); + case 3: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + $arg3 = array_shift($args); + if (static::$isPhp54) { + return $callback($arg1, $arg2, $arg3); + } + return call_user_func($callback, $arg1, $arg2, $arg3); + default: + return call_user_func_array($callback, $args); + } + } + + /** + * Invoke as functor + * + * @return mixed + */ + public function __invoke() + { + return $this->call(func_get_args()); + } + + /** + * Get all callback metadata + * + * @return array + */ + public function getMetadata() + { + return $this->metadata; + } + + /** + * Retrieve a single metadatum + * + * @param string $name + * @return mixed + */ + public function getMetadatum($name) + { + if (array_key_exists($name, $this->metadata)) { + return $this->metadata[$name]; + } + return null; + } + + /** + * Validate a static method call + * + * Validates that a static method call in PHP 5.4 will actually work + * + * @param string $callback + * @return true|array + * @throws Exception\InvalidCallbackException if invalid + */ + protected function validateStringCallbackFor54($callback) + { + if (!strstr($callback, '::')) { + return true; + } + + list($class, $method) = explode('::', $callback, 2); + + if (!class_exists($class)) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a class that does not exist', + $callback + )); + } + + $r = new ReflectionClass($class); + if (!$r->hasMethod($method)) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that does not exist', + $callback + )); + } + $m = $r->getMethod($method); + if (!$m->isStatic()) { + throw new Exception\InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that is not static', + $callback + )); + } + + // returning a non boolean value may not be nice for a validate method, + // but that allows the usage of a static string callback without using + // the call_user_func function. + return array($class, $method); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/DateTime.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/DateTime.php new file mode 100644 index 0000000000000000000000000000000000000000..5c88ad4732cdef1abcbc31cf0033d3099ad0ae4b --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/DateTime.php @@ -0,0 +1,47 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use DateTimeZone; + +trigger_error('DateTime extension deprecated as of ZF 2.1.4; use the \DateTime constructor to parse extended ISO8601 dates instead', E_USER_DEPRECATED); + +/** + * DateTime + * + * An extension of the \DateTime object. + * + * @deprecated + */ +class DateTime extends \DateTime +{ + /** + * The DateTime::ISO8601 constant used by php's native DateTime object does + * not allow for fractions of a second. This function better handles ISO8601 + * formatted date strings. + * + * @param string $time + * @param DateTimeZone $timezone + * @return mixed + */ + public static function createFromISO8601($time, DateTimeZone $timezone = null) + { + $format = self::ISO8601; + if (isset($time[19]) && $time[19] === '.') { + $format = 'Y-m-d\TH:i:s.uO'; + } + + if ($timezone !== null) { + return self::createFromFormat($format, $time, $timezone); + } + + return self::createFromFormat($format, $time); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/DispatchableInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/DispatchableInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..ab672fa13f8e24d8afd0bbd2fd73930798793ceb --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/DispatchableInterface.php @@ -0,0 +1,25 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Zend\Stdlib\RequestInterface as Request; +use Zend\Stdlib\ResponseInterface as Response; + +interface DispatchableInterface +{ + /** + * Dispatch a request + * + * @param Request $request + * @param null|Response $response + * @return Response|mixed + */ + public function dispatch(Request $request, Response $response = null); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ErrorHandler.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ErrorHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..5096f53d9d32028fe426ea93b45b639bd0561c3a --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ErrorHandler.php @@ -0,0 +1,115 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use ErrorException; + +/** + * ErrorHandler that can be used to catch internal PHP errors + * and convert to a ErrorException instance. + */ +abstract class ErrorHandler +{ + /** + * Active stack + * + * @var array + */ + protected static $stack = array(); + + /** + * Check if this error handler is active + * + * @return bool + */ + public static function started() + { + return (bool) static::getNestedLevel(); + } + + /** + * Get the current nested level + * + * @return int + */ + public static function getNestedLevel() + { + return count(static::$stack); + } + + /** + * Starting the error handler + * + * @param int $errorLevel + */ + public static function start($errorLevel = \E_WARNING) + { + if (!static::$stack) { + set_error_handler(array(get_called_class(), 'addError'), $errorLevel); + } + + static::$stack[] = null; + } + + /** + * Stopping the error handler + * + * @param bool $throw Throw the ErrorException if any + * @return null|ErrorException + * @throws ErrorException If an error has been catched and $throw is true + */ + public static function stop($throw = false) + { + $errorException = null; + + if (static::$stack) { + $errorException = array_pop(static::$stack); + + if (!static::$stack) { + restore_error_handler(); + } + + if ($errorException && $throw) { + throw $errorException; + } + } + + return $errorException; + } + + /** + * Stop all active handler + * + * @return void + */ + public static function clean() + { + if (static::$stack) { + restore_error_handler(); + } + + static::$stack = array(); + } + + /** + * Add an error to the stack + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @return void + */ + public static function addError($errno, $errstr = '', $errfile = '', $errline = 0) + { + $stack = & static::$stack[count(static::$stack) - 1]; + $stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/BadMethodCallException.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/BadMethodCallException.php new file mode 100644 index 0000000000000000000000000000000000000000..6cf1c9ecc077c13a03919f3557795ff381e6d383 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/BadMethodCallException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Bad method call exception + */ +class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/DomainException.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/DomainException.php new file mode 100644 index 0000000000000000000000000000000000000000..2744570f28f9dd6bbdb93e0989501bb5717aef5c --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/DomainException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Domain exception + */ +class DomainException extends \DomainException implements ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExceptionInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0424a4ea9a878632c765e6ad2da3ec705a98984a --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExceptionInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Exception marker interface + */ +interface ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExtensionNotLoadedException.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExtensionNotLoadedException.php new file mode 100644 index 0000000000000000000000000000000000000000..b883641a63da367170c086214e2cf614b6764c3b --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExtensionNotLoadedException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Extension not loaded exception + */ +class ExtensionNotLoadedException extends RuntimeException +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidArgumentException.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..9efb0e09b5a5a50da4879115476b506e2f103c52 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidArgumentException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Invalid Argument Exception + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidCallbackException.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidCallbackException.php new file mode 100644 index 0000000000000000000000000000000000000000..30e97e83bda469acbda2d9ebd6168c6d439bf7e0 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidCallbackException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Invalid callback exception + */ +class InvalidCallbackException extends DomainException implements ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/LogicException.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/LogicException.php new file mode 100644 index 0000000000000000000000000000000000000000..55e07d6a9775eaa9efebe0c1b7b084fc679df8d8 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/LogicException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Logic exception + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/RuntimeException.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..20c065587d23bbff8a796ccf1f009523aee870a1 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/RuntimeException.php @@ -0,0 +1,17 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Exception; + +/** + * Runtime exception + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Glob.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Glob.php new file mode 100644 index 0000000000000000000000000000000000000000..a9e29fd0c68082fc53de6da662c85bd3e0128f73 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Glob.php @@ -0,0 +1,205 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Zend\Stdlib\Exception; +use Zend\Stdlib\ErrorHandler; + +/** + * Wrapper for glob with fallback if GLOB_BRACE is not available. + */ +abstract class Glob +{ + /**#@+ + * Glob constants. + */ + const GLOB_MARK = 0x01; + const GLOB_NOSORT = 0x02; + const GLOB_NOCHECK = 0x04; + const GLOB_NOESCAPE = 0x08; + const GLOB_BRACE = 0x10; + const GLOB_ONLYDIR = 0x20; + const GLOB_ERR = 0x40; + /**#@-*/ + + /** + * Find pathnames matching a pattern. + * + * @see http://docs.php.net/glob + * @param string $pattern + * @param int $flags + * @param bool $forceFallback + * @return array + * @throws Exception\RuntimeException + */ + public static function glob($pattern, $flags = 0, $forceFallback = false) + { + if (!defined('GLOB_BRACE') || $forceFallback) { + return static::fallbackGlob($pattern, $flags); + } + + return static::systemGlob($pattern, $flags); + } + + /** + * Use the glob function provided by the system. + * + * @param string $pattern + * @param int $flags + * @return array + * @throws Exception\RuntimeException + */ + protected static function systemGlob($pattern, $flags) + { + if ($flags) { + $flagMap = array( + self::GLOB_MARK => GLOB_MARK, + self::GLOB_NOSORT => GLOB_NOSORT, + self::GLOB_NOCHECK => GLOB_NOCHECK, + self::GLOB_NOESCAPE => GLOB_NOESCAPE, + self::GLOB_BRACE => GLOB_BRACE, + self::GLOB_ONLYDIR => GLOB_ONLYDIR, + self::GLOB_ERR => GLOB_ERR, + ); + + $globFlags = 0; + + foreach ($flagMap as $internalFlag => $globFlag) { + if ($flags & $internalFlag) { + $globFlags |= $globFlag; + } + } + } else { + $globFlags = 0; + } + + ErrorHandler::start(); + $res = glob($pattern, $globFlags); + $err = ErrorHandler::stop(); + if ($res === false) { + throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err); + } + return $res; + } + + /** + * Expand braces manually, then use the system glob. + * + * @param string $pattern + * @param int $flags + * @return array + * @throws Exception\RuntimeException + */ + protected static function fallbackGlob($pattern, $flags) + { + if (!$flags & self::GLOB_BRACE) { + return static::systemGlob($pattern, $flags); + } + + $flags &= ~self::GLOB_BRACE; + $length = strlen($pattern); + $paths = array(); + + if ($flags & self::GLOB_NOESCAPE) { + $begin = strpos($pattern, '{'); + } else { + $begin = 0; + + while (true) { + if ($begin === $length) { + $begin = false; + break; + } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) { + $begin++; + } elseif ($pattern[$begin] === '{') { + break; + } + + $begin++; + } + } + + if ($begin === false) { + return static::systemGlob($pattern, $flags); + } + + $next = static::nextBraceSub($pattern, $begin + 1, $flags); + + if ($next === null) { + return static::systemGlob($pattern, $flags); + } + + $rest = $next; + + while ($pattern[$rest] !== '}') { + $rest = static::nextBraceSub($pattern, $rest + 1, $flags); + + if ($rest === null) { + return static::systemGlob($pattern, $flags); + } + } + + $p = $begin + 1; + + while (true) { + $subPattern = substr($pattern, 0, $begin) + . substr($pattern, $p, $next - $p) + . substr($pattern, $rest + 1); + + $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE); + + if ($result) { + $paths = array_merge($paths, $result); + } + + if ($pattern[$next] === '}') { + break; + } + + $p = $next + 1; + $next = static::nextBraceSub($pattern, $p, $flags); + } + + return array_unique($paths); + } + + /** + * Find the end of the sub-pattern in a brace expression. + * + * @param string $pattern + * @param int $begin + * @param int $flags + * @return int|null + */ + protected static function nextBraceSub($pattern, $begin, $flags) + { + $length = strlen($pattern); + $depth = 0; + $current = $begin; + + while ($current < $length) { + if (!$flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') { + if (++$current === $length) { + break; + } + + $current++; + } else { + if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) { + break; + } elseif ($pattern[$current++] === '{') { + $depth++; + } + } + } + + return ($current < $length ? $current : null); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/AbstractHydrator.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/AbstractHydrator.php new file mode 100644 index 0000000000000000000000000000000000000000..4cb9a4356f724c27187bd3b27a6a2c40715839a0 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/AbstractHydrator.php @@ -0,0 +1,198 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +use ArrayObject; +use Zend\Stdlib\Exception; +use Zend\Stdlib\Hydrator\Filter\FilterComposite; +use Zend\Stdlib\Hydrator\StrategyEnabledInterface; +use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; + +abstract class AbstractHydrator implements HydratorInterface, StrategyEnabledInterface +{ + /** + * The list with strategies that this hydrator has. + * + * @var ArrayObject + */ + protected $strategies; + + /** + * Composite to filter the methods, that need to be hydrated + * @var Filter\FilterComposite + */ + protected $filterComposite; + + /** + * Initializes a new instance of this class. + */ + public function __construct() + { + $this->strategies = new ArrayObject(); + $this->filterComposite = new FilterComposite(); + } + + /** + * Gets the strategy with the given name. + * + * @param string $name The name of the strategy to get. + * @return StrategyInterface + */ + public function getStrategy($name) + { + if (isset($this->strategies[$name])) { + return $this->strategies[$name]; + } + + if (!isset($this->strategies['*'])) { + throw new Exception\InvalidArgumentException(sprintf( + '%s: no strategy by name of "%s", and no wildcard strategy present', + __METHOD__, + $name + )); + } + + return $this->strategies['*']; + } + + /** + * Checks if the strategy with the given name exists. + * + * @param string $name The name of the strategy to check for. + * @return bool + */ + public function hasStrategy($name) + { + return array_key_exists($name, $this->strategies) + || array_key_exists('*', $this->strategies); + } + + /** + * Adds the given strategy under the given name. + * + * @param string $name The name of the strategy to register. + * @param StrategyInterface $strategy The strategy to register. + * @return HydratorInterface + */ + public function addStrategy($name, StrategyInterface $strategy) + { + $this->strategies[$name] = $strategy; + return $this; + } + + /** + * Removes the strategy with the given name. + * + * @param string $name The name of the strategy to remove. + * @return HydratorInterface + */ + public function removeStrategy($name) + { + unset($this->strategies[$name]); + return $this; + } + + /** + * Converts a value for extraction. If no strategy exists the plain value is returned. + * + * @param string $name The name of the strategy to use. + * @param mixed $value The value that should be converted. + * @param array $object The object is optionally provided as context. + * @return mixed + */ + public function extractValue($name, $value, $object = null) + { + if ($this->hasStrategy($name)) { + $strategy = $this->getStrategy($name); + $value = $strategy->extract($value, $object); + } + return $value; + } + + /** + * Converts a value for hydration. If no strategy exists the plain value is returned. + * + * @param string $name The name of the strategy to use. + * @param mixed $value The value that should be converted. + * @param array $data The whole data is optionally provided as context. + * @return mixed + */ + public function hydrateValue($name, $value, $data = null) + { + if ($this->hasStrategy($name)) { + $strategy = $this->getStrategy($name); + $value = $strategy->hydrate($value, $data); + } + return $value; + } + + /** + * Get the filter instance + * + * @return Filter\FilterComposite + */ + public function getFilter() + { + return $this->filterComposite; + } + + /** + * Add a new filter to take care of what needs to be hydrated. + * To exclude e.g. the method getServiceLocator: + * + * <code> + * $composite->addFilter("servicelocator", + * function($property) { + * list($class, $method) = explode('::', $property); + * if ($method === 'getServiceLocator') { + * return false; + * } + * return true; + * }, FilterComposite::CONDITION_AND + * ); + * </code> + * + * @param string $name Index in the composite + * @param callable|Filter\FilterInterface $filter + * @param int $condition + * @return Filter\FilterComposite + */ + public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR) + { + return $this->filterComposite->addFilter($name, $filter, $condition); + } + + /** + * Check whether a specific filter exists at key $name or not + * + * @param string $name Index in the composite + * @return bool + */ + public function hasFilter($name) + { + return $this->filterComposite->hasFilter($name); + } + + /** + * Remove a filter from the composition. + * To not extract "has" methods, you simply need to unregister it + * + * <code> + * $filterComposite->removeFilter('has'); + * </code> + * + * @param $name + * @return Filter\FilterComposite + */ + public function removeFilter($name) + { + return $this->filterComposite->removeFilter($name); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/AggregateHydrator.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/AggregateHydrator.php new file mode 100644 index 0000000000000000000000000000000000000000..bdcf1eb0adfdbad7ac0af43365373cdbe28fa78c --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/AggregateHydrator.php @@ -0,0 +1,87 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Aggregate; + +use Zend\EventManager\EventManager; +use Zend\EventManager\EventManagerAwareInterface; +use Zend\EventManager\EventManagerInterface; +use Zend\Stdlib\Exception; +use Zend\Stdlib\Hydrator\Filter\FilterComposite; +use Zend\Stdlib\Hydrator\HydratorInterface; + +/** + * Aggregate hydrator that composes multiple hydrators via events + */ +class AggregateHydrator implements HydratorInterface, EventManagerAwareInterface +{ + const DEFAULT_PRIORITY = 1; + + /** + * @var \Zend\EventManager\EventManagerInterface|null + */ + protected $eventManager; + + /** + * Attaches the provided hydrator to the list of hydrators to be used while hydrating/extracting data + * + * @param \Zend\Stdlib\Hydrator\HydratorInterface $hydrator + * @param int $priority + */ + public function add(HydratorInterface $hydrator, $priority = self::DEFAULT_PRIORITY) + { + $this->getEventManager()->attachAggregate(new HydratorListener($hydrator), $priority); + } + + /** + * {@inheritDoc} + */ + public function extract($object) + { + $event = new ExtractEvent($this, $object); + + $this->getEventManager()->trigger($event); + + return $event->getExtractedData(); + } + + /** + * {@inheritDoc} + */ + public function hydrate(array $data, $object) + { + $event = new HydrateEvent($this, $object, $data); + + $this->getEventManager()->trigger($event); + + return $event->getHydratedObject(); + } + + /** + * {@inheritDoc} + */ + public function setEventManager(EventManagerInterface $eventManager) + { + $eventManager->setIdentifiers(array(__CLASS__, get_class($this))); + + $this->eventManager = $eventManager; + } + + /** + * {@inheritDoc} + */ + public function getEventManager() + { + if (null === $this->eventManager) { + $this->setEventManager(new EventManager()); + } + + return $this->eventManager; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/ExtractEvent.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/ExtractEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..dfdfbcfb6b508183c4b4a0b22ae23790df395b0e --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/ExtractEvent.php @@ -0,0 +1,99 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Aggregate; + + +use Zend\EventManager\Event; + +/** + * Event triggered when the {@see \Zend\Stdlib\Hydrator\Aggregate\AggregateHydrator} extracts + * data from an object + */ +class ExtractEvent extends Event +{ + const EVENT_EXTRACT = 'extract'; + + /** + * {@inheritDoc} + */ + protected $name = self::EVENT_EXTRACT; + + /** + * @var object + */ + protected $extractionObject; + + /** + * @var array + */ + protected $extractedData = array(); + + /** + * @param object $target + * @param object $extractionObject + */ + public function __construct($target, $extractionObject) + { + $this->target = $target; + $this->extractionObject = $extractionObject; + } + + /** + * Retrieves the object from which data is extracted + * + * @return object + */ + public function getExtractionObject() + { + return $this->extractionObject; + } + + /** + * @param object $extractionObject + * + * @return void + */ + public function setExtractionObject($extractionObject) + { + $this->extractionObject = $extractionObject; + } + + /** + * Retrieves the data that has been extracted + * + * @return array + */ + public function getExtractedData() + { + return $this->extractedData; + } + + /** + * @param array $extractedData + * + * @return void + */ + public function setExtractedData(array $extractedData) + { + $this->extractedData = $extractedData; + } + + /** + * Merge provided data with the extracted data + * + * @param array $additionalData + * + * @return void + */ + public function mergeExtractedData(array $additionalData) + { + $this->extractedData = array_merge($this->extractedData, $additionalData); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydrateEvent.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydrateEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..11bab0237974918d80a6d01c736b3e4ef7d51ac9 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydrateEvent.php @@ -0,0 +1,85 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Aggregate; + + +use Zend\EventManager\Event; + +/** + * Event triggered when the {@see \Zend\Stdlib\Hydrator\Aggregate\AggregateHydrator} hydrates + * data into an object + */ +class HydrateEvent extends Event +{ + const EVENT_HYDRATE = 'hydrate'; + + /** + * {@inheritDoc} + */ + protected $name = self::EVENT_HYDRATE; + + /** + * @var object + */ + protected $hydratedObject; + + /** + * @var array + */ + protected $hydrationData; + + /** + * @param object $target + * @param object $hydratedObject + * @param array $hydrationData + */ + public function __construct($target, $hydratedObject, array $hydrationData) + { + $this->target = $target; + $this->hydratedObject = $hydratedObject; + $this->hydrationData = $hydrationData; + } + + /** + * Retrieves the object that is being hydrated + * + * @return object + */ + public function getHydratedObject() + { + return $this->hydratedObject; + } + + /** + * @param object $hydratedObject + */ + public function setHydratedObject($hydratedObject) + { + $this->hydratedObject = $hydratedObject; + } + + /** + * Retrieves the data that is being used for hydration + * + * @return array + */ + public function getHydrationData() + { + return $this->hydrationData; + } + + /** + * @param array $hydrationData + */ + public function setHydrationData(array $hydrationData) + { + $this->hydrationData = $hydrationData; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydratorListener.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydratorListener.php new file mode 100644 index 0000000000000000000000000000000000000000..68cc67274cb96510c9ac58daa1cb01efeb8fcdaf --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydratorListener.php @@ -0,0 +1,81 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Aggregate; + + +use Zend\EventManager\AbstractListenerAggregate; +use Zend\EventManager\EventManagerInterface; +use Zend\Stdlib\Hydrator\HydratorInterface; + +/** + * Aggregate listener wrapping around a hydrator. Listens + * to {@see \Zend\Stdlib\Hydrator\Aggregate::EVENT_HYDRATE} and + * {@see \Zend\Stdlib\Hydrator\Aggregate::EVENT_EXTRACT} + */ +class HydratorListener extends AbstractListenerAggregate +{ + /** + * @var \Zend\Stdlib\Hydrator\HydratorInterface + */ + protected $hydrator; + + /** + * @param \Zend\Stdlib\Hydrator\HydratorInterface $hydrator + */ + public function __construct(HydratorInterface $hydrator) + { + $this->hydrator = $hydrator; + } + + /** + * {@inheritDoc} + */ + public function attach(EventManagerInterface $events) + { + $this->listeners[] = $events->attach(HydrateEvent::EVENT_HYDRATE, array($this, 'onHydrate')); + $this->listeners[] = $events->attach(ExtractEvent::EVENT_EXTRACT, array($this, 'onExtract')); + } + + /** + * Callback to be used when {@see \Zend\Stdlib\Hydrator\Aggregate\HydrateEvent::EVENT_HYDRATE} is triggered + * + * @param \Zend\Stdlib\Hydrator\Aggregate\HydrateEvent $event + * + * @return object + * + * @internal + */ + public function onHydrate(HydrateEvent $event) + { + $object = $this->hydrator->hydrate($event->getHydrationData(), $event->getHydratedObject()); + + $event->setHydratedObject($object); + + return $object; + } + + /** + * Callback to be used when {@see \Zend\Stdlib\Hydrator\Aggregate\ExtractEvent::EVENT_EXTRACT} is triggered + * + * @param \Zend\Stdlib\Hydrator\Aggregate\ExtractEvent $event + * + * @return array + * + * @internal + */ + public function onExtract(ExtractEvent $event) + { + $data = $this->hydrator->extract($event->getExtractionObject()); + + $event->mergeExtractedData($data); + + return $data; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ArraySerializable.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ArraySerializable.php new file mode 100644 index 0000000000000000000000000000000000000000..d9631122e15e547608afba8e4fb2cbeaaca0d601 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ArraySerializable.php @@ -0,0 +1,77 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +use Zend\Stdlib\Exception; + +class ArraySerializable extends AbstractHydrator +{ + + /** + * Extract values from the provided object + * + * Extracts values via the object's getArrayCopy() method. + * + * @param object $object + * @return array + * @throws Exception\BadMethodCallException for an $object not implementing getArrayCopy() + */ + public function extract($object) + { + if (!is_callable(array($object, 'getArrayCopy'))) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided object to implement getArrayCopy()', __METHOD__ + )); + } + + $data = $object->getArrayCopy(); + + foreach ($data as $name => $value) { + if (!$this->getFilter()->filter($name)) { + unset($data[$name]); + continue; + } + + $data[$name] = $this->extractValue($name, $value); + } + + return $data; + } + + /** + * Hydrate an object + * + * Hydrates an object by passing $data to either its exchangeArray() or + * populate() method. + * + * @param array $data + * @param object $object + * @return object + * @throws Exception\BadMethodCallException for an $object not implementing exchangeArray() or populate() + */ + public function hydrate(array $data, $object) + { + $self = $this; + array_walk($data, function (&$value, $name) use ($self) { + $value = $self->hydrateValue($name, $value); + }); + + if (is_callable(array($object, 'exchangeArray'))) { + $object->exchangeArray($data); + } elseif (is_callable(array($object, 'populate'))) { + $object->populate($data); + } else { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided object to implement exchangeArray() or populate()', __METHOD__ + )); + } + return $object; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ClassMethods.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ClassMethods.php new file mode 100644 index 0000000000000000000000000000000000000000..e0c3f99ed4735839d9aeacc0cfc317c8796c8d09 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ClassMethods.php @@ -0,0 +1,190 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +use ReflectionMethod; +use Traversable; +use Zend\Stdlib\Exception; +use Zend\Stdlib\ArrayUtils; +use Zend\Stdlib\Hydrator\Filter\FilterComposite; +use Zend\Stdlib\Hydrator\Filter\FilterProviderInterface; +use Zend\Stdlib\Hydrator\Filter\GetFilter; +use Zend\Stdlib\Hydrator\Filter\HasFilter; +use Zend\Stdlib\Hydrator\Filter\IsFilter; +use Zend\Stdlib\Hydrator\Filter\MethodMatchFilter; +use Zend\Stdlib\Hydrator\Filter\NumberOfParameterFilter; + +class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface +{ + /** + * Flag defining whether array keys are underscore-separated (true) or camel case (false) + * @var bool + */ + protected $underscoreSeparatedKeys = true; + + /** + * Define if extract values will use camel case or name with underscore + * @param bool|array $underscoreSeparatedKeys + */ + public function __construct($underscoreSeparatedKeys = true) + { + parent::__construct(); + $this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys); + + $this->filterComposite->addFilter("is", new IsFilter()); + $this->filterComposite->addFilter("has", new HasFilter()); + $this->filterComposite->addFilter("get", new GetFilter()); + $this->filterComposite->addFilter("parameter", new NumberOfParameterFilter(), FilterComposite::CONDITION_AND); + } + + /** + * @param array|Traversable $options + * @return ClassMethods + * @throws Exception\InvalidArgumentException + */ + public function setOptions($options) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (!is_array($options)) { + throw new Exception\InvalidArgumentException( + 'The options parameter must be an array or a Traversable' + ); + } + if (isset($options['underscoreSeparatedKeys'])) { + $this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']); + } + + return $this; + } + + /** + * @param bool $underscoreSeparatedKeys + * @return ClassMethods + */ + public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys) + { + $this->underscoreSeparatedKeys = $underscoreSeparatedKeys; + + return $this; + } + + /** + * @return bool + */ + public function getUnderscoreSeparatedKeys() + { + return $this->underscoreSeparatedKeys; + } + + /** + * Extract values from an object with class methods + * + * Extracts the getter/setter of the given $object. + * + * @param object $object + * @return array + * @throws Exception\BadMethodCallException for a non-object $object + */ + public function extract($object) + { + if (!is_object($object)) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided $object to be a PHP object)', __METHOD__ + )); + } + + $filter = null; + if ($object instanceof FilterProviderInterface) { + $filter = new FilterComposite( + array($object->getFilter()), + array(new MethodMatchFilter("getFilter")) + ); + } else { + $filter = $this->filterComposite; + } + + $transform = function ($letters) { + $letter = array_shift($letters); + + return '_' . strtolower($letter); + }; + $attributes = array(); + $methods = get_class_methods($object); + + foreach ($methods as $method) { + if ( + !$filter->filter( + get_class($object) . '::' . $method + ) + ) { + continue; + } + + $reflectionMethod = new ReflectionMethod(get_class($object) . '::' . $method); + if ($reflectionMethod->getNumberOfParameters() > 0) { + continue; + } + + $attribute = $method; + if (preg_match('/^get/', $method)) { + $attribute = substr($method, 3); + if (!property_exists($object, $attribute)) { + $attribute = lcfirst($attribute); + } + } + + if ($this->underscoreSeparatedKeys) { + $attribute = preg_replace_callback('/([A-Z])/', $transform, $attribute); + } + $attributes[$attribute] = $this->extractValue($attribute, $object->$method(), $object); + } + + return $attributes; + } + + /** + * Hydrate an object by populating getter/setter methods + * + * Hydrates an object by getter/setter methods of the object. + * + * @param array $data + * @param object $object + * @return object + * @throws Exception\BadMethodCallException for a non-object $object + */ + public function hydrate(array $data, $object) + { + if (!is_object($object)) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided $object to be a PHP object)', __METHOD__ + )); + } + + $transform = function ($letters) { + $letter = substr(array_shift($letters), 1, 1); + + return ucfirst($letter); + }; + + foreach ($data as $property => $value) { + $method = 'set' . ucfirst($property); + if ($this->underscoreSeparatedKeys) { + $method = preg_replace_callback('/(_[a-z])/', $transform, $method); + } + if (is_callable(array($object, $method))) { + $value = $this->hydrateValue($property, $value, $data); + $object->$method($value); + } + } + + return $object; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterComposite.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterComposite.php new file mode 100644 index 0000000000000000000000000000000000000000..f5ce7e9c8d034856f3370521ddce2f64bcc2a44f --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterComposite.php @@ -0,0 +1,198 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +namespace Zend\Stdlib\Hydrator\Filter; + +use ArrayObject; +use Zend\Stdlib\Exception\InvalidArgumentException; + +class FilterComposite implements FilterInterface +{ + /** + * @var ArrayObject + */ + protected $orFilter; + + /** + * @var ArrayObject + */ + protected $andFilter; + + /** + * Constant to add with "or" conditition + */ + const CONDITION_OR = 1; + + /** + * Constant to add with "and" conditition + */ + const CONDITION_AND = 2; + + /** + * Define default Filter + * + * @throws InvalidArgumentException + */ + public function __construct($orFilter = array(), $andFilter = array()) + { + array_walk($orFilter, + function($value, $key) { + if ( + !is_callable($value) + && !$value instanceof FilterInterface + ) { + throw new InvalidArgumentException( + 'The value of ' . $key . ' should be either a callable or ' . + 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' + ); + } + } + ); + + array_walk($andFilter, + function($value, $key) { + if ( + !is_callable($value) + && !$value instanceof FilterInterface + ) { + throw new InvalidArgumentException( + 'The value of ' . $key . ' should be either a callable or ' . + 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' + ); + } + } + ); + + $this->orFilter = new ArrayObject($orFilter); + $this->andFilter = new ArrayObject($andFilter); + } + + /** + * Add a filter to the composite. Has to be indexed with $name in + * order to identify a specific filter. + * + * This example will exclude all methods from the hydration, that starts with 'getService' + * <code> + * $composite->addFilter('exclude', + * function($method) { + * if (preg_match('/^getService/', $method) { + * return false; + * } + * return true; + * }, FilterComposite::CONDITION_AND + * ); + * </code> + * + * @param string $name + * @param callable|FilterInterface $filter + * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND + * @throws InvalidArgumentException + * @return FilterComposite + */ + public function addFilter($name, $filter, $condition = self::CONDITION_OR) + { + if (!is_callable($filter) && !($filter instanceof FilterInterface)) { + throw new InvalidArgumentException( + 'The value of ' . $name . ' should be either a callable or ' . + 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' + ); + } + + if ($condition === self::CONDITION_OR) { + $this->orFilter[$name] = $filter; + } elseif ($condition === self::CONDITION_AND) { + $this->andFilter[$name] = $filter; + } + + return $this; + } + + /** + * Remove a filter from the composition + * + * @param $name string Identifier for the filter + * @return FilterComposite + */ + public function removeFilter($name) + { + if (isset($this->orFilter[$name])) { + unset($this->orFilter[$name]); + } + + if (isset($this->andFilter[$name])) { + unset($this->andFilter[$name]); + } + + return $this; + } + + /** + * Check if $name has a filter registered + * + * @param $name string Identifier for the filter + * @return bool + */ + public function hasFilter($name) + { + return isset($this->orFilter[$name]) || isset($this->andFilter[$name]); + } + + /** + * Filter the composite based on the AND and OR condition + * Will return true if one from the "or conditions" and all from + * the "and condition" returns true. Otherwise false + * + * @param $property string Parameter will be e.g. Parent\Namespace\Class::method + * @return bool + */ + public function filter($property) + { + $andCount = count($this->andFilter); + $orCount = count($this->orFilter); + // return true if no filters are registered + if ($orCount === 0 && $andCount === 0) { + return true; + } elseif ($orCount === 0 && $andCount !== 0) { + $returnValue = true; + } else { + $returnValue = false; + } + + // Check if 1 from the or filters return true + foreach ($this->orFilter as $filter) { + if (is_callable($filter)) { + if ($filter($property) === true) { + $returnValue = true; + break; + } + continue; + } else { + if ($filter->filter($property) === true) { + $returnValue = true; + break; + } + } + } + + // Check if all of the and condition return true + foreach ($this->andFilter as $filter) { + if (is_callable($filter)) { + if ($filter($property) === false) { + return false; + } + continue; + } else { + if ($filter->filter($property) === false) { + return false; + } + } + } + + return $returnValue; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..30bd3575a13dabfd95bd6c3a22abb8de438f4140 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +namespace Zend\Stdlib\Hydrator\Filter; + +interface FilterInterface +{ + /** + * Should return true, if the given filter + * does not match + * + * @param string $property The name of the property + * @return bool + */ + public function filter($property); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterProviderInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..18f3597a65a17b17c308957fbff6c30b03c84372 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterProviderInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +namespace Zend\Stdlib\Hydrator\Filter; + +interface FilterProviderInterface +{ + /** + * Provides a filter for hydration + * + * @return FilterInterface + */ + public function getFilter(); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/GetFilter.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/GetFilter.php new file mode 100644 index 0000000000000000000000000000000000000000..d112396ec0161041c12ef9dbecd96dc4e495bacd --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/GetFilter.php @@ -0,0 +1,27 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +namespace Zend\Stdlib\Hydrator\Filter; + +class GetFilter implements FilterInterface +{ + public function filter($property) + { + $pos = strpos($property, '::'); + if ($pos !== false) { + $pos += 2; + } else { + $pos = 0; + } + + if (substr($property, $pos, 3) === 'get') { + return true; + } + return false; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/HasFilter.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/HasFilter.php new file mode 100644 index 0000000000000000000000000000000000000000..dfc23f97f20748c9672f07910fe39efe73ad15c6 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/HasFilter.php @@ -0,0 +1,27 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +namespace Zend\Stdlib\Hydrator\Filter; + +class HasFilter implements FilterInterface +{ + public function filter($property) + { + $pos = strpos($property, '::'); + if ($pos !== false) { + $pos += 2; + } else { + $pos = 0; + } + + if (substr($property, $pos, 3) === 'has') { + return true; + } + return false; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/IsFilter.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/IsFilter.php new file mode 100644 index 0000000000000000000000000000000000000000..233ae139f6f0a3132c2028e7ef590923943dcac8 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/IsFilter.php @@ -0,0 +1,27 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +namespace Zend\Stdlib\Hydrator\Filter; + +class IsFilter implements FilterInterface +{ + public function filter($property) + { + $pos = strpos($property, '::'); + if ($pos !== false) { + $pos += 2; + } else { + $pos = 0; + } + + if (substr($property, $pos, 2) === 'is') { + return true; + } + return false; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/MethodMatchFilter.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/MethodMatchFilter.php new file mode 100644 index 0000000000000000000000000000000000000000..a61cd5a3d614ea86b0227abf86957b0d937147ca --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/MethodMatchFilter.php @@ -0,0 +1,48 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +namespace Zend\Stdlib\Hydrator\Filter; + +class MethodMatchFilter implements FilterInterface +{ + /** + * The method to exclude + * @var string + */ + protected $method = null; + + /** + * Either an exclude or an include + * @var bool + */ + protected $exclude = null; + + /** + * @param string $method The method to exclude or include + * @param bool $exclude If the method should be excluded + */ + public function __construct($method, $exclude = true) + { + $this->method = $method; + $this->exclude = $exclude; + } + + public function filter($property) + { + $pos = strpos($property, '::'); + if ($pos !== false) { + $pos += 2; + } else { + $pos = 0; + } + if (substr($property, $pos) === $this->method) { + return $this->exclude ? false : true; + } + return $this->exclude ? true : false; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/NumberOfParameterFilter.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/NumberOfParameterFilter.php new file mode 100644 index 0000000000000000000000000000000000000000..7f4e05289f3e6916dc2889221f5b8a890a190ccb --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/NumberOfParameterFilter.php @@ -0,0 +1,54 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Filter; + +use ReflectionException; +use ReflectionMethod; +use Zend\Stdlib\Exception\InvalidArgumentException; +use Zend\Stdlib\Hydrator\Filter\FilterInterface; + +class NumberOfParameterFilter implements FilterInterface +{ + /** + * The number of parameters beeing accepted + * @var int + */ + protected $numberOfParameters = null; + + /** + * @param int $numberOfParameters Number of accepted parameters + */ + public function __construct($numberOfParameters = 0) + { + $this->numberOfParameters = 0; + } + + /** + * @param string $property the name of the property + * @return bool + * @throws InvalidArgumentException + */ + public function filter($property) + { + try { + $reflectionMethod = new ReflectionMethod($property); + } catch (ReflectionException $exception) { + throw new InvalidArgumentException( + "Method $property doesn't exist" + ); + } + + if ($reflectionMethod->getNumberOfParameters() !== $this->numberOfParameters) { + return false; + } + + return true; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorAwareInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorAwareInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f2784b3bb2848d3bf2034b99bde055d6979e7722 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorAwareInterface.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +interface HydratorAwareInterface +{ + /** + * Set hydrator + * + * @param HydratorInterface $hydrator + * @return HydratorAwareInterface + */ + public function setHydrator(HydratorInterface $hydrator); + + /** + * Retrieve hydrator + * + * @return HydratorInterface + */ + public function getHydrator(); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c6b3e89e20a4b5fb1a5f176adbbf6c54f4a4749e --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorInterface.php @@ -0,0 +1,30 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +interface HydratorInterface +{ + /** + * Extract values from an object + * + * @param object $object + * @return array + */ + public function extract($object); + + /** + * Hydrate $object with the provided $data. + * + * @param array $data + * @param object $object + * @return object + */ + public function hydrate(array $data, $object); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..740cfb435de318bd10d129e199a4585c66db558c --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +interface HydratorOptionsInterface +{ + /** + * @param array|\Traversable $options + * @return HydratorOptionsInterface + */ + public function setOptions($options); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorPluginManager.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorPluginManager.php new file mode 100644 index 0000000000000000000000000000000000000000..0e9892a25299f317212b2cde3ccdc7bd4c45b41b --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorPluginManager.php @@ -0,0 +1,56 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +use Zend\ServiceManager\AbstractPluginManager; +use Zend\Stdlib\Exception; + +/** + * Plugin manager implementation for hydrators. + * + * Enforces that adapters retrieved are instances of HydratorInterface + */ +class HydratorPluginManager extends AbstractPluginManager +{ + /** + * Whether or not to share by default + * + * @var bool + */ + protected $shareByDefault = false; + + /** + * Default set of adapters + * + * @var array + */ + protected $invokableClasses = array( + 'arrayserializable' => 'Zend\Stdlib\Hydrator\ArraySerializable', + 'classmethods' => 'Zend\Stdlib\Hydrator\ClassMethods', + 'objectproperty' => 'Zend\Stdlib\Hydrator\ObjectProperty', + 'reflection' => 'Zend\Stdlib\Hydrator\Reflection' + ); + + /** + * {@inheritDoc} + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof HydratorInterface) { + // we're okay + return; + } + + throw new Exception\RuntimeException(sprintf( + 'Plugin of type %s is invalid; must implement Zend\Stdlib\Hydrator\HydratorInterface', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)) + )); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ObjectProperty.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ObjectProperty.php new file mode 100644 index 0000000000000000000000000000000000000000..c0bf569a2fed3e96e0584ad8b77e5059cf3590dd --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ObjectProperty.php @@ -0,0 +1,71 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +use Zend\Stdlib\Exception; + +class ObjectProperty extends AbstractHydrator +{ + /** + * Extract values from an object + * + * Extracts the accessible non-static properties of the given $object. + * + * @param object $object + * @return array + * @throws Exception\BadMethodCallException for a non-object $object + */ + public function extract($object) + { + if (!is_object($object)) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided $object to be a PHP object)', __METHOD__ + )); + } + + $data = get_object_vars($object); + + $filter = $this->getFilter(); + foreach ($data as $name => $value) { + // Filter keys, removing any we don't want + if (!$filter->filter($name)) { + unset($data[$name]); + continue; + } + // Extract data + $data[$name] = $this->extractValue($name, $value); + } + + return $data; + } + + /** + * Hydrate an object by populating public properties + * + * Hydrates an object by setting public properties of the object. + * + * @param array $data + * @param object $object + * @return object + * @throws Exception\BadMethodCallException for a non-object $object + */ + public function hydrate(array $data, $object) + { + if (!is_object($object)) { + throw new Exception\BadMethodCallException(sprintf( + '%s expects the provided $object to be a PHP object)', __METHOD__ + )); + } + foreach ($data as $property => $value) { + $object->$property = $this->hydrateValue($property, $value, $data); + } + return $object; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Reflection.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Reflection.php new file mode 100644 index 0000000000000000000000000000000000000000..1c093c88b379e9476ba653c4ffad4100442e7706 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Reflection.php @@ -0,0 +1,92 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +use ReflectionClass; +use Zend\Stdlib\Exception; + +class Reflection extends AbstractHydrator +{ + /** + * Simple in-memory array cache of ReflectionProperties used. + * @var array + */ + protected static $reflProperties = array(); + + /** + * Extract values from an object + * + * @param object $object + * @return array + */ + public function extract($object) + { + $result = array(); + foreach (self::getReflProperties($object) as $property) { + $propertyName = $property->getName(); + if (!$this->filterComposite->filter($propertyName)) { + continue; + } + + $value = $property->getValue($object); + $result[$propertyName] = $this->extractValue($propertyName, $value, $object); + } + + return $result; + } + + /** + * Hydrate $object with the provided $data. + * + * @param array $data + * @param object $object + * @return object + */ + public function hydrate(array $data, $object) + { + $reflProperties = self::getReflProperties($object); + foreach ($data as $key => $value) { + if (isset($reflProperties[$key])) { + $reflProperties[$key]->setValue($object, $this->hydrateValue($key, $value, $data)); + } + } + return $object; + } + + /** + * Get a reflection properties from in-memory cache and lazy-load if + * class has not been loaded. + * + * @static + * @param string|object $input + * @throws Exception\InvalidArgumentException + * @return array + */ + protected static function getReflProperties($input) + { + if (is_object($input)) { + $input = get_class($input); + } elseif (!is_string($input)) { + throw new Exception\InvalidArgumentException('Input must be a string or an object.'); + } + + if (!isset(static::$reflProperties[$input])) { + $reflClass = new ReflectionClass($input); + $reflProperties = $reflClass->getProperties(); + + foreach ($reflProperties as $property) { + $property->setAccessible(true); + static::$reflProperties[$input][$property->getName()] = $property; + } + } + + return static::$reflProperties[$input]; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/ClosureStrategy.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/ClosureStrategy.php new file mode 100644 index 0000000000000000000000000000000000000000..1367b5c06d11a5e09530bf8e7d2766331bb2e07c --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/ClosureStrategy.php @@ -0,0 +1,100 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Strategy; + +class ClosureStrategy implements StrategyInterface +{ + /** + * Function, used in extract method, default: + * function($value) { + * return $value; + * }; + * @var callable + */ + protected $extractFunc = null; + + /** + * Function, used in hydrate method, default: + * function($value) { + * return $value; + * }; + * @var callable + */ + protected $hydrateFunc = null; + + /** + * You can describe how your values will extract and hydrate, like this: + * $hydrator->addStrategy('category', new ClosureStrategy( + * function(Category $value) { + * return (int)$value->id; + * }, + * function($value) { + * return new Category((int)$value); + * } + * )); + * + * @param callable $extractFunc - anonymous function, that extract values + * from object + * @param callable $hydrateFunc - anonymous function, that hydrate values + * into object + */ + public function __construct($extractFunc = null, $hydrateFunc = null) + { + if (isset($extractFunc)) { + if (!is_callable($extractFunc)) { + throw new \Exception('$extractFunc must be callable'); + } + + $this->extractFunc = $extractFunc; + } else { + $this->extractFunc = function($value) { + return $value; + }; + } + + if (isset($hydrateFunc)) { + if (!is_callable($hydrateFunc)) { + throw new \Exception('$hydrateFunc must be callable'); + } + + $this->hydrateFunc = $hydrateFunc; + } else { + $this->hydrateFunc = function($value) { + return $value; + }; + } + } + + /** + * Converts the given value so that it can be extracted by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be extracted. + */ + public function extract($value) + { + $func = $this->extractFunc; + + return $func($value); + } + + /** + * Converts the given value so that it can be hydrated by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be hydrated. + */ + public function hydrate($value) + { + $func = $this->hydrateFunc; + + return $func($value); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/DefaultStrategy.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/DefaultStrategy.php new file mode 100644 index 0000000000000000000000000000000000000000..d98f1f4c7277247e98cd068784f1a477de1a3ef2 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/DefaultStrategy.php @@ -0,0 +1,35 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Strategy; + +class DefaultStrategy implements StrategyInterface +{ + /** + * Converts the given value so that it can be extracted by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be extracted. + */ + public function extract($value) + { + return $value; + } + + /** + * Converts the given value so that it can be hydrated by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be hydrated. + */ + public function hydrate($value) + { + return $value; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php new file mode 100644 index 0000000000000000000000000000000000000000..67b323ad6a01fdc3140f0f3c1b0cde30edf4340c --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php @@ -0,0 +1,123 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Strategy; + +use Zend\Stdlib\Exception\InvalidArgumentException; +use Zend\Serializer\Adapter\AdapterInterface as SerializerAdapter; +use Zend\Serializer\Serializer as SerializerFactory; + +class SerializableStrategy implements StrategyInterface +{ + /** + * @var string|SerializerAdapter + */ + protected $serializer; + + /** + * @var array + */ + protected $serializerOptions = array(); + + /** + * + * @param mixed $serializer string or SerializerAdapter + * @param mixed $serializerOptions + */ + public function __construct($serializer, $serializerOptions = null) + { + $this->setSerializer($serializer); + if ($serializerOptions) { + $this->setSerializerOptions($serializerOptions); + } + } + + /** + * Serialize the given value so that it can be extracted by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be extracted. + */ + public function extract($value) + { + $serializer = $this->getSerializer(); + return $serializer->serialize($value); + } + + /** + * Unserialize the given value so that it can be hydrated by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be hydrated. + */ + public function hydrate($value) + { + $serializer = $this->getSerializer(); + return $serializer->unserialize($value); + } + + /** + * Set serializer + * + * @param string|SerializerAdapter $serializer + * @return SerializableStrategy + */ + public function setSerializer($serializer) + { + if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) { + throw new InvalidArgumentException(sprintf( + '%s expects either a string serializer name or Zend\Serializer\Adapter\AdapterInterface instance; ' + . 'received "%s"', + __METHOD__, + (is_object($serializer) ? get_class($serializer) : gettype($serializer)) + )); + } + $this->serializer = $serializer; + return $this; + } + + /** + * Get serializer + * + * @return SerializerAdapter + */ + public function getSerializer() + { + if (is_string($this->serializer)) { + $options = $this->getSerializerOptions(); + $this->setSerializer(SerializerFactory::factory($this->serializer, $options)); + } elseif (null === $this->serializer) { + $this->setSerializer(SerializerFactory::getDefaultAdapter()); + } + + return $this->serializer; + } + + /** + * Set configuration options for instantiating a serializer adapter + * + * @param mixed $serializerOptions + * @return SerializableStrategy + */ + public function setSerializerOptions($serializerOptions) + { + $this->serializerOptions = $serializerOptions; + return $this; + } + + /** + * Get configuration options for instantiating a serializer adapter + * + * @return mixed + */ + public function getSerializerOptions() + { + return $this->serializerOptions; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/StrategyInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/StrategyInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..85c21cc3f8fc0bfd3019b15342451020a7972f65 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/StrategyInterface.php @@ -0,0 +1,29 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator\Strategy; + +interface StrategyInterface +{ + /** + * Converts the given value so that it can be extracted by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be extracted. + */ + public function extract($value); + + /** + * Converts the given value so that it can be hydrated by the hydrator. + * + * @param mixed $value The original value. + * @return mixed Returns the value that should be hydrated. + */ + public function hydrate($value); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/StrategyEnabledInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/StrategyEnabledInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..41fda04c4ecea80df75d64d4a74d16742811b790 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/StrategyEnabledInterface.php @@ -0,0 +1,48 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\Hydrator; + +use Zend\Stdlib\Hydrator\Strategy\StrategyInterface; + +interface StrategyEnabledInterface +{ + /** + * Adds the given strategy under the given name. + * + * @param string $name The name of the strategy to register. + * @param StrategyInterface $strategy The strategy to register. + * @return StrategyEnabledInterface + */ + public function addStrategy($name, StrategyInterface $strategy); + + /** + * Gets the strategy with the given name. + * + * @param string $name The name of the strategy to get. + * @return StrategyInterface + */ + public function getStrategy($name); + + /** + * Checks if the strategy with the given name exists. + * + * @param string $name The name of the strategy to check for. + * @return bool + */ + public function hasStrategy($name); + + /** + * Removes the strategy with the given name. + * + * @param string $name The name of the strategy to remove. + * @return StrategyEnabledInterface + */ + public function removeStrategy($name); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/InitializableInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/InitializableInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..39a71ebf236a299358e9a3d348fd4c4876479894 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/InitializableInterface.php @@ -0,0 +1,23 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +/** + * Interface to allow objects to have initialization logic + */ +interface InitializableInterface +{ + /** + * Init an object + * + * @return void + */ + public function init(); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Message.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Message.php new file mode 100644 index 0000000000000000000000000000000000000000..3e3f1f5be51114276357493a2795993a4b395d50 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Message.php @@ -0,0 +1,118 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Traversable; + +class Message implements MessageInterface +{ + /** + * @var array + */ + protected $metadata = array(); + + /** + * @var string + */ + protected $content = ''; + + /** + * Set message metadata + * + * Non-destructive setting of message metadata; always adds to the metadata, never overwrites + * the entire metadata container. + * + * @param string|int|array|Traversable $spec + * @param mixed $value + * @throws Exception\InvalidArgumentException + * @return Message + */ + public function setMetadata($spec, $value = null) + { + if (is_scalar($spec)) { + $this->metadata[$spec] = $value; + return $this; + } + if (!is_array($spec) && !$spec instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expected a string, array, or Traversable argument in first position; received "%s"', + (is_object($spec) ? get_class($spec) : gettype($spec)) + )); + } + foreach ($spec as $key => $value) { + $this->metadata[$key] = $value; + } + return $this; + } + + /** + * Retrieve all metadata or a single metadatum as specified by key + * + * @param null|string|int $key + * @param null|mixed $default + * @throws Exception\InvalidArgumentException + * @return mixed + */ + public function getMetadata($key = null, $default = null) + { + if (null === $key) { + return $this->metadata; + } + + if (!is_scalar($key)) { + throw new Exception\InvalidArgumentException('Non-scalar argument provided for key'); + } + + if (array_key_exists($key, $this->metadata)) { + return $this->metadata[$key]; + } + + return $default; + } + + /** + * Set message content + * + * @param mixed $value + * @return Message + */ + public function setContent($value) + { + $this->content = $value; + return $this; + } + + /** + * Get message content + * + * @return mixed + */ + public function getContent() + { + return $this->content; + } + + /** + * @return string + */ + public function toString() + { + $request = ''; + foreach ($this->getMetadata() as $key => $value) { + $request .= sprintf( + "%s: %s\r\n", + (string) $key, + (string) $value + ); + } + $request .= "\r\n" . $this->getContent(); + return $request; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/MessageInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/MessageInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0abb1ff6b8af73456bb869d25e3ec280e6ec0056 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/MessageInterface.php @@ -0,0 +1,45 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +interface MessageInterface +{ + /** + * Set metadata + * + * @param string|int|array|\Traversable $spec + * @param mixed $value + */ + public function setMetadata($spec, $value = null); + + /** + * Get metadata + * + * @param null|string|int $key + * @return mixed + */ + public function getMetadata($key = null); + + /** + * Set content + * + * @param mixed $content + * @return mixed + */ + public function setContent($content); + + /** + * Get content + * + * @return mixed + */ + public function getContent(); + +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ParameterObjectInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ParameterObjectInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..416b8c2985f291adc6c0a0bb12ae385977f86367 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ParameterObjectInterface.php @@ -0,0 +1,38 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +interface ParameterObjectInterface +{ + /** + * @param string $key + * @param mixed $value + * @return void + */ + public function __set($key, $value); + + /** + * @param string $key + * @return mixed + */ + public function __get($key); + + /** + * @param string $key + * @return bool + */ + public function __isset($key); + + /** + * @param string $key + * @return void + */ + public function __unset($key); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Parameters.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Parameters.php new file mode 100644 index 0000000000000000000000000000000000000000..be72f3fd98d8bded5304ad8d0b04a9d331bc12eb --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Parameters.php @@ -0,0 +1,115 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use ArrayObject as PhpArrayObject; + +class Parameters extends PhpArrayObject implements ParametersInterface +{ + /** + * Constructor + * + * Enforces that we have an array, and enforces parameter access to array + * elements. + * + * @param array $values + */ + public function __construct(array $values = null) + { + if (null === $values) { + $values = array(); + } + parent::__construct($values, ArrayObject::ARRAY_AS_PROPS); + } + + /** + * Populate from native PHP array + * + * @param array $values + * @return void + */ + public function fromArray(array $values) + { + $this->exchangeArray($values); + } + + /** + * Populate from query string + * + * @param string $string + * @return void + */ + public function fromString($string) + { + $array = array(); + parse_str($string, $array); + $this->fromArray($array); + } + + /** + * Serialize to native PHP array + * + * @return array + */ + public function toArray() + { + return $this->getArrayCopy(); + } + + /** + * Serialize to query string + * + * @return string + */ + public function toString() + { + return http_build_query($this); + } + + /** + * Retrieve by key + * + * Returns null if the key does not exist. + * + * @param string $name + * @return mixed + */ + public function offsetGet($name) + { + if (isset($this[$name])) { + return parent::offsetGet($name); + } + return null; + } + + /** + * @param string $name + * @param mixed $default optional default value + * @return mixed + */ + public function get($name, $default = null) + { + if (isset($this[$name])) { + return parent::offsetGet($name); + } + return $default; + } + + /** + * @param string $name + * @param mixed $value + * @return Parameters + */ + public function set($name, $value) + { + $this[$name] = $value; + return $this; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ParametersInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ParametersInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e955b2ac7ac224ad0b8847b03dc0220b675ef527 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ParametersInterface.php @@ -0,0 +1,86 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use ArrayAccess; +use Countable; +use Serializable; +use Traversable; + +/* + * Basically, an ArrayObject. You could simply define something like: + * class QueryParams extends ArrayObject implements Parameters {} + * and have 90% of the functionality + */ +interface ParametersInterface extends ArrayAccess, Countable, Serializable, Traversable +{ + /** + * Constructor + * + * @param array $values + */ + public function __construct(array $values = null); + + /** + * From array + * + * Allow deserialization from standard array + * + * @param array $values + * @return mixed + */ + public function fromArray(array $values); + + /** + * From string + * + * Allow deserialization from raw body; e.g., for PUT requests + * + * @param $string + * @return mixed + */ + public function fromString($string); + + /** + * To array + * + * Allow serialization back to standard array + * + * @return mixed + */ + public function toArray(); + + /** + * To string + * + * Allow serialization to query format; e.g., for PUT or POST requests + * + * @return mixed + */ + public function toString(); + + /** + * Get + * + * @param string $name + * @param mixed|null $default + * @return mixed + */ + public function get($name, $default = null); + + /** + * Set + * + * @param string $name + * @param mixed $value + * @return ParametersInterface + */ + public function set($name, $value); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/PriorityQueue.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/PriorityQueue.php new file mode 100644 index 0000000000000000000000000000000000000000..bf6a624ac832e68b1d90bdf3cfc581782022ba95 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/PriorityQueue.php @@ -0,0 +1,302 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Countable; +use IteratorAggregate; +use Serializable; + +/** + * Re-usable, serializable priority queue implementation + * + * SplPriorityQueue acts as a heap; on iteration, each item is removed from the + * queue. If you wish to re-use such a queue, you need to clone it first. This + * makes for some interesting issues if you wish to delete items from the queue, + * or, as already stated, iterate over it multiple times. + * + * This class aggregates items for the queue itself, but also composes an + * "inner" iterator in the form of an SplPriorityQueue object for performing + * the actual iteration. + */ +class PriorityQueue implements Countable, IteratorAggregate, Serializable +{ + const EXTR_DATA = 0x00000001; + const EXTR_PRIORITY = 0x00000002; + const EXTR_BOTH = 0x00000003; + + /** + * Inner queue class to use for iteration + * @var string + */ + protected $queueClass = 'Zend\Stdlib\SplPriorityQueue'; + + /** + * Actual items aggregated in the priority queue. Each item is an array + * with keys "data" and "priority". + * @var array + */ + protected $items = array(); + + /** + * Inner queue object + * @var SplPriorityQueue + */ + protected $queue; + + /** + * Insert an item into the queue + * + * Priority defaults to 1 (low priority) if none provided. + * + * @param mixed $data + * @param int $priority + * @return PriorityQueue + */ + public function insert($data, $priority = 1) + { + $priority = (int) $priority; + $this->items[] = array( + 'data' => $data, + 'priority' => $priority, + ); + $this->getQueue()->insert($data, $priority); + return $this; + } + + /** + * Remove an item from the queue + * + * This is different than {@link extract()}; its purpose is to dequeue an + * item. + * + * This operation is potentially expensive, as it requires + * re-initialization and re-population of the inner queue. + * + * Note: this removes the first item matching the provided item found. If + * the same item has been added multiple times, it will not remove other + * instances. + * + * @param mixed $datum + * @return bool False if the item was not found, true otherwise. + */ + public function remove($datum) + { + $found = false; + foreach ($this->items as $key => $item) { + if ($item['data'] === $datum) { + $found = true; + break; + } + } + if ($found) { + unset($this->items[$key]); + $this->queue = null; + + if (!$this->isEmpty()) { + $queue = $this->getQueue(); + foreach ($this->items as $item) { + $queue->insert($item['data'], $item['priority']); + } + } + return true; + } + return false; + } + + /** + * Is the queue empty? + * + * @return bool + */ + public function isEmpty() + { + return (0 === $this->count()); + } + + /** + * How many items are in the queue? + * + * @return int + */ + public function count() + { + return count($this->items); + } + + /** + * Peek at the top node in the queue, based on priority. + * + * @return mixed + */ + public function top() + { + return $this->getIterator()->top(); + } + + /** + * Extract a node from the inner queue and sift up + * + * @return mixed + */ + public function extract() + { + return $this->getQueue()->extract(); + } + + /** + * Retrieve the inner iterator + * + * SplPriorityQueue acts as a heap, which typically implies that as items + * are iterated, they are also removed. This does not work for situations + * where the queue may be iterated multiple times. As such, this class + * aggregates the values, and also injects an SplPriorityQueue. This method + * retrieves the inner queue object, and clones it for purposes of + * iteration. + * + * @return SplPriorityQueue + */ + public function getIterator() + { + $queue = $this->getQueue(); + return clone $queue; + } + + /** + * Serialize the data structure + * + * @return string + */ + public function serialize() + { + return serialize($this->items); + } + + /** + * Unserialize a string into a PriorityQueue object + * + * Serialization format is compatible with {@link Zend\Stdlib\SplPriorityQueue} + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->insert($item['data'], $item['priority']); + } + } + + /** + * Serialize to an array + * + * By default, returns only the item data, and in the order registered (not + * sorted). You may provide one of the EXTR_* flags as an argument, allowing + * the ability to return priorities or both data and priority. + * + * @param int $flag + * @return array + */ + public function toArray($flag = self::EXTR_DATA) + { + switch ($flag) { + case self::EXTR_BOTH: + return $this->items; + break; + case self::EXTR_PRIORITY: + return array_map(function ($item) { + return $item['priority']; + }, $this->items); + case self::EXTR_DATA: + default: + return array_map(function ($item) { + return $item['data']; + }, $this->items); + } + } + + /** + * Specify the internal queue class + * + * Please see {@link getIterator()} for details on the necessity of an + * internal queue class. The class provided should extend SplPriorityQueue. + * + * @param string $class + * @return PriorityQueue + */ + public function setInternalQueueClass($class) + { + $this->queueClass = (string) $class; + return $this; + } + + /** + * Does the queue contain the given datum? + * + * @param mixed $datum + * @return bool + */ + public function contains($datum) + { + foreach ($this->items as $item) { + if ($item['data'] === $datum) { + return true; + } + } + return false; + } + + /** + * Does the queue have an item with the given priority? + * + * @param int $priority + * @return bool + */ + public function hasPriority($priority) + { + foreach ($this->items as $item) { + if ($item['priority'] === $priority) { + return true; + } + } + return false; + } + + /** + * Get the inner priority queue instance + * + * @throws \DomainException + * @return SplPriorityQueue + */ + protected function getQueue() + { + if (null === $this->queue) { + $this->queue = new $this->queueClass(); + if (!$this->queue instanceof \SplPriorityQueue) { + throw new \DomainException(sprintf( + 'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"', + get_class($this->queue) + )); + } + } + return $this->queue; + } + + /** + * Add support for deep cloning + * + * @return void + */ + public function __clone() + { + if (null !== $this->queue) { + $this->queue = clone $this->queue; + } + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/README.md b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a2dcb84191c2f6c83f97e6b83707c447326b62f8 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/README.md @@ -0,0 +1,15 @@ +Stdlib Component from ZF2 +========================= + +This is the Stdlib component for ZF2. + +- File issues at https://github.com/zendframework/zf2/issues +- Create pull requests against https://github.com/zendframework/zf2 +- Documentation is at http://framework.zend.com/docs + +LICENSE +------- + +The files in this archive are released under the [Zend Framework +license](http://framework.zend.com/license), which is a 3-clause BSD license. + diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Request.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Request.php new file mode 100644 index 0000000000000000000000000000000000000000..8427bc08f3abfdbc4c60be6e1e42ed09d721149c --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Request.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +class Request extends Message implements RequestInterface +{ + // generic request implementation +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/RequestInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/RequestInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..4a2252de4e02259483e3f99db442dd1a9f841fe2 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/RequestInterface.php @@ -0,0 +1,14 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +interface RequestInterface extends MessageInterface +{ +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Response.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Response.php new file mode 100644 index 0000000000000000000000000000000000000000..1c2ea76b19af553c9243768c48bfb283a8683250 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/Response.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +class Response extends Message implements ResponseInterface +{ + // generic response implementation +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ResponseInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ResponseInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..cf5d0edd4ee0a0bfbf03489373ad65005ad0823f --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/ResponseInterface.php @@ -0,0 +1,15 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +interface ResponseInterface extends MessageInterface +{ + +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplPriorityQueue.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplPriorityQueue.php new file mode 100644 index 0000000000000000000000000000000000000000..5baa967ff93f03e50a76f8d3ac16b874d27076aa --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplPriorityQueue.php @@ -0,0 +1,93 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Serializable; + +/** + * Serializable version of SplPriorityQueue + * + * Also, provides predictable heap order for datums added with the same priority + * (i.e., they will be emitted in the same order they are enqueued). + */ +class SplPriorityQueue extends \SplPriorityQueue implements Serializable +{ + /** + * @var int Seed used to ensure queue order for items of the same priority + */ + protected $serial = PHP_INT_MAX; + + /** + * Insert a value with a given priority + * + * Utilizes {@var $serial} to ensure that values of equal priority are + * emitted in the same order in which they are inserted. + * + * @param mixed $datum + * @param mixed $priority + * @return void + */ + public function insert($datum, $priority) + { + if (!is_array($priority)) { + $priority = array($priority, $this->serial--); + } + parent::insert($datum, $priority); + } + + + /** + * Serialize to an array + * + * Array will be priority => data pairs + * + * @return array + */ + public function toArray() + { + $array = array(); + foreach (clone $this as $item) { + $array[] = $item; + } + return $array; + } + + + /** + * Serialize + * + * @return string + */ + public function serialize() + { + $clone = clone $this; + $clone->setExtractFlags(self::EXTR_BOTH); + + $data = array(); + foreach ($clone as $item) { + $data[] = $item; + } + + return serialize($data); + } + + /** + * Deserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->insert($item['data'], $item['priority']); + } + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplQueue.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplQueue.php new file mode 100644 index 0000000000000000000000000000000000000000..e18ebc682184341198768a36f2f4aa40d6155aaf --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplQueue.php @@ -0,0 +1,55 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Serializable; + +/** + * Serializable version of SplQueue + */ +class SplQueue extends \SplQueue implements Serializable +{ + /** + * Return an array representing the queue + * + * @return array + */ + public function toArray() + { + $array = array(); + foreach ($this as $item) { + $array[] = $item; + } + return $array; + } + + /** + * Serialize + * + * @return string + */ + public function serialize() + { + return serialize($this->toArray()); + } + + /** + * Unserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->push($item); + } + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplStack.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplStack.php new file mode 100644 index 0000000000000000000000000000000000000000..3bb8f679601b9339340588b6b062168f3c9868b5 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/SplStack.php @@ -0,0 +1,55 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Serializable; + +/** + * Serializable version of SplStack + */ +class SplStack extends \SplStack implements Serializable +{ + /** + * Serialize to an array representing the stack + * + * @return array + */ + public function toArray() + { + $array = array(); + foreach ($this as $item) { + $array[] = $item; + } + return $array; + } + + /** + * Serialize + * + * @return string + */ + public function serialize() + { + return serialize($this->toArray()); + } + + /** + * Unserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->unshift($item); + } + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringUtils.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringUtils.php new file mode 100644 index 0000000000000000000000000000000000000000..2945f9aa6275ad1e93748de2f2424b2409cc8a25 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringUtils.php @@ -0,0 +1,189 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib; + +use Zend\Stdlib\ErrorHandler; +use Zend\Stdlib\StringWrapper\StringWrapperInterface; + +/** + * Utility class for handling strings of different character encodings + * using available PHP extensions. + * + * Declared abstract, as we have no need for instantiation. + */ +abstract class StringUtils +{ + + /** + * Ordered list of registered string wrapper instances + * + * @var StringWrapperInterface[] + */ + protected static $wrapperRegistry = null; + + /** + * A list of known single-byte character encodings (upper-case) + * + * @var string[] + */ + protected static $singleByteEncodings = array( + 'ASCII', '7BIT', '8BIT', + 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', + 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', + 'ISO-8859-11', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', + 'CP-1251', 'CP-1252', + // TODO + ); + + /** + * Is PCRE compiled with Unicode support? + * + * @var bool + **/ + protected static $hasPcreUnicodeSupport = null; + + /** + * Get registered wrapper classes + * + * @return string[] + */ + public static function getRegisteredWrappers() + { + if (static::$wrapperRegistry === null) { + static::$wrapperRegistry = array(); + + if (extension_loaded('intl')) { + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Intl'; + } + + if (extension_loaded('mbstring')) { + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\MbString'; + } + + if (extension_loaded('iconv')) { + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Iconv'; + } + + static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Native'; + } + + return static::$wrapperRegistry; + } + + /** + * Register a string wrapper class + * + * @param string $wrapper + * @return void + */ + public static function registerWrapper($wrapper) + { + $wrapper = (string) $wrapper; + if (!in_array($wrapper, static::$wrapperRegistry, true)) { + static::$wrapperRegistry[] = $wrapper; + } + } + + /** + * Unregister a string wrapper class + * + * @param string $wrapper + * @return void + */ + public static function unregisterWrapper($wrapper) + { + $index = array_search((string) $wrapper, static::$wrapperRegistry, true); + if ($index !== false) { + unset(static::$wrapperRegistry[$index]); + } + } + + /** + * Reset all registered wrappers so the default wrappers will be used + * + * @return void + */ + public static function resetRegisteredWrappers() + { + static::$wrapperRegistry = null; + } + + /** + * Get the first string wrapper supporting the given character encoding + * and supports to convert into the given convert encoding. + * + * @param string $encoding Character encoding to support + * @param string|null $convertEncoding OPTIONAL character encoding to convert in + * @return StringWrapperInterface + * @throws Exception\RuntimeException If no wrapper supports given character encodings + */ + public static function getWrapper($encoding = 'UTF-8', $convertEncoding = null) + { + foreach (static::getRegisteredWrappers() as $wrapperClass) { + if ($wrapperClass::isSupported($encoding, $convertEncoding)) { + $wrapper = new $wrapperClass($encoding, $convertEncoding); + $wrapper->setEncoding($encoding, $convertEncoding); + return $wrapper; + } + } + + throw new Exception\RuntimeException( + 'No wrapper found supporting "' . $encoding . '"' + . (($convertEncoding !== null) ? ' and "' . $convertEncoding . '"' : '') + ); + } + + /** + * Get a list of all known single-byte character encodings + * + * @return string[] + */ + public static function getSingleByteEncodings() + { + return static::$singleByteEncodings; + } + + /** + * Check if a given encoding is a known single-byte character encoding + * + * @param string $encoding + * @return bool + */ + public static function isSingleByteEncoding($encoding) + { + return in_array(strtoupper($encoding), static::$singleByteEncodings); + } + + /** + * Check if a given string is valid UTF-8 encoded + * + * @param string $str + * @return bool + */ + public static function isValidUtf8($str) + { + return is_string($str) && ($str === '' || preg_match('/^./su', $str) == 1); + } + + /** + * Is PCRE compiled with Unicode support? + * + * @return bool + */ + public static function hasPcreUnicodeSupport() + { + if (static::$hasPcreUnicodeSupport === null) { + ErrorHandler::start(); + static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1; + ErrorHandler::stop(); + } + return static::$hasPcreUnicodeSupport; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/AbstractStringWrapper.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/AbstractStringWrapper.php new file mode 100644 index 0000000000000000000000000000000000000000..e22649e7fa22adbef090dd697f080980723a1658 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/AbstractStringWrapper.php @@ -0,0 +1,272 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\StringWrapper; + +use Zend\Stdlib\Exception; +use Zend\Stdlib\StringUtils; + +abstract class AbstractStringWrapper implements StringWrapperInterface +{ + /** + * The character encoding working on + * @var string|null + */ + protected $encoding = 'UTF-8'; + + /** + * An optionally character encoding to convert to + * @var string|null + */ + protected $convertEncoding; + + /** + * Check if the given character encoding is supported by this wrapper + * and the character encoding to convert to is also supported. + * + * @param string $encoding + * @param string|null $convertEncoding + * @return bool + */ + public static function isSupported($encoding, $convertEncoding = null) + { + $supportedEncodings = static::getSupportedEncodings(); + + if (!in_array(strtoupper($encoding), $supportedEncodings)) { + return false; + } + + if ($convertEncoding !== null && !in_array(strtoupper($convertEncoding), $supportedEncodings)) { + return false; + } + + return true; + } + + /** + * Set character encoding working with and convert to + * + * @param string $encoding The character encoding to work with + * @param string|null $convertEncoding The character encoding to convert to + * @return StringWrapperInterface + */ + public function setEncoding($encoding, $convertEncoding = null) + { + $supportedEncodings = static::getSupportedEncodings(); + + $encodingUpper = strtoupper($encoding); + if (!in_array($encodingUpper, $supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support character encoding "' . $encoding . '"' + ); + } + + + if ($convertEncoding !== null) { + $convertEncodingUpper = strtoupper($convertEncoding); + if (!in_array($convertEncodingUpper, $supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support character encoding "' . $convertEncoding . '"' + ); + } + + $this->convertEncoding = $convertEncodingUpper; + } else { + $this->convertEncoding = null; + } + $this->encoding = $encodingUpper; + + return $this; + } + + /** + * Get the defined character encoding to work with + * + * @return string + * @throws Exception\LogicException If no encoding was defined + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Get the defined character encoding to convert to + * + * @return string|null + */ + public function getConvertEncoding() + { + return $this->convertEncoding; + } + + /** + * Convert a string from defined character encoding to the defined convert encoding + * + * @param string $str + * @param bool $reverse + * @return string|false + */ + public function convert($str, $reverse = false) + { + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $from = $reverse ? $convertEncoding : $encoding; + $to = $reverse ? $encoding : $convertEncoding; + throw new Exception\RuntimeException(sprintf( + 'Converting from "%s" to "%s" isn\'t supported by this string wrapper', + $from, + $to + )); + } + + /** + * Wraps a string to a given number of characters + * + * @param string $string + * @param int $width + * @param string $break + * @param bool $cut + * @return string|false + */ + public function wordWrap($string, $width = 75, $break = "\n", $cut = false) + { + $string = (string) $string; + if ($string === '') { + return ''; + } + + $break = (string) $break; + if ($break === '') { + throw new Exception\InvalidArgumentException('Break string cannot be empty'); + } + + $width = (int) $width; + if ($width === 0 && $cut) { + throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); + } + + if (StringUtils::isSingleByteEncoding($this->getEncoding())) { + return wordwrap($string, $width, $break, $cut); + } + + $stringWidth = $this->strlen($string); + $breakWidth = $this->strlen($break); + + $result = ''; + $lastStart = $lastSpace = 0; + + for ($current = 0; $current < $stringWidth; $current++) { + $char = $this->substr($string, $current, 1); + + $possibleBreak = $char; + if ($breakWidth !== 1) { + $possibleBreak = $this->substr($string, $current, $breakWidth); + } + + if ($possibleBreak === $break) { + $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth); + $current += $breakWidth - 1; + $lastStart = $lastSpace = $current + 1; + continue; + } + + if ($char === ' ') { + if ($current - $lastStart >= $width) { + $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; + $lastStart = $current + 1; + } + + $lastSpace = $current; + continue; + } + + if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { + $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; + $lastStart = $lastSpace = $current; + continue; + } + + if ($current - $lastStart >= $width && $lastStart < $lastSpace) { + $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break; + $lastStart = $lastSpace = $lastSpace + 1; + continue; + } + } + + if ($lastStart !== $current) { + $result .= $this->substr($string, $lastStart, $current - $lastStart); + } + + return $result; + } + + /** + * Pad a string to a certain length with another string + * + * @param string $input + * @param int $padLength + * @param string $padString + * @param int $padType + * @return string + */ + public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT) + { + if (StringUtils::isSingleByteEncoding($this->getEncoding())) { + return str_pad($input, $padLength, $padString, $padType); + } + + $lengthOfPadding = $padLength - $this->strlen($input); + if ($lengthOfPadding <= 0) { + return $input; + } + + $padStringLength = $this->strlen($padString); + if ($padStringLength === 0) { + return $input; + } + + $repeatCount = floor($lengthOfPadding / $padStringLength); + + if ($padType === STR_PAD_BOTH) { + $lastStringLeft = ''; + $lastStringRight = ''; + $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2; + + $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength; + $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2); + $lastStringRightLength += $lastStringLength % 2; + + $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength); + $lastStringRight = $this->substr($padString, 0, $lastStringRightLength); + + return str_repeat($padString, $repeatCountLeft) . $lastStringLeft + . $input + . str_repeat($padString, $repeatCountRight) . $lastStringRight; + } + + $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); + + if ($padType === STR_PAD_LEFT) { + return str_repeat($padString, $repeatCount) . $lastString . $input; + } + + return $input . str_repeat($padString, $repeatCount) . $lastString; + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Iconv.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Iconv.php new file mode 100644 index 0000000000000000000000000000000000000000..35dc39a1c91c93198f52057623b31c3d28eb4b2e --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Iconv.php @@ -0,0 +1,289 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\StringWrapper; + +use Zend\Stdlib\Exception; + +class Iconv extends AbstractStringWrapper +{ + /** + * List of supported character sets (upper case) + * + * @var string[] + * @link http://www.gnu.org/software/libiconv/ + */ + protected static $encodings = array( + // European languages + 'ASCII', + 'ISO-8859-1', + 'ISO-8859-2', + 'ISO-8859-3', + 'ISO-8859-4', + 'ISO-8859-5', + 'ISO-8859-7', + 'ISO-8859-9', + 'ISO-8859-10', + 'ISO-8859-13', + 'ISO-8859-14', + 'ISO-8859-15', + 'ISO-8859-16', + 'KOI8-R', + 'KOI8-U', + 'KOI8-RU', + 'CP1250', + 'CP1251', + 'CP1252', + 'CP1253', + 'CP1254', + 'CP1257', + 'CP850', + 'CP866', + 'CP1131', + 'MACROMAN', + 'MACCENTRALEUROPE', + 'MACICELAND', + 'MACCROATIAN', + 'MACROMANIA', + 'MACCYRILLIC', + 'MACUKRAINE', + 'MACGREEK', + 'MACTURKISH', + 'MACINTOSH', + + // Semitic languages + 'ISO-8859-6', + 'ISO-8859-8', + 'CP1255', + 'CP1256', + 'CP862', + 'MACHEBREW', + 'MACARABIC', + + // Japanese + 'EUC-JP', + 'SHIFT_JIS', + 'CP932', + 'ISO-2022-JP', + 'ISO-2022-JP-2', + 'ISO-2022-JP-1', + + // Chinese + 'EUC-CN', + 'HZ', + 'GBK', + 'CP936', + 'GB18030', + 'EUC-TW', + 'BIG5', + 'CP950', + 'BIG5-HKSCS', + 'BIG5-HKSCS:2004', + 'BIG5-HKSCS:2001', + 'BIG5-HKSCS:1999', + 'ISO-2022-CN', + 'ISO-2022-CN-EXT', + + // Korean + 'EUC-KR', + 'CP949', + 'ISO-2022-KR', + 'JOHAB', + + // Armenian + 'ARMSCII-8', + + // Georgian + 'GEORGIAN-ACADEMY', + 'GEORGIAN-PS', + + // Tajik + 'KOI8-T', + + // Kazakh + 'PT154', + 'RK1048', + + // Thai + 'ISO-8859-11', + 'TIS-620', + 'CP874', + 'MACTHAI', + + // Laotian + 'MULELAO-1', + 'CP1133', + + // Vietnamese + 'VISCII', + 'TCVN', + 'CP1258', + + // Platform specifics + 'HP-ROMAN8', + 'NEXTSTEP', + + // Full Unicode + 'UTF-8', + 'UCS-2', + 'UCS-2BE', + 'UCS-2LE', + 'UCS-4', + 'UCS-4BE', + 'UCS-4LE', + 'UTF-16', + 'UTF-16BE', + 'UTF-16LE', + 'UTF-32', + 'UTF-32BE', + 'UTF-32LE', + 'UTF-7', + 'C99', + 'JAVA', + + /* Commented out because that's internal encodings not existing in real world + // Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment) + 'UCS-2-INTERNAL', + 'UCS-4-INTERNAL', + + // Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment, + // and with OS and locale dependent semantics) + 'char', + 'wchar_t', + '', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding. + */ + + // When configured with the option --enable-extra-encodings, + // it also provides support for a few extra encodings: + + // European languages + 'CP437', + 'CP737', + 'CP775', + 'CP852', + 'CP853', + 'CP855', + 'CP857', + 'CP858', + 'CP860', + 'CP861', + 'CP863', + 'CP865', + 'CP869', + 'CP1125', + + // Semitic languages + 'CP864', + + // Japanese + 'EUC-JISX0213', + 'Shift_JISX0213', + 'ISO-2022-JP-3', + + // Chinese + 'BIG5-2003', // (experimental) + + // Turkmen + 'TDS565', + + // Platform specifics + 'ATARIST', + 'RISCOS-LATIN1', + ); + + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings() + { + return static::$encodings; + } + + /** + * Constructor + * + * @throws Exception\ExtensionNotLoadedException + */ + public function __construct() + { + if (!extension_loaded('iconv')) { + throw new Exception\ExtensionNotLoadedException( + 'PHP extension "iconv" is required for this wrapper' + ); + } + } + + /** + * Returns the length of the given string + * + * @param string $str + * @return int|false + */ + public function strlen($str) + { + return iconv_strlen($str, $this->getEncoding()); + } + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null) + { + return iconv_substr($str, $offset, $length, $this->getEncoding()); + } + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0) + { + return iconv_strpos($haystack, $needle, $offset, $this->getEncoding()); + } + + /** + * Convert a string from defined encoding to the defined convert encoding + * + * @param string $str + * @param bool $reverse + * @return string|false + */ + public function convert($str, $reverse = false) + { + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $fromEncoding = $reverse ? $convertEncoding : $encoding; + $toEncoding = $reverse ? $encoding : $convertEncoding; + + // automatically add "//IGNORE" to not stop converting on invalid characters + // invalid characters triggers a notice anyway + return iconv($fromEncoding, $toEncoding . '//IGNORE', $str); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Intl.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Intl.php new file mode 100644 index 0000000000000000000000000000000000000000..1c3973bb9da31486c040377ca0ff1c823edbf758 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Intl.php @@ -0,0 +1,83 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\StringWrapper; + +use Zend\Stdlib\Exception; + +class Intl extends AbstractStringWrapper +{ + /** + * List of supported character sets (upper case) + * + * @var string[] + */ + protected static $encodings = array('UTF-8'); + + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings() + { + return static::$encodings; + } + + /** + * Constructor + * + * @throws Exception\ExtensionNotLoadedException + */ + public function __construct() + { + if (!extension_loaded('intl')) { + throw new Exception\ExtensionNotLoadedException( + 'PHP extension "intl" is required for this wrapper' + ); + } + } + + /** + * Returns the length of the given string + * + * @param string $str + * @return int|false + */ + public function strlen($str) + { + return grapheme_strlen($str); + } + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null) + { + return grapheme_substr($str, $offset, $length); + } + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0) + { + return grapheme_strpos($haystack, $needle, $offset); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/MbString.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/MbString.php new file mode 100644 index 0000000000000000000000000000000000000000..cc47d6ee32eaea67be72613f1bbfdd2b957d099e --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/MbString.php @@ -0,0 +1,121 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\StringWrapper; + +use Zend\Stdlib\Exception; + +class MbString extends AbstractStringWrapper +{ + /** + * List of supported character sets (upper case) + * + * @var null|string[] + * @link http://php.net/manual/mbstring.supported-encodings.php + */ + protected static $encodings = null; + + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings() + { + if (static::$encodings === null) { + static::$encodings = array_map('strtoupper', mb_list_encodings()); + + // FIXME: Converting € (UTF-8) to ISO-8859-16 gives a wrong result + $indexIso885916 = array_search('ISO-8859-16', static::$encodings, true); + if ($indexIso885916 !== false) { + unset(static::$encodings[$indexIso885916]); + } + } + + return static::$encodings; + } + + /** + * Constructor + * + * @throws Exception\ExtensionNotLoadedException + */ + public function __construct() + { + if (!extension_loaded('mbstring')) { + throw new Exception\ExtensionNotLoadedException( + 'PHP extension "mbstring" is required for this wrapper' + ); + } + } + + /** + * Returns the length of the given string + * + * @param string $str + * @return int|false + */ + public function strlen($str) + { + return mb_strlen($str, $this->getEncoding()); + } + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null) + { + return mb_substr($str, $offset, $length, $this->getEncoding()); + } + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0) + { + return mb_strpos($haystack, $needle, $offset, $this->getEncoding()); + } + + /** + * Convert a string from defined encoding to the defined convert encoding + * + * @param string $str + * @param bool $reverse + * @return string|false + */ + public function convert($str, $reverse = false) + { + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $fromEncoding = $reverse ? $convertEncoding : $encoding; + $toEncoding = $reverse ? $encoding : $convertEncoding; + return mb_convert_encoding($str, $toEncoding, $fromEncoding); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Native.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Native.php new file mode 100644 index 0000000000000000000000000000000000000000..978b731118d096055d7a008847dcdec54c40dfd2 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Native.php @@ -0,0 +1,134 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\StringWrapper; + +use Zend\Stdlib\Exception; +use Zend\Stdlib\StringUtils; + +class Native extends AbstractStringWrapper +{ + /** + * The character encoding working on + * (overwritten to change defaut encoding) + * + * @var string + */ + protected $encoding = 'ASCII'; + + /** + * Check if the given character encoding is supported by this wrapper + * and the character encoding to convert to is also supported. + * + * @param string $encoding + * @param string|null $convertEncoding + * @return bool + */ + public static function isSupported($encoding, $convertEncoding = null) + { + $encodingUpper = strtoupper($encoding); + $supportedEncodings = static::getSupportedEncodings(); + + if (!in_array($encodingUpper, $supportedEncodings)) { + return false; + } + + // This adapter doesn't support to convert between encodings + if ($convertEncoding !== null && $encodingUpper !== strtoupper($convertEncoding)) { + return false; + } + + return true; + } + + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings() + { + return StringUtils::getSingleByteEncodings(); + } + + /** + * Set character encoding working with and convert to + * + * @param string $encoding The character encoding to work with + * @param string|null $convertEncoding The character encoding to convert to + * @return StringWrapperInterface + */ + public function setEncoding($encoding, $convertEncoding = null) + { + $supportedEncodings = static::getSupportedEncodings(); + + $encodingUpper = strtoupper($encoding); + if (!in_array($encodingUpper, $supportedEncodings)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support character encoding "' . $encoding . '"' + ); + } + + if ($encodingUpper !== strtoupper($convertEncoding)) { + $this->convertEncoding = $encodingUpper; + } + + if ($convertEncoding !== null) { + if ($encodingUpper !== strtoupper($convertEncoding)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support to convert between character encodings' + ); + } + + $this->convertEncoding = $encodingUpper; + } else { + $this->convertEncoding = null; + } + $this->encoding = $encodingUpper; + + return $this; + } + + /** + * Returns the length of the given string + * + * @param string $str + * @return int|false + */ + public function strlen($str) + { + return strlen($str); + } + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null) + { + return substr($str, $offset, $length); + } + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0) + { + return strpos($haystack, $needle, $offset); + } +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/StringWrapperInterface.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/StringWrapperInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..974b0be48990a1c1bf6ed05252eca68ecd4d3c53 --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/StringWrapperInterface.php @@ -0,0 +1,111 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Zend\Stdlib\StringWrapper; + +interface StringWrapperInterface +{ + /** + * Check if the given character encoding is supported by this wrapper + * and the character encoding to convert to is also supported. + * + * @param string $encoding + * @param string|null $convertEncoding + */ + public static function isSupported($encoding, $convertEncoding = null); + + /** + * Get a list of supported character encodings + * + * @return string[] + */ + public static function getSupportedEncodings(); + + /** + * Set character encoding working with and convert to + * + * @param string $encoding The character encoding to work with + * @param string|null $convertEncoding The character encoding to convert to + * @return StringWrapperInterface + */ + public function setEncoding($encoding, $convertEncoding = null); + + /** + * Get the defined character encoding to work with (upper case) + * + * @return string + */ + public function getEncoding(); + + /** + * Get the defined character encoding to convert to (upper case) + * + * @return string|null + */ + public function getConvertEncoding(); + + /** + * Returns the length of the given string + * + * @param string $str + * @return int|false + */ + public function strlen($str); + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null); + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0); + + /** + * Convert a string from defined encoding to the defined convert encoding + * + * @param string $str + * @param bool $reverse + * @return string|false + */ + public function convert($str, $reverse = false); + + /** + * Wraps a string to a given number of characters + * + * @param string $str + * @param int $width + * @param string $break + * @param bool $cut + * @return string + */ + public function wordWrap($str, $width = 75, $break = "\n", $cut = false); + + /** + * Pad a string to a certain length with another string + * + * @param string $input + * @param int $padLength + * @param string $padString + * @param int $padType + * @return string + */ + public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT); +} diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/compatibility/autoload.php b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/compatibility/autoload.php new file mode 100644 index 0000000000000000000000000000000000000000..cfc5696262e152ad5637c88d8708d80322f7375d --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/compatibility/autoload.php @@ -0,0 +1,14 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @deprecated + */ + +/** + * Legacy purposes only, to prevent code that references it from breaking. + */ +trigger_error('Polyfill autoload support (file library/Zend/Stdlib/compatibility/autoload.php) is no longer necessary; please remove your require statement referencing this file', E_USER_DEPRECATED); diff --git a/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/composer.json b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..217c5eaa40ead6da3d90d99430c3998d1f10851f --- /dev/null +++ b/core/vendor/zendframework/zend-stdlib/Zend/Stdlib/composer.json @@ -0,0 +1,28 @@ +{ + "name": "zendframework/zend-stdlib", + "description": " ", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "stdlib" + ], + "autoload": { + "psr-0": { + "Zend\\Stdlib\\": "" + } + }, + "target-dir": "Zend/Stdlib", + "suggest": { + "zendframework/zend-servicemanager": "To support hydrator plugin manager usage", + "zendframework/zend-eventmanager": "To support aggregate hydrator usage" + }, + "require": { + "php": ">=5.3.3" + }, + "extra": { + "branch-alias": { + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + } + } +}