add zend feed 3rdparty component

This commit is contained in:
Bernhard Posselt 2014-10-04 19:03:52 +02:00
Родитель 0125079c02
Коммит eae7948b3d
119 изменённых файлов: 18725 добавлений и 184 удалений

10
3rdparty/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
nbproject
._*
.~lock.*
.buildpath
.DS_Store
.idea
.project
.settings
composer.lock
vendor/bin

3
3rdparty/.gitmodules поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
[submodule "vendor/ZF2"]
path = vendor/ZF2
url = https://github.com/zendframework/zf2.git

10
3rdparty/ZendFeed/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
nbproject
._*
.~lock.*
.buildpath
.DS_Store
.idea
.project
.settings
composer.lock
vendor/bin

3
3rdparty/ZendFeed/.gitmodules поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
[submodule "vendor/ZF2"]
path = vendor/ZF2
url = https://github.com/zendframework/zf2.git

3
3rdparty/ZendFeed/CONTRIBUTING.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
# CONTRIBUTING
Please don't open pull requests against this repository, please use https://github.com/zendframework/zf2.

15
3rdparty/ZendFeed/Exception/BadMethodCallException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

13
3rdparty/ZendFeed/Exception/ExceptionInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

15
3rdparty/ZendFeed/Exception/InvalidArgumentException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

15
3rdparty/ZendFeed/Exception/RuntimeException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

291
3rdparty/ZendFeed/PubSubHubbub/AbstractCallback.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

51
3rdparty/ZendFeed/PubSubHubbub/CallbackInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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 Zend\Mvc\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();
}

15
3rdparty/ZendFeed/PubSubHubbub/Exception/ExceptionInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

Просмотреть файл

@ -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-2014 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
{}

17
3rdparty/ZendFeed/PubSubHubbub/Exception/RuntimeException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

211
3rdparty/ZendFeed/PubSubHubbub/HttpResponse.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

39
3rdparty/ZendFeed/PubSubHubbub/Model/AbstractModel.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}
}

142
3rdparty/ZendFeed/PubSubHubbub/Model/Subscription.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

Просмотреть файл

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

147
3rdparty/ZendFeed/PubSubHubbub/PubSubHubbub.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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 ZendOAuth 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 a 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;
}
}

397
3rdparty/ZendFeed/PubSubHubbub/Publisher.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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\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;
}
}

837
3rdparty/ZendFeed/PubSubHubbub/Subscriber.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

316
3rdparty/ZendFeed/PubSubHubbub/Subscriber/Callback.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

15
3rdparty/ZendFeed/PubSubHubbub/Version.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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';
}

15
3rdparty/ZendFeed/README.md поставляемый Normal file
Просмотреть файл

@ -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.

224
3rdparty/ZendFeed/Reader/AbstractEntry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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']
);
}
}
}

300
3rdparty/ZendFeed/Reader/AbstractFeed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

17
3rdparty/ZendFeed/Reader/Collection.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
class Collection extends ArrayObject
{
}

27
3rdparty/ZendFeed/Reader/Collection/AbstractCollection.php поставляемый Normal file
Просмотреть файл

@ -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-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Feed\Reader\Collection;
use ArrayObject;
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();
}

29
3rdparty/ZendFeed/Reader/Collection/Author.php поставляемый Normal file
Просмотреть файл

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

35
3rdparty/ZendFeed/Reader/Collection/Category.php поставляемый Normal file
Просмотреть файл

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

17
3rdparty/ZendFeed/Reader/Collection/Collection.php поставляемый Normal file
Просмотреть файл

@ -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-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Feed\Reader\Collection;
use ArrayObject;
class Collection extends ArrayObject
{
}

230
3rdparty/ZendFeed/Reader/Entry/AbstractEntry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}
}

370
3rdparty/ZendFeed/Reader/Entry/Atom.php поставляемый Normal file
Просмотреть файл

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

129
3rdparty/ZendFeed/Reader/Entry/EntryInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

599
3rdparty/ZendFeed/Reader/Entry/Rss.php поставляемый Normal file
Просмотреть файл

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

17
3rdparty/ZendFeed/Reader/Exception/BadMethodCallException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

15
3rdparty/ZendFeed/Reader/Exception/ExceptionInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

17
3rdparty/ZendFeed/Reader/Exception/InvalidArgumentException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

17
3rdparty/ZendFeed/Reader/Exception/RuntimeException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

233
3rdparty/ZendFeed/Reader/Extension/AbstractEntry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

176
3rdparty/ZendFeed/Reader/Extension/AbstractFeed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

628
3rdparty/ZendFeed/Reader/Extension/Atom/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}
}

536
3rdparty/ZendFeed/Reader/Extension/Atom/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}
}

37
3rdparty/ZendFeed/Reader/Extension/Content/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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/');
}
}

73
3rdparty/ZendFeed/Reader/Extension/CreativeCommons/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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');
}
}

71
3rdparty/ZendFeed/Reader/Extension/CreativeCommons/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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');
}
}

238
3rdparty/ZendFeed/Reader/Extension/DublinCore/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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/');
}
}

281
3rdparty/ZendFeed/Reader/Extension/DublinCore/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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/');
}
}

180
3rdparty/ZendFeed/Reader/Extension/Podcast/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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');
}
}

277
3rdparty/ZendFeed/Reader/Extension/Podcast/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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');
}
}

121
3rdparty/ZendFeed/Reader/Extension/Slash/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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/');
}
}

151
3rdparty/ZendFeed/Reader/Extension/Syndication/Feed.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,151 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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 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/');
}
}

72
3rdparty/ZendFeed/Reader/Extension/Thread/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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');
}
}

50
3rdparty/ZendFeed/Reader/Extension/WellFormedWeb/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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/');
}
}

80
3rdparty/ZendFeed/Reader/ExtensionManager.php поставляемый Normal file
Просмотреть файл

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

29
3rdparty/ZendFeed/Reader/ExtensionManagerInterface.php поставляемый Normal file
Просмотреть файл

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

77
3rdparty/ZendFeed/Reader/ExtensionPluginManager.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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__
));
}
}

307
3rdparty/ZendFeed/Reader/Feed/AbstractFeed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

409
3rdparty/ZendFeed/Reader/Feed/Atom.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,409 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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 = $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);
}
}
}

94
3rdparty/ZendFeed/Reader/Feed/Atom/Source.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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() {}
}

111
3rdparty/ZendFeed/Reader/Feed/FeedInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

707
3rdparty/ZendFeed/Reader/Feed/Rss.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,707 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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()
{
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;
}
}
}

127
3rdparty/ZendFeed/Reader/FeedSet.php поставляемый Normal file
Просмотреть файл

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

21
3rdparty/ZendFeed/Reader/Http/ClientInterface.php поставляемый Normal file
Просмотреть файл

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

27
3rdparty/ZendFeed/Reader/Http/ResponseInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

678
3rdparty/ZendFeed/Reader/Reader.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,678 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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;
$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\ClientInterface $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)
{
$trimmed = trim($string);
if (!is_string($string) || empty($trimmed)) {
throw new Exception\InvalidArgumentException('Only non empty strings are allowed as input');
}
$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;
}
}

184
3rdparty/ZendFeed/Uri.php поставляемый Normal file
Просмотреть файл

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

847
3rdparty/ZendFeed/Writer/AbstractFeed.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,847 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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;
$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());
}
}
}

237
3rdparty/ZendFeed/Writer/Deleted.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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'];
}
}

766
3rdparty/ZendFeed/Writer/Entry.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,766 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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 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 an 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());
}
}
}

22
3rdparty/ZendFeed/Writer/Exception/BadMethodCallException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

19
3rdparty/ZendFeed/Writer/Exception/ExceptionInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{
}

22
3rdparty/ZendFeed/Writer/Exception/InvalidArgumentException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

17
3rdparty/ZendFeed/Writer/Exception/RuntimeException.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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
{}

164
3rdparty/ZendFeed/Writer/Extension/AbstractRenderer.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

109
3rdparty/ZendFeed/Writer/Extension/Atom/Renderer/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

76
3rdparty/ZendFeed/Writer/Extension/Content/Renderer/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

Просмотреть файл

@ -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-2014 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;
}
}

80
3rdparty/ZendFeed/Writer/Extension/DublinCore/Renderer/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

246
3rdparty/ZendFeed/Writer/Extension/ITunes/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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];
}
}

362
3rdparty/ZendFeed/Writer/Extension/ITunes/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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];
}
}

200
3rdparty/ZendFeed/Writer/Extension/ITunes/Renderer/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

304
3rdparty/ZendFeed/Writer/Extension/ITunes/Renderer/Feed.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

49
3rdparty/ZendFeed/Writer/Extension/RendererInterface.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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();
}

75
3rdparty/ZendFeed/Writer/Extension/Slash/Renderer/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

129
3rdparty/ZendFeed/Writer/Extension/Threading/Renderer/Entry.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

Просмотреть файл

@ -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-2014 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;
}
}

80
3rdparty/ZendFeed/Writer/ExtensionManager.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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\AbstractRenderer
*/
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);
}
}

29
3rdparty/ZendFeed/Writer/ExtensionManagerInterface.php поставляемый Normal file
Просмотреть файл

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

80
3rdparty/ZendFeed/Writer/ExtensionPluginManager.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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__
));
}
}

240
3rdparty/ZendFeed/Writer/Feed.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,240 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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;
/**
*/
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();
}
}

127
3rdparty/ZendFeed/Writer/FeedFactory.php поставляемый Normal file
Просмотреть файл

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

233
3rdparty/ZendFeed/Writer/Renderer/AbstractRenderer.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}
}

425
3rdparty/ZendFeed/Writer/Renderer/Entry/Atom.php поставляемый Normal file
Просмотреть файл

@ -0,0 +1,425 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 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;
$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)
{
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);
}
}

102
3rdparty/ZendFeed/Writer/Renderer/Entry/Atom/Deleted.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
use Zend\Feed\Writer;
use Zend\Feed\Writer\Renderer;
class Deleted extends Renderer\AbstractRenderer implements Renderer\RendererInterface
{
/**
* Constructor
*
* @param Writer\Deleted $container
*/
public function __construct(Writer\Deleted $container)
{
parent::__construct($container);
}
/**
* Render atom entry
*
* @return 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);
}
}
}

104
3rdparty/ZendFeed/Writer/Renderer/Entry/AtomDeleted.php поставляемый Normal file
Просмотреть файл

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

329
3rdparty/ZendFeed/Writer/Renderer/Entry/Rss.php поставляемый Normal file
Просмотреть файл

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

403
3rdparty/ZendFeed/Writer/Renderer/Feed/AbstractAtom.php поставляемый Normal file
Просмотреть файл

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

96
3rdparty/ZendFeed/Writer/Renderer/Feed/Atom.php поставляемый Normal file
Просмотреть файл

@ -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-2014 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;
}
}

400
3rdparty/ZendFeed/Writer/Renderer/Feed/Atom/AbstractAtom.php поставляемый Normal file
Просмотреть файл

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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше