.gitignore 0000666 00000000023 13052362033 0006530 0 ustar 00 artifacts/
vendor/
.scrutinizer.yml 0000666 00000000073 13052362033 0007727 0 ustar 00 imports:
- php
tools:
external_code_coverage: true
.travis.yml 0000666 00000001436 13052362033 0006662 0 ustar 00 language: php
php:
- 5.6
- 7.0
- 7.1
- nightly
env:
global:
- PHPUNIT_BIN='vendor/bin/phpunit'
- PHPUNIT_CONFIG='phpunit.xml.dist'
- PHPUNIT_FLAGS='--stop-on-failure --verbose'
- GUZZLE_VERSION="~6.2"
matrix:
include:
- php: '5.6'
env:
- PHPUNIT_FLAGS="--stop-on-failure --verbose --coverage-text --coverage-clover=coverage.xml"
allow_failures:
- php: nightly
before_script:
- composer require guzzlehttp/guzzle:${GUZZLE_VERSION}
script : $PHPUNIT_BIN -c $PHPUNIT_CONFIG $PHPUNIT_FLAGS
after_script:
- |
if [ -f "coverage.xml" ]; then
echo 'sending clover to Scrutinizer'
wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover coverage.xml
echo 'done'
fi
CHANGELOG.md 0000666 00000003206 13052362033 0006357 0 ustar 00 CHANGELOG
=========
0.8.0 (2015-04-25)
-------------------
* RuleSet's default rule can be set
* Atom and RSS enclosures support
0.7.0 (2015-04-21)
-------------------
* RSS/RDF Format support
0.6.0 (2015-04-15)
-------------------
* OptionalField is replaced by Element
* item supports multiple elements of same names
* Element supports multiple attributes
* Fixer system to repair feeds after parsing -(like missing date)
0.5.2 (2015-04-01)
-------------------
* alias system to fetch same data from different nodes (like lastBuildDate and lastPubDate in RSS)
* lastBuildDate is now an alias of lastPubDate in RSS standard
0.5.1 (2015-03-23)
-------------------
* atom specifications : "content" node instead of "description"
0.5.0 (2015-02-23)
------------------
* FeedIo main class
0.4.0 (2015-01-25)
------------------
* Guzzle Client
0.3.1 (2015-01-18)
------------------
* updated the Changelog
0.3.0 (2014-12-13)
------------------
* Removed ParserAbstract, Parser/Rss Parser/Atom
* Added Parser class. This class parses a Feed using a Standard
* Added StandardAbstract
* Added Standard/Atom
* Added Standard/Rss
* Added Formatter class. This class formats a Feed using a Standard
0.2.0 (2014-11-23)
------------------
* added ClientInterface to handle HTTP queries
* added ParserAbstract
* added Parser/Rss
* added Parser/atom
* Feed now extends Item
0.1.0 (2014-09-06)
------------------
* added FeedInterface to represent a Feed which is the whole RSS/Atom document
* added NodeInterface to represent a Node which contains basic attributes of the whole document or an item
* added ItemInterface to represent an Item
* project structure
LICENSE 0000666 00000002065 13052362033 0005555 0 ustar 00 The MIT License (MIT)
Copyright (c) 2014 alexdebril
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Makefile 0000666 00000000377 13052362033 0006214 0 ustar 00 all: clean coverage
test:
vendor/bin/phpunit
test-live-feeds:
vendor/bin/phpunit -c phpunit-feeds.xml
coverage:
vendor/bin/phpunit --coverage-html=artifacts/coverage
view-coverage:
open artifacts/coverage/index.html
clean:
rm -rf artifacts/*
README.md 0000666 00000012122 13052362033 0006022 0 ustar 00 # feed-io
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/9cabcb4b-695e-43fa-8b83-a1f9ecefea88/big.png)](https://insight.sensiolabs.com/projects/9cabcb4b-695e-43fa-8b83-a1f9ecefea88)
[![Latest Stable Version](https://poser.pugx.org/debril/feed-io/v/stable.png)](https://packagist.org/packages/debril/feed-io)
[![Build Status](https://secure.travis-ci.org/alexdebril/feed-io.png?branch=master)](http://travis-ci.org/alexdebril/feed-io)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/alexdebril/feed-io/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/alexdebril/feed-io/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/alexdebril/feed-io/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/alexdebril/feed-io/?branch=master)
[![PHP Tested versions](https://php-eye.com/badge/debril/feed-io/tested.svg)](https://php-eye.com/package/debril/feed-io)
[![Dependency Status](https://www.versioneye.com/php/debril:feed-io/2.3.1/badge?style=flat-square)](https://www.versioneye.com/php/debril:feed-io/2.3.1)
[feed-io](https://github.com/alexdebril/feed-io) is a PHP library built to consume and serve RSS / Atom feeds. It features:
- Atom / RSS read and write support
- a Command line interface to read feeds
- HTTP Headers support when reading feeds in order to save network traffic
- Detection of the format (RSS / Atom) when reading feeds
- Enclosure support to handle external medias like audio content
- PSR compliant logging
- Content filtering to fetch only the newest items
- Malformed feeds auto correction
- DateTime detection and conversion
- A generic HTTP ClientInterface
- Guzzle Client integration
Keep informed about new releases and incoming features : http://debril.org/category/feed-io
# Installation
Use Composer to add feed-io into your project's requirements :
```sh
composer require debril/feed-io
```
# Requirements
feed-io requires :
- php 5.6+
- psr/log 1.0
- guzzlehttp/guzzle 6.2+
it suggests :
- monolog/monolog 1.10+
Monolog is not the only library suitable to handle feed-io's logs, you can use any PSR/Log compliant library instead.
# Fetching the repository
Do this if you want to contribute (and you're welcome to do so):
```sh
git clone https://github.com/alexdebril/feed-io.git
cd feed-io/
composer install
```
# Unit Testing
You can run the unit test suites using the following command in the library's source directory:
```sh
make test
```
Usage
=====
## CLI
Let's suppose you installed feed-io using Composer, you can use its command line client to read feeds from your terminal :
```shell
./vendor/bin/feedio read http://php.net/feed.atom
```
You can specify the number of items you want to read using the --count option. The instruction below will display the latest item :
```shell
./vendor/bin/feedio read -c 1 http://php.net/feed.atom
```
## reading
feed-io is designed to read feeds across the internet and to publish your own. Its main class is [FeedIo](https://github.com/alexdebril/feed-io/blob/master/src/FeedIo/FeedIo.php) :
```php
// create a simple FeedIo instance
$feedIo = \FeedIo\Factory::create()->getFeedIo();
// read a feed
$result = $feedIo->read($url);
// or read a feed since a certain date
$result = $feedIo->readSince($url, new \DateTime('-7 days'));
// get title
$feedTitle = $result->getFeed()->getTitle();
// iterate through items
foreach( $result->getFeed() as $item ) {
echo $item->getTitle();
}
```
## formatting an object into a XML stream
```php
// build the feed
$feed = new FeedIo\Feed;
$feed->setTitle('...');
// convert it into Atom
$dom = $feedIo->toAtom($feed);
// or ...
$dom = $feedIo->format($feed, 'atom');
```
## building a feed including medias
```php
// build the feed
$feed = new FeedIo\Feed;
$feed->setTitle('...');
$item = $feed->newItem();
// build the media
$media = new \FeedIo\Feed\Item\Media
$media->setUrl('http://yourdomain.tld/medias/some-podcast.mp3');
$media->setType('audio/mpeg');
// add it to the item
$item->addMedia($media);
$feed->add($item);
```
## activate logging
feed-io natively supports PSR-3 logging, you can activate it by choosing a 'builder' in the factory :
```php
$feedIo = \FeedIo\Factory::create(['builder' => 'monolog'])->getFeedIo();
```
feed-io only provides a builder to create Monolog\Logger instances. You can write your own, as long as the Builder implements BuilderInterface.
## Building a FeedIo instance without the factory
To create a new FeedIo instance you only need to inject two dependencies :
- an HTTP Client implementing FeedIo\Adapter\ClientInterface. It can be wrapper for an external library like FeedIo\Adapter\Guzzle\Client
- a PSR-3 logger implementing Psr\Log\LoggerInterface
```php
// first dependency : the HTTP client
// here we use Guzzle as a dependency for the client
$guzzle = new GuzzleHttp\Client();
// Guzzle is wrapped in this adapter which is a FeedIo\Adapter\ClientInterface implementation
$client = new FeedIo\Adapter\Guzzle\Client($guzzle);
// second dependency : a PSR-3 logger
$logger = new Psr\Log\NullLogger();
// now create FeedIo's instance
$feedIo = new FeedIo\FeedIo($client, $logger);
```
bin/feedio 0000666 00000002204 13052362033 0006471 0 ustar 00 #!/usr/bin/env php
setName('feed-io : the CLI feed reader');
$application->add(new \FeedIo\Command\ReadCommand());
$application->run();
} else {
main($argc, $argv);
exit;
}
/**
* This function is invoked if symfony/console is not installed
*/
function main($argc, $argv) {
if ( $argc < 2 ) {
echo 'feed-io version 2.4' . PHP_EOL;
echo 'Usage : ' . PHP_EOL;
echo "\t feed-io [url]" . PHP_EOL;
exit;
}
$feedIo = \FeedIo\Factory::create()->getFeedIo();
$feed = array_reverse(iterator_to_array($feedIo->read($argv[$argc-1])->getFeed()));
foreach( $feed as $i => $item ) {
echo "\033[32m{$item->getLastModified()->format(\DateTime::ATOM)} : \033[34m{$item->getTitle()}\033[0m";
echo strip_tags(nl2br($item->getDescription())) . PHP_EOL;
}
} composer.json 0000666 00000001553 13052362033 0007273 0 ustar 00 {
"name": "debril/feed-io",
"description": "PHP library built to consume and serve RSS / Atom feeds",
"keywords": ["rss", "atom", "feed", "news", "CLI", "client"],
"homepage": "http://debril.org/category/feed-io/",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Alexandre Debril",
"email": "alex.debril@gmail.com"
}
],
"bin" : [
"bin/feedio"
],
"require": {
"php": ">=5.6.0",
"guzzlehttp/guzzle": "~6.2",
"psr/log": "~1.0"
},
"require-dev": {
"phpunit/phpunit": ">=5.5.0",
"monolog/monolog": "1.*"
},
"suggest": {
"monolog/monolog": "Allows to handle logs",
"symfony/console": "Allows to use the command line interface"
},
"autoload": {
"psr-4": {"FeedIo\\": "src/FeedIo"}
}
}
composer.lock 0000666 00000162653 13052362033 0007263 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "d88dd6e823aaf601f1702261ddd966d1",
"content-hash": "bb7b6c2e8f3b427fe533cfec4185460b",
"packages": [
{
"name": "guzzlehttp/guzzle",
"version": "6.2.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
"reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.3.1",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.0",
"psr/log": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.2-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2016-10-08 15:01:37"
},
{
"name": "guzzlehttp/promises",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "2693c101803ca78b27972d84081d027fca790a1e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/2693c101803ca78b27972d84081d027fca790a1e",
"reference": "2693c101803ca78b27972d84081d027fca790a1e",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-11-18 17:47:58"
},
{
"name": "guzzlehttp/psr7",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "PSR-7 message implementation",
"keywords": [
"http",
"message",
"stream",
"uri"
],
"time": "2016-06-24 23:00:38"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06 14:39:51"
},
{
"name": "psr/log",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2016-10-10 12:19:37"
}
],
"packages-dev": [
{
"name": "doctrine/instantiator",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
"shasum": ""
},
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"constructor",
"instantiate"
],
"time": "2015-06-14 21:17:01"
},
{
"name": "monolog/monolog",
"version": "1.22.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "bad29cb8d18ab0315e6c477751418a82c850d558"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558",
"reference": "bad29cb8d18ab0315e6c477751418a82c850d558",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"psr/log": "~1.0"
},
"provide": {
"psr/log-implementation": "1.0.0"
},
"require-dev": {
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"graylog2/gelf-php": "~1.0",
"jakub-onderka/php-parallel-lint": "0.9",
"php-amqplib/php-amqplib": "~2.4",
"php-console/php-console": "^3.1.3",
"phpunit/phpunit": "~4.5",
"phpunit/phpunit-mock-objects": "2.3.0",
"ruflin/elastica": ">=0.90 <3.0",
"sentry/sentry": "^0.13",
"swiftmailer/swiftmailer": "~5.3"
},
"suggest": {
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
"ext-mongo": "Allow sending log messages to a MongoDB server",
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"php-console/php-console": "Allow sending log messages to Google Chrome",
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"sentry/sentry": "Allow sending log messages to a Sentry server"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Monolog\\": "src/Monolog"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
"homepage": "http://github.com/Seldaek/monolog",
"keywords": [
"log",
"logging",
"psr-3"
],
"time": "2016-11-26 00:15:39"
},
{
"name": "myclabs/deep-copy",
"version": "1.5.5",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108",
"reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"doctrine/collections": "1.*",
"phpunit/phpunit": "~4.1"
},
"type": "library",
"autoload": {
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
"homepage": "https://github.com/myclabs/DeepCopy",
"keywords": [
"clone",
"copy",
"duplicate",
"object",
"object graph"
],
"time": "2016-10-31 17:19:45"
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"shasum": ""
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"time": "2015-12-27 11:43:31"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
"reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0@dev",
"phpdocumentor/type-resolver": "^0.2.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "^4.4"
},
"type": "library",
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2016-09-30 07:12:33"
},
{
"name": "phpdocumentor/type-resolver",
"version": "0.2.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
"reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0"
},
"require-dev": {
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "^5.2||^4.8.24"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"time": "2016-11-25 06:54:22"
},
{
"name": "phpspec/prophecy",
"version": "v1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb",
"reference": "6c52c2722f8460122f96f86346600e1077ce22cb",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1",
"sebastian/recursion-context": "^1.0|^2.0"
},
"require-dev": {
"phpspec/phpspec": "^2.0",
"phpunit/phpunit": "^4.8 || ^5.6.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2016-11-21 14:58:47"
},
{
"name": "phpunit/php-code-coverage",
"version": "4.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/903fd6318d0a90b4770a009ff73e4a4e9c437929",
"reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0",
"phpunit/php-file-iterator": "~1.3",
"phpunit/php-text-template": "~1.2",
"phpunit/php-token-stream": "^1.4.2",
"sebastian/code-unit-reverse-lookup": "~1.0",
"sebastian/environment": "^1.3.2 || ^2.0",
"sebastian/version": "~1.0|~2.0"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "^5.4"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.4.0",
"ext-xmlwriter": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"time": "2016-11-28 16:00:31"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
"reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"time": "2016-10-03 07:40:28"
},
{
"name": "phpunit/php-text-template",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"time": "2015-06-21 13:50:34"
},
{
"name": "phpunit/php-timer",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4|~5"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"time": "2016-05-12 18:03:57"
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.9",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b",
"reference": "3b402f65a4cc90abf6e1104e388b896ce209631b",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [
"tokenizer"
],
"time": "2016-11-15 14:06:22"
},
{
"name": "phpunit/phpunit",
"version": "5.7.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "336aff0ac52e306c98e7455bc3e8d7b0bf777a5e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/336aff0ac52e306c98e7455bc3e8d7b0bf777a5e",
"reference": "336aff0ac52e306c98e7455bc3e8d7b0bf777a5e",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"myclabs/deep-copy": "~1.3",
"php": "^5.6 || ^7.0",
"phpspec/prophecy": "^1.3.1",
"phpunit/php-code-coverage": "^4.0.3",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "^3.2",
"sebastian/comparator": "~1.2.2",
"sebastian/diff": "~1.2",
"sebastian/environment": "^1.3.4 || ^2.0",
"sebastian/exporter": "~2.0",
"sebastian/global-state": "~1.0",
"sebastian/object-enumerator": "~2.0",
"sebastian/resource-operations": "~1.0",
"sebastian/version": "~1.0|~2.0",
"symfony/yaml": "~2.1|~3.0"
},
"conflict": {
"phpdocumentor/reflection-docblock": "3.0.2"
},
"require-dev": {
"ext-pdo": "*"
},
"suggest": {
"ext-xdebug": "*",
"phpunit/php-invoker": "~1.1"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.7.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"time": "2016-12-03 08:33:00"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "3.4.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "90a08f5deed5f7ac35463c161f2e8fa0e5652faf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/90a08f5deed5f7ac35463c161f2e8fa0e5652faf",
"reference": "90a08f5deed5f7ac35463c161f2e8fa0e5652faf",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.6 || ^7.0",
"phpunit/php-text-template": "^1.2",
"sebastian/exporter": "^1.2 || ^2.0"
},
"conflict": {
"phpunit/phpunit": "<5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^5.4"
},
"suggest": {
"ext-soap": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Mock Object library for PHPUnit",
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
"keywords": [
"mock",
"xunit"
],
"time": "2016-11-27 07:52:03"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe",
"reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"phpunit/phpunit": "~5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"time": "2016-02-13 06:45:14"
},
{
"name": "sebastian/comparator",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f",
"reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2 || ~2.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"time": "2016-11-19 09:18:40"
},
{
"name": "sebastian/diff",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff"
],
"time": "2015-12-08 07:14:41"
},
{
"name": "sebastian/environment",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
"reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
"shasum": ""
},
"require": {
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"time": "2016-11-26 07:53:53"
},
{
"name": "sebastian/exporter",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
"reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/recursion-context": "~2.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"time": "2016-11-19 08:54:04"
},
{
"name": "sebastian/global-state",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"time": "2015-10-12 03:26:01"
},
{
"name": "sebastian/object-enumerator",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35",
"reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35",
"shasum": ""
},
"require": {
"php": ">=5.6",
"sebastian/recursion-context": "~2.0"
},
"require-dev": {
"phpunit/phpunit": "~5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"time": "2016-11-19 07:35:10"
},
{
"name": "sebastian/recursion-context",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a",
"reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2016-11-19 07:33:16"
},
{
"name": "sebastian/resource-operations",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
"reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
"shasum": ""
},
"require": {
"php": ">=5.6.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"time": "2015-07-28 20:34:47"
},
{
"name": "sebastian/version",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
"reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2016-10-03 07:35:21"
},
{
"name": "symfony/yaml",
"version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "f2300ba8fbb002c028710b92e1906e7457410693"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/f2300ba8fbb002c028710b92e1906e7457410693",
"reference": "f2300ba8fbb002c028710b92e1906e7457410693",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"require-dev": {
"symfony/console": "~2.8|~3.0"
},
"suggest": {
"symfony/console": "For validating YAML files using the lint command"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2016-11-18 21:17:59"
},
{
"name": "webmozart/assert",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f",
"reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"time": "2016-11-23 20:04:58"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.6.0"
},
"platform-dev": []
}
doc/specifications-support.md 0000666 00000004032 13052362033 0012350 0 ustar 00 # synopsis
This document explains which attributes are supported by feed-io and how to access them
## top level document : feed (atom) / channel (rss)
interface : FeedInterface
| atom | rss | getter | setter
| title | title | getTitle | setTitle
| link | link | getLink | setLink
| updated | pubDate / lastBuildDate | getLastModified | setLastModified
| id | N/A | getPublicId | setPublicId
| N/A | description | getDescription | setDescription
| category | category | not supported | not supported
| author | N/A | not supported | not supported
| contributor | N/A | not supported | not supported
| icon / logo | image | not supported | not supported
| rights | copyright | not supported | not supported
| subtitle | N/A | not supported | not supported
| lang | language | not supported | not supported
| base | N/A | not supported | not supported
| generator | generator | not supported | not supported
| N/A | managingEditor | not supported | not supported
| N/A | webMaster | not supported | not supported
| N/A | docs | not supported | not supported
| N/A | cloud | not supported | not supported
| N/A | ttl | not supported | not supported
| N/A | rating | not supported | not supported
| N/A | textInput | not supported | not supported
| N/A | skipdays | not supported | not supported
| N/A | skipHours | not supported | not supported
## entry (atom) / item (rss)
Interface : ItemInterface
| atom | rss | getter | setter
| title | title | getTitle | setTitle
| link | link | getLink | setLink
| link | enclosure | getMedias | addMedia
| updated / published | pubDate | getLastModified | setLastModified
| id | guid | getPublicId | setPublicId
| content | description | getDescription | setDescription
| summary | N/A | not supported | not supported
| source | source | not supported | not supported
| category | category | not supported | not supported
| author | N/A | not supported | not supported
| contributor | N/A | not supported | not supported
| N/A | comments | not supported | not supported
| rights | N/A | not supported | not supported
examples/bootstrap.php 0000666 00000000511 13052362033 0011106 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$loader = require __DIR__."/../vendor/autoload.php";
date_default_timezone_set('UTC');
examples/factory.php 0000666 00000001556 13052362033 0010552 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.DIRECTORY_SEPARATOR.'bootstrap.php';
$feedIo = \FeedIo\Factory::create()->getFeedIo();
$result = $feedIo->read('http://php.net/feed.atom');
echo "feed title : {$result->getFeed()->getTitle()} \n ";
foreach ($result->getFeed() as $item) {
echo "item title : {$item->getTitle()} \n ";
// let's turn php.net into a PodCast
$media = new \FeedIo\Feed\Item\Media();
$media->setUrl('http://yourdomain.tld/medias/some-podcast.mp3');
$media->setType('audio/mpeg');
// add it to the item
$item->addMedia($media);
}
$domDocument = $feedIo->toAtom($result->getFeed());
echo $domDocument->saveXML();
examples/feedio.php 0000666 00000001731 13052362033 0010331 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.DIRECTORY_SEPARATOR.'bootstrap.php';
$client = new \FeedIo\Adapter\Guzzle\Client(new GuzzleHttp\Client());
$logger = new \Psr\Log\NullLogger();
$feedIo = new \FeedIo\FeedIo($client, $logger);
$result = $feedIo->read('http://php.net/feed.atom');
echo "feed title : {$result->getFeed()->getTitle()} \n ";
foreach ($result->getFeed() as $item) {
echo "item title : {$item->getTitle()} \n ";
// let's turn php.net into a PodCast
$media = new \FeedIo\Feed\Item\Media();
$media->setUrl('http://yourdomain.tld/medias/some-podcast.mp3');
$media->setType('audio/mpeg');
// add it to the item
$item->addMedia($media);
}
$domDocument = $feedIo->toAtom($result->getFeed());
echo $domDocument->saveXML();
examples/guzzle-client.php 0000666 00000000731 13052362033 0011671 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.DIRECTORY_SEPARATOR.'bootstrap.php';
$client = new \FeedIo\Adapter\Guzzle\Client(new GuzzleHttp\Client());
$response = $client->getResponse('http://php.net/feed.atom', new \DateTime());
echo $response->getBody();
examples/media.php 0000666 00000001505 13052362033 0010154 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.DIRECTORY_SEPARATOR.'bootstrap.php';
$feed = new \FeedIo\Feed();
// ask for a new Item
$item = $feed->newItem();
// build the media
$media = new \FeedIo\Feed\Item\Media();
$media->setUrl('http://yourdomain.tld/medias/some-podcast.mp3');
$media->setType('audio/mpeg');
// add it to the item
$item->addMedia($media);
// add the item to the feed
$feed->add($item);
$client = new \FeedIo\Adapter\NullClient();
$logger = new \Psr\Log\NullLogger();
$feedIo = new \FeedIo\FeedIo($client, $logger);
$domDocument = $feedIo->toAtom($result->getFeed());
echo $domDocument->saveXML();
examples/modifiedSince.php 0000666 00000001374 13052362033 0011643 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.DIRECTORY_SEPARATOR.'bootstrap.php';
$client = new \FeedIo\Adapter\Guzzle\Client(new GuzzleHttp\Client());
$logger = new \Psr\Log\NullLogger();
$feedIo = new \FeedIo\FeedIo($client, $logger);
$result = $feedIo->readSince('http://php.net/feed.atom', new \DateTime('-1 month'));
echo "feed title : {$result->getFeed()->getTitle()} \n ";
$newItems = $result->getFeed();
foreach($newItems as $value) {
echo $value->getTitle() . ' : ' . $value->getLastModified()->format(\DateTime::ATOM) . PHP_EOL;
}
examples/parse-rss.php 0000666 00000002552 13052362033 0011017 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.DIRECTORY_SEPARATOR.'bootstrap.php';
// new DateTimeBuilder : it will be used by the parser to convert formatted dates into DateTime instances
$dateTimeBuilder = new \FeedIo\Rule\DateTimeBuilder();
// new Standard\\Rss : it will provide all standard specific rules to the parser
$standard = new \FeedIo\Standard\Rss($dateTimeBuilder);
// new Parser: it will turn a RSS stream into a Feed instance, using the rules provided by the Standard
// the Logger must implement the PSR3 logging standard
$parser = new \FeedIo\Parser($standard, new \Psr\Log\NullLogger());
// the file is sample-rss.xml
$file = dirname(__FILE__)."/../tests/samples/rss/sample-rss.xml";
// we load it using the Dom library
$document = new DOMDocument();
$document->load($file, LIBXML_NOBLANKS | LIBXML_COMPACT);
// Now let's parse it
// The second argument must implement FeedInterface
$feed = $parser->parse($document, new \FeedIo\Feed());
// $feed is now ready
echo "feed's title : {$feed->getTitle()} \n";
// FeedInterface extends \Iterator, we can iterate through it
foreach ($feed as $item) {
echo "item's title : {$item->getTitle()} \n";
}
phpunit-feeds.xml 0000666 00000000615 13052362033 0010044 0 ustar 00
tests/live-feeds/src/FeedIo/
phpunit.xml.dist 0000666 00000000604 13052362033 0007720 0 ustar 00
tests/FeedIo/src/FeedIo/
src/FeedIo/Adapter/ClientInterface.php 0000666 00000001461 13052362033 0013621 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter;
/**
* Describes a HTTP Client used by \FeedIo\Reader
*
* getResponse() MUST return an instance of \FeedIo\Adapter\ResponseInterface or throw an exception
*
*/
interface ClientInterface
{
/**
* @param string $url
* @param \DateTime $modifiedSince
* @throws \FeedIo\Adapter\NotFoundException
* @throws \FeedIo\Adapter\ServerErrorException
* @return \FeedIo\Adapter\ResponseInterface
*/
public function getResponse($url, \DateTime $modifiedSince);
}
src/FeedIo/Adapter/FileSystem/Client.php 0000666 00000001714 13052362033 0014065 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter\FileSystem;
use FeedIo\Adapter\ClientInterface;
use FeedIo\Adapter\NotFoundException;
/**
* Filesystem client
*/
class Client implements ClientInterface
{
/**
* @param string $path
* @param \DateTime $modifiedSince
* @throws \FeedIo\Adapter\NotFoundException
* @return \FeedIo\Adapter\ResponseInterface
*/
public function getResponse($path, \DateTime $modifiedSince)
{
if (file_exists($path)) {
return new Response(
file_get_contents($path),
new \DateTime('@'.filemtime($path))
);
}
throw new NotFoundException($path);
}
}
src/FeedIo/Adapter/FileSystem/Response.php 0000666 00000002352 13052362033 0014444 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter\FileSystem;
use FeedIo\Adapter\ResponseInterface;
/**
*
*/
class Response implements ResponseInterface
{
/**
* @var string
*/
protected $fileContent;
/**
* @var \DateTime
*/
protected $lastModified;
/**
* @param string $fileContent
* @param \DateTime $lastModified
*/
public function __construct($fileContent, \DateTime $lastModified)
{
$this->fileContent = $fileContent;
$this->lastModified = $lastModified;
}
/**
* @return string
*/
public function getBody()
{
return $this->fileContent;
}
/**
* @return array
*/
public function getHeaders()
{
return array();
}
/**
* @param string $name
* @return string
*/
public function getHeader($name)
{
return '';
}
/**
* @return \DateTime
*/
public function getLastModified()
{
return $this->lastModified;
}
}
src/FeedIo/Adapter/Guzzle/Client.php 0000666 00000003064 13052362033 0013261 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter\Guzzle;
use FeedIo\Adapter\ClientInterface;
use FeedIo\Adapter\NotFoundException;
use FeedIo\Adapter\ServerErrorException;
use GuzzleHttp\Exception\BadResponseException;
/**
* Guzzle dependent HTTP client
*/
class Client implements ClientInterface
{
/**
* @var \GuzzleHttp\ClientInterface
*/
protected $guzzleClient;
/**
* @param \GuzzleHttp\ClientInterface $guzzleClient
*/
public function __construct(\GuzzleHttp\ClientInterface $guzzleClient)
{
$this->guzzleClient = $guzzleClient;
}
/**
* @param string $url
* @param \DateTime $modifiedSince
* @throws \FeedIo\Adapter\NotFoundException
* @throws \FeedIo\Adapter\ServerErrorException
* @return \FeedIo\Adapter\ResponseInterface
*/
public function getResponse($url, \DateTime $modifiedSince)
{
try {
return new Response($this->guzzleClient->request('get', $url));
} catch (BadResponseException $e) {
switch ((int) $e->getResponse()->getStatusCode()) {
case 404:
throw new NotFoundException($e->getMessage());
default:
throw new ServerErrorException($e->getMessage());
}
}
}
}
src/FeedIo/Adapter/Guzzle/Response.php 0000666 00000003161 13052362033 0013637 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter\Guzzle;
use FeedIo\Adapter\ResponseInterface;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
/**
* Guzzle dependent HTTP Response
*/
class Response implements ResponseInterface
{
const HTTP_LAST_MODIFIED = 'Last-Modified';
/**
* @var \Psr\Http\Message\ResponseInterface
*/
protected $psrResponse;
/**
* @param \Psr\Http\Message\ResponseInterface
*/
public function __construct(PsrResponseInterface $psrResponse)
{
$this->psrResponse = $psrResponse;
}
/**
* @return \Psr\Http\Message\StreamInterface
*/
public function getBody()
{
return $this->psrResponse->getBody();
}
/**
* @return \DateTime|null
*/
public function getLastModified()
{
if ($this->psrResponse->hasHeader(static::HTTP_LAST_MODIFIED)) {
$lastModified = \DateTime::createFromFormat(\DateTime::RFC2822, $this->getHeader(static::HTTP_LAST_MODIFIED));
return false === $lastModified ? null : $lastModified;
}
return;
}
/**
* @return array
*/
public function getHeaders()
{
return $this->psrResponse->getHeaders();
}
/**
* @param string $name
* @return string[]
*/
public function getHeader($name)
{
return $this->psrResponse->getHeader($name);
}
}
src/FeedIo/Adapter/NotFoundException.php 0000666 00000000534 13052362033 0014175 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter;
use FeedIo\FeedIoException;
class NotFoundException extends FeedIoException
{
}
src/FeedIo/Adapter/NullClient.php 0000666 00000001176 13052362033 0012636 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter;
/**
* Fake HTTP client
*/
class NullClient implements ClientInterface
{
/**
* @param string $url
* @param \DateTime $modifiedSince
* @return \FeedIo\Adapter\ResponseInterface
*/
public function getResponse($url, \DateTime $modifiedSince)
{
return new NullResponse();
}
}
src/FeedIo/Adapter/NullResponse.php 0000666 00000001477 13052362033 0013222 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter;
/**
* Null HTTP Response
*/
class NullResponse implements ResponseInterface
{
/**
* @return string
*/
public function getBody()
{
return;
}
/**
* @return \DateTime
*/
public function getLastModified()
{
return new \DateTime('@0');
}
/**
* @return array
*/
public function getHeaders()
{
return array();
}
/**
* @param string $name
* @return array|string
*/
public function getHeader($name)
{
return $name;
}
}
src/FeedIo/Adapter/ResponseInterface.php 0000666 00000001311 13052362033 0014173 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter;
/**
* Describes a HTTP Response as returned by an instance of ClientInterface
*
*/
interface ResponseInterface
{
/**
* @return string
*/
public function getBody();
/**
* @return \DateTime
*/
public function getLastModified();
/**
* @return array
*/
public function getHeaders();
/**
* @param string $name
* @return string
*/
public function getHeader($name);
}
src/FeedIo/Adapter/ServerErrorException.php 0000666 00000000537 13052362033 0014724 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter;
use FeedIo\FeedIoException;
class ServerErrorException extends FeedIoException
{
}
src/FeedIo/Command/ReadCommand.php 0000666 00000003746 13052362033 0012742 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Command;
use FeedIo\Factory;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ReadCommand extends Command
{
protected function configure()
{
$this->setName('read')
->setDescription('reads a feed')
->addArgument(
'url',
InputArgument::REQUIRED,
'Please provide the feed\' URL'
)
->addOption('count', 'c', InputOption::VALUE_OPTIONAL)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$url = $input->getArgument('url');
$feed = $this->readFeed($url);
$output->writeln("{$feed->getTitle()}");
$limit = $this->getLimit($input);
foreach( $feed as $i => $item ) {
$output->writeln("{$item->getLastModified()->format(\DateTime::ATOM)} : {$item->getTitle()}");
$output->writeln("{$item->getDescription()}");
if ( ! is_null($limit) && $limit === $i+1 )
break;
}
}
/**
* @param string $url
* @return \FeedIo\FeedInterface
*/
public function readFeed($url)
{
$feedIo = Factory::create()->getFeedIo();
return $feedIo->read($url)->getFeed();
}
/**
* @param InputInterface $input
* @return int|null
*/
public function getLimit(InputInterface $input)
{
if ( $input->hasOption('count') ) {
return intval($input->getOption('count'));
}
return null;
}
}
src/FeedIo/DateRuleAbstract.php 0000666 00000002526 13052362033 0012376 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Rule\DateTimeBuilder;
abstract class DateRuleAbstract extends RuleAbstract
{
/**
* @var \FeedIo\Rule\DateTimeBuilder
*/
protected $dateTimeBuilder = null;
/**
* @var string
*/
protected $defaultFormat = \DateTime::RSS;
/**
* @param \FeedIo\Rule\DateTimeBuilder $dateTimeBuilder
* @return $this
*/
public function setDateTimeBuilder(DateTimeBuilder $dateTimeBuilder)
{
$this->dateTimeBuilder = $dateTimeBuilder;
return $this;
}
/**
* @return DateTimeBuilder
*/
public function getDateTimeBuilder()
{
if (is_null($this->dateTimeBuilder)) {
throw new \UnexpectedValueException('date time builder should not be null');
}
return $this->dateTimeBuilder;
}
/**
* @return string
*/
public function getDefaultFormat()
{
return $this->defaultFormat;
}
/**
* @param string $defaultFormat
*/
public function setDefaultFormat($defaultFormat)
{
$this->defaultFormat = $defaultFormat;
}
}
src/FeedIo/Factory.php 0000666 00000006131 13052362033 0010610 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Factory\MissingDependencyException;
use FeedIo\Factory\LoggerBuilderInterface;
use FeedIo\Factory\ClientBuilderInterface;
use FeedIo\Factory\BuilderInterface;
class Factory
{
/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* @var \FeedIo\Adapter\ClientInterface
*/
protected $client;
/**
* @var \FeedIo\Factory\ClientBuilderInterface
*/
protected $clientBuilder;
/**
* @var \FeedIo\Factory\LoggerBuilderInterface
*/
protected $loggerBuilder;
static public function create(
array $loggerConfig = [
'builder' => 'NullLogger',
'config' => [],
],
array $clientConfig = [
'builder' => 'GuzzleClient',
'config' => [],
]
)
{
$factory = new static();
$factory->setClientBuilder(
$factory->getBuilder($clientConfig['builder'], $factory->extractConfig($clientConfig)))
->setLoggerBuilder(
$factory->getBuilder($loggerConfig['builder'],$factory->extractConfig($loggerConfig)));
return $factory;
}
/**
* @param $builderConfig
* @return array
*/
public function extractConfig(array $builderConfig)
{
return isset($builderConfig['config']) ? $builderConfig['config']:[];
}
/**
* @return \FeedIo\FeedIo
*/
public function getFeedIo()
{
return new FeedIo(
$this->clientBuilder->getClient(),
$this->loggerBuilder->getLogger()
);
}
public function getBuilder($builder, array $args = [])
{
$class = "\\FeedIo\\Factory\\Builder\\{$builder}Builder";
if ( ! class_exists($class) ) {
$class = $builder;
}
$reflection = new \ReflectionClass($class);
return $reflection->newInstanceArgs($args);
}
public function setLoggerBuilder(LoggerBuilderInterface $loggerBuilder)
{
$this->loggerBuilder = $loggerBuilder;
return $this;
}
public function setClientBuilder(ClientBuilderInterface $clientBuilder)
{
$this->clientBuilder = $clientBuilder;
return $this;
}
/**
* @param BuilderInterface $builder
* @return boolean true if the dependency is met
*/
public function checkDependency(BuilderInterface $builder)
{
if ( ! class_exists($builder->getMainClassName()) ) {
$message = "missing {$builder->getPackageName()}, please install it using composer : composer require {$builder->getPackageName()}";
throw new MissingDependencyException($message);
}
return true;
}
}
src/FeedIo/Factory/Builder/GuzzleClientBuilder.php 0000666 00000002103 13052362033 0016117 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Factory\Builder;
use FeedIo\Factory\ClientBuilderInterface;
use \FeedIo\Adapter\Guzzle\Client;
use \GuzzleHttp\Client as GuzzleClient;
/**
* @package FeedIo
*/
class GuzzleClientBuilder implements ClientBuilderInterface
{
/**
* This method MUST return a \FeedIo\Adapter\ClientInterface instance
* @return \FeedIo\Adapter\ClientInterface
*/
public function getClient()
{
return new Client(new GuzzleClient);
}
/**
* This method MUST return the name of the main class
* @return string
*/
public function getMainClassName()
{
return '\GuzzleHttp\Client';
}
/**
* This method MUST return the name of the package name
* @return string
*/
public function getPackageName()
{
return 'guzzlehttp/guzzle';
}
}
src/FeedIo/Factory/Builder/MonologBuilder.php 0000666 00000004246 13052362033 0015124 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Factory\Builder;
use FeedIo\Factory\LoggerBuilderInterface;
use Monolog\Logger;
/**
* @package FeedIo
*/
class MonologBuilder implements LoggerBuilderInterface
{
protected $loggerName = 'feed-io';
protected $handlersConfig = [
[
'class' => 'Monolog\Handler\StreamHandler',
'params' => ['php://stdout', Logger::DEBUG],
],
];
/**
* @param array $config
*/
public function __construct(array $config = [])
{
$this->loggerName = isset($config['name']) ? $config['name']:$this->loggerName;
$this->handlersConfig = isset($config['handlers']) ? $config['handlers']:$this->handlersConfig;
}
/**
* This method MUST return a valid PSR3 logger
* @return \Monolog\Logger
*/
public function getLogger()
{
$logger = new Logger($this->loggerName);
foreach ( $this->handlersConfig as $config ) {
$handler = $this->newHandler($config['class'], $config['params']);
$logger->pushHandler($handler);
}
return $logger;
}
/**
* @param string $class
* @param array $params
* @return Monolog\Handler\HandlerInterface
*/
public function newHandler($class, array $params = [])
{
$reflection = new \ReflectionClass($class);
if ( ! $reflection->implementsInterface('Monolog\Handler\HandlerInterface') ) {
throw new \InvalidArgumentException();
}
return $reflection->newInstanceArgs($params);
}
/**
* This method MUST return the name of the main class
* @return string
*/
public function getMainClassName()
{
return 'Monolog\Logger';
}
/**
* This method MUST return the name of the package name
* @return string
*/
public function getPackageName()
{
return 'monolog/monolog';
}
}
src/FeedIo/Factory/Builder/NullLoggerBuilder.php 0000666 00000001736 13052362033 0015565 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Factory\Builder;
use FeedIo\Factory\LoggerBuilderInterface;
use \Psr\Log\NullLogger;
/**
* @package FeedIo
*/
class NullLoggerBuilder implements LoggerBuilderInterface
{
/**
* This method MUST return a valid PSR3 logger
* @return \Psr\Log\NullLogger
*/
public function getLogger()
{
return new \Psr\Log\NullLogger;
}
/**
* This method MUST return the name of the main class
* @return string
*/
public function getMainClassName()
{
return '\Psr\Log\NullLogger';
}
/**
* This method MUST return the name of the package name
* @return string
*/
public function getPackageName()
{
return 'psr/log';
}
}
src/FeedIo/Factory/BuilderInterface.php 0000666 00000001134 13052362033 0014015 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Factory;
/**
* @package FeedIo
*/
interface BuilderInterface
{
/**
* This method MUST return the name of the main class
* @return string
*/
public function getMainClassName();
/**
* This method MUST return the name of the package name
* @return string
*/
public function getPackageName();
}
src/FeedIo/Factory/ClientBuilderInterface.php 0000666 00000001020 13052362033 0015146 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Factory;
/**
* @package FeedIo
*/
interface ClientBuilderInterface extends BuilderInterface
{
/**
* This method MUST return a \FeedIo\Adapter\ClientInterface instance
* @return \FeedIo\Adapter\ClientInterface
*/
public function getClient();
}
src/FeedIo/Factory/LoggerBuilderInterface.php 0000666 00000000762 13052362033 0015163 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Factory;
/**
* @package FeedIo
*/
interface LoggerBuilderInterface extends BuilderInterface
{
/**
* This method MUST return a valid PSR3 logger
* @return \Psr\Log\LoggerInterface
*/
public function getLogger();
}
src/FeedIo/Factory/MissingDependencyException.php 0000666 00000000545 13052362033 0016102 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Factory;
use FeedIo\FeedIoException;
class MissingDependencyException extends FeedIoException
{
}
src/FeedIo/Feed.php 0000666 00000006126 13052362033 0010050 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Feed\Node;
use FeedIo\Feed\Item;
use FeedIo\Feed\ItemInterface;
class Feed extends Node implements FeedInterface, \JsonSerializable
{
/**
* @var \ArrayIterator
*/
protected $items;
/**
* @var string $url
*/
protected $url;
public function __construct()
{
$this->items = new \ArrayIterator();
parent::__construct();
}
/**
* @return string $url
*/
public function getUrl()
{
return $this->url;
}
/**
* @param string $url
* @return FeedInterface
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* (PHP 5 >= 5.0.0)
* Return the current element
* @link http://php.net/manual/en/iterator.current.php
* @return mixed Can return any type.
*/
public function current()
{
return $this->items->current();
}
/**
* (PHP 5 >= 5.0.0)
* Move forward to next element
* @link http://php.net/manual/en/iterator.next.php
* @return void Any returned value is ignored.
*/
public function next()
{
return $this->items->next();
}
/**
* (PHP 5 >= 5.0.0)
* Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php
* @return mixed scalar on success, or null on failure.
*/
public function key()
{
return $this->items->key();
}
/**
* (PHP 5 >= 5.0.0)
* Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
public function valid()
{
return $this->items->valid();
}
/**
* (PHP 5 >= 5.0.0)
* Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php
* @return void Any returned value is ignored.
*/
public function rewind()
{
return $this->items->rewind();
}
/**
* @param ItemInterface $item
* @return $this
*/
public function add(ItemInterface $item)
{
$this->items->append($item);
return $this;
}
/**
* @return ItemInterface
*/
public function newItem()
{
return new Item();
}
/**
* @return array
*/
public function jsonSerialize()
{
return $this->toArray();
}
/**
* @return array
*/
public function toArray()
{
$items = [];
foreach( $this->items as $item ) {
$items[] = $item->toArray();
}
$properties = parent::toArray();
$properties['items'] = $items;
return $properties;
}
}
src/FeedIo/Feed/Item.php 0000666 00000002165 13052362033 0010745 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed;
use FeedIo\Feed\Item\Media;
use FeedIo\Feed\Item\MediaInterface;
class Item extends Node implements ItemInterface
{
/**
* @var \ArrayIterator
*/
protected $medias;
public function __construct()
{
$this->medias = new \ArrayIterator();
parent::__construct();
}
/**
* @param MediaInterface $media
* @return $this
*/
public function addMedia(MediaInterface $media)
{
$this->medias->append($media);
return $this;
}
/**
* @return \ArrayIterator
*/
public function getMedias()
{
return $this->medias;
}
/**
* @return boolean
*/
public function hasMedia()
{
return $this->medias->count() > 0;
}
/**
* @return MediaInterface
*/
public function newMedia()
{
return new Media();
}
}
src/FeedIo/Feed/Item/Media.php 0000666 00000002445 13052362033 0011765 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Item;
class Media implements MediaInterface
{
/**
* @var string
*/
protected $type;
/**
* @var string
*/
protected $url;
/**
* @var int
*/
protected $length;
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @param string $type
* @return $this
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* @param string $url
* @return $this
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* @return string
*/
public function getLength()
{
return $this->length;
}
/**
* @param string $length
* @return $this
*/
public function setLength($length)
{
$this->length = intval($length);
return $this;
}
}
src/FeedIo/Feed/Item/MediaInterface.php 0000666 00000002332 13052362033 0013601 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Item;
/**
* Describe a Media instance
*
* most of the time medias are defined as enclosure in the XML document
*
* Atom :
*
*
* RSS :
*
*
*
* // will display http://example.org/video.mpeg
* echo $media->getUrl();
*
*/
interface MediaInterface
{
/**
* @return string
*/
public function getType();
/**
* @param string $type
* @return $this
*/
public function setType($type);
/**
* @return string
*/
public function getUrl();
/**
* @param string $url
* @return $this
*/
public function setUrl($url);
/**
* @return string
*/
public function getLength();
/**
* @param string $length
* @return $this
*/
public function setLength($length);
}
src/FeedIo/Feed/ItemInterface.php 0000666 00000003045 13052362033 0012564 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed;
use FeedIo\Feed\Item\MediaInterface;
/**
* Describes an Item instance
*
* an item holds three types of properties :
* - basic values inherited from the NodeInterface like title, description, URL
* - MediaInterface instances for medias like videos, images and podcasts
* - ElementInterface instances for nodes not related to a known property of the ItemInterface instance
*
* ElementInterface instances are accessed using two methods :
*
* - ItemInterface::getElementIterator($name). Use it to read an array of elements or if you need to get an ElementInterface instance
* - ItemInterface::getValue($name). use it to get the element's v lue
*
*/
interface ItemInterface extends NodeInterface
{
/**
* adds $media to the object's attributes
*
* @param MediaInterface $media
* @return $this
*/
public function addMedia(MediaInterface $media);
/**
* returns the current object's medias
*
* @return \ArrayIterator
*/
public function getMedias();
/**
* returns true if at least one MediaInterface exists in the object's attributes
*
* @return boolean
*/
public function hasMedia();
/**
* returns a new MediaInterface
*
* @return MediaInterface
*/
public function newMedia();
}
src/FeedIo/Feed/Node.php 0000666 00000013706 13052362033 0010737 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed;
use FeedIo\Feed\Node\Category;
use FeedIo\Feed\Node\CategoryInterface;
use FeedIo\Feed\Node\Element;
use FeedIo\Feed\Node\ElementIterator;
use FeedIo\Feed\Node\ElementInterface;
class Node implements NodeInterface
{
/**
* @var \ArrayIterator
*/
protected $elements;
/**
* @var \ArrayIterator
*/
protected $categories;
/**
* @var string
*/
protected $title;
/**
* @var string
*/
protected $publicId;
/**
* @var string
*/
protected $description;
/**
* @var \DateTime
*/
protected $lastModified;
/**
* @var string
*/
protected $link;
public function __construct()
{
$this->elements = new \ArrayIterator();
$this->categories = new \ArrayIterator();
}
/**
* @param string $name element name
* @param string $value element value
* @return $this
*/
public function set($name, $value)
{
$element = $this->newElement();
$element->setName($name);
$element->setValue($value);
$this->addElement($element);
return $this;
}
/**
* returns node's categories
*
* @return \ArrayIterator
*/
public function getCategories()
{
return $this->categories;
}
/**
* @return \Generator
*/
public function getCategoriesGenerator()
{
foreach( $this->categories as $category ) {
yield $category->getlabel();
}
}
/**
* adds a category to the node
*
* @param \FeedIo\Feed\Node\CategoryInterface $category
* @return $this
*/
public function addCategory(CategoryInterface $category)
{
$this->categories->append($category);
return $this;
}
/**
* returns a new CategoryInterface
*
* @return \FeedIo\Feed\Node\CategoryInterface
*/
public function newCategory()
{
return new Category();
}
/**
* @return ElementInterface
*/
public function newElement()
{
return new Element();
}
/**
* @param string $name element name
* @return mixed
*/
public function getValue($name)
{
foreach ($this->getElementIterator($name) as $element) {
return $element->getValue();
}
return;
}
/**
* @param string $name element name
* @return ElementIterator
*/
public function getElementIterator($name)
{
return new ElementIterator($this->elements, $name);
}
/**
* @param string $name element name
* @return boolean true if the element exists
*/
public function hasElement($name)
{
$filter = $this->getElementIterator($name);
return $filter->count() > 0;
}
/**
* @param ElementInterface $element
* @return $this
*/
public function addElement(ElementInterface $element)
{
$this->elements->append($element);
return $this;
}
/**
* Returns all the item's optional elements
* @return \ArrayIterator
*/
public function getAllElements()
{
return $this->elements;
}
/**
* Returns the item's optional elements tag names
* @return array
*/
public function listElements()
{
foreach ($this->elements as $element) {
yield ($element->getName());
}
}
/**
* @return \Generator
*/
public function getElementsGenerator()
{
$elements = $this->getAllElements();
foreach( $elements as $element ) {
yield $element->getName() => $element->getValue();
}
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $title
* @return $this
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* @return string
*/
public function getPublicId()
{
return $this->publicId;
}
/**
* @param string $publicId
* @return $this
*/
public function setPublicId($publicId)
{
$this->publicId = $publicId;
return $this;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @param string $description
* @return $this
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* @return \DateTime
*/
public function getLastModified()
{
return $this->lastModified;
}
/**
* @param \DateTime $lastModified
* @return $this
*/
public function setLastModified(\DateTime $lastModified)
{
$this->lastModified = $lastModified;
return $this;
}
/**
* @return string
*/
public function getLink()
{
return $this->link;
}
/**
* @param string $link
* @return $this
*/
public function setLink($link)
{
$this->link = $link;
return $this;
}
/**
* @return array
*/
public function toArray()
{
$properties = get_object_vars($this);
foreach( $properties as $name => $property ) {
if ( $property instanceof \DateTime ) {
$properties[$name] = $property->format(\DateTime::ATOM);
}
}
$properties['elements'] = iterator_to_array($this->getElementsGenerator());
$properties['categories'] = iterator_to_array($this->getCategoriesGenerator());
return $properties;
}
}
src/FeedIo/Feed/Node/Category.php 0000666 00000002573 13052362033 0012514 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
class Category implements CategoryInterface
{
/**
* @var string
*/
protected $term;
/**
* @var string
*/
protected $scheme;
/**
* @var string
*/
protected $label;
/**
* @return string
*/
public function getTerm()
{
return $this->term;
}
/**
* @param string $term
* @return $this
*/
public function setTerm($term)
{
$this->term = $term;
return $this;
}
/**
* @return string
*/
public function getScheme()
{
return $this->scheme;
}
/**
* @param string $scheme
* @return $this
*/
public function setScheme($scheme)
{
$this->scheme = $scheme;
return $this;
}
/**
* @return string
*/
public function getLabel()
{
return $this->label;
}
/**
* @param string $label
* @return $this
*/
public function setLabel($label)
{
$this->label = $label;
return $this;
}
}
src/FeedIo/Feed/Node/CategoryInterface.php 0000666 00000001601 13052362033 0014324 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
/**
* Describe a Category instance
*
*/
interface CategoryInterface
{
/**
* @return string
*/
public function getTerm();
/**
* @param string $term
* @return $this
*/
public function setTerm($term);
/**
* @return string
*/
public function getScheme();
/**
* @param string $scheme
* @return $this
*/
public function setScheme($scheme);
/**
* @return string
*/
public function getLabel();
/**
* @param string $label
* @return $this
*/
public function setLabel($label);
}
src/FeedIo/Feed/Node/Element.php 0000666 00000003157 13052362033 0012327 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
class Element implements ElementInterface
{
/**
* @var string
*/
protected $name;
/**
* @var string
*/
protected $value;
/**
* @var array
*/
protected $attributes = array();
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
* @return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* @param string $value
* @return $this
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* @param string $name
* @return string
*/
public function getAttribute($name)
{
if (array_key_exists($name, $this->attributes)) {
return $this->attributes[$name];
}
return;
}
/**
* @return array
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* @param string $name
* @param string $value
* @return $this
*/
public function setAttribute($name, $value)
{
$this->attributes[$name] = $value;
return $this;
}
}
src/FeedIo/Feed/Node/ElementInterface.php 0000666 00000003001 13052362033 0014134 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
/**
* Describe an Element instance
*
* $name matches the node's tag name
* $value matches the node's content
* each attribute matches an attribute of the node
*
* for example, to represent this XML node
*
* http://example.org/some-sound.mp3
*
* you must set the ElementInstance's properties this way
*
*
* $item->setName('media');
* $item->setValue('http://example.org/some-sound.mp3');
* $item->setAttribute('lenght', 45668);
* $item->setAttribute('type', 'audio/mpeg');
*
*
*/
interface ElementInterface
{
/**
* @return string
*/
public function getName();
/**
* @param string $name
* @return $this
*/
public function setName($name);
/**
* @return string
*/
public function getValue();
/**
* @param string $value
* @return $this
*/
public function setValue($value);
/**
* @param string $name
* @return string
*/
public function getAttribute($name);
/**
* @return array
*/
public function getAttributes();
/**
* @param string $name
* @param string $value
* @return $this
*/
public function setAttribute($name, $value);
}
src/FeedIo/Feed/Node/ElementIterator.php 0000666 00000002340 13052362033 0014032 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
/**
* Iterator to filter elements by name
* @see \FilterIterator
*/
class ElementIterator extends \FilterIterator
{
/**
* @var string $name Element name to accept
*/
protected $name;
/**
* @param \Iterator $iterator Set of elements to filter
* @param string $name Element name to accept
*/
public function __construct(\Iterator $iterator, $name)
{
parent::__construct($iterator);
$this->name = $name;
}
/**
* override PHP's count implementation.
* @return int
*/
public function count()
{
$count = 0;
foreach ($this as $node) {
$count++;
}
return $count;
}
/**
* @return boolean True if the current element's name matches the expected one
*/
public function accept()
{
$element = $this->getInnerIterator()->current();
return (0 == strcasecmp($this->name, $element->getName()));
}
}
src/FeedIo/Feed/NodeInterface.php 0000666 00000007331 13052362033 0012555 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed;
use FeedIo\Feed\Node\ElementInterface;
use FeedIo\Feed\Node\CategoryInterface;
/**
* Describes a node instance
*
* A node exposes attributes which are common to feeds and items
*/
interface NodeInterface
{
/**
* Returns node's title
*
* @return string
*/
public function getTitle();
/**
* Sets nodes's title
*
* @param string $title
* @return $this
*/
public function setTitle($title);
/**
* Returns node's public id
*
* @return string
*/
public function getPublicId();
/**
* sets node's public id
*
* @param string $id
* @return $this
*/
public function setPublicId($id);
/**
* Returns node's description
*
* @return string
*/
public function getDescription();
/**
* Sets node's description
*
* @param string $description
* @return $this
*/
public function setDescription($description);
/**
* Returns the node's last modified date
*
* @return \DateTime
*/
public function getLastModified();
/**
* Sets the node's last modified date
*
* @param \DateTime $lastModified
* @return $this
*/
public function setLastModified(\DateTime $lastModified);
/**
* Returns the node's link
*
* @return string
*/
public function getLink();
/**
* Sets the nodes's link
*
* @param string $link
* @return $this
*/
public function setLink($link);
/**
* returns node's categories
*
* @return \ArrayIterator
*/
public function getCategories();
/**
* adds a category to the node
*
* @param \FeedIo\Feed\Node\CategoryInterface $category
* @return $this
*/
public function addCategory(CategoryInterface $category);
/**
* returns a new CategoryInterface
*
* @return \FeedIo\Feed\Node\CategoryInterface
*/
public function newCategory();
/**
* returns a new ElementInterface
*
* @return \FeedIo\Feed\Node\ElementInterface
*/
public function newElement();
/**
* returns an element's value
*
* @param string $name element name
* @return mixed
*/
public function getValue($name);
/**
* creates a new ElementInterface called $name and sets its value to $value
*
* @param string $name element name
* @param string $value element value
* @return $this
*/
public function set($name, $value);
/**
* returns the ElementIterator to iterate over ElementInterface instances called $name
*
* @param string $name element name
* @return \FeedIo\Feed\Node\ElementIterator
*/
public function getElementIterator($name);
/**
* returns true if an ElementInterface instance called $name exists
*
* @param string $name element name
* @return boolean true if the element exists
*/
public function hasElement($name);
/**
* adds $element to the object's attributes
*
* @param ElementInterface $element
* @return $this
*/
public function addElement(ElementInterface $element);
/**
* Returns all the item's elements
*
* @return \ArrayIterator
*/
public function getAllElements();
/**
* Returns the item's elements tag names
*
* @return array
*/
public function listElements();
}
src/FeedIo/FeedInterface.php 0000666 00000001760 13052362033 0011670 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Feed\NodeInterface;
use FeedIo\Feed\ItemInterface;
/**
* Interface FeedInterface
* Represents the top node of a news feed
* @package FeedIo
*/
interface FeedInterface extends \Iterator, NodeInterface
{
/**
* This method MUST return the feed's full URL
* @return string
*/
public function getUrl();
/**
* @param string $url
* @return FeedInterface
*/
public function setUrl($url);
/**
* Atom : feed.entry
* Rss : rss.channel.item
* @param ItemInterface $item
* @return FeedInterface
*/
public function add(ItemInterface $item);
/**
* @return ItemInterface
*/
public function newItem();
}
src/FeedIo/FeedIo.php 0000666 00000017410 13052362033 0010336 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Filter\ModifiedSince;
use FeedIo\Reader;
use FeedIo\Reader\FixerSet;
use FeedIo\Reader\FixerAbstract;
use FeedIo\Rule\DateTimeBuilder;
use FeedIo\Adapter\ClientInterface;
use FeedIo\Standard\Atom;
use FeedIo\Standard\Rss;
use FeedIo\Standard\Rdf;
use Psr\Log\LoggerInterface;
/**
* This class acts as a facade. It provides methods to access feed-io main features
*
*
* // $client is a \FeedIo\Adapter\ClientInterface instance, $logger a \Psr\Log\LoggerInterface
* $feedIo = new FeedIo($client, $logger);
*
* // read a feed. Output is a Result instance
* $result = $feedIo->read('http://somefeed.org/feed.rss');
*
* // use the feed
* $feed = $result->getFeed();
* echo $feed->getTitle();
*
* // and its items
* foreach ( $feed as $item ) {
* echo $item->getTitle();
* echo $item->getDescription();
* }
*
*
*
*
* // build the feed to publish
* $feed = new \FeedIo\Feed;
* $feed->setTitle('title');
* // ...
*
* // add items to it
* $item = new \FeedIo\Feed\Item
* $item->setTitle('my great post');
*
* // want to publish a media ? no problem
* $media = new \FeedIo\Feed\Item\Media
* $media->setUrl('http://yourdomain.tld/medias/some-podcast.mp3');
* $media->setType('audio/mpeg');
*
* // add it to the item
* $item->addMedia($media);
*
* // add the item to the feed (almost there)
* $feed->add($item);
*
* // format it in atom
* $feedIo->toAtom($feed);
*
*
*/
class FeedIo
{
/**
* @var \FeedIo\Reader
*/
protected $reader;
/**
* @var \FeedIo\Rule\DateTimeBuilder
*/
protected $dateTimeBuilder;
/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* @var array
*/
protected $standards;
/**
* @var \FeedIo\Reader\FixerSet
*/
protected $fixerSet;
/**
* @param \FeedIo\Adapter\ClientInterface $client
* @param \Psr\Log\LoggerInterface $logger
*/
public function __construct(ClientInterface $client, LoggerInterface $logger)
{
$this->logger = $logger;
$this->dateTimeBuilder = new DateTimeBuilder();
$this->setReader(new Reader($client, $logger));
$this->loadCommonStandards();
$this->loadFixerSet();
}
/**
* Loads main standards (RSS, RDF, Atom) in current object's attributes
*
* @return $this
*/
protected function loadCommonStandards()
{
$standards = $this->getCommonStandards();
foreach ($standards as $name => $standard) {
$this->addStandard($name, $standard);
}
return $this;
}
/**
* adds a filter to the reader
*
* @param \FeedIo\FilterInterface $filter
* @return $this
*/
public function addFilter(FilterInterface $filter)
{
$this->getReader()->addFilter($filter);
return $this;
}
/**
* Returns main standards
*
* @return array
*/
public function getCommonStandards()
{
return array(
'atom' => new Atom($this->dateTimeBuilder),
'rss' => new Rss($this->dateTimeBuilder),
'rdf' => new Rdf($this->dateTimeBuilder),
);
}
/**
* @param string $name
* @param \FeedIo\StandardAbstract $standard
* @return $this
*/
public function addStandard($name, StandardAbstract $standard)
{
$name = strtolower($name);
$this->standards[$name] = $standard;
$this->reader->addParser(
new Parser($standard, $this->logger)
);
return $this;
}
/**
* @return \FeedIo\Reader\FixerSet
*/
public function getFixerSet()
{
return $this->fixerSet;
}
/**
* @return $this
*/
protected function loadFixerSet()
{
$this->fixerSet = new FixerSet();
$fixers = $this->getBaseFixers();
foreach ($fixers as $fixer) {
$this->addFixer($fixer);
}
return $this;
}
/**
* @param FixerAbstract $fixer
* @return $this
*/
public function addFixer(FixerAbstract $fixer)
{
$fixer->setLogger($this->logger);
$this->fixerSet->add($fixer);
return $this;
}
/**
* @return array
*/
public function getBaseFixers()
{
return array(
new Reader\Fixer\LastModified(),
new Reader\Fixer\PublicId(),
);
}
/**
* @return \FeedIo\Rule\DateTimeBuilder
*/
public function getDateTimeBuilder()
{
return $this->dateTimeBuilder;
}
/**
* @return \FeedIo\Reader
*/
public function getReader()
{
return $this->reader;
}
/**
* @param \FeedIo\Reader
* @return $this
*/
public function setReader(Reader $reader)
{
$this->reader = $reader;
return $this;
}
/**
* @param $url
* @param FeedInterface $feed
* @param \DateTime $modifiedSince
* @return \FeedIo\Reader\Result
*/
public function read($url, FeedInterface $feed = null, \DateTime $modifiedSince = null)
{
if (is_null($feed)) {
$feed = new Feed();
}
if ($modifiedSince instanceof \DateTime) {
$this->addFilter(new ModifiedSince($modifiedSince));
}
$this->logAction($feed, "read access : $url into a %s instance");
$result = $this->reader->read($url, $feed, $modifiedSince);
$this->fixerSet->correct($result->getFeed());
return $result;
}
/**
* @param $url
* @param \DateTime $modifiedSince
* @return \FeedIo\Reader\Result
*/
public function readSince($url, \DateTime $modifiedSince)
{
return $this->read($url, new Feed(), $modifiedSince);
}
/**
* @return $this
*/
public function resetFilters()
{
$this->getReader()->resetFilters();
return $this;
}
/**
* @param FeedInterface $feed
* @param string $standard Standard's name
* @return \DomDocument
*/
public function format(FeedInterface $feed, $standard)
{
$this->logAction($feed, "formatting a %s in $standard format");
$formatter = new Formatter($this->getStandard($standard), $this->logger);
return $formatter->toDom($feed);
}
/**
* @param \FeedIo\FeedInterface $feed
* @return \DomDocument
*/
public function toRss(FeedInterface $feed)
{
return $this->format($feed, 'rss');
}
/**
* @param \FeedIo\FeedInterface $feed
* @return \DomDocument
*/
public function toAtom(FeedInterface $feed)
{
return $this->format($feed, 'atom');
}
/**
* @param string $name
* @return \FeedIo\StandardAbstract
* @throws \OutOfBoundsException
*/
public function getStandard($name)
{
$name = strtolower($name);
if (array_key_exists($name, $this->standards)) {
return $this->standards[$name];
}
throw new \OutOfBoundsException("no standard found for $name");
}
/**
* @param \FeedIo\FeedInterface $feed
* @param string $message
* @return $this
*/
protected function logAction(FeedInterface $feed, $message)
{
$class = get_class($feed);
$this->logger->debug(sprintf($message, $class));
return $this;
}
}
src/FeedIo/FeedIoException.php 0000666 00000000467 13052362033 0012221 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
class FeedIoException extends \RuntimeException
{
}
src/FeedIo/Filter/ModifiedSince.php 0000666 00000001576 13052362033 0013140 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Filter;
use FeedIo\Feed\ItemInterface;
use FeedIo\FilterInterface;
class ModifiedSince implements FilterInterface
{
/**
* @var \DateTime
*/
protected $date;
/**
* ModifiedSince constructor.
* @param \DateTime $date
*/
public function __construct(\DateTime $date)
{
$this->date = $date;
}
/**
* @param ItemInterface $item
* @return bool
*/
public function isValid(ItemInterface $item)
{
if ($item->getLastModified() instanceof \DateTime) {
return $item->getLastModified() > $this->date;
}
return false;
}
}
src/FeedIo/FilterInterface.php 0000666 00000000673 13052362033 0012254 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Feed\ItemInterface;
interface FilterInterface
{
/**
* @param ItemInterface $item
* @return bool
*/
public function isValid(ItemInterface $item);
}
src/FeedIo/Formatter.php 0000666 00000010003 13052362033 0011135 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Feed\NodeInterface;
use FeedIo\Rule\OptionalField;
use Psr\Log\LoggerInterface;
/**
* Turns a FeedInterface instance into a XML document.
*
* Depends on :
* - FeedIo\StandardAbstract
* - Psr\Log\LoggerInterface
*
*/
class Formatter
{
/**
* @var StandardAbstract
*/
protected $standard;
/**
* @var LoggerInterface
*/
protected $logger;
/**
* @param StandardAbstract $standard
* @param LoggerInterface $logger
*/
public function __construct(StandardAbstract $standard, LoggerInterface $logger)
{
$this->standard = $standard;
$this->logger = $logger;
}
/**
* @param \DOMDocument $document
* @param FeedInterface $feed
* @return $this
*/
public function setHeaders(\DOMDocument $document, FeedInterface $feed)
{
$rules = $this->standard->getFeedRuleSet();
$elements = $this->buildElements($rules, $document, $feed);
foreach ($elements as $element) {
$this->standard->getMainElement($document)->appendChild($element);
}
return $this;
}
/**
* @param \DOMDocument $document
* @param NodeInterface $node
* @return $this
*/
public function addItem(\DOMDocument $document, NodeInterface $node)
{
$domItem = $document->createElement($this->standard->getItemNodeName());
$rules = $this->standard->getItemRuleSet();
$elements = $this->buildElements($rules, $document, $node);
foreach ($elements as $element) {
$domItem->appendChild($element);
}
$this->standard->getMainElement($document)->appendChild($domItem);
return $this;
}
/**
* @param RuleSet $ruleSet
* @param \DOMDocument $document
* @param NodeInterface $node
* @return array
*/
public function buildElements(RuleSet $ruleSet, \DOMDocument $document, NodeInterface $node)
{
$rules = $this->getAllRules($ruleSet, $node);
$elements = array();
foreach ($rules as $rule) {
$elements[] = $rule->createElement($document, $node);
}
return array_filter($elements);
}
/**
* @param RuleSet $ruleSet
* @param NodeInterface $node
* @return array|\ArrayIterator
*/
public function getAllRules(RuleSet $ruleSet, NodeInterface $node)
{
$rules = $ruleSet->getRules();
$optionalFields = $node->listElements();
foreach ($optionalFields as $optionalField) {
$rules[] = new OptionalField($optionalField);
}
return $rules;
}
/**
* @return \DOMDocument
*/
public function getEmptyDocument()
{
return new \DOMDocument('1.0', 'utf-8');
}
/**
* @return \DOMDocument
*/
public function getDocument()
{
$document = $this->getEmptyDocument();
return $this->standard->format($document);
}
/**
* @param FeedInterface $feed
* @return string
*/
public function toString(FeedInterface $feed)
{
$document = $this->toDom($feed);
return $document->saveXML();
}
/**
* @param FeedInterface $feed
* @return \DomDocument
*/
public function toDom(FeedInterface $feed)
{
$document = $this->getDocument();
$this->setHeaders($document, $feed);
$this->setItems($document, $feed);
return $document;
}
/**
* @param \DOMDocument $document
* @param FeedInterface $feed
* @return $this
*/
public function setItems(\DOMDocument $document, FeedInterface $feed)
{
foreach ($feed as $item) {
$this->addItem($document, $item);
}
return $this;
}
}
src/FeedIo/Parser.php 0000666 00000011720 13052362033 0010435 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use DOMDocument;
use FeedIo\Feed\ItemInterface;
use FeedIo\Feed\NodeInterface;
use FeedIo\Parser\MissingFieldsException;
use FeedIo\Parser\UnsupportedFormatException;
use Psr\Log\LoggerInterface;
/**
* Parses a DOM document if its format matches the parser's standard
*
* Depends on :
* - FeedIo\StandardAbstract
* - Psr\Log\LoggerInterface
*
*/
class Parser
{
/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* @var array[FilterInterface]
*/
protected $filters = array();
/**
* @var StandardAbstract
*/
protected $standard;
/**
* @param StandardAbstract $standard
* @param LoggerInterface $logger
*/
public function __construct(StandardAbstract $standard, LoggerInterface $logger)
{
$this->standard = $standard;
$this->logger = $logger;
}
/**
* @return StandardAbstract
*/
public function getStandard()
{
return $this->standard;
}
/**
* @param $tagName
* @return bool
*/
public function isItem($tagName)
{
return (strtolower($this->standard->getItemNodeName()) === strtolower($tagName));
}
/**
* @param FilterInterface $filter
* @return $this
*/
public function addFilter(FilterInterface $filter)
{
$this->filters[] = $filter;
return $this;
}
/**
* Reset filters
* @return $this
*/
public function resetFilters()
{
$this->filters = [];
return $this;
}
/**
* @param DOMDocument $document
* @param FeedInterface $feed
* @return \FeedIo\FeedInterface
* @throws Parser\MissingFieldsException
* @throws Parser\UnsupportedFormatException
*/
public function parse(DOMDocument $document, FeedInterface $feed)
{
if (!$this->standard->canHandle($document)) {
throw new UnsupportedFormatException('this is not a supported format');
}
$this->checkBodyStructure($document, $this->standard->getMandatoryFields());
$element = $this->standard->getMainElement($document);
$this->parseNode($feed, $element, $this->standard->getFeedRuleSet());
return $feed;
}
/**
* @param DOMDocument $document
* @param array $mandatoryFields
* @return $this
* @throws MissingFieldsException
*/
public function checkBodyStructure(DOMDocument $document, array $mandatoryFields)
{
$errors = array();
$element = $document->documentElement;
foreach ($mandatoryFields as $field) {
$list = $element->getElementsByTagName($field);
if (0 === $list->length) {
$errors[] = $field;
}
}
if (!empty($errors)) {
$message = "missing mandatory field(s) : ".implode(',', $errors);
$this->logger->warning($message);
throw new MissingFieldsException($message);
}
return $this;
}
/**
* @param NodeInterface $item
* @param \DOMElement $element
* @param RuleSet $ruleSet
* @return NodeInterface
*/
public function parseNode(NodeInterface $item, \DOMElement $element, RuleSet $ruleSet)
{
foreach ($element->childNodes as $node) {
if ($node instanceof \DOMElement) {
$this->handleNode($item, $node, $ruleSet);
}
}
return $item;
}
/**
* @param NodeInterface $item
* @param \DOMElement $node
* @param RuleSet $ruleSet
* @return $this
*/
protected function handleNode(NodeInterface $item, \DOMElement $node, RuleSet $ruleSet)
{
if ($this->isItem($node->tagName) && $item instanceof FeedInterface) {
$newItem = $this->parseNode($item->newItem(), $node, $this->standard->getItemRuleSet());
$this->addValidItem($item, $newItem);
} else {
$rule = $ruleSet->get($node->tagName);
$rule->setProperty($item, $node);
}
return $this;
}
/**
* @param FeedInterface $feed
* @param NodeInterface $item
* @return $this
*/
public function addValidItem(FeedInterface $feed, NodeInterface $item)
{
if ($item instanceof ItemInterface && $this->isValid($item)) {
$feed->add($item);
}
return $this;
}
/**
* @param ItemInterface $item
* @return bool
*/
public function isValid(ItemInterface $item)
{
foreach ($this->filters as $filter) {
if (!$filter->isValid($item)) {
return false;
}
}
return true;
}
}
src/FeedIo/Parser/MissingFieldsException.php 0000666 00000000540 13052362033 0015052 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Parser;
use FeedIo\FeedIoException;
class MissingFieldsException extends FeedIoException
{
}
src/FeedIo/Parser/UnsupportedFormatException.php 0000666 00000000544 13052362033 0016017 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Parser;
use FeedIo\FeedIoException;
class UnsupportedFormatException extends FeedIoException
{
}
src/FeedIo/Reader.php 0000666 00000011441 13052362033 0010403 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Adapter\ClientInterface;
use FeedIo\Reader\ReadErrorException;
use FeedIo\Reader\Result;
use FeedIo\Reader\NoAccurateParserException;
use Psr\Log\LoggerInterface;
/**
* Consumes feeds and return corresponding Result instances
*
* Depends on :
* - FeedIo\Adapter\ClientInterface
* - Psr\Log\LoggerInterface
*
* A Reader instance MUST have at least one parser added with the addParser() method to read feeds
* It will throw a NoAccurateParserException if it cannot find a suitable parser for the feed.
*/
class Reader
{
/**
* @var \FeedIo\Adapter\ClientInterface;
*/
protected $client;
/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* @var array
*/
protected $parsers = array();
/**
* @param ClientInterface $client
* @param LoggerInterface $logger
*/
public function __construct(ClientInterface $client, LoggerInterface $logger)
{
$this->client = $client;
$this->logger = $logger;
}
/**
* @param Parser $parser
* @return $this
*/
public function addParser(Parser $parser)
{
$this->logger->debug("new parser added : ".get_class($parser->getStandard()));
$this->parsers[] = $parser;
return $this;
}
/**
* adds a filter to every parsers
*
* @param \FeedIo\FilterInterface $filter
* @return $this
*/
public function addFilter(FilterInterface $filter)
{
foreach ($this->parsers as $parser) {
$parser->addFilter($filter);
}
return $this;
}
/**
* Reset filters on every parsers
* @return $this
*/
public function resetFilters()
{
foreach ($this->parsers as $parser) {
$parser->resetFilters();
}
return $this;
}
/**
* @param string $body
* @return \DOMDocument
*/
public function loadDocument($body)
{
set_error_handler(
/**
* @param string $errno
*/
function ($errno, $errstr) {
throw new \InvalidArgumentException("malformed xml string. parsing error : $errstr ($errno)");
}
);
$domDocument = new \DOMDocument();
$domDocument->loadXML($body);
restore_error_handler();
return $domDocument;
}
/**
* @param $url
* @param FeedInterface $feed
* @param \DateTime $modifiedSince
* @return \FeedIo\Reader\Result
* @throws ReadErrorException
*/
public function read($url, FeedInterface $feed, \DateTime $modifiedSince = null)
{
$this->logger->debug("start reading {$url}");
if (is_null($modifiedSince)) {
$this->logger->notice("no 'modifiedSince' parameter given, setting it to 01/01/1970");
$modifiedSince = new \DateTime('@0');
}
try {
$response = $this->client->getResponse($url, $modifiedSince);
$this->logger->debug("response ok, now turning it into a DomDocument");
$document = $this->loadDocument($response->getBody());
$this->parseDocument($document, $feed);
$this->logger->info("{$url} successfully parsed");
return new Result($document, $feed, $modifiedSince, $response, $url);
} catch (\Exception $e) {
$this->logger->warning("{$url} read error : {$e->getMessage()}");
throw new ReadErrorException($e);
}
}
/**
* @param \DOMDocument $document
* @param FeedInterface $feed
* @return FeedInterface
* @throws Parser\UnsupportedFormatException
* @throws Reader\NoAccurateParserException
*/
public function parseDocument(\DOMDocument $document, FeedInterface $feed)
{
$parser = $this->getAccurateParser($document);
$this->logger->debug("accurate parser : ".get_class($parser));
return $parser->parse($document, $feed);
}
/**
* @param \DOMDocument $document
* @return ParserAbstract
* @throws Reader\NoAccurateParserException
*/
public function getAccurateParser(\DOMDocument $document)
{
foreach ($this->parsers as $parser) {
if ($parser->getStandard()->canHandle($document)) {
return $parser;
}
}
$message = 'No parser can handle this stream';
$this->logger->error($message);
throw new NoAccurateParserException($message);
}
}
src/FeedIo/Reader/Fixer/LastModified.php 0000666 00000002226 13052362033 0014025 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader\Fixer;
use FeedIo\FeedInterface;
use FeedIo\Reader\FixerAbstract;
class LastModified extends FixerAbstract
{
/**
* @param FeedInterface $feed
* @return $this
*/
public function correct(FeedInterface $feed)
{
if (is_null($feed->getLastModified())) {
$this->logger->notice("correct last modified date for feed {$feed->getTitle()}");
$feed->setLastModified(
$this->searchLastModified($feed)
);
}
return $this;
}
/**
* @param FeedInterface $feed
* @return \DateTime
*/
public function searchLastModified(FeedInterface $feed)
{
$latest = new \DateTime('@0');
foreach ($feed as $item) {
if ($item->getLastModified() > $latest) {
$latest = $item->getLastModified();
}
}
return $latest;
}
}
src/FeedIo/Reader/Fixer/PublicId.php 0000666 00000001764 13052362033 0013162 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader\Fixer;
use FeedIo\FeedInterface;
use FeedIo\Reader\FixerAbstract;
class PublicId extends FixerAbstract
{
/**
* @param FeedInterface $feed
* @return $this
*/
public function correct(FeedInterface $feed)
{
if (is_null($feed->getPublicId())) {
$this->logger->notice("correct public id for feed {$feed->getTitle()}");
$feed->setPublicId($feed->getLink());
$this->fixItems($feed);
}
return $this;
}
/**
* @param FeedInterface $feed
* @return $this
*/
protected function fixItems(FeedInterface $feed)
{
foreach ($feed as $item) {
$item->setPublicId($item->getLink());
}
return $this;
}
}
src/FeedIo/Reader/FixerAbstract.php 0000666 00000001264 13052362033 0013146 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader;
use FeedIo\FeedInterface;
use Psr\Log\LoggerInterface;
abstract class FixerAbstract
{
/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* @param \Psr\Log\LoggerInterface
* @return $this
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
return $this;
}
abstract public function correct(FeedInterface $feed);
}
src/FeedIo/Reader/FixerSet.php 0000666 00000001425 13052362033 0012135 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader;
use FeedIo\FeedInterface;
class FixerSet
{
protected $fixers = array();
/**
* @param \FeedIo\Reader\FixerAbstract
* @return $this
*/
public function add(FixerAbstract $fixer)
{
$this->fixers[] = $fixer;
return $this;
}
/**
* @param FeedInterface $feed
* @return $this
*/
public function correct(FeedInterface $feed)
{
foreach ($this->fixers as $fixer) {
$fixer->correct($feed);
}
return $this;
}
}
src/FeedIo/Reader/NoAccurateParserException.php 0000666 00000000543 13052362033 0015464 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader;
use FeedIo\FeedIoException;
class NoAccurateParserException extends FeedIoException
{
}
src/FeedIo/Reader/ReadErrorException.php 0000666 00000000534 13052362033 0014150 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader;
use FeedIo\FeedIoException;
class ReadErrorException extends FeedIoException
{
}
src/FeedIo/Reader/Result.php 0000666 00000004501 13052362033 0011660 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader;
use FeedIo\Adapter\ResponseInterface;
use FeedIo\FeedInterface;
/**
* Result of the read() operation
*
* a Result instance holds the following :
*
* - the Feed instance
* - Date and time of the request
* - value of the 'modifiedSince' header sent throught the request
* - the raw response
* - the DOM document
* - URL of the feed
*/
class Result
{
/**
* @var \DateTime
*/
protected $modifiedSince;
/**
* @var \DateTime
*/
protected $date;
/**
* @var \FeedIo\FeedInterface
*/
protected $feed;
/**
* @var \FeedIo\Adapter\ResponseInterface
*/
protected $response;
/**
* @var \DomDocument
*/
protected $document;
/**
* @var string
*/
protected $url;
/**
* @param \DOMDocument $document
* @param FeedInterface $feed
* @param \DateTime $modifiedSince
* @param ResponseInterface $response
* @param $url
*/
public function __construct(
\DOMDocument $document,
FeedInterface $feed,
\DateTime $modifiedSince,
ResponseInterface $response,
$url
) {
$this->date = new \DateTime();
$this->document = $document;
$this->feed = $feed;
$this->modifiedSince = $modifiedSince;
$this->response = $response;
$this->url = $url;
}
/**
* @return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* @return \DomDocument
*/
public function getDocument()
{
return $this->document;
}
/**
* @return FeedInterface
*/
public function getFeed()
{
return $this->feed;
}
/**
* @return \DateTime
*/
public function getModifiedSince()
{
return $this->modifiedSince;
}
/**
* @return ResponseInterface
*/
public function getResponse()
{
return $this->response;
}
/**
* @return string
*/
public function getUrl()
{
return $this->url;
}
}
src/FeedIo/Rule/Atom/Category.php 0000666 00000002652 13052362033 0012571 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule\Atom;
use FeedIo\Feed\Node\CategoryInterface;
use FeedIo\Feed\NodeInterface;
class Category extends \FeedIo\Rule\Category
{
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return mixed
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
$category = $node->newCategory();
$category->setScheme($this->getAttributeValue($element, 'scheme'))
->setLabel($this->getAttributeValue($element, 'label'))
->setTerm($this->getAttributeValue($element, 'term'));
$node->addCategory($category);
return $this;
}
/**
* @param \DomDocument $document
* @param CategoryInterface $category
* @return \DomElement
*/
public function createCategoryElement(\DomDocument $document, CategoryInterface $category)
{
$element = $document->createElement($this->getNodeName());
$element->setAttribute('scheme', $category->getScheme());
$element->setAttribute('term', $category->getTerm());
$element->setAttribute('label', $category->getLabel());
return $element;
}
}
src/FeedIo/Rule/Atom/Link.php 0000666 00000002227 13052362033 0011707 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule\Atom;
use FeedIo\Feed\NodeInterface;
use FeedIo\RuleAbstract;
class Link extends RuleAbstract
{
const NODE_NAME = 'link';
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return mixed
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
if ($element->hasAttribute('href')) {
$node->setLink($element->getAttribute('href'));
}
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
$element = $document->createElement(static::NODE_NAME);
$element->setAttribute('href', $node->getLink());
return $element;
}
}
src/FeedIo/Rule/Atom/LinkNode.php 0000666 00000003214 13052362033 0012512 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule\Atom;
use FeedIo\Feed\NodeInterface;
use FeedIo\RuleAbstract;
use FeedIo\RuleSet;
use FeedIo\Rule\Media;
class LinkNode extends RuleAbstract
{
const NODE_NAME = 'link';
/**
* @var \FeedIo\RuleSet
*/
protected $ruleSet;
/**
* @param string $nodeName
*/
public function __construct($nodeName = null)
{
parent::__construct($nodeName);
$mediaRule = new Media();
$mediaRule->setUrlAttributeName('href');
$this->ruleSet = new RuleSet(new Link('related'));
$this->ruleSet->add($mediaRule);
}
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return mixed
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
if ($element->hasAttribute('rel')) {
$this->ruleSet->get($element->getAttribute('rel'))->setProperty($node, $element);
} else {
$this->ruleSet->getDefault()->setProperty($node, $element);
}
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
return $this->ruleSet->getDefault()->createElement($document, $node);
}
}
src/FeedIo/Rule/Category.php 0000666 00000003646 13052362033 0011675 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\Node\CategoryInterface;
use FeedIo\Feed\NodeInterface;
use FeedIo\RuleAbstract;
class Category extends RuleAbstract
{
const NODE_NAME = 'category';
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return mixed
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
$category = $node->newCategory();
$category->setScheme($this->getAttributeValue($element, 'domain'))
->setLabel($element->nodeValue)
->setTerm($element->nodeValue);
$node->addCategory($category);
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement|null
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
if ( ! is_null($node->getCategories()) ) {
foreach( $node->getCategories() as $category ) {
return $this->createCategoryElement($document, $category);
}
}
return;
}
/**
* @param \DomDocument $document
* @param CategoryInterface $category
* @return \DomElement
*/
public function createCategoryElement(\DomDocument $document, CategoryInterface $category)
{
$element = $document->createElement(
$this->getNodeName(),
is_null($category->getTerm()) ? $category->getLabel():$category->getTerm()
);
$element->setAttribute('domain', $category->getScheme());
return $element;
}
}
src/FeedIo/Rule/DateTimeBuilder.php 0000666 00000005651 13052362033 0013121 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
class DateTimeBuilder
{
/**
* Supported date formats
* @var array
*/
protected $dateFormats = [
\DateTime::RFC2822,
\DateTime::ATOM,
\DateTime::RFC3339,
\DateTime::RSS,
\DateTime::W3C,
'Y-m-d\TH:i:s.uP',
'Y-m-d',
'd/m/Y',
'D, d M Y H:i O',
'D, d M Y H:i:s O',
'D M d Y H:i:s e',
];
/**
* @var \DateTimeZone
*/
protected $timezone;
/**
* @var string
*/
protected $lastGuessedFormat = \DateTime::RFC2822;
public function __construct()
{
$this->setTimezone(new \DateTimeZone(date_default_timezone_get()));
}
/**
* @param $dateFormat
* @return $this
*/
public function addDateFormat($dateFormat)
{
$this->dateFormats[] = $dateFormat;
return $this;
}
/**
* @param array $dateFormats
* @return $this
*/
public function setDateFormats(array $dateFormats)
{
$this->dateFormats = $dateFormats;
return $this;
}
/**
* @return string
*/
public function getLastGuessedFormat()
{
return $this->lastGuessedFormat;
}
/**
*
* @param string $date
* @return string|false date Format
* @throws InvalidArgumentException
*/
public function guessDateFormat($date)
{
foreach ($this->dateFormats as $format) {
$test = \DateTime::createFromFormat($format, $date);
if ($test instanceof \DateTime) {
$this->lastGuessedFormat = $format;
return $format;
}
}
return false;
}
/**
* Creates a DateTime instance for the given string. Default format is RFC2822
* @param string $string
* @return \DateTime
* @throws InvalidArgumentException
*/
public function convertToDateTime($string)
{
$string = trim($string);
foreach ([$this->getLastGuessedFormat(), $this->guessDateFormat($string) ] as $format) {
$date = \DateTime::createFromFormat($format, $string);
if ($date instanceof \DateTime) {
$date->setTimezone($this->getTimezone());
return $date;
}
}
throw new \InvalidArgumentException('Impossible to convert date : '.$string);
}
/**
* @return \DateTimeZone
*/
public function getTimezone()
{
return $this->timezone;
}
/**
* @param \DateTimeZone $timezone
*/
public function setTimezone(\DateTimeZone $timezone)
{
$this->timezone = $timezone;
}
}
src/FeedIo/Rule/Description.php 0000666 00000002423 13052362033 0012373 0 ustar 00 firstChild && $element->firstChild->nodeType == XML_CDATA_SECTION_NODE ) {
$string = $element->firstChild->textContent;
} else {
foreach($element->childNodes as $childNode) {
$string .= $element->ownerDocument->saveXML($childNode);
}
}
$node->setDescription($string);
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DOMDocument $document
* @param NodeInterface $node
* @return \DOMElement
*/
public function createElement(\DOMDocument $document, NodeInterface $node)
{
$description = htmlspecialchars($node->getDescription());
return $document->createElement($this->getNodeName(), $description);
}
}
src/FeedIo/Rule/Link.php 0000666 00000002007 13052362033 0011003 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\NodeInterface;
use FeedIo\RuleAbstract;
class Link extends RuleAbstract
{
const NODE_NAME = 'link';
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return mixed
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
$node->setLink($element->nodeValue);
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
return $document->createElement($this->getNodeName(), $node->getLink());
}
}
src/FeedIo/Rule/Media.php 0000666 00000004635 13052362033 0011136 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\Item;
use FeedIo\Feed\Item\MediaInterface;
use FeedIo\Feed\ItemInterface;
use FeedIo\Feed\NodeInterface;
use FeedIo\RuleAbstract;
class Media extends RuleAbstract
{
const NODE_NAME = 'enclosure';
protected $urlAttributeName = 'url';
/**
* @return string
*/
public function getUrlAttributeName()
{
return $this->urlAttributeName;
}
/**
* @param string $name
* @return $this
*/
public function setUrlAttributeName($name)
{
$this->urlAttributeName = $name;
return $this;
}
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return $this
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
if ($node instanceof ItemInterface) {
$media = $node->newMedia();
$media->setType($this->getAttributeValue($element, 'type'))
->setUrl($this->getAttributeValue($element, $this->getUrlAttributeName()))
->setLength($this->getAttributeValue($element, 'length'));
$node->addMedia($media);
}
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
if ($node instanceof ItemInterface) {
foreach ($node->getMedias() as $media) {
return $this->createMediaElement($document, $media);
}
}
return;
}
/**
* @param \DomDocument $document
* @param MediaInterface $media
* @return \DomElement
*/
public function createMediaElement(\DomDocument $document, MediaInterface $media)
{
$element = $document->createElement($this->getNodeName());
$element->setAttribute($this->getUrlAttributeName(), $media->getUrl());
$element->setAttribute('type', $media->getType());
$element->setAttribute('length', $media->getLength());
return $element;
}
}
src/FeedIo/Rule/ModifiedSince.php 0000666 00000002240 13052362033 0012607 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\NodeInterface;
use FeedIo\DateRuleAbstract;
class ModifiedSince extends DateRuleAbstract
{
const NODE_NAME = 'pubDate';
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return $this
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
$node->setLastModified($this->getDateTimeBuilder()->convertToDateTime($element->nodeValue));
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
return $document->createElement(
$this->getNodeName(),
$node->getLastModified()->format($this->getDefaultFormat())
);
}
}
src/FeedIo/Rule/OptionalField.php 0000666 00000003465 13052362033 0012650 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\NodeInterface;
use FeedIo\Feed\Node\ElementInterface;
use FeedIo\RuleAbstract;
class OptionalField extends RuleAbstract
{
const NODE_NAME = 'default';
/**
* @param NodeInterface $node
* @param \DOMElement $domElement
* @return $this
*/
public function setProperty(NodeInterface $node, \DOMElement $domElement)
{
$element = $node->newElement();
$element->setName($domElement->nodeName);
$element->setValue($domElement->nodeValue);
foreach($domElement->attributes as $attribute) {
$element->setAttribute($attribute->name, $attribute->value);
}
$node->addElement($element);
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
$domElement = $document->createElement($this->getNodeName());
foreach ($node->getElementIterator($this->getNodeName()) as $element) {
$this->buildDomElement($domElement, $element);
}
return $domElement;
}
public function buildDomElement(\DomElement $domElement, ElementInterface $element)
{
$domElement->nodeValue = $element->getValue();
foreach ($element->getAttributes() as $name => $value) {
$domElement->setAttribute($name, $value);
}
return $domElement;
}
}
src/FeedIo/Rule/PublicId.php 0000666 00000001570 13052362033 0011605 0 ustar 00 setPublicId($element->nodeValue);
return $node;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
return $document->createElement($this->getNodeName(), $node->getPublicId());
}
}
src/FeedIo/Rule/Structure.php 0000666 00000003333 13052362033 0012111 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\NodeInterface;
use FeedIo\RuleAbstract;
use FeedIo\RuleSet;
class Structure extends RuleAbstract
{
const NODE_NAME = 'structure';
/**
* @var \FeedIo\RuleSet
*/
protected $ruleSet;
/**
* @param string $nodeName
* @param RuleSet $ruleSet
*/
public function __construct($nodeName = null, $ruleSet = null)
{
parent::__construct($nodeName);
$this->ruleSet = is_null($ruleSet) ? new RuleSet() : $ruleSet;
}
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return mixed
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
foreach ($element->childNodes as $domNode) {
if ($domNode instanceof \DomElement) {
$rule = $this->ruleSet->get($domNode->tagName);
$rule->setProperty($node, $domNode);
}
}
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
$element = $document->createElement($this->getNodeName());
foreach ($this->ruleSet->getRules() as $rule) {
$element->appendChild($rule->createElement($document, $node));
}
return $element;
}
}
src/FeedIo/Rule/Title.php 0000666 00000002064 13052362033 0011172 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\NodeInterface;
use FeedIo\RuleAbstract;
class Title extends RuleAbstract
{
const NODE_NAME = 'title';
/**
* @param NodeInterface $node
* @param \DOMElement $element
* @return $this
*/
public function setProperty(NodeInterface $node, \DOMElement $element)
{
$node->setTitle($element->nodeValue);
return $this;
}
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
public function createElement(\DomDocument $document, NodeInterface $node)
{
$title = htmlspecialchars($node->getTitle());
return $document->createElement(static::NODE_NAME, $title);
}
}
src/FeedIo/RuleAbstract.php 0000666 00000003107 13052362033 0011574 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Feed\NodeInterface;
abstract class RuleAbstract
{
const NODE_NAME = 'node';
/**
* @var string
*/
protected $nodeName;
/**
* @param string $nodeName
*/
public function __construct($nodeName = null)
{
$this->nodeName = is_null($nodeName) ? static::NODE_NAME : $nodeName;
}
/**
* @return string
*/
public function getNodeName()
{
return $this->nodeName;
}
/**
* @param \DOMElement $element
* @param string $name
* @return string|null
*/
public function getAttributeValue(\DOMElement $element, $name)
{
if ($element->hasAttribute($name)) {
return $element->getAttribute($name);
}
return;
}
/**
* Sets the accurate $item property according to the DomElement content
*
* @param NodeInterface $node
* @param \DOMElement $element
* @return mixed
*/
abstract public function setProperty(NodeInterface $node, \DOMElement $element);
/**
* creates the accurate DomElement content according to the $item's property
*
* @param \DomDocument $document
* @param NodeInterface $node
* @return \DomElement
*/
abstract public function createElement(\DomDocument $document, NodeInterface $node);
}
src/FeedIo/RuleSet.php 0000666 00000004271 13052362033 0010567 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Rule\OptionalField;
class RuleSet
{
/**
* @var \ArrayIterator
*/
protected $rules;
/**
* @var array
*/
protected $aliases = array();
/**
* @var RuleAbstract
*/
protected $default;
/**
* @param RuleAbstract $default default rule
*/
public function __construct(RuleAbstract $default = null)
{
$this->rules = new \ArrayIterator(array());
$this->default = is_null($default) ? new OptionalField() : $default;
}
/**
* @return RuleAbstract
*/
public function getDefault()
{
return $this->default;
}
/**
* @return array
*/
public function getRules()
{
return $this->rules->getArrayCopy();
}
/**
* @param RuleAbstract $rule
* @return $this
*/
public function add(RuleAbstract $rule, array $aliases = array())
{
$this->rules->offsetSet(strtolower($rule->getNodeName()), $rule);
$this->addAliases($rule->getNodeName(), $aliases);
return $this;
}
/**
* @param string $name
* @param array $aliases
* @return $this
*/
public function addAliases($name, array $aliases)
{
foreach ($aliases as $alias) {
$this->aliases[strtolower($alias)] = strtolower($name);
}
return $this;
}
/**
* @param string $name
* @return RuleAbstract
* @throws NotFoundException
*/
public function get($name)
{
$name = $this->getNameForAlias(strtolower($name));
if ($this->rules->offsetExists($name)) {
return $this->rules->offsetGet($name);
}
return $this->default;
}
/**
* @param string $alias
*/
public function getNameForAlias($alias)
{
if (array_key_exists($alias, $this->aliases)) {
return $this->aliases[$alias];
}
return $alias;
}
}
src/FeedIo/Standard/Atom.php 0000666 00000004514 13052362033 0011644 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Standard;
use DOMDocument;
use FeedIo\Rule\Atom\LinkNode;
use FeedIo\Rule\Description;
use FeedIo\Rule\PublicId;
use FeedIo\Rule\Atom\Category;
use FeedIo\StandardAbstract;
class Atom extends StandardAbstract
{
/**
* Atom document must have a root node
*/
const ROOT_NODE_TAGNAME = 'feed';
const ITEM_NODE = 'entry';
/**
* Formats the document according to the standard's specification
* @param \DOMDocument $document
* @return \DOMDocument
*/
public function format(\DOMDocument $document)
{
$element = $document->createElement('feed');
$element->setAttribute('xmlns', 'http://www.w3.org/2005/Atom');
$document->appendChild($element);
return $document;
}
/**
* Tells if the parser can handle the feed or not
* @param \DOMDocument $document
* @return mixed
*/
public function canHandle(\DOMDocument $document)
{
return self::ROOT_NODE_TAGNAME === $document->documentElement->tagName;
}
/**
* @param DOMDocument $document
* @return \DomElement
*/
public function getMainElement(\DOMDocument $document)
{
return $document->documentElement;
}
/**
* Builds and returns a rule set to parse the root node
* @return \FeedIo\RuleSet
*/
public function buildFeedRuleSet()
{
$ruleSet = $this->buildBaseRuleSet();
$ruleSet
->add(new LinkNode())
->add(new PublicId('id'))
->add($this->getModifiedSinceRule('updated'))
;
return $ruleSet;
}
/**
* Builds and returns a rule set to parse an item
* @return \FeedIo\RuleSet
*/
public function buildItemRuleSet()
{
$ruleSet = $this->buildFeedRuleSet();
$ruleSet->add(new Description('content'), ['summary']);
return $ruleSet;
}
/**
* @return RuleSet
*/
protected function buildBaseRuleSet()
{
$ruleSet = parent::buildBaseRuleSet();
$ruleSet->add(new Category());
return $ruleSet;
}
}
src/FeedIo/Standard/Rdf.php 0000666 00000002501 13052362033 0011451 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Standard;
use DOMDocument;
use FeedIo\RuleSet;
use FeedIo\Rule\Structure;
class Rdf extends Rss
{
/**
* Format version
*/
const VERSION = '1.0';
/**
* RDF document must have a root node
*/
const ROOT_NODE_TAGNAME = 'rdf';
/**
* publication date
*/
const DATE_NODE_TAGNAME = 'dc:date';
/**
* Tells if the parser can handle the feed or not
* @param \DOMDocument $document
* @return boolean
*/
public function canHandle(\DOMDocument $document)
{
return false !== strpos($document->documentElement->tagName, static::ROOT_NODE_TAGNAME);
}
/**
* @param DOMDocument $document
* @return \DomElement
*/
public function getMainElement(\DOMDocument $document)
{
return $document->documentElement;
}
/**
* @return RuleSet
*/
public function buildFeedRuleSet()
{
$ruleSet = new RuleSet();
$ruleSet->add(new Structure(static::CHANNEL_NODE_TAGNAME, $this->buildItemRuleSet()));
return $ruleSet;
}
}
src/FeedIo/Standard/Rss.php 0000666 00000005366 13052362033 0011521 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Standard;
use DOMDocument;
use FeedIo\Rule\Description;
use FeedIo\Rule\Link;
use FeedIo\Rule\PublicId;
use FeedIo\Rule\Media;
use FeedIo\Rule\Category;
use FeedIo\StandardAbstract;
class Rss extends StandardAbstract
{
/**
* Format version
*/
const VERSION = '2.0';
/**
* RSS document must have a root node
*/
const ROOT_NODE_TAGNAME = 'rss';
/**
* node contains feed's metadata
*/
const CHANNEL_NODE_TAGNAME = 'channel';
/**
* publication date
*/
const DATE_NODE_TAGNAME = 'pubDate';
/**
* Formats the document according to the standard's specification
* @param \DOMDocument $document
* @return mixed
*/
public function format(\DOMDocument $document)
{
$rss = $document->createElement(static::ROOT_NODE_TAGNAME);
$rss->setAttribute('version', static::VERSION);
$channel = $document->createElement(static::CHANNEL_NODE_TAGNAME);
$rss->appendChild($channel);
$document->appendChild($rss);
return $document;
}
/**
* Tells if the parser can handle the feed or not
* @param \DOMDocument $document
* @return boolean
*/
public function canHandle(\DOMDocument $document)
{
return static::ROOT_NODE_TAGNAME === $document->documentElement->tagName;
}
/**
* @param DOMDocument $document
* @return \DomElement
*/
public function getMainElement(\DOMDocument $document)
{
return $document->documentElement->getElementsByTagName(static::CHANNEL_NODE_TAGNAME)->item(0);
}
/**
* @return RuleSet
*/
public function buildFeedRuleSet()
{
$ruleSet = $this->buildItemRuleSet();
$ruleSet->add(
$this->getModifiedSinceRule('lastPubDate'),
array('lastBuildDate')
);
return $ruleSet;
}
/**
* @return RuleSet
*/
public function buildItemRuleSet()
{
$ruleSet = $this->buildBaseRuleSet();
$ruleSet
->add(new Link())
->add(new PublicId())
->add(new Description())
->add(new Media())
->add($this->getModifiedSinceRule(static::DATE_NODE_TAGNAME));
return $ruleSet;
}
/**
* @return RuleSet
*/
protected function buildBaseRuleSet()
{
$ruleSet = parent::buildBaseRuleSet();
$ruleSet->add(new Category());
return $ruleSet;
}
}
src/FeedIo/StandardAbstract.php 0000666 00000006407 13052362033 0012433 0 ustar 00 dateTimeBuilder = $dateTimeBuilder;
}
/**
* Formats the document according to the standard's specification
* @param \DOMDocument $document
* @return mixed
*/
abstract public function format(\DOMDocument $document);
/**
* Tells if the parser can handle the feed or not
* @param \DOMDocument $document
* @return mixed
*/
abstract public function canHandle(\DOMDocument $document);
/**
* @param \DOMDocument $document
* @return \DomElement
*/
abstract public function getMainElement(\DOMDocument $document);
/**
* Builds and returns a rule set to parse the root node
* @return \FeedIo\RuleSet
*/
abstract public function buildFeedRuleSet();
/**
* Builds and returns a rule set to parse an item
* @return \FeedIo\RuleSet
*/
abstract public function buildItemRuleSet();
/**
* @return string
*/
public function getItemNodeName()
{
return static::ITEM_NODE;
}
/**
* @return string
*/
public function getDefaultDateFormat()
{
return static::DATETIME_FORMAT;
}
/**
* @return array
*/
public function getMandatoryFields()
{
return $this->mandatoryFields;
}
/**
* Returns the RuleSet used to parse the feed's main node
* @return \FeedIo\RuleSet
*/
public function getFeedRuleSet()
{
if (is_null($this->feedRuleSet)) {
$this->feedRuleSet = $this->buildFeedRuleSet();
}
return $this->feedRuleSet;
}
/**
* @return \FeedIo\RuleSet
*/
public function getItemRuleSet()
{
if (is_null($this->itemRuleSet)) {
$this->itemRuleSet = $this->buildItemRuleSet();
}
return $this->itemRuleSet;
}
/**
* @param string $tagName
* @return ModifiedSince
*/
public function getModifiedSinceRule($tagName)
{
$rule = new ModifiedSince($tagName);
$rule->setDefaultFormat($this->getDefaultDateFormat());
$rule->setDateTimeBuilder($this->dateTimeBuilder);
return $rule;
}
/**
* @return RuleSet
*/
protected function buildBaseRuleSet()
{
$ruleSet = $ruleSet = new RuleSet();
$ruleSet->add(new Title());
return $ruleSet;
}
}
tests/FeedIo/Adapter/FileSystem/ClientTest.php 0000666 00000002454 13052362033 0015302 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter\FileSystem;
class ClientTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Adapter\FileSystem\Client
*/
protected $object;
protected function setUp()
{
$this->object = new Client();
}
public function testGetResponse()
{
$response = $this->object->getResponse(
__DIR__.'/../../../samples/sample-atom.xml',
new \DateTime()
);
$this->assertInstanceOf('\FeedIo\Adapter\ResponseInterface', $response);
$this->assertEquals(file_get_contents(__DIR__.'/../../../samples/sample-atom.xml'), $response->getBody());
$this->assertEquals(array(), $response->getHeaders());
$this->assertEquals('', $response->getHeader('name'));
$this->assertInstanceOf('\DateTime', $response->getLastModified());
}
/**
* @expectedException \FeedIo\Adapter\NotFoundException
*/
public function testGetNotFound()
{
$client = new Client();
$client->getResponse('/opt/nowhere.xml', new \DateTime());
}
}
tests/FeedIo/Adapter/Guzzle/ClientTest.php 0000666 00000005642 13052362033 0014500 0 ustar 00 a great stream
XML;
/**
* @var \FeedIo\Adapter\Guzzle\Client
*/
protected $object;
protected function setUp()
{
$this->object = new Client($this->getGuzzleClient());
}
public function testGetResponse()
{
$response = $this->object->getResponse('http://somewhere', new \DateTime());
$this->assertInstanceOf('\FeedIo\Adapter\ResponseInterface', $response);
$this->assertEquals($this->body, $response->getBody());
$this->assertEquals(array(), $response->getHeaders());
$this->assertEquals('Tue, 15 Nov 1994 12:45:26 GMT', $response->getHeader('name'));
$this->assertInstanceOf('\DateTime', $response->getLastModified());
$this->assertEquals(1994, $response->getLastModified()->format('Y'));
}
/**
* @expectedException \FeedIo\Adapter\NotFoundException
*/
public function testGetNotFound()
{
$client = new Client($this->getErroredClient(404));
$client->getResponse('http://test', new \DateTime());
}
/**
* @expectedException \FeedIo\Adapter\ServerErrorException
*/
public function testGetServerError()
{
$client = new Client($this->getErroredClient(500));
$client->getResponse('http://test', new \DateTime());
}
/**
* @param $statusCode
* @return \GuzzleHttp\ClientInterface
*/
protected function getErroredClient($statusCode)
{
$exception = new BadResponseException(
'message',
new \GuzzleHttp\Psr7\Request('get', 'http://test'),
new \GuzzleHttp\Psr7\Response("{$statusCode}")
);
$guzzleClient = $this->getMockForAbstractClass('\GuzzleHttp\ClientInterface');
$guzzleClient->expects($this->any())->method('request')->will($this->throwException($exception));
return $guzzleClient;
}
/**
* @return \GuzzleHttp\ClientInterface
*/
protected function getGuzzleClient()
{
$response = $this->getMockForAbstractClass('\Psr\Http\Message\ResponseInterface');
$response->expects($this->any())->method('getBody')->will($this->returnValue($this->body));
$response->expects($this->any())->method('getHeader')->will($this->returnValue('Tue, 15 Nov 1994 12:45:26 GMT'));
$response->expects($this->any())->method('getHeaders')->will($this->returnValue(array()));
$response->expects($this->any())->method('hasHeader')->will($this->returnValue(true));
$client = $this->createMock('\GuzzleHttp\Client');
$client->expects($this->any())->method('request')->will($this->returnValue($response));
return $client;
}
}
tests/FeedIo/Adapter/NullClientTest.php 0000666 00000001456 13052362033 0014052 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Adapter;
class NullClientTest extends \PHPUnit_Framework_TestCase
{
public function testGetResponse()
{
$client = new NullClient();
$response = $client->getResponse('', new \DateTime());
$this->assertInstanceOf('\FeedIo\Adapter\NullResponse', $response);
$this->assertInstanceOf('\DateTime', $response->getLastModified());
$this->assertNull($response->getBody());
$this->assertInternalType('array', $response->getHeaders());
$this->assertEquals('foo', $response->getHeader('foo'));
}
}
tests/FeedIo/DateRuleAbstractTest.php 0000666 00000002250 13052362033 0013603 0 ustar 00 object = $this->getDateRule();
}
public function testSetDateTimeBuilder()
{
$this->assertInstanceOf(
'\FeedIo\DateRuleAbstract',
$this->object->setDateTimeBuilder(new DateTimeBuilder())
);
}
public function testGetDateTimeBuilder()
{
$dateTimeBuilder = new DateTimeBuilder();
$this->object->setDateTimeBuilder($dateTimeBuilder);
$this->assertEquals($dateTimeBuilder, $this->object->getDateTimeBuilder());
}
/**
* @expectedException \UnexpectedValueException
*/
public function testGetDateTimeBuilderFailure()
{
$this->object->getDateTimeBuilder();
}
/**
* @return \FeedIo\DateRuleAbstract
*/
protected function getDateRule()
{
return $this->getMockForAbstractClass('\FeedIo\DateRuleAbstract');
}
}
tests/FeedIo/Factory/Builder/GuzzleClientBuilderTest.php 0000666 00000001323 13052362033 0017335 0 ustar 00 assertEquals('\GuzzleHttp\Client', $builder->getMainClassName());
}
public function testGetPackageName()
{
$builder = new GuzzleClientBuilder();
$this->assertEquals('guzzlehttp/guzzle', $builder->getPackageName());
}
public function testGetClient()
{
$builder = new GuzzleClientBuilder();
$this->assertInstanceOf('\FeedIo\Adapter\ClientInterface', $builder->getClient());
}
}
tests/FeedIo/Factory/Builder/MonologBuilderTest.php 0000666 00000002656 13052362033 0016342 0 ustar 00 assertEquals('Monolog\Logger', $builder->getMainClassName());
}
public function testGetPackageName()
{
$builder = new MonologBuilder();
$this->assertEquals('monolog/monolog', $builder->getPackageName());
}
public function testNewHandler()
{
$builder = new MonologBuilder();
$handler = $builder->newHandler('Monolog\Handler\StreamHandler', ['php://stdout', Logger::DEBUG]);
$this->assertInstanceOf('Monolog\Handler\StreamHandler', $handler);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testNewInvalidHandler()
{
$builder = new MonologBuilder();
$handler = $builder->newHandler('stdClass', []);
}
public function testGetLogger()
{
$builder = new MonologBuilder();
$logger = $builder->getLogger();
$this->assertInstanceOf('Monolog\Logger', $logger);
$handlers = $logger->getHandlers();
$this->assertCount(1, $handlers);
foreach ( $handlers as $handler) {
$this->assertInstanceOf('Monolog\Handler\StreamHandler', $handler);
}
}
}
tests/FeedIo/Factory/Builder/NullLoggerBuilderTest.php 0000666 00000001232 13052362033 0016767 0 ustar 00 assertEquals('\Psr\Log\NullLogger', $builder->getMainClassName());
}
public function testGetPackageName()
{
$builder = new NullLoggerBuilder();
$this->assertEquals('psr/log', $builder->getPackageName());
}
public function testGetLogger()
{
$builder = new NullLoggerBuilder();
$logger = $builder->getLogger();
$this->assertInstanceOf('\Psr\Log\NullLogger', $logger);
}
}
tests/FeedIo/FactoryTest.php 0000666 00000007660 13052362033 0012033 0 ustar 00 assertTrue($factory->checkDependency(
$this->getBuilder('stdClass', 'php/php')
));
}
/**
* @expectedException FeedIo\Factory\MissingDependencyException
*/
public function testCheckMissingDependency()
{
$factory = new Factory();
$factory->checkDependency(
$this->getBuilder('IDontExist', 'php/php')
);
}
public function testSetLoggerBuilder()
{
$factory = new Factory();
$loggerBuilder = $this->getMockForAbstractClass('\FeedIo\Factory\LoggerBuilderInterface');
$factory->setLoggerBuilder($loggerBuilder);
$this->assertAttributeInstanceOf('\FeedIo\Factory\LoggerBuilderInterface', 'loggerBuilder', $factory);
}
public function testSetClientBuilder()
{
$factory = new Factory();
$clientBuilder = $this->getMockForAbstractClass('\FeedIo\Factory\ClientBuilderInterface');
$factory->setClientBuilder($clientBuilder);
$this->assertAttributeInstanceOf('\FeedIo\Factory\ClientBuilderInterface', 'clientBuilder', $factory);
}
public function testExtractConfig()
{
$config = ['foo' => 'bar'];
$builderConfig = ['config' => $config];
$factory = new Factory();
$this->assertEquals($config, $factory->extractConfig($builderConfig));
}
public function testExtractEmptyConfig()
{
$builderConfig = [];
$factory = new Factory();
$this->assertEquals([], $factory->extractConfig($builderConfig));
}
public function testCreate()
{
$factory = Factory::create();
$this->assertInstanceOf('\FeedIo\Factory', $factory);
}
public function testGetBuilder()
{
$factory = new Factory();
$this->assertInstanceOf('\FeedIo\Factory\Builder\\MonologBuilder', $factory->getBuilder('monolog'));
}
public function testGetExternalBuilder()
{
$factory = new Factory();
$this->assertInstanceOf('stdClass', $factory->getBuilder('stdClass'));
}
public function testCreateWithMonolog()
{
$factory = Factory::create(['builder' => 'monolog']);
$this->assertAttributeInstanceOf('\FeedIo\Factory\Builder\\MonologBuilder', 'loggerBuilder', $factory);
}
public function testGetFeedIoAfterCreate()
{
$factory = Factory::create();
$feedIo = $factory->getFeedIo();
$this->assertInstanceOf('\FeedIo\FeedIo', $feedIo);
}
public function testGetFeedIo()
{
$factory = new Factory();
$clientBuilder = $this->getMockForAbstractClass('\FeedIo\Factory\ClientBuilderInterface');
$clientBuilder
->expects($this->once())
->method('getClient')
->will($this->returnValue(new \FeedIo\Adapter\Guzzle\Client(new \GuzzleHttp\Client())));
$factory->setClientBuilder($clientBuilder);
$loggerBuilder = $this->getMockForAbstractClass('\FeedIo\Factory\LoggerBuilderInterface');
$loggerBuilder
->expects($this->once())
->method('getLogger')
->will($this->returnValue(new \Psr\Log\NullLogger));
$factory->setLoggerBuilder($loggerBuilder);
$this->assertInstanceOf('FeedIo\FeedIo', $factory->getFeedIo());
}
protected function getBuilder($className, $package)
{
$builder = $this->getMockForAbstractClass('\FeedIo\Factory\BuilderInterface');
$builder->expects($this->any())->method('getMainClassName')->will($this->returnValue($className));
$builder->expects($this->any())->method('getPackageName')->will($this->returnValue($package));
return $builder;
}
}
tests/FeedIo/Feed/Item/MediaTest.php 0000666 00000001551 13052362033 0013175 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Item;
class MediaTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Feed\Item\Media
*/
protected $object;
protected function setUp()
{
$this->object = new Media();
}
public function testSetType()
{
$this->object->setType('image/jpeg');
$this->assertEquals('image/jpeg', $this->object->getType());
}
public function testSetLength()
{
$this->object->setLength('87669');
$this->assertInternalType('integer', $this->object->getLength());
$this->assertEquals(87669, $this->object->getLength());
}
}
tests/FeedIo/Feed/ItemTest.php 0000666 00000010265 13052362033 0012160 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed;
use FeedIo\Feed\Node\Element;
use FeedIo\Feed\Item\Media;
class ItemTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Feed\Item
*/
protected $object;
protected function setUp()
{
$this->object = new Item();
}
public function testGetElementIterator()
{
$element = new Element();
$element->setName('foo');
$this->object->addElement($element);
$element2 = new Element();
$element2->setName('bar');
$this->object->addElement($element2);
$iterator = $this->object->getElementIterator('foo');
$this->assertInstanceOf('\FeedIo\Feed\Node\ElementIterator', $iterator);
$this->assertTrue($iterator->count() > 0);
$count = 0;
foreach ($iterator as $element) {
$count++;
$this->assertEquals('foo', $element->getName());
}
$this->assertEquals(1, $count);
}
public function testNewElement()
{
$this->assertInstanceOf('\FeedIo\Feed\Node\ElementInterface', $this->object->newElement());
}
public function testSet()
{
$this->object->set('foo', 'bar');
$this->assertEquals('bar', $this->object->getValue('foo'));
}
public function testGetValue()
{
$this->assertNull($this->object->getValue('null'));
$this->object->set('name', 'value');
$this->assertEquals('value', $this->object->getValue('name'));
}
public function testSetValue()
{
$this->object->set('foo', 'bar');
$element = new Element();
$element->setName('foo');
$element->setValue('bar');
$this->assertAttributeContainsOnly($element, 'elements', $this->object);
}
public function testHasElement()
{
$this->assertFalse($this->object->hasElement('foo'));
$this->object->set('name', 'value');
$this->assertFalse($this->object->hasElement('foo'));
$this->assertTrue($this->object->hasElement('name'));
}
public function testGetAllElements()
{
$element = new Element();
$element->setName('foo');
$this->object->addElement($element);
$element2 = new Element();
$element2->setName('bar');
$this->object->addElement($element2);
$iterator = $this->object->getAllElements();
$this->assertInstanceOf('\ArrayIterator', $iterator);
$this->assertEquals(2, $iterator->count());
}
public function testListElements()
{
$element = new Element();
$element->setName('foo');
$this->object->addElement($element);
$element2 = new Element();
$element2->setName('bar');
$this->object->addElement($element2);
$elements = array();
foreach($this->object->listElements() as $element) {
$elements[] = $element;
}
$this->assertEquals(array('foo', 'bar'), $elements);
}
public function testNewMedia()
{
$this->assertInstanceOf('\FeedIo\Feed\Item\MediaInterface', $this->object->newMedia());
}
public function testAddMedia()
{
$media = new Media();
$media->setType('audio/mp3');
$this->assertInstanceOf('FeedIo\Feed\Item', $this->object->addMedia($media));
$this->assertAttributeContains($media, 'medias', $this->object);
}
public function testHasMedia()
{
$this->assertFalse($this->object->hasMedia());
$this->object->addMedia(new Media());
$this->assertTrue($this->object->hasMedia());
}
public function testGetMedias()
{
$this->object->addMedia(new Media());
$iterator = $this->object->getMedias();
$this->assertInstanceOf('\ArrayIterator', $iterator);
$count = 0;
foreach ($iterator as $media) {
$count++;
$this->assertInstanceOf('FeedIo\Feed\Item\MediaInterface', $media);
}
$this->assertEquals(1, $count);
}
}
tests/FeedIo/Feed/Node/CategoryTest.php 0000666 00000002063 13052362033 0013721 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
class CategoryTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Feed\Item\Category
*/
protected $object;
protected function setUp()
{
$this->object = new Category;
}
public function testScheme()
{
$scheme = 'http://...';
$this->object->setScheme($scheme);
$this->assertEquals($scheme, $this->object->getScheme());
}
public function testLabel()
{
$label = 'a nice label';
$this->object->setLabel($label);
$this->assertEquals($label, $this->object->getLabel());
}
public function testTerm()
{
$term = 'nice';
$this->object->setTerm($term);
$this->assertEquals($term, $this->object->getTerm());
}
}
tests/FeedIo/Feed/Node/ElementIteratorTest.php 0000666 00000002207 13052362033 0015247 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
class ElementIteratorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Feed\Item\ElementIterator
*/
protected $object;
protected function setUp()
{
$array = new \ArrayIterator();
$element1 = new Element();
$element1->setName('foo');
$element2 = new Element();
$element2->setName('bar');
$array->append($element1);
$array->append($element2);
$this->object = new ElementIterator($array, 'foo');
}
public function testValid()
{
foreach ($this->object as $element) {
$this->assertEquals('foo', $element->getName());
}
}
public function testCount()
{
$this->assertEquals(1, $this->object->count());
$filter = new ElementIterator(new \ArrayIterator(), 'foo');
$this->assertEquals(0, $filter->count());
}
}
tests/FeedIo/Feed/Node/ElementTest.php 0000666 00000002334 13052362033 0013536 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed\Node;
class ElementTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Feed\Item\Element
*/
protected $object;
public function testSetName()
{
$element = new Element();
$element->setName('foo');
$this->assertEquals('foo', $element->getName());
}
public function testSetValue()
{
$element = new Element();
$text = 'lorem ipsum';
$element->setValue($text);
$this->assertEquals($text, $element->getValue());
}
public function testAttributes()
{
$element = new Element();
$element->setAttribute('url', 'http://foo.com');
$this->assertEquals('http://foo.com', $element->getAttribute('url'));
$this->assertEquals(array('url' => 'http://foo.com'), $element->getAttributes());
}
public function testGetNullAttribute()
{
$element = new Element();
$this->assertNull($element->getAttribute('null'));
}
}
tests/FeedIo/Feed/NodeTest.php 0000666 00000007200 13052362033 0012142 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Feed;
use FeedIo\Feed\Node\Category;
class NodeTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Feed\Node
*/
protected $object;
protected function setUp()
{
$this->object = new Node();
}
public function testTitle()
{
$title = 'my brilliant title';
$this->assertInstanceOf('\FeedIo\Feed\Node', $this->object->setTitle($title));
$this->assertEquals($title, $this->object->getTitle());
}
public function testPublicId()
{
$publicId = 'a12';
$this->assertInstanceOf('\FeedIo\Feed\Node', $this->object->setPublicId($publicId));
$this->assertEquals($publicId, $this->object->getPublicId());
}
public function testDescription()
{
$description = 'lorem ipsum';
$this->assertInstanceOf('\FeedIo\Feed\Node', $this->object->setDescription($description));
$this->assertEquals($description, $this->object->getDescription());
}
public function testLink()
{
$link = 'http://localhost';
$this->assertInstanceOf('\FeedIo\Feed\Node', $this->object->setLink($link));
$this->assertEquals($link, $this->object->getLink());
}
public function testLastModified()
{
$lastModified = new \DateTime();
$this->assertInstanceOf('\FeedIo\Feed\Node', $this->object->setLastModified($lastModified));
$this->assertEquals($lastModified, $this->object->getLastModified());
}
public function testNewCategory()
{
$this->assertInstanceOf('\FeedIo\Feed\Node\CategoryInterface', $this->object->newCategory());
}
public function testGetCategoryAsGenerator()
{
$category = new Category();
$category->setLabel('test');
$this->object->addCategory($category);
$categories = $this->object->getCategoriesGenerator();
$this->assertEquals('test', $categories->current());
}
public function testGetElementsAsGenerator()
{
$this->object->set('foo', 'bar');
$elements = $this->object->getElementsGenerator();
$this->assertEquals('foo', $elements->key());
$this->assertEquals('bar', $elements->current());
}
public function testToArray()
{
$category = new Category();
$category->setLabel('test');
$this->object->set('foo', 'bar')
->setLastModified(new \DateTime())
->setTitle('my title')
->addCategory($category)
->setDescription('lorem ipsum');
$out = $this->object->toArray();
$this->assertEquals('lorem ipsum', $out['description']);
$this->assertEquals('my title', $out['title']);
$this->assertEquals('bar', $out['elements']['foo']);
$this->assertEquals('test', $out['categories'][0]);
$this->assertInternalType('string', $out['lastModified']);
}
public function testAddCategory()
{
$category = new \FeedIo\Feed\Node\Category;
$category->setTerm('term');
$this->object->addCategory($category);
$categories = $this->object->getCategories();
$count = 0;
foreach( $categories as $testedCategory ) {
$count++;
$this->assertEquals('term', $testedCategory->getTerm());
$this->assertEquals($category, $testedCategory);
}
$this->assertEquals(1, $count);
}
}
tests/FeedIo/FeedIoTest.php 0000666 00000013155 13052362033 0011553 0 ustar 00 getMockForAbstractClass('\FeedIo\Adapter\ClientInterface');
$response = $this->createMock('FeedIo\Adapter\ResponseInterface');
$response->expects($this->any())->method('getBody')->will($this->returnValue(
file_get_contents(dirname(__FILE__)."/../samples/expected-atom.xml")
));
$response->expects($this->any())->method('getLastModified')->will($this->returnValue(new \DateTime()));
$client->expects($this->any())->method('getResponse')->will($this->returnValue($response));
$this->object = new FeedIo($client, new \Psr\Log\NullLogger());
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
protected function tearDown()
{
}
/**
* @covers FeedIo\FeedIo::__construct
* @covers FeedIo\FeedIo::loadCommonStandards
*/
public function testConstruct()
{
$client = $this->getMockForAbstractClass('\FeedIo\Adapter\ClientInterface');
$feedIo = new FeedIo($client, new \Psr\Log\NullLogger());
$this->assertInstanceOf('\FeedIo\Reader', $feedIo->getReader());
}
/**
* @covers FeedIo\FeedIo::getCommonStandards
*/
public function testGetCommonStandards()
{
$standards = $this->object->getCommonStandards();
$this->assertInternalType('array', $standards);
foreach ($standards as $standard) {
$this->assertInstanceOf('\FeedIo\StandardAbstract', $standard);
}
}
public function testFixerSet()
{
$this->assertInstanceOf('\FeedIo\Reader\FixerSet', $this->object->getFixerSet());
}
public function testGetBaseFixers()
{
$fixers = $this->object->getBaseFixers();
foreach ($fixers as $fixer) {
$this->assertInstanceOf('\FeedIo\Reader\FixerAbstract', $fixer);
}
}
public function testAddFilter()
{
$filter = $this->getMockForAbstractClass('FeedIo\FilterInterface');
$this->object->addFilter($filter);
}
/**
* @covers FeedIo\FeedIo::addStandard
*/
public function testAddStandard()
{
$this->object->addStandard('atom2', new Atom(new DateTimeBuilder()));
$this->assertInstanceOf('\FeedIo\Standard\Atom', $this->object->getStandard('atom2'));
}
/**
* @covers FeedIo\FeedIo::getDateTimeBuilder
*/
public function testGetDateTimeBuilder()
{
$this->assertInstanceOf('\FeedIo\Rule\DateTimeBuilder', $this->object->getDateTimeBuilder());
}
/**
* @covers FeedIo\FeedIo::getReader
*/
public function testGetReader()
{
$this->assertInstanceOf('\FeedIo\Reader', $this->object->getReader());
}
/**
* @covers FeedIo\FeedIo::setReader
*/
public function testSetReader()
{
$logger = new \Psr\Log\NullLogger();
$reader = new Reader(
new Adapter\Guzzle\Client(
new \GuzzleHttp\Client(),
$logger
),
$logger
);
$this->object->setReader($reader);
$this->assertEquals($reader, $this->object->getReader());
}
/**
* @covers FeedIo\FeedIo::read
*/
public function testRead()
{
$result = $this->object->read('http://whatever.com');
$this->assertInstanceOf('\FeedIo\Reader\Result', $result);
$this->assertEquals('sample title', $result->getFeed()->getTitle());
}
/**
* @covers FeedIo\FeedIo::readSince
*/
public function testReadSince()
{
$result = $this->object->readSince('http://whatever.com', new \DateTime());
$this->assertInstanceOf('\FeedIo\Reader\Result', $result);
$this->assertEquals('sample title', $result->getFeed()->getTitle());
}
/**
* @covers FeedIo\FeedIo::format
* @covers FeedIo\FeedIo::logAction
*/
public function testFormat()
{
$feed = new Feed();
$feed->setLastModified(new \DateTime());
$document = $this->object->format($feed, 'atom');
$this->assertInstanceOf('DomDocument', $document);
}
/**
* @covers FeedIo\FeedIo::toRss
*/
public function testToRss()
{
$feed = new Feed();
$feed->setLastModified(new \DateTime());
$document = $this->object->toRss($feed);
$this->assertInstanceOf('DomDocument', $document);
$this->assertEquals('rss', $document->documentElement->tagName);
}
/**
* @covers FeedIo\FeedIo::toAtom
*/
public function testToAtom()
{
$feed = new Feed();
$feed->setLastModified(new \DateTime());
$document = $this->object->toAtom($feed);
$this->assertInstanceOf('DomDocument', $document);
$this->assertEquals('feed', $document->documentElement->tagName);
}
/**
* @covers FeedIo\FeedIo::getStandard
*/
public function testGetStandard()
{
$this->assertInstanceOf('\FeedIo\Standard\Atom', $this->object->getStandard('atom'));
}
/**
* @expectedException \OutOfBoundsException
*/
public function testWrongStandard()
{
$this->object->getStandard('fake');
}
}
tests/FeedIo/FeedTest.php 0000666 00000006114 13052362033 0011260 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
class FeedTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Feed
*/
protected $object;
/**
*
*/
public function setUp()
{
$this->object = new Feed();
}
/**
* @covers FeedIo\Feed::__construct
*/
public function testConstruct()
{
$this->assertAttributeEquals(new \ArrayIterator(), 'items', $this->object);
}
public function testNext()
{
$item1 = new Feed\Item();
$item2 = clone $item1;
$item2->setTitle('item2');
$this->object->add($item1);
$this->object->add($item2);
$this->object->rewind();
$this->assertEquals($item1, $this->object->current());
$this->assertNull($this->object->next());
$this->assertEquals($item2, $this->object->current());
}
public function testIsValid()
{
$item = new Feed\Item();
$this->object->add($item);
$this->object->rewind();
$this->assertTrue($this->object->valid());
$this->object->next();
$this->assertFalse($this->object->valid());
}
public function testRewind()
{
$item = new Feed\Item();
$this->object->add($item);
$this->object->next();
$this->assertFalse($this->object->valid());
$this->object->rewind();
$this->assertEquals($item, $this->object->current());
}
public function testKey()
{
$this->assertNull($this->object->key());
$this->object->add(new Feed\Item());
$this->object->add(new Feed\Item());
$this->assertEquals(0, $this->object->key());
$this->object->next();
$this->assertEquals(1, $this->object->key());
}
public function testAdd()
{
$item = new Feed\Item();
$this->object->add($item);
$this->assertAttributeEquals(new \ArrayIterator(array($item)), 'items', $this->object);
$this->assertEquals($this->object->current(), $item);
}
public function testUrl()
{
$url = 'http://localhost';
$feed = new Feed;
$feed->setUrl($url);
$this->assertEquals($url, $feed->getUrl());
}
public function testToArray()
{
$item = new Feed\Item();
$item->setTitle('foo-bar');
$this->object->add($item);
$out = $this->object->toArray();
$this->assertEquals('foo-bar', $out['items'][0]['title']);
}
public function testJsonSerialize()
{
$item = new Feed\Item();
$item->setTitle('foo-bar');
$this->object->add($item);
$this->object->setTitle('hello');
$this->object->setLastModified(new \DateTime());
$json = json_encode($this->object);
$this->assertInternalType('string', $json);
$this->assertInstanceOf('stdClass', json_decode($json));
}
}
tests/FeedIo/Filter/ModifiedSinceTest.php 0000666 00000002077 13052362033 0014350 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Filter;
use FeedIo\Feed\Item;
use FeedIo\Feed;
class ModifiedSinceTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Filter\ModifiedSince
*/
protected $object;
protected function setUp()
{
$this->object = new ModifiedSince(new \DateTime('-10 days'));
}
public function testIsValid()
{
$item = new Item();
$item->setLastModified(new \DateTime('-8 days'));
$this->assertTrue($this->object->isValid($item));
}
public function testIsTooOld()
{
$item = new Item();
$item->setLastModified(new \DateTime('-12 days'));
$this->assertFalse($this->object->isValid($item));
}
public function testIsNotValid()
{
$item = new Item();
$this->assertFalse($this->object->isValid($item));
}
}
tests/FeedIo/FormatterTest.php 0000666 00000006073 13052362033 0012364 0 ustar 00 add(new Title());
$document = new \DOMDocument();
$document->loadXML('');
$standard = $this->getMockForAbstractClass(
'\FeedIo\StandardAbstract',
array(new DateTimeBuilder()),
'StandardMock',
true,
true,
true,
['format', 'getMainElement', 'setHeaders', 'buildFeedRuleSet', 'buildItemRuleSet']
);
$standard->expects($this->any())->method('format')->will($this->returnValue(
$document
));
$standard->expects($this->any())->method('getMainElement')->will($this->returnValue(
$document->documentElement->firstChild
));
$standard->expects($this->any())->method('setHeaders')->will($this->returnSelf());
$standard->expects($this->any())->method('buildFeedRuleSet')->will($this->returnValue($ruleSet));
$standard->expects($this->any())->method('buildItemRuleSet')->will($this->returnValue($ruleSet));
$this->object = new Formatter($standard, new NullLogger());
}
public function testGetEmptyDocument()
{
$this->assertInstanceOf('\DomDocument', $this->object->getEmptyDocument());
}
public function testGetDocument()
{
$this->assertInstanceOf('\DomDocument', $this->object->getDocument());
}
public function testGetAllRules()
{
$item = new Item();
$item->set('title', 'the title');
$item->set('description', 'the description');
$rules = $this->object->getAllRules(new RuleSet(), $item);
$this->assertCount(2, $rules);
$ruleNames = array('title', 'description');
foreach ($rules as $rule) {
$this->assertEquals(current($ruleNames), $rule->getNodeName());
next($ruleNames);
}
}
public function testToString()
{
$feed = new Feed();
$feed->setTitle('foo-bar');
$out = $this->object->toString($feed);
$this->assertInternalType('string', $out);
$this->assertContains('foo-bar', $out);
$this->assertEquals('
foo-bar
', $out);
}
public function testToDom()
{
$feed = new Feed();
$this->assertInstanceOf('\DomDocument', $this->object->toDom($feed));
}
public function testSetItems()
{
$feed = new Feed();
$feed->add(new Item());
$feed->add(new Item());
$document = $this->object->getDocument();
$this->object->setItems($document, $feed);
$this->assertEquals(2, $document->getElementsByTagName('item')->length);
}
}
tests/FeedIo/Parser/AtomTest.php 0000666 00000002462 13052362033 0012553 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Parser;
use FeedIo\Feed;
use FeedIo\Rule\DateTimeBuilder;
use FeedIo\Standard\Atom;
class AtomTest extends ParserTestAbstract
{
const SAMPLE_FILE = 'sample-atom.xml';
const ENCLOSURE_FILE = 'enclosure-atom.xml';
/**
* @var \FeedIo\Parser\Atom
*/
protected $object;
/**
* @return \FeedIo\StandardAbstract
*/
public function getStandard()
{
return new Atom(new DateTimeBuilder());
}
public function testEnclosure()
{
$document = $this->buildDomDocument(static::ENCLOSURE_FILE);
$feed = $this->object->parse($document, new Feed());
$count = 0;
foreach ($feed as $item) {
$count++;
$this->assertTrue($item->hasMedia());
$media = $item->getMedias()->current();
$this->assertInstanceOf('\FeedIo\Feed\Item\MediaInterface', $media);
$this->assertEquals('video/mpeg', $media->getType());
$this->assertInternalType('string', $media->getUrl());
}
$this->assertEquals(1, $count);
}
}
tests/FeedIo/Parser/ParserTestAbstract.php 0000666 00000006515 13052362033 0014576 0 ustar 00 getStandard();
$this->object = new Parser($standard, new NullLogger());
}
public function testCanHandle()
{
$document = $this->buildDomDocument(static::SAMPLE_FILE);
$this->assertTrue($this->object->getStandard()->canHandle($document));
}
public function testGetMainElement()
{
$document = $this->buildDomDocument(static::SAMPLE_FILE);
$element = $this->object->getStandard()->getMainElement($document);
$this->assertInstanceOf('\DomElement', $element);
}
public function testBuildFeedRuleSet()
{
$ruleSet = $this->object->getStandard()->buildFeedRuleSet();
$this->assertInstanceOf('\FeedIo\RuleSet', $ruleSet);
}
public function testBuildItemRuleSet()
{
$ruleSet = $this->object->getStandard()->buildItemRuleSet();
$this->assertInstanceOf('\FeedIo\RuleSet', $ruleSet);
}
public function testParseBody()
{
$document = $this->buildDomDocument(static::SAMPLE_FILE);
$feed = $this->object->parse($document, new Feed());
$this->assertInstanceOf('\FeedIo\Feed', $feed);
$this->assertNotEmpty($feed->getTitle(), 'title must not be empty');
$this->assertNotEmpty($feed->getLink(), 'link must not be empty');
$this->assertNotEmpty($feed->getLastModified(), 'lastModified must not be empty');
$this->assertTrue($feed->valid(), 'the feed must contain an item');
$this->runCategoriesTest($feed);
$item = $feed->current();
$this->assertInstanceOf('\FeedIo\Feed\ItemInterface', $item);
if ($item instanceof \FeedIo\Feed\ItemInterface) {
$this->assertNotEmpty($item->getTitle());
$this->assertNotEmpty($item->getDescription());
$this->assertNotEmpty($item->getPublicId());
$this->assertNotEmpty($item->getLastModified());
$this->assertNotEmpty($item->getLink());
$this->assertCount(1, $item->getAllElements());
$this->assertTrue($item->hasElement('author'));
$this->runCategoriesTest($item);
}
}
protected function runCategoriesTest(\FeedIo\Feed\NodeInterface $node)
{
$categories = $node->getCategories();
$this->assertCount(1, $categories);
$category = $categories->current();
$this->assertInstanceOf('\FeedIo\Feed\Node\CategoryInterface', $category);
$this->assertNotEmpty($category->getTerm());
$this->assertNotEmpty($category->getLabel());
}
/**
* @param $filename
* @return \DOMDocument
*/
protected function buildDomDocument($filename)
{
$file = dirname(__FILE__)."/../../samples/{$filename}";
$domDocument = new \DOMDocument();
$domDocument->load($file, LIBXML_NOBLANKS | LIBXML_COMPACT);
return $domDocument;
}
}
tests/FeedIo/Parser/RdfTest.php 0000666 00000002776 13052362033 0012376 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Parser;
use FeedIo\Feed;
use FeedIo\Rule\DateTimeBuilder;
use FeedIo\Standard\Rdf;
class RdfTest extends ParserTestAbstract
{
const SAMPLE_FILE = 'sample-rdf.xml';
/**
* @return \FeedIo\StandardAbstract
*/
public function getStandard()
{
return new Rdf(new DateTimeBuilder());
}
public function testParseBody()
{
$document = $this->buildDomDocument(static::SAMPLE_FILE);
$feed = $this->object->parse($document, new Feed());
$this->assertInstanceOf('\FeedIo\Feed', $feed);
$this->assertNotEmpty($feed->getTitle(), 'title must not be empty');
$this->assertNotEmpty($feed->getLink(), 'link must not be empty');
$this->assertNotEmpty($feed->getLastModified(), 'lastModified must not be empty');
$this->assertTrue($feed->valid(), 'the feed must contain an item');
$item = $feed->current();
$this->assertInstanceOf('\FeedIo\Feed\ItemInterface', $item);
if ($item instanceof \FeedIo\Feed\ItemInterface) {
$this->assertNotEmpty($item->getTitle());
$this->assertNotEmpty($item->getDescription());
$this->assertNotEmpty($item->getLastModified());
$this->assertNotEmpty($item->getLink());
}
}
}
tests/FeedIo/Parser/RssTest.php 0000666 00000002356 13052362033 0012424 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Parser;
use FeedIo\Feed;
use FeedIo\Rule\DateTimeBuilder;
use FeedIo\Standard\Rss;
class RssTest extends ParserTestAbstract
{
const SAMPLE_FILE = 'rss/sample-rss.xml';
const ENCLOSURE_FILE = 'rss/rss-enclosure.xml';
/**
* @return \FeedIo\StandardAbstract
*/
public function getStandard()
{
return new Rss(new DateTimeBuilder());
}
public function testEnclosure()
{
$document = $this->buildDomDocument(static::ENCLOSURE_FILE);
$feed = $this->object->parse($document, new Feed());
$count = 0;
foreach ($feed as $item) {
$count++;
$this->assertTrue($item->hasMedia());
$media = $item->getMedias()->current();
$this->assertInstanceOf('\FeedIo\Feed\Item\MediaInterface', $media);
$this->assertEquals('audio/mpeg', $media->getType());
$this->assertInternalType('string', $media->getUrl());
}
$this->assertEquals(1, $count);
}
}
tests/FeedIo/ParserTest.php 0000666 00000011575 13052362033 0011660 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Feed\Item;
use FeedIo\Rule\DateTimeBuilder;
use Psr\Log\NullLogger;
class ParserTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\ParserAbstract
*/
protected $object;
public function setUp()
{
$date = new DateTimeBuilder();
$date->addDateFormat(\DateTime::ATOM);
$standard = $this->getMockForAbstractClass(
'\FeedIo\StandardAbstract',
array($date),
'StandardMock',
true,
true,
true,
['canHandle', 'getMainElement', 'buildFeedRuleSet']
);
$standard->expects($this->any())->method('canHandle')->will($this->returnValue(true));
$standard->expects($this->any())->method('buildFeedRuleSet')->will($this->returnValue(new RuleSet()));
$standard->expects($this->any())->method('getMainElement')->will($this->returnValue(new \DOMElement('test')));
$this->object = new Parser($standard, new NullLogger());
}
public function testParse()
{
$document = new \DOMDocument();
$document->loadXML('');
$feed = $this->object->parse($document, new Feed());
$this->assertInstanceOf('FeedIo\Feed', $feed);
}
public function testParseNode()
{
$document = new \DOMDocument();
$xml = <<feed-io
https://github.com/alexdebril/feed-io
feed-io is a library
XML;
$document->loadXML($xml);
$feed = new Feed();
$this->object->parseNode($feed, $document->documentElement, new RuleSet());
$this->assertInstanceOf('\Iterator', $feed->getElementIterator('description'));
$iterator = $feed->getElementIterator('description');
$count = 0;
foreach ($iterator as $element) {
$this->assertInstanceOf('\FeedIo\Feed\Node\ElementInterface', $element);
$this->assertEquals('feed-io is a library', $element->getValue());
$count++;
}
$this->assertEquals(1, $count);
}
/**
* @expectedException \FeedIo\Parser\UnsupportedFormatException
*/
public function testParseBadDocument()
{
$document = new \DOMDocument();
$document->loadXML('');
$standard = $this->getMockForAbstractClass(
'\FeedIo\StandardAbstract',
array(new DateTimeBuilder())
);
$standard->expects($this->any())->method('canHandle')->will($this->returnValue(false));
$parser = new Parser($standard, new NullLogger());
$parser->parse($document, new Feed());
}
public function testIsValid()
{
$item = new Item();
$item->setLastModified(new \DateTime('-1day'));
$this->object->addFilter($this->getFilterMock(true));
$this->assertTrue($this->object->isValid($item));
}
public function testIsNotValid()
{
$item = new Item();
$this->object->addFilter($this->getFilterMock(false));
$this->assertFalse($this->object->isValid($item));
}
public function testCheckStructure()
{
$rss = <<RSS Title
RSS;
$document = new \DOMDocument();
$document->loadXML($rss);
$this->assertInstanceOf(
'\FeedIo\Parser',
$this->object->checkBodyStructure($document, array('channel', 'title'))
);
}
/**
* @expectedException \FeedIo\Parser\MissingFieldsException
*/
public function testCheckBadStructure()
{
$document = new \DOMDocument();
$document->loadXML('');
$this->assertInstanceOf(
'\FeedIo\Parser',
$this->object->checkBodyStructure($document, array('channel'))
);
}
public function testAddResetFilters()
{
$filter = $this->getMockForAbstractClass('\FeedIo\FilterInterface');
$this->object->addFilter($filter);
$this->assertAttributeCount(1, 'filters', $this->object);
$this->object->resetFilters();
$this->assertAttributeCount(0, 'filters', $this->object);
}
/**
* @param boolean $returnValue
* @return \FeedIo\FilterInterface
*/
protected function getFilterMock($returnValue)
{
$filter = $this->getMockForAbstractClass('\FeedIo\FilterInterface');
$filter->expects($this->once())
->method('isValid')
->will($this->returnValue($returnValue));
return $filter;
}
}
tests/FeedIo/Reader/Fixer/LastModifiedTest.php 0000666 00000002742 13052362033 0015243 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader\Fixer;
use FeedIo\Feed;
use FeedIo\Feed\Item;
use Psr\Log\NullLogger;
class LastModifiedTest extends \PHPUnit_Framework_TestCase
{
/**
* @var FeedIo\Reader\Fixer\LastModified
*/
protected $object;
/**
* @var \DateTime
*/
protected $newest;
protected function setUp()
{
$this->newest = new \DateTime('2014-01-01');
$this->object = new LastModified();
$this->object->setLogger(new NullLogger());
}
public function testSearchLastModified()
{
$feed = $this->getFeed();
$this->assertEquals(
$this->newest,
$this->object->searchLastModified($feed)
);
}
public function testCorrect()
{
$feed = $this->getFeed();
$this->assertNull($feed->getLastModified());
$this->object->correct($feed);
$this->assertEquals($this->newest, $feed->getLastModified());
}
protected function getFeed()
{
$item1 = new Item();
$item1->setLastModified($this->newest);
$item2 = new Item();
$item2->setLastModified(new \DateTime('2013-01-01'));
$feed = new Feed();
$feed->add($item1)->add($item2);
return $feed;
}
}
tests/FeedIo/Reader/Fixer/PublicIdTest.php 0000666 00000002263 13052362033 0014370 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader\Fixer;
use FeedIo\Feed;
use FeedIo\Feed\Item;
use Psr\Log\NullLogger;
class PublicIdTest extends \PHPUnit_Framework_TestCase
{
/**
* @var FeedIo\Reader\Fixer\PublicId
*/
protected $object;
protected function setUp()
{
$this->object = new PublicId();
$this->object->setLogger(new NullLogger());
}
public function testCorrect()
{
$feed = $this->getFeed();
$this->assertNull($feed->getPublicId());
$this->object->correct($feed);
$this->assertEquals($feed->getLink(), $feed->getPublicId());
foreach ($feed as $item) {
$this->assertEquals($item->getLink(), $item->getPublicId());
}
}
protected function getFeed()
{
$item1 = new Item();
$item1->setLink('http://localhost/1');
$feed = new Feed();
$feed->add($item1)->setLink('http://localhost/');
return $feed;
}
}
tests/FeedIo/Reader/FixerMock.php 0000666 00000001250 13052362033 0012642 0 ustar 00 logger = $logger;
return $this;
}
/**
* @param FeedInterface $feed
* @return $this
*/
public function correct(FeedInterface $feed)
{
$feed->setTitle('corrected');
return $this;
}
}
tests/FeedIo/Reader/FixerSetTest.php 0000666 00000001565 13052362033 0013355 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader;
use FeedIo\Feed;
class FixerSetTest extends \PHPUnit_Framework_TestCase
{
public function testAdd()
{
$fixer = $this->getMockForAbstractClass('\FeedIo\Reader\FixerAbstract');
$fixerSet = new FixerSet();
$fixerSet->add($fixer);
$this->assertAttributeContainsOnly($fixer, 'fixers', $fixerSet);
}
public function testCorrect()
{
$fixer = new FixerMock();
$fixerSet = new FixerSet();
$fixerSet->add($fixer);
$feed = new Feed();
$fixerSet->correct($feed);
$this->assertEquals('corrected', $feed->getTitle());
}
}
tests/FeedIo/Reader/ResultTest.php 0000666 00000003010 13052362033 0013065 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Reader;
use FeedIo\Feed;
class ResultTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Reader\Result
*/
protected $object;
protected $modifiedSince;
protected $resultDate;
protected function setUp()
{
$this->modifiedSince = new \DateTime('-10 days');
$this->resultDate = new \DateTime();
$response = $this->getMockForAbstractClass('\FeedIo\Adapter\ResponseInterface');
$this->object = new Result(
new \DOMDocument(),
new Feed(),
$this->modifiedSince,
$response,
'http://localhost'
);
}
public function testResult()
{
$this->assertInstanceOf('\DomDocument', $this->object->getDocument());
$this->assertInstanceOf('\FeedIo\FeedInterface', $this->object->getFeed());
$this->assertEquals($this->resultDate->format(\DateTime::ATOM), $this->object->getDate()->format(\DateTime::ATOM));
$this->assertEquals($this->modifiedSince->format(\DateTime::ATOM), $this->object->getModifiedSince()->format(\DateTime::ATOM));
$this->assertInstanceOf('\FeedIo\Adapter\ResponseInterface', $this->object->getresponse());
$this->assertEquals('http://localhost', $this->object->getUrl());
}
}
tests/FeedIo/ReaderTest.php 0000666 00000012036 13052362033 0011617 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Adapter\ServerErrorException;
use Psr\Log\NullLogger;
use FeedIo\Rule\DateTimeBuilder;
class ReaderTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Reader
*/
protected $object;
public function setUp()
{
$this->object = new Reader(
$this->getClientMock(),
new NullLogger()
);
}
/**
* @return \FeedIo\Adapter\ClientInterface
*/
protected function getClientMock()
{
$client = $this->createMock('FeedIo\Adapter\ClientInterface');
$response = $this->createMock('FeedIo\Adapter\ResponseInterface');
$response->expects($this->any())->method('getBody')->will($this->returnValue(''));
$client->expects($this->any())->method('getResponse')->will($this->returnValue($response));
return $client;
}
/**
* @return \FeedIo\Adapter\ClientInterface
*/
protected function getFaultyClientMock()
{
$client = $this->createMock('FeedIo\Adapter\ClientInterface');
$client->expects($this->any())->method('getResponse')->will(
$this->throwException(new ServerErrorException())
);
return $client;
}
/**
* @return \FeedIo\Parser
*/
protected function getParser()
{
$standard = $this->getMockForAbstractClass(
'\FeedIo\StandardAbstract',
array(new DateTimeBuilder())
);
$standard->expects($this->any())->method('canHandle')->will($this->returnValue(true));
$standard->expects($this->any())->method('buildFeedRuleSet')->will($this->returnValue(new RuleSet()));
$standard->expects($this->any())->method('buildItemRuleSet')->will($this->returnValue(new RuleSet()));
$file = dirname(__FILE__)."/../samples/rss/sample-rss.xml";
$domDocument = new \DOMDocument();
$domDocument->load($file, LIBXML_NOBLANKS | LIBXML_COMPACT);
$standard->expects($this->any())->method('getMainElement')->will($this->returnValue(
$domDocument->documentElement->getElementsByTagName('channel')->item(0)
));
$parser = new Parser($standard, new NullLogger());
return $parser;
}
public function testLoadDocument()
{
$document = $this->object->loadDocument('');
$this->assertInstanceOf('\DomDocument', $document);
}
/**
* @expectedException InvalidArgumentException
*/
public function testLoadMalformedDocument()
{
$document = $this->object->loadDocument('');
$this->assertInstanceOf('\DomDocument', $document);
}
/**
* @covers \FeedIo\Reader::addParser
*/
public function testAddParser()
{
$parser = $this->getParser();
$this->object->addParser($parser);
$this->assertAttributeEquals(array($parser), 'parsers', $this->object);
}
public function testGetAccurateParser()
{
$this->object->addParser($this->getParser());
$parser = $this->object->getAccurateParser(new \DOMDocument());
$this->assertInstanceOf('\FeedIo\Parser', $parser);
}
/**
* @expectedException \FeedIo\Reader\NoAccurateParserException
*/
public function testGetAccurateParserFailure()
{
$this->object->getAccurateParser(new \DOMDocument());
}
public function testParseDocument()
{
$this->object->addParser($this->getParser());
$feed = $this->object->parseDocument(new \DOMDocument(), new Feed());
$this->assertInstanceOf('\FeedIo\Feed', $feed);
$this->assertEquals('This is an example of an RSS feed', $feed->getValue('description'));
}
/**
* @covers \FeedIo\Reader::read
*/
public function testReadWithModifiedSince()
{
$feed = new Feed();
$this->object->addParser($this->getParser());
$modifiedSince = new \DateTime();
$url = 'http://localhost';
$result = $this->object->read($url, $feed, $modifiedSince);
$this->assertEquals($url, $result->getUrl());
$this->assertEquals($modifiedSince, $result->getModifiedSince());
$this->assertInstanceOf('\DOMDocument', $result->getDocument());
}
/**
* @covers \FeedIo\Reader::read
*/
public function testReadWithoutModifiedSince()
{
$feed = new Feed();
$this->object->addParser($this->getParser());
$result = $this->object->read('fakeurl', $feed);
$this->assertEquals(new \DateTime('@0'), $result->getModifiedSince());
}
/**
* @covers \FeedIo\Reader::read
* @expectedException \FeedIo\Reader\ReadErrorException
*/
public function testReadException()
{
$reader = new Reader($this->getFaultyClientMock(), new NullLogger());
$reader->read('fault', new Feed());
}
}
tests/FeedIo/Rule/Atom/CategoryTest.php 0000666 00000004253 13052362033 0014003 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule\Atom;
use FeedIo\Feed\Item;
class CategoryTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Rule\Atom\Category
*/
protected $object;
protected function setUp()
{
$this->object = new Category();
}
public function testSetProperty()
{
$item = new Item();
$document = new \DomDocument();
$element = $document->createElement('category');
$element->setAttribute('scheme', 'http');
$element->setAttribute('label', 'FooBar');
$element->setAttribute('term', 'foobar');
$this->object->setProperty($item, $element);
$count = 0;
foreach ($item->getCategories() as $category) {
$count++;
$this->assertEquals('foobar', $category->getTerm());
$this->assertEquals('FooBar', $category->getLabel());
$this->assertEquals('http', $category->getScheme());
}
$this->assertEquals(1, $count);
}
public function testCreateCategoryElement()
{
$category = new \FeedIo\Feed\Node\Category();
$category->setLabel('Foo');
$category->setTerm('foo');
$category->setScheme('bar');
$element = $this->object->createCategoryElement(new \DomDocument(), $category);
$this->assertEquals('Foo', $element->getAttribute('label'));
$this->assertEquals('foo', $element->getAttribute('term'));
$this->assertEquals('bar', $element->getAttribute('scheme'));
}
public function testCreateElement()
{
$category = new \FeedIo\Feed\Node\Category();
$category->setLabel('foo');
$item = new Item;
$item->addCategory($category);
$element = $this->object->createElement(new \DomDocument, $item);
$this->assertEquals('foo', $element->getAttribute('label'));
}
}
tests/FeedIo/Rule/Atom/LinkNodeTest.php 0000666 00000003473 13052362033 0013734 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule\Atom;
use FeedIo\Feed\Item;
class LinkNodeTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Link
*/
protected $object;
const LINK = 'http://localhost';
protected function setUp()
{
$this->object = new LinkNode();
}
public function testSet()
{
$item = new Item();
$document = new \DOMDocument();
$link = $document->createElement('link');
$link->setAttribute('href', 'http://localhost');
$this->object->setProperty($item, $link);
$this->assertEquals('http://localhost', $item->getLink());
}
public function testSetMedia()
{
$item = new Item();
$document = new \DOMDocument();
$link = $document->createElement('link');
$link->setAttribute('href', 'http://localhost/video.mpeg');
$link->setAttribute('rel', 'enclosure');
$this->object->setProperty($item, $link);
$this->assertTrue($item->hasMedia());
$count = 0;
foreach ($item->getMedias() as $media) {
$count++;
$this->assertEquals($link->getAttribute('href'), $media->getUrl());
}
$this->assertEquals(1, $count);
}
public function testCreateElement()
{
$item = new Item();
$item->setLink(self::LINK);
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertInstanceOf('\DomElement', $element);
$this->assertEquals(self::LINK, $element->getAttribute('href'));
$this->assertEquals('link', $element->nodeName);
}
}
tests/FeedIo/Rule/Atom/LinkTest.php 0000666 00000002330 13052362033 0013115 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule\Atom;
use FeedIo\Feed\Item;
class LinkTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Link
*/
protected $object;
const LINK = 'http://localhost';
protected function setUp()
{
$this->object = new Link();
}
public function testSet()
{
$item = new Item();
$document = new \DOMDocument();
$link = $document->createElement('link');
$link->setAttribute('href', 'http://localhost');
$this->object->setProperty($item, $link);
$this->assertEquals('http://localhost', $item->getLink());
}
public function testCreateElement()
{
$item = new Item();
$item->setLink(self::LINK);
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertInstanceOf('\DomElement', $element);
$this->assertEquals(self::LINK, $element->getAttribute('href'));
$this->assertEquals('link', $element->nodeName);
}
}
tests/FeedIo/Rule/CategoryTest.php 0000666 00000004266 13052362033 0013107 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\Item;
class CategoryTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Rule\Category
*/
protected $object;
protected function setUp()
{
$this->object = new Category();
}
public function testSetProperty()
{
$item = new Item();
$element = new \DomElement('category', 'foo');
$this->object->setProperty($item, $element);
$count = 0;
foreach ($item->getCategories() as $category) {
$count++;
$this->assertEquals('foo', $category->getTerm());
$this->assertEquals('foo', $category->getLabel());
}
$this->assertEquals(1, $count);
}
public function testCreateCategoryElement()
{
$category = new \FeedIo\Feed\Node\Category();
$category->setLabel('foo');
$category->setScheme('bar');
$element = $this->object->createCategoryElement(new \DomDocument(), $category);
$this->assertEquals('foo', $element->nodeValue);
$this->assertEquals('bar', $element->getAttribute('domain'));
}
public function testCreateCategoryElementUsingTerm()
{
$category = new \FeedIo\Feed\Node\Category();
$category->setTerm('foo');
$element = $this->object->createCategoryElement(new \DomDocument(), $category);
$this->assertEquals('foo', $element->nodeValue);
}
public function testCreateElement()
{
$category = new \FeedIo\Feed\Node\Category();
$category->setLabel('foo');
$item = new Item;
$this->assertNull($this->object->createElement(new \DomDocument, $item));
$item->addCategory($category);
$element = $this->object->createElement(new \DomDocument, $item);
$this->assertEquals('foo', $element->nodeValue);
}
}
tests/FeedIo/Rule/DateTest.php 0000666 00000006007 13052362033 0012202 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
class DateTest extends \PHPUnit_Framework_TestCase
{
/**
* Timezone used to test a timezone switch.
* Longyearbyen is the only place in the world where the testSetTimezone() test will fail,
* I hope it won't bother anyone
*/
const ALTERNATE_TIMEZONE = 'Arctic/Longyearbyen';
/**
* @var \FeedIo\Parser\DateTimeBuilder
*/
protected $object;
protected function setUp()
{
$this->object = new DateTimeBuilder();
}
public function testGetTimezone()
{
$timezone = $this->object->getTimezone();
$this->assertEquals(date_default_timezone_get(), $timezone->getName());
}
public function testSetDateFormats()
{
$formats = array(\DateTime::ATOM);
$this->object->setDateFormats($formats);
$this->assertAttributeEquals($formats, 'dateFormats', $this->object);
}
public function testGuessDateFormat()
{
$formats = array(\DateTime::ATOM, \DateTime::RFC1036);
$this->object->setDateFormats($formats);
$date = new \DateTime();
$format = $this->object->guessDateFormat($date->format(\DateTime::ATOM));
$this->assertEquals(\DateTime::ATOM, $format);
}
public function testDontGuessDateFormat()
{
$this->object->addDateFormat(\DateTime::ATOM);
$this->assertFalse($this->object->guessDateFormat('foo'));
}
public function testConvertDateFormat()
{
$formats = array(\DateTime::ATOM, \DateTime::RFC1036);
$this->object->setDateFormats($formats);
$date = new \DateTime('now');
$this->assertEquals($date->format(\DateTime::ATOM), $this->object->convertToDateTime($date->format(\DateTime::ATOM))->format(\DateTime::ATOM));
$this->assertEquals(\DateTime::ATOM, $this->object->getLastGuessedFormat());
$this->assertEquals($date->format(\DateTime::ATOM), $this->object->convertToDateTime($date->format(\DateTime::RFC1036))->format(\DateTime::ATOM));
$this->assertEquals(\DateTime::RFC1036, $this->object->getLastGuessedFormat());
}
/**
* @expectedException \InvalidArgumentException
*/
public function testDontConvertDateFormat()
{
$this->object->addDateFormat(\DateTime::ATOM);
$this->object->convertToDateTime('foo');
}
public function testSetTimezone()
{
$this->object->setTimezone(new \DateTimeZone(self::ALTERNATE_TIMEZONE));
$this->assertEquals(self::ALTERNATE_TIMEZONE, $this->object->getTimezone()->getName());
$this->object->addDateFormat(\DateTime::ATOM);
$date = new \DateTime();
$return = $this->object->convertToDateTime($date->format(\DateTime::ATOM));
$this->assertEquals(self::ALTERNATE_TIMEZONE, $return->getTimezone()->getName());
}
}
tests/FeedIo/Rule/DescriptionTest.php 0000666 00000003341 13052362033 0013606 0 ustar 00 a title
A paragraph
second paragraph
';
protected function setUp()
{
$this->object = new Description();
}
public function testGetNodeName()
{
$this->assertEquals('description', $this->object->getNodeName());
}
public function testSet()
{
$item = new Item();
$document = new \DOMDocument();
$element = $document->createElement('description', self::DESCRIPTION);
$document->appendChild($element);
$this->object->setProperty($item, $element);
$this->assertEquals(self::DESCRIPTION, $item->getDescription());
}
public function testSetProperty()
{
$item = new Item();
$document = new \DOMDocument();
$element = $document->createElement('description', self::HTML_DESCRIPTION);
$document->appendChild($element);
$this->object->setProperty($item, $element);
$this->assertEquals(htmlentities(self::HTML_DESCRIPTION), $item->getDescription());
}
public function testCreateElement()
{
$item = new Item();
$item->setDescription(self::DESCRIPTION);
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertInstanceOf('\DomElement', $element);
$this->assertEquals(self::DESCRIPTION, $element->nodeValue);
$this->assertEquals('description', $element->nodeName);
}
}
tests/FeedIo/Rule/LinkTest.php 0000666 00000002063 13052362033 0012220 0 ustar 00 object = new Link();
}
public function testGetNodeName()
{
$this->assertEquals('link', $this->object->getNodeName());
}
public function testSet()
{
$item = new Item();
$this->object->setProperty($item, new \DOMElement('link', self::LINK));
$this->assertEquals(self::LINK, $item->getLink());
}
public function testCreateElement()
{
$item = new Item();
$item->setLink(self::LINK);
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertInstanceOf('\DomElement', $element);
$this->assertEquals(self::LINK, $element->nodeValue);
$this->assertEquals('link', $element->nodeName);
}
}
tests/FeedIo/Rule/MediaTest.php 0000666 00000004541 13052362033 0012345 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\Item;
use FeedIo\Feed\Item\MediaInterface;
class MediaTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Rule\Media
*/
protected $object;
protected function setUp()
{
$this->object = new Media();
}
public function testSetProperty()
{
$document = new \DomDocument();
$media = $document->createElement('enclosure');
$media->setAttribute('url', 'http://localhost');
$media->setAttribute('length', '12345');
$media->setAttribute('type', 'audio/mp3');
$item = new Item();
$this->object->setProperty($item, $media);
$this->assertTrue($item->hasMedia());
$count = 0;
foreach ($item->getMedias() as $itemMedia) {
$this->assertInternalType('string', $itemMedia->getType());
$this->assertInternalType('string', $itemMedia->getUrl());
$this->assertInternalType('integer', $itemMedia->getLength());
$this->assertEquals($media->getAttribute('url'), $itemMedia->getUrl());
$count++;
}
$this->assertEquals(1, $count);
}
public function testCreateElement()
{
$item = new Item();
$this->assertNull($this->object->createElement(new \DomDocument(), $item));
$media = new \FeedIo\Feed\Item\Media();
$media->setType('audio')
->setUrl('http://localhost')
->setLength(123);
$item->addMedia($media);
$element = $this->object->createMediaElement(new \DomDocument(), $media);
$this->assertMediaEqualsElement($media, $element);
$secondElement = $this->object->createElement(new \DomDocument(), $item);
$this->assertMediaEqualsElement($media, $element);
}
protected function assertMediaEqualsElement(MediaInterface $media, \DomElement $element)
{
$this->assertEquals($media->getUrl(), $element->getAttribute('url'));
$this->assertEquals($media->getType(), $element->getAttribute('type'));
$this->assertEquals($media->getLength(), $element->getAttribute('length'));
}
}
tests/FeedIo/Rule/ModifiedSinceTest.php 0000666 00000004375 13052362033 0014035 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\Item;
class ModifiedSinceTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\Rule\ModifiedSince
*/
protected $object;
protected function setUp()
{
$date = new DateTimeBuilder();
$date->addDateFormat(\DateTime::ATOM);
$this->object = new ModifiedSince();
$this->object->setDateTimeBuilder($date);
}
public function testSet()
{
$item = new Item();
$date = new \DateTime('-3 days');
$element = new \DOMElement('pubDate', $date->format(\DateTime::ATOM));
$this->object->setProperty($item, $element);
$this->assertEquals($date->format(\DateTime::ATOM), $item->getLastModified()->format(\DateTime::ATOM));
}
public function testAddedFormat()
{
$item = new Item();
$dateTime = new \DateTime('-3 days');
$element = new \DOMElement('pubDate', $dateTime->format(\DateTime::RSS));
$dateTimeBuilder = new DateTimeBuilder();
$dateTimeBuilder->addDateFormat(\DateTime::ATOM);
$modifiedSince = new ModifiedSince();
$modifiedSince->setDateTimeBuilder($dateTimeBuilder);
$dateTimeBuilder->addDateFormat(\DateTime::RSS);
$modifiedSince->setProperty($item, $element);
$this->assertEquals($dateTime->format(\DateTime::ATOM), $item->getLastModified()->format(\DateTime::ATOM));
}
public function testGetDate()
{
$this->assertInstanceOf('\FeedIo\Rule\DateTimeBuilder', $this->object->getDateTimeBuilder());
}
public function testCreateElement()
{
$item = new Item();
$date = new \DateTime();
$item->setLastModified($date);
$this->object->setDefaultFormat(\DateTime::ATOM);
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertInstanceOf('\DomElement', $element);
$this->assertEquals($date->format(\DateTime::ATOM), $element->nodeValue);
$this->assertEquals('pubDate', $element->nodeName);
}
}
tests/FeedIo/Rule/OptionalFieldTest.php 0000666 00000004413 13052362033 0014055 0 ustar 00 object = new OptionalField();
}
public function testSetProperty()
{
$document = new \DomDocument();
$element = $document->createElement('test', 'a test value');
$element->setAttribute('foo', 'bar');
$item = new Item();
$this->object->setProperty($item, $element);
$this->assertTrue($item->hasElement('test'));
$this->assertEquals('a test value', $item->getValue('test'));
$itemElements = $item->getElementIterator('test');
$count = 0;
foreach ($itemElements as $itemElement) {
$count++;
$this->assertEquals('bar', $itemElement->getAttribute('foo'));
}
$this->assertEquals(1, $count);
}
public function testCreateElement()
{
$item = new Item();
$item->set('default', 'a test value');
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertEquals('default', $element->nodeName);
$this->assertEquals('a test value', $element->nodeValue);
}
public function testCreateElementWithAttributes()
{
$element = new Element();
$element->setName('default');
$element->setValue('value');
$element->setAttribute('foo', 'bar');
$item = new Item();
$item->addElement($element);
$domElement = $this->object->createElement(new \DOMDocument(), $item);
$this->assertEquals('default', $domElement->nodeName);
$this->assertEquals('value', $domElement->nodeValue);
$this->assertTrue($domElement->hasAttribute('foo'));
}
public function testDontCreateElement()
{
$item = new Item();
$item->set('another', 'a test value');
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertEquals('default', $element->nodeName);
$this->assertEquals('', $element->nodeValue);
}
}
tests/FeedIo/Rule/PublicIdTest.php 0000666 00000002062 13052362033 0013015 0 ustar 00 object = new PublicId();
}
public function testGetNodeName()
{
$this->assertEquals('guid', $this->object->getNodeName());
}
public function testSet()
{
$item = new Item();
$this->object->setProperty($item, new \DOMElement('guid', 'foo'));
$this->assertEquals('foo', $item->getPublicId());
}
public function testCreateElement()
{
$item = new Item();
$item->setPublicId(self::PUBLIC_ID);
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertInstanceOf('\DomElement', $element);
$this->assertEquals(self::PUBLIC_ID, $element->nodeValue);
$this->assertEquals('guid', $element->nodeName);
}
}
tests/FeedIo/Rule/StructureTest.php 0000666 00000003245 13052362033 0013326 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\RuleSet;
use FeedIo\Feed\Item;
class StructureTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Structure
*/
protected $object;
protected function setUp()
{
$ruleSet = new RuleSet();
$ruleSet->add(new Title());
$this->object = new Structure('foo', $ruleSet);
}
public function testGetNodeName()
{
$this->assertEquals('foo', $this->object->getNodeName());
}
public function testConstruct()
{
$ruleSet = new RuleSet();
$ruleSet->add(new Title());
$structure = new Structure('foo', $ruleSet);
$this->assertAttributeEquals($ruleSet, 'ruleSet', $structure);
}
public function testSet()
{
$document = new \DomDocument();
$foo = $document->createElement('foo');
$document->appendChild($foo);
$bar = $document->createElement('title', 'hello');
$foo->appendChild($bar);
$item = new Item();
$this->object->setProperty($item, $foo);
$this->assertEquals('hello', $item->getTitle());
}
public function testCreateElement()
{
$item = new Item();
$item->setTitle('foo-bar');
$document = new \DomDocument();
$element = $this->object->createElement($document, $item);
$node = 'foo-bar';
$this->assertEquals($node, $document->saveXML($element));
}
}
tests/FeedIo/Rule/TitleTest.php 0000666 00000002325 13052362033 0012405 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Rule;
use FeedIo\Feed\Item;
class TitleTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Title
*/
protected $object;
const TITLE = 'my great article';
protected function setUp()
{
$this->object = new Title();
}
public function testGetNodeName()
{
$this->assertEquals('title', $this->object->getNodeName());
}
public function testSet()
{
$item = new Item();
$this->object->setProperty($item, new \DOMElement('title', 'feed-io title'));
$this->assertEquals('feed-io title', $item->getTitle());
}
public function testCreateElement()
{
$item = new Item();
$item->setTitle(self::TITLE);
$element = $this->object->createElement(new \DOMDocument(), $item);
$this->assertInstanceOf('\DomElement', $element);
$this->assertEquals(self::TITLE, $element->nodeValue);
$this->assertEquals('title', $element->nodeName);
}
}
tests/FeedIo/RuleSetTest.php 0000666 00000003243 13052362033 0012000 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Rule\OptionalField;
class RuleSetTest extends \PHPUnit_Framework_TestCase
{
/**
* @var RuleSet
*/
protected $object;
protected function setUp()
{
$this->object = new RuleSet();
}
public function testAdd()
{
$rule = $this->getMockForAbstractClass('\FeedIo\RuleAbstract');
$this->object->add($rule);
$this->assertEquals($rule, $this->object->get('node'));
}
public function testAddAliases()
{
$name = 'main-node';
$aliases = array('node1', 'node2');
$this->object->addAliases($name, $aliases);
$this->assertEquals($name, $this->object->getNameForAlias('node1'));
$this->assertEquals($name, $this->object->getNameForAlias($name));
}
public function testGetByAlias()
{
$rule = $this->getMockForAbstractClass('\FeedIo\RuleAbstract');
$this->object->add($rule, array('alias'));
$this->assertEquals($rule, $this->object->get('alias'));
}
public function testGetRules()
{
$rule = $this->getMockForAbstractClass('\FeedIo\RuleAbstract');
$this->object->add($rule);
$rules = $this->object->getRules();
$rules[] = new OptionalField('test');
$this->assertCount(2, $rules, '$rules MUST have two offsets');
$this->assertCount(1, $this->object->getRules(), '$this->object->getRules() MUST have one offset');
}
}
tests/FeedIo/Standard/AtomTest.php 0000666 00000001432 13052362033 0013053 0 ustar 00
';
/**
* @var Atom
*/
protected $object;
protected function setUp()
{
$this->object = new Atom(
new DateTimeBuilder()
);
}
public function testFormat()
{
$dom = new \DOMDocument('1.0', 'utf-8');
$dom = $this->object->format($dom);
$this->assertEquals(
str_replace("\n", '', static::FORMATTED_DOCUMENT),
str_replace("\n", '', $dom->saveXML())
);
}
}
tests/FeedIo/Standard/RdfTest.php 0000666 00000001651 13052362033 0012671 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo\Standard;
use FeedIo\Rule\DateTimeBuilder;
class RdfTest extends \PHPUnit_Framework_TestCase
{
const FORMATTED_DOCUMENT = '';
/**
* @var Rdf
*/
protected $object;
protected function setUp()
{
$this->object = new Rdf(
new DateTimeBuilder()
);
}
public function testFormat()
{
$dom = new \DOMDocument('1.0', 'utf-8');
$dom = $this->object->format($dom);
$this->assertEquals(
str_replace("\n", '', static::FORMATTED_DOCUMENT),
str_replace("\n", '', $dom->saveXML())
);
}
}
tests/FeedIo/Standard/RssTest.php 0000666 00000001417 13052362033 0012725 0 ustar 00 ';
/**
* @var Atom
*/
protected $object;
protected function setUp()
{
$this->object = new Rss(
new DateTimeBuilder()
);
}
public function testFormat()
{
$dom = new \DOMDocument('1.0', 'utf-8');
$dom = $this->object->format($dom);
$this->assertEquals(
str_replace("\n", '', static::FORMATTED_DOCUMENT),
str_replace("\n", '', $dom->saveXML())
);
}
}
tests/FeedIo/StandardAbstractTest.php 0000666 00000004422 13052362033 0013641 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FeedIo;
use FeedIo\Rule\DateTimeBuilder;
class StandardAbstractTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \FeedIo\StandardAbstract
*/
protected $object;
public function setUp()
{
$date = new DateTimeBuilder();
$date->addDateFormat(\DateTime::ATOM);
$this->object = $this->getMockForAbstractClass(
'\FeedIo\StandardAbstract',
array($date)
);
$this->object->expects($this->any())->method('canHandle')->will($this->returnValue(true));
$this->object->expects($this->any())->method('buildFeedRuleSet')->will($this->returnValue(new RuleSet()));
$this->object->expects($this->any())->method('buildItemRuleSet')->will($this->returnValue(new RuleSet()));
$this->object->expects($this->any())->method('getMainElement')->will($this->returnValue(new \DOMElement('test')));
}
public function testGetItemNodeName()
{
$this->assertInternalType('string', $this->object->getItemNodeName());
}
public function testGetMandatoryFields()
{
$this->assertInternalType('array', $this->object->getMandatoryFields());
}
public function testGetFeedRuleSet()
{
$this->assertInstanceOf('\FeedIo\RuleSet', $this->object->getFeedRuleSet());
}
public function testGetItemRuleSet()
{
$this->assertInstanceOf('\FeedIo\RuleSet', $this->object->getItemRuleSet());
}
public function testGetModifiedSinceRule()
{
$modifiedSince = $this->object->getModifiedSinceRule('pubDate');
$this->assertInstanceOf('\FeedIo\Rule\ModifiedSince', $modifiedSince);
$this->assertEquals('pubDate', $modifiedSince->getNodeName());
}
public function testBuildBaseRuleSet()
{
$reflection = new \ReflectionClass(get_class($this->object));
$method = $reflection->getMethod('buildBaseRuleSet');
$method->setAccessible(true);
$ruleSet = $method->invoke($this->object);
$this->assertInstanceOf('\FeedIo\RuleSet', $ruleSet);
}
}
tests/FeedIo/StandardFormatter/AtomTest.php 0000666 00000000674 13052362033 0014746 0 ustar 00 standard = $this->newStandard();
}
public function testFormat()
{
$category = new Category();
$category->setTerm('sample');
$category->setLabel('sample');
$category->setScheme('http://localhost');
$date = new \DateTime('2014/12/01');
$feed = new Feed();
$feed->setTitle('sample title');
$feed->setLastModified($date);
$feed->setLink('http://localhost');
$feed->setPublicId(1);
$feed->addCategory($category);
$item = new Item();
$item->setPublicId(42);
$item->setLastModified($date);
$item->setTitle('item title');
$item->setDescription('A great description');
$item->setLink('http://localhost/item/1');
$item->set('author', 'name');
$item->addCategory($category);
$feed->add($item);
$formatter = new Formatter($this->standard, new NullLogger());
$document = $formatter->toDom($feed);
$this->assertXmlStringEqualsXmlFile($this->getSampleFile(), $document->saveXML());
}
protected function getSampleFile()
{
return dirname(__FILE__)."/../../samples/".static::SAMPLE_FILE;
}
}
tests/FeedIo/StandardFormatter/RssTest.php 0000666 00000000674 13052362033 0014615 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$loader = require __DIR__."/../vendor/autoload.php";
$loader->addPsr4('FeedIo\\', __DIR__.'/FeedIo');
date_default_timezone_set('UTC');
tests/live-feeds/StandardFeedsTest.php 0000666 00000012356 13052362033 0014021 0 ustar 00 object = new FeedIo($client, $logger);
}
/**
* @dataProvider provideUrls
*/
public function testFeed($url)
{
try {
$result = $this->object->read($url);
$this->performAssertions($result);
} catch (\FeedIo\Reader\ReadErrorException $e) {
throw $e;
$this->markTestIncomplete("read error : {$e->getMessage()}");
}
}
protected function performAssertions(\FeedIo\Reader\Result $result)
{
$feed = $result->getFeed();
$this->assertInstanceOf('\FeedIo\FeedInterface', $feed);
$this->performStringAssertions(
array(
'title' => $feed->getTitle(),
'link' => $feed->getLink(),
)
);
$this->assertInstanceOf('\DateTime', $feed->getLastModified());
foreach ($feed as $item) {
$this->performItemAssertions($item);
}
}
protected function performItemAssertions(\FeedIo\Feed\ItemInterface $item)
{
$this->assertInstanceOf('\DateTime', $item->getLastModified());
$this->performStringAssertions(
array(
'title' => $item->getTitle(),
'link' => $item->getLink(),
'description' => $item->getDescription(),
)
);
}
protected function performStringAssertions(array $strings)
{
foreach ($strings as $name => $string) {
$this->assertInternalType('string', $string, "$name must be a string");
$this->assertTrue(strlen($string) > 0, "$name cannot be empty");
$this->assertEncodingIsUtf8($string, $name);
}
}
protected function assertEncodingIsUtf8($string, $name)
{
return $this->assertTrue(mb_check_encoding($string, 'utf-8'), "$name must be utf-8 encoded");
}
/**
* @return array
*/
public function provideUrls()
{
$urls = $this->getUrls();
$out = array();
foreach ($urls as $url) {
$out[] = array($url);
}
return $out;
}
protected function getUrls()
{
$localhost = array(
'http://127.0.0.1:8080/feed-io/tests/samples/expected-atom.xml',
'http://127.0.0.1:8080/feed-io/tests/samples/sample-atom.xml',
'http://127.0.0.1:8080/feed-io/tests/samples/sample-atom-html.xml',
'http://127.0.0.1:8080/feed-io/tests/samples/rss/expected-rss.xml',
'http://127.0.0.1:8080/feed-io/tests/samples/rss/sample-rss.xml',
'http://127.0.0.1:8080/feed-io/tests/samples/sample-rdf.xml',
);
$urls = array(
'http://feeds.bbci.co.uk/news/rss.xml?edition=uk',
'http://feeds.feedburner.com/dailyjs',
'http://feeds.feedburner.com/HighScalability',
'http://feeds.feedburner.com/symfony/blog',
'http://feeds.mashable.com/Mashable',
'http://feeds.slate.com/slate',
'http://feeds.wired.com/wired/index',
'http://feeds2.feedburner.com/blogspot/Egta',
'http://feeds2.feedburner.com/LeJournalduGeek',
'http://feeds2.feedburner.com/Webappers',
'http://liberation.fr.feedsportal.com/c/32268/fe.ed/rss.liberation.fr/rss/44/',
'http://liberation.fr.feedsportal.com/c/32268/fe.ed/rss.liberation.fr/rss/54/',
'http://liberation.fr.feedsportal.com/c/32268/fe.ed/rss.liberation.fr/rss/latest/',
'http://linuxfr.org/journaux.atom',
'http://php.net/feed.atom',
'http://pipes.yahoo.com/pipes/pipe.run?_id=647030be6aceb6d005c3775a1c19401c&_render=rss',
'http://rss.lemonde.fr/c/205/f/3050/index.rss',
'http://rss.slashdot.org/Slashdot/slashdot',
'http://rue89.feedsportal.com/c/33822/f/608948/index.rss',
'http://what-if.xkcd.com/feed.atom',
'http://www.debian.org/News/news',
'http://www.gizmodo.fr/feed',
'http://www.larvf.com/rss/article/10135',
'http://www.lemonde.fr/sciences/rss_full.xml',
'http://www.lemonde.fr/technologies/rss_full.xml',
'http://www.metalorgie.com/feed/news',
'http://www.sitepoint.com/feed/',
'http://www.slate.fr/rss.xml',
'http://xkcd.com/rss.xml',
);
return $this->isLocalhostUp() ? array_merge($localhost, $urls) : $urls;
}
/**
*
*/
protected function isLocalhostUp()
{
$client = new \GuzzleHttp\Client();
try {
$response = $client->get('http://127.0.0.1:8080/feed-io/tests/');
return 200 === (int) $response->getStatusCode();
} catch (\Exception $e) {
return false;
}
return true;
}
}
tests/samples/enclosure-atom.xml 0000666 00000001436 13052362033 0013036 0 ustar 00
Example FeedA subtitle.urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af62003-12-13T18:30:02ZA partial entryurn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a2003-12-13T18:30:02Z
A title
A paragraph
tests/samples/expected-atom.xml 0000666 00000001205 13052362033 0012632 0 ustar 00
sample title1Mon, 01 Dec 2014 00:00:00 +0000item title42Mon, 01 Dec 2014 00:00:00 +0000A great descriptionname
tests/samples/rss/expected-rss.xml 0000666 00000001403 13052362033 0013310 0 ustar 00
sample titlesample
http://localhost
1Mon, 01 Dec 2014 00:00:00 +0000Mon, 01 Dec 2014 00:00:00 +0000item titlesample
http://localhost/item/1
42A great descriptionMon, 01 Dec 2014 00:00:00 +0000name
tests/samples/rss/rss-enclosure.xml 0000666 00000001637 13052362033 0013517 0 ustar 00
RSS TitleThis is an example of an RSS feed1
http://www.someexamplerssdomain.com/main.html
Mon, 06 Sep 2010 00:01:00 GMTMon, 06 Sep 2009 16:45:00 GMT1800Example entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 06 Sep 2009 16:45:00 GMTJohn Doe
tests/samples/rss/sample-rss-media.xml 0000666 00000001631 13052362033 0014050 0 ustar 00
RSS TitleThis is an example of an RSS feed
http://www.someexamplerssdomain.com/main.html
Mon, 06 Sep 2010 00:01:00 GMTMon, 06 Sep 2009 16:45:00 GMT1800Example entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 06 Sep 2009 16:45:00 GMTJohn Doe
tests/samples/rss/sample-rss-nodate.xml 0000666 00000002557 13052362033 0014253 0 ustar 00
RSS TitleThis is an example of an RSS feed
http://www.someexamplerssdomain.com/main.html
1800Example entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 06 Sep 2009 16:45:00 GMTJohn DoeExample entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 13 Sep 2009 16:45:00 GMTJohn DoeExample entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 31 Aug 2009 16:45:00 GMTJohn Doe
tests/samples/rss/sample-rss-pubdate.xml 0000666 00000001312 13052362033 0014411 0 ustar 00
RSS TitleThis is an example of an RSS feed
http://www.someexamplerssdomain.com/main.html
Mon, 06 Sep 2009 16:45:00 GMT1800Example entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 06 Sep 2009 16:45:00 GMTJohn Doe
tests/samples/rss/sample-rss.xml 0000666 00000001657 13052362033 0013003 0 ustar 00
RSS TitleThis is an example of an RSS feed1sample
http://www.someexamplerssdomain.com/main.html
Mon, 06 Sep 2010 00:01:00 GMTMon, 06 Sep 2009 16:45:00 GMT1800somethingExample entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 06 Sep 2009 16:45:00 GMTJohn Doe
tests/samples/rss/truncated-rss.xml 0000666 00000001172 13052362033 0013503 0 ustar 00
RSS TitleThis is an example of an RSS feed
http://www.someexamplerssdomain.com/main.html
1800Example entryHere is some text containing an interesting description.
http://www.wikipedia.org/
unique string per itemMon, 06 Sep 2009 16:45:00 +0000
tests/samples/sample-atom-html.xml 0000666 00000002040 13052362033 0013252 0 ustar 00
Example FeedA subtitle.urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af62003-12-13T18:30:02ZAtom-Powered Robots Run Amokurn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a2003-12-13T18:30:02Z
<div> A title </div>
<p> A paragraph </p>
John Doejohndoe@example.comhttp://johndoe.com
tests/samples/sample-atom-namespaced.xml 0000666 00000003021 13052362033 0014406 0 ustar 00
Example FeedA subtitle.urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af62003-12-13T18:30:02ZAtom-Powered Robots Run Amokurn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a2003-12-13T18:30:02Z
A title
A paragraph
John Doejohndoe@example.comhttp://johndoe.comhttp://original-link.com/item.htmlA partial entryurn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a2003-12-13T18:30:02Z
A title
A paragraph
tests/samples/sample-atom.xml 0000666 00000003026 13052362033 0012315 0 ustar 00
Example FeedA subtitle.urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af62003-12-13T18:30:02ZAtom-Powered Robots Run Amokurn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a2003-12-13T18:30:02Z
A title
A paragraph
John Doejohndoe@example.comhttp://johndoe.comA partial entryurn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a2003-12-13T18:30:02Z