This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

6
vendor/essence/essence/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
vendor
.buildpath
.settings
.project

8
vendor/essence/essence/.travis.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
language: php
php:
- 5.4
- 5.5
- 5.6
script: phpunit

25
vendor/essence/essence/LICENSE.txt vendored Normal file
View File

@@ -0,0 +1,25 @@
The FreeBSD License
Copyright (c) 2012, Félix Girault
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.

307
vendor/essence/essence/README.md vendored Normal file
View File

@@ -0,0 +1,307 @@
Essence
=======
[![Build status](https://secure.travis-ci.org/felixgirault/essence.png?branch=master)](http://travis-ci.org/felixgirault/essence)
[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/felixgirault/essence/badges/quality-score.png?s=464b060a5623fa2124308bfc8a41aa8fa6a0ed05)](https://scrutinizer-ci.com/g/felixgirault/essence/)
[![Total downloads](https://poser.pugx.org/fg/essence/d/total.png)](https://packagist.org/packages/fg/essence)
Essence is a simple PHP library to extract media information from websites, like youtube videos, twitter statuses or blog articles.
If you were already using Essence 1.x.x, you should take a look at [the migration guide](https://github.com/felixgirault/essence/wiki/Migrating-from-1.x.x-to-2.x.x).
Also note that a [version 3.0](https://github.com/felixgirault/essence/tree/version-3.0.0) is under active development.
Example
-------
Essence is designed to be really easy to use.
Using the main class of the library, you can retrieve information in just those few lines:
```php
$Essence = Essence\Essence::instance( );
$Media = $Essence->embed( 'http://www.youtube.com/watch?v=39e3KYAmXK4' );
if ( $Media ) {
// That's all, you're good to go !
}
```
Then, just do anything you want with the data:
```html+php
<article>
<header>
<h1><?php echo $Media->title; ?></h1>
<p>By <?php echo $Media->authorName; ?></p>
</header>
<div class="player">
<?php echo $Media->html; ?>
</div>
</article>
```
If you aren't using composer, you should run the Essence bootstrap before using it:
```php
require_once 'path/to/essence/bootstrap.php';
```
What you get
------------
Using Essence, you will mainly interact with Media objects.
Media is a simple container for all the information that are fetched from an URL.
Here are the default properties it provides:
* type
* version
* url
* title
* description
* authorName
* authorUrl
* providerName
* providerUrl
* cacheAge
* thumbnailUrl
* thumbnailWidth
* thumbnailHeight
* html
* width
* height
These properties were gathered from the OEmbed and OpenGraph specifications, and merged together in a united interface.
Based on such standards, these properties should be a solid starting point.
However, "non-standard" properties can and will also be setted.
Here is how you can manipulate the Media properties:
```php
// through dedicated methods
if ( !$Media->has( 'foo' )) {
$Media->set( 'foo', 'bar' );
}
$value = $Media->get( 'foo' );
// or directly like a class attribute
$Media->customValue = 12;
```
Note that Essence will always try to fill the `html` property when it is not available.
Advanced usage
--------------
The Essence class provides some useful utility functions to ensure you will get some information.
### Extracting URLs
The `extract( )` method lets you extract embeddable URLs from a web page.
For example, here is how you could get the URL of all videos in a blog post:
```php
$urls = $Essence->extract( 'http://www.blog.com/article' );
// [
// 'http://www.youtube.com/watch?v=123456'
// 'http://www.dailymotion.com/video/a1b2c_lolcat-fun'
// ]
```
You can then get information from all the extracted URLs:
```php
$medias = $Essence->embedAll( $urls );
// [
// 'http://www.youtube.com/watch?v=123456' => Media( ... )
// 'http://www.dailymotion.com/video/a1b2c_lolcat-fun' => Media( ... )
// ]
```
### Replacing URLs in text
Essence can replace any embeddable URL in a text by information about it.
By default, any URL will be replaced by the `html` property of the found Media.
```php
$text = 'Check out this awesome video: http://www.youtube.com/watch?v=123456'
echo $Essence->replace( $text );
// Check out this awesome video: <iframe src="http://www.youtube.com/embed/123456"></iframe>
```
But you can do more by passing a callback to control which information will replace the URL:
```php
echo $Essence->replace( $text, function( $Media ) {
return sprintf(
'<p class="title">%s</p><div class="player">%s</div>',
$Media->title,
$Media->html
);
});
// Check out this awesome video:
// <p class="title">Video title</p>
// <div class="player">
// <iframe src="http://www.youtube.com/embed/123456"></iframe>
// <div>
```
This makes it easy to build rich templates or even to integrate a templating engine:
```php
echo $Essence->replace( $text, function( $Media ) use ( $TwigTemplate ) {
return $TwigTemplate->render( $Media->properties( ));
});
```
### Configuring providers
It is possible to pass some options to the providers.
For example, OEmbed providers accepts the `maxwidth` and `maxheight` parameters, as specified in the OEmbed spec.
```php
$Media = $Essence->embed( $url, [
'maxwidth' => 800,
'maxheight' => 600
]);
$medias = $Essence->embedAll( $urls, [
'maxwidth' => 800,
'maxheight' => 600
]);
$Media = $Essence->extract( $text, null, [
'maxwidth' => 800,
'maxheight' => 600
]);
```
Other providers will just ignore the options they don't handle.
Configuration
-------------
Essence currently supports 36 specialized providers:
```html
23hq Dipity Official.fm Ted
Bandcamp Flickr Polldaddy Twitter
Blip.tv FunnyOrDie Prezi Vhx
Cacoo HowCast Qik Viddler
CanalPlus Huffduffer Revision3 Vimeo
Chirb.it Hulu Scribd Yfrog
Clikthrough Ifixit Shoudio Youtube
CollegeHumor Imgur Sketchfab
Dailymotion Instagram SlideShare
Deviantart Mobypicture SoundCloud
```
Plus the `OEmbed` and `OpenGraph` providers, which can be used to embed any URL.
You can configure these providers by passing a configuration array:
```php
$Essence = Essence\Essence::instance([
'providers' => [
// the OpenGraph provider will try to embed any URL that matches
// the filter
'Ted' => [
'class' => 'OpenGraph',
'filter' => '#ted\.com/talks/.*#i'
],
// the OEmbed provider will query the endpoint, %s beeing replaced
// by the requested URL.
'Youtube' => [
'class' => 'OEmbed',
'filter' => '#youtube\.com/.*#',
'endpoint' => 'http://www.youtube.com/oembed?format=json&url=%s'
]
]
]);
// you can also load a configuration array from a file
$Essence = Essence\Essence::instance([
'providers' => 'path/to/config/file.php'
]);
```
You can use custom providers by specifying a fully-qualified class name in the 'class' option.
If no configuration is provided, the default configuration will be loaded from the `lib/providers.php` file.
Customization
-------------
Almost everything in Essence can be configured through dependency injection.
Under the hoods, the `instance( )` method uses a dependency injection container to return a fully configured instance of Essence.
To customize the Essence behavior, the easiest way is to configure injection settings when building Essence:
```php
$Essence = Essence\Essence::instance([
// the container will return a new CustomCacheEngine each time a cache
// engine is needed
'Cache' => function( ) {
return new CustomCacheEngine( );
},
// the container will return a unique instance of CustomHttpClient
// each time an HTTP client is needed
'Http' => Essence\Di\Container::unique( function( ) {
return new CustomHttpClient( );
})
]);
```
The default injection settings are defined in the [Standard](https://github.com/felixgirault/essence/blob/master/lib/Essence/Di/Container/Standard.php) container class.
Try it out
----------
Once you've installed essence, you should try to run `./cli/essence.php` in a terminal.
This script allows you to test Essence quickly:
```
# will fetch and print information about the video
./cli/essence.php embed http://www.youtube.com/watch?v=4S_NHY9c8uM
# will fetch and print all embeddable URLs found at the given HTML page
./cli/essence.php extract http://www.youtube.com/watch?v=4S_NHY9c8uM
```
Third-party libraries
---------------------
* Interfaces to integrate other libraries: https://github.com/felixgirault/essence-interfaces
* CakePHP plugin: https://github.com/felixgirault/cakephp-essence
* Demo framework by Sean Steindl: https://github.com/laughingwithu/Essence_demo
* Symfony bundle by Ka Yue Yeung: https://github.com/kayue/KayueEssenceBundle
If you're interested in embedding videos, you should take a look at the [Multiplayer](https://github.com/felixgirault/multiplayer) lib.
It allows you to build customizable embed codes painlessly:
```php
$Multiplayer = new Multiplayer\Multiplayer( );
if ( $Media->type === 'video' ) {
echo $Multiplayer->html( $Media->url, [
'autoPlay' => true,
'highlightColor' => 'BADA55'
]);
}
```

87
vendor/essence/essence/cli/essence.php vendored Normal file
View File

@@ -0,0 +1,87 @@
#!/usr/bin/php -q
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
require_once dirname( dirname( __FILE__ )) . '/lib/bootstrap.php';
/**
*
*/
if ( $argc < 3 ) {
echo "Too few arguments.\n";
} else {
main( $argv[ 1 ], $argv[ 2 ]);
}
/**
*
*/
function main( $method, $url ) {
$Essence = Essence\Essence::instance( );
switch ( $method ) {
case 'embed':
dumpMedia( $Essence->embed( $url ));
break;
case 'extract':
dumpArray( $Essence->extract( $url ));
break;
}
}
/**
*
*/
function dumpMedia( $Media ) {
if ( !$Media ) {
echo "No results.\n";
return;
}
$data = [ ];
foreach ( $Media as $key => $value ) {
if ( $value ) {
$data[ $key ] = $value;
}
}
dumpArray( $data );
}
/**
*
*/
function dumpArray( array $data ) {
if ( empty( $data )) {
echo "No results.\n";
return;
}
$lengths = array_map( 'strlen', array_keys( $data ));
$length = max( $lengths );
foreach ( $data as $key => $value ) {
printf( "%{$length}s: %s\n", $key, $value );
}
}

31
vendor/essence/essence/composer.json vendored Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "fg/essence",
"type": "library",
"description": "Extracts informations about medias on the web, like youtube videos, twitter statuses or blog articles.",
"authors": [{
"name": "Félix Girault",
"email": "felix.girault@gmail.com",
"homepage": "http://www.felix-girault.fr",
"role": "Developer"
}],
"keywords": [
"embed",
"oembed",
"opengraph",
"media"
],
"license": "BSD-2-Clause",
"homepage": "http://github.com/felixgirault/essence",
"require": {
"php": ">=5.4.0",
"ext-curl": "*"
},
"suggest": {
"felixgirault/essence-interfaces": "Allows better integration with different frameworks."
},
"autoload": {
"files": [
"lib/bootstrap.php"
]
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Cache;
/**
* Handles caching.
*
* @package Essence.Cache
*/
interface Engine {
/**
* Returns if data exists for the given key.
*
* @param string $key The key to test.
* @return boolean Whether there is data for the key or not.
*/
public function has( $key );
/**
* Returns the data for the given key.
*
* @param string $key The key to search for.
* @param mixed $default Default value to return if there is no data.
* @return mixed The data.
*/
public function get( $key, $default = false );
/**
* Sets the data for the given key.
*
* @param string $key The key for the data.
* @param mixed $data The data.
* @return mixed $data The passed data.
*/
public function set( $key, $data );
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Cache\Engine;
use Essence\Cache\Engine;
/**
* Does absolutely nothing.
*
* @package Essence.Cache.Engine
*/
class Null implements Engine {
/**
* {@inheritDoc}
*/
public function has( $key ) {
return false;
}
/**
* {@inheritDoc}
*/
public function get( $key, $default = null ) {
return $default;
}
/**
* {@inheritDoc}
*/
public function set( $key, $data ) { }
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Cache\Engine;
use Essence\Cache\Engine;
/**
* Handles caching for a single session.
*
* @package Essence.Cache.Engine
*/
class Volatile implements Engine {
/**
* Data.
*
* @var array
*/
protected $_data = [ ];
/**
* {@inheritDoc}
*/
public function has( $key ) {
return array_key_exists( $key, $this->_data );
}
/**
* {@inheritDoc}
*/
public function get( $key, $default = null ) {
return $this->has( $key )
? $this->_data[ $key ]
: $default;
}
/**
* {@inheritDoc}
*/
public function set( $key, $data ) {
$this->_data[ $key ] = $data;
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
/**
* Allows an object to cache method calls.
*
* @package Essence
*/
trait Cacheable {
/**
* Internal cache engine.
*
* @var Essence\Cache\Engine
*/
protected $_Cache = null;
/**
* Returns the cached result of a method call.
*
* @param string $method The method to cache.
* @param ... mixed Parameters to be passed to the method.
* @return mixed Cached result.
*/
protected function _cached( $method ) {
$signature = $method;
$args = [ ];
if ( func_num_args( ) > 1 ) {
$args = array_slice( func_get_args( ), 1 );
$signature .= json_encode( $args );
}
$key = $this->_cacheKey( $signature );
if ( $this->_Cache->has( $key )) {
return $this->_Cache->get( $key );
}
$result = call_user_func_array( [ $this, $method ], $args );
$this->_Cache->set( $key, $result );
return $result;
}
/**
* Generates a key from the given signature.
*
* @param string $signature Method signature.
* @return string Generated key.
*/
protected function _cacheKey( $signature ) {
return md5( $signature );
}
}

View File

@@ -0,0 +1,175 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
/**
* Makes a class configurable.
*
* @package Essence
*/
trait Configurable {
/**
* An array of properties, to be defined in classes using the trait.
*
* @var array
*/
// protected $_properties = array( );
/**
* @see has( )
*/
public function __isset( $property ) {
return $this->has( $property );
}
/**
* @see get( )
*/
public function __get( $property ) {
return $this->get( $property );
}
/**
* @see set( )
*/
public function __set( $property, $value ) {
return $this->set( $property, $value );
}
/**
* Returns if there is any value for the given property.
*
* @param string $property Property name.
* @param boolean True if the property exists, otherwise false.
*/
public function has( $property ) {
return !empty( $this->_properties[ $property ]);
}
/**
* Returns the value of the given property.
*
* @param string $property Property name.
* @param mixed $default Default value to be returned in case the property
* doesn't exists.
* @return mixed The property value, or $default.
*/
public function get( $property, $default = null ) {
return isset( $this->_properties[ $property ])
? $this->_properties[ $property ]
: $default;
}
/**
* Sets the value of the given property.
*
* @param string $property Property name.
* @param string $value New value.
*/
public function set( $property, $value ) {
$this->_properties[ $property ] = $value;
}
/**
* Sets the value of a property if it is empty.
*
* @param string $property Property name.
* @param string $default Default value.
*/
public function setDefault( $property, $default ) {
if ( !$this->has( $property )) {
$this->set( $property, $default );
}
}
/**
* Sets default values.
*
* @see setDefault( )
* @param string $properties Default properties.
*/
public function setDefaults( $properties ) {
$this->_properties += $properties;
}
/**
* Returns the entire set of properties.
*
* @return array Properties.
*/
public function properties( ) {
return $this->_properties;
}
/**
* Sets the entire set of properties.
*
* @param array $properties Properties to set.
*/
public function setProperties( array $properties ) {
$this->_properties = $properties;
}
/**
* Merges the given properties with the current ones.
*
* @param array $properties Properties to merge.
*/
public function configure( array $properties ) {
$this->_properties = array_merge( $this->_properties, $properties );
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Di;
use Essence\Configurable;
use Closure;
/**
* A simple dependency injection container.
* Inspired by Pimple (https://github.com/fabpot/Pimple).
*
* @package Essence.Di
*/
class Container {
use Configurable;
/**
* Container properties.
*
* @var array
*/
protected $_properties = [ ];
/**
* Returns the value of the given property.
*
* @param string $property Property name.
* @param mixed $default Default value to be returned in case the property
* doesn't exists.
* @return mixed The property value, or the result of the closure execution
* if property is a closure, or $default.
*/
public function get( $property, $default = null ) {
$value = $default;
if ( $this->has( $property )) {
$value = $this->_properties[ $property ];
if ( $value instanceof Closure ) {
$value = $value( $this );
}
}
return $value;
}
/**
* Returns a wrapper that memoizes the result of the given closure.
*
* @param Closure $closure Closure to wrap.
* @return Closure Wrapper.
*/
public static function unique( Closure $closure ) {
return function( $Container ) use ( $closure ) {
static $result = null;
if ( $result === null ) {
$result = $closure( $Container );
}
return $result;
};
}
}

View File

@@ -0,0 +1,183 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Di\Container;
use Essence\Essence;
use Essence\Di\Container;
use Essence\Cache\Engine\Volatile as VolatileCacheEngine;
use Essence\Dom\Parser\Native as NativeDomParser;
use Essence\Http\Client\Curl as CurlHttpClient;
use Essence\Http\Client\Native as NativeHttpClient;
use Essence\Log\Logger\NullClass as NullLogger;
use Essence\Provider\Collection;
use Essence\Provider\OEmbed;
use Essence\Provider\OEmbed\Vimeo;
use Essence\Provider\OEmbed\Youtube;
use Essence\Provider\OpenGraph;
use Essence\Media\Preparator;
use Essence\Media\Preparator\Bandcamp as BandcampPreparator;
use Essence\Media\Preparator\Vine as VinePreparator;
use Essence\Media\Preparator\Youtube as YoutubePreparator;
/**
* Contains the default injection properties.
*
* @package Essence.Di.Container
*/
class Standard extends Container {
/**
* Sets the default properties.
*/
public function __construct( array $properties = [ ]) {
$this->_properties = $properties + [
// Providers are loaded from the default config file
'providers' => ESSENCE_DEFAULT_PROVIDERS,
// A volatile cache engine is shared across the application
'Cache' => Container::unique( function( ) {
return new VolatileCacheEngine( );
}),
// User agent
'HttpUserAgent' => 'Essence',
// A cURL HTTP client is shared across the application
// If cURL isn't available, a native client is used
'Http' => Container::unique( function( $C ) {
$Http = function_exists( 'curl_init' )
? new CurlHttpClient( )
: new NativeHttpClient( );
$Http->setUserAgent( $C->get( 'HttpUserAgent' ));
return $Http;
}),
// A native DOM parser is shared across the application
'Dom' => Container::unique( function( ) {
return new NativeDomParser( );
}),
// A null logger is shared across the application
'Log' => Container::unique( function( ) {
return new NullLogger( );
}),
//
'Preparator' => Container::unique( function( ) {
return new Preparator( );
}),
// The OEmbed provider uses the shared HTTP client, DOM parser
// and logger.
'OEmbed' => function( $C ) {
return new OEmbed(
$C->get( 'Http' ),
$C->get( 'Dom' ),
$C->get( 'Log' ),
$C->get( 'Preparator' )
);
},
// The Vimeo provider uses the shared HTTP client, DOM parser
// and logger.
'Vimeo' => function( $C ) {
return new Vimeo(
$C->get( 'Http' ),
$C->get( 'Dom' ),
$C->get( 'Log' ),
$C->get( 'Preparator' )
);
},
//
'YoutubePreparator' => Container::unique( function( ) {
return new YoutubePreparator( );
}),
// The Youtube provider uses the shared HTTP client, DOM parser
// and logger.
'Youtube' => function( $C ) {
return new Youtube(
$C->get( 'Http' ),
$C->get( 'Dom' ),
$C->get( 'Log' ),
$C->get( 'YoutubePreparator' )
);
},
// The OpenGraph provider uses the shared HTTP client, DOM parser
// and logger.
'OpenGraph' => function( $C ) {
return new OpenGraph(
$C->get( 'Http' ),
$C->get( 'Dom' ),
$C->get( 'Log' ),
$C->get( 'Preparator' )
);
},
//
'BandcampPreparator' => Container::unique( function( ) {
return new BandcampPreparator( );
}),
// The Bandcamp provider uses the shared HTTP client, DOM parser
// and logger.
'Bandcamp' => function( $C ) {
return new OpenGraph(
$C->get( 'Http' ),
$C->get( 'Dom' ),
$C->get( 'Log' ),
$C->get( 'BandcampPreparator' )
);
},
//
'VinePreparator' => Container::unique( function( ) {
return new VinePreparator( );
}),
// The Vine provider uses the shared HTTP client, DOM parser
// and logger.
'Vine' => function( $C ) {
return new OpenGraph(
$C->get( 'Http' ),
$C->get( 'Dom' ),
$C->get( 'Log' ),
$C->get( 'VinePreparator' )
);
},
// The provider collection uses the container
'Collection' => function( $C ) {
$Collection = new Collection( $C );
$Collection->load( $C->get( 'providers' ));
return $Collection;
},
// Essence uses the provider collection, and the shared cache engine,
// HTTP client and DOM parser.
'Essence' => function( $C ) {
return new Essence(
$C->get( 'Collection' ),
$C->get( 'Cache' ),
$C->get( 'Http' ),
$C->get( 'Dom' ),
$C->get( 'Log' )
);
}
];
}
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Dom;
/**
* Handles HTML related operations.
*
* @package Essence.Dom
*/
interface Parser {
/**
* Extracts tags attributes from the given HTML document.
*
* Getting all attributes of all img tags in the document:
*
* @code
* $attributes = Parser::extractAttributes( $html, [ 'img' ]);
* @endcode
*
* Getting src attribute of all img tags in the document:
* (if a tag doesn't have the src attribute, it will not be taken into
* account)
*
* @code
* $attributes = Parser::extractAttributes( $html, [ 'img' => 'src' ]);
* @endcode
*
* Getting src and alt attributes of all img tags in the document:
* (if a tag doesn't have the src or alt attribute, it will not be taken
* into account)
*
* @code
* $attributes = Parser::extractAttributes( $html, [
* 'img' => [
* 'src',
* 'alt'
* ]
* ]);
* @endcode
*
* Getting src attribute of all img tags in the document, where their
* src attribute matches a pattern:
* (if the src attribute of a tag doesn't match the pattern, the tag will
* not be taken into account)
*
* @code
* $attributes = Parser::extractAttributes( $html, [
* 'img' => [
* 'src' => '/foo/i',
* 'alt'
* ]
* ]);
* @endcode
*
* Example result:
*
* @code
* $attributes = Parser::extractAttributes( $html, [
* 'img' => 'src',
* 'a' => [
* 'href' => '/foo/i',
* 'alt'
* ]
* ]);
*
* => [
* 'img' => [
* [ 'src' => 'http://www.website.com/foo.png' ],
* [ 'src' => 'http://www.website.com/bar.png' ],
* ],
* 'a' => [
* [
* 'href' => 'http://www.foo.com',
* 'alt' => 'foo'
* ]
* ]
* ]
* @endcode
*
* @param string $html An HTML document.
* @param array $options Options defining which attributes to extract.
* @return array Extracted attributes indexed by tag name.
*/
public function extractAttributes( $html, array $options );
}

View File

@@ -0,0 +1,148 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Dom\Parser;
use Essence\Dom\Parser;
use Essence\Exception;
use Essence\Utility\Hash;
use DomDocument;
use DomNode;
/**
* Handles HTML related operations through DomDocument.
*
* @package Essence.Dom.Parser
*/
class Native implements Parser {
/**
* {@inheritDoc}
*/
public function extractAttributes( $html, array $options ) {
$Document = $this->_document( $html );
$options = Hash::normalize( $options, [ ]);
$data = [ ];
foreach ( $options as $name => $required ) {
$tags = $Document->getElementsByTagName( $name );
$required = Hash::normalize(( array )$required, '' );
$data[ $name ] = [ ];
foreach ( $tags as $Tag ) {
if ( $Tag->hasAttributes( )) {
$attributes = $this->_extractAttributesFromTag(
$Tag,
$required
);
if ( !empty( $attributes )) {
$data[ $name ][ ] = $attributes;
}
}
}
}
return $data;
}
/**
* Builds and returns a DomDocument from the given HTML source.
*
* @param string $html HTML source.
* @return DomDocument DomDocument.
*/
protected function _document( $html ) {
$reporting = error_reporting( 0 );
$html = $this->fixCharset( $html );
$Document = DomDocument::loadHTML( $html );
error_reporting( $reporting );
if ( !$Document ) {
throw new Exception( 'Unable to load HTML document.' );
}
return $Document;
}
/**
* If necessary, fixes the given HTML's charset to work with the current
* version of Libxml (used by DomDocument). Older versions of Libxml
* recognize only
*
* <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
*
* from HTML4, and not the new HTML5 form:
*
* <meta charset="utf-8">
*
* with the result that parsed strings can have funny characters.
*
* @param string $html HTML source.
* @return string the fixed HTML
* @see "HTML5, character encodings and DOMDocument loadHTML and loadHTMLFile"
* http://www.glenscott.co.uk/blog/html5-character-encodings-and-domdocument-loadhtml-and-loadhtmlfile/
*/
protected function fixCharset( $html ) {
// The fix is from https://github.com/glenscott/dom-document-charset/blob/master/DOMDocumentCharset.php
if ( LIBXML_VERSION < 20800 && stripos($html, 'meta charset') !== false ) {
$html = preg_replace( '/<meta charset=["\']?([^"\']+)"/i',
'<meta http-equiv="Content-Type" content="text/html; charset=$1"',
$html );
}
return $html;
}
/**
* Extracts attributes from the given tag.
*
* @param DOMNode $Tag Tag to extract attributes from.
* @param array $required Required attributes.
* @return array Extracted attributes.
*/
protected function _extractAttributesFromTag( DOMNode $Tag, array $required ) {
$attributes = [ ];
foreach ( $Tag->attributes as $name => $Attribute ) {
if ( !empty( $required )) {
if ( isset( $required[ $name ])) {
$pattern = $required[ $name ];
if ( $pattern && !preg_match( $pattern, $Attribute->value )) {
return [ ];
}
} else {
continue;
}
}
$attributes[ $name ] = $Attribute->value;
}
$diff = array_diff_key( $required, $attributes );
return empty( $diff )
? $attributes
: [ ];
}
}

View File

@@ -0,0 +1,344 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use Essence\Cacheable;
use Essence\Configurable;
use Essence\Di\Container\Standard as StandardContainer;
use Essence\Cache\Engine as CacheEngine;
use Essence\Dom\Parser as DomParser;
use Essence\Http\Client as HttpClient;
use Essence\Log\Logger;
use Essence\Provider\Collection;
use Essence\Exception;
/**
* Gathers embed informations from URLs.
*
* @package Essence
*/
class Essence {
use Cacheable;
use Configurable;
/**
* A collection of providers to query.
*
* @var Essence\ProviderCollection
*/
protected $_Collection = null;
/**
* Internal HTTP client.
*
* @var Essence\Http\Client
*/
protected $_Http = null;
/**
* Internal DOM parser.
*
* @var Essence\Dom\Parser
*/
protected $_Dom = null;
/**
* Internal Logger.
*
* @var Essence\Log\Logger
*/
protected $_Logger = null;
/**
* Configuration options.
*
* ### Options
*
* - 'urlPattern' string A pattern to match URLs.
*
* @var array
*/
protected $_properties = [
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
'urlPattern' =>
'#
(?<url>
(?<!=["\'])
(?:https?:)//
(?:www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)?
(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+
(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'"\.,<>?«»“”‘’])
)
#ix'
];
/**
* Constructor.
*
* @param Essence\ProviderCollection $Collection Provider collection.
* @param Essence\Cache\Engine $Cache Cache engine.
* @param Essence\Http\Client $Http HTTP client.
* @param Essence\Dom\Parser $Cache DOM parser.
* @param Essence\Log\Logger $Logger Logger.
*/
public function __construct(
Collection $Collection,
CacheEngine $Cache,
HttpClient $Http,
DomParser $Dom,
Logger $Logger
) {
$this->_Collection = $Collection;
$this->_Cache = $Cache;
$this->_Http = $Http;
$this->_Dom = $Dom;
$this->_Logger = $Logger;
}
/**
* Builds a fully configured instance of Essence.
*
* @param array $configuration Dependency injection configuration.
* @return Essence\Essence Essence instance.
*/
public static function instance( array $configuration = [ ]) {
$Container = new StandardContainer( $configuration );
return $Container->get( 'Essence' );
}
/**
* Extracts embeddable URLs from either an URL or an HTML source.
*
* @param string $source The URL or HTML source to be extracted.
* @return array An array of extracted URLs.
*/
public function extract( $source ) {
return $this->_cached( '_extract', $source );
}
/**
* Implementation of the extract method.
*
* @see extract( )
* @param string $source The URL or HTML source to be extracted.
* @return array An array of extracted URLs.
*/
protected function _extract( $source ) {
if ( filter_var( $source, FILTER_VALIDATE_URL )) {
try {
$source = $this->_Http->get( $source );
} catch ( Exception $Exception ) {
$this->_Logger->log(
Logger::notice,
"Unable to fetch $source",
[ 'exception' => $Exception ]
);
return [ ];
}
}
$urls = $this->_extractUrls( $source );
$embeddable = [ ];
foreach ( $urls as $url ) {
if ( $this->_Collection->hasProvider( $url )) {
$embeddable[ ] = $url;
}
}
return array_unique( $embeddable );
}
/**
* Extracts URLs from an HTML source.
*
* @param string $html The HTML source to extract URLs from.
* @return array Extracted URLs.
*/
protected function _extractUrls( $html ) {
$options = [
'a' => 'href',
'embed' => 'src',
'iframe' => 'src'
];
try {
$attributes = $this->_Dom->extractAttributes( $html, $options );
} catch ( Exception $Exception ) {
$this->_Logger->log(
Logger::notice,
'Error parsing HTML source',
[ 'exception' => $Exception, 'html' => $html ]
);
return [ ];
}
$urls = [ ];
foreach ( $options as $tagName => $attributeName ) {
foreach ( $attributes[ $tagName ] as $tag ) {
$urls[ ] = $tag[ $attributeName ];
}
}
return $urls;
}
/**
* Fetches embed informations from the given URL.
*
* This method now supports an array of options that can be interpreted
* at will by the providers.
*
* Thanks to Peter Niederlag (https://github.com/t3dev) for his request
* (https://github.com/felixgirault/essence/pull/1).
*
* @param string $url URL to fetch informations from.
* @param array $options Custom options to be interpreted by a provider.
* @return Essence\Media Embed informations.
*/
public function embed( $url, array $options = [ ]) {
return $this->_cached( '_embed', $url, $options );
}
/**
* Implementation of the embed method.
*
* @see embed( )
* @param string $url URL to fetch informations from.
* @param array $options Custom options to be interpreted by a provider.
* @return Essence\Media Embed informations.
*/
protected function _embed( $url, array $options ) {
$providers = $this->_Collection->providers( $url );
$Media = null;
foreach ( $providers as $Provider ) {
if ( $Media = $Provider->embed( $url, $options )) {
break;
}
}
return $Media;
}
/**
* Fetches embed informations from the given URLs.
*
* @param array $urls An array of URLs to fetch informations from.
* @param array $options Custom options to be interpreted by a provider.
* @return array An array of embed informations, indexed by URL.
*/
public function embedAll( array $urls, array $options = [ ]) {
$medias = [ ];
foreach ( $urls as $url ) {
$medias[ $url ] = $this->embed( $url, $options );
}
return $medias;
}
/**
* Replaces URLs in the given text by media informations if they point on
* an embeddable resource.
* By default, links will be replaced by the html property of Media.
* If $callback is a callable function, it will be used to generate
* replacement strings, given a Media object.
*
* @code
* $text = $Essence->replace( $text, function( $Media ) {
* return '<div class="title">' . $Media->title . '</div>';
* });
* @endcode
*
* This behavior should make it easy to integrate third party templating
* engines.
* The pattern to match urls can be configured using the 'urlPattern'
* configuration option.
*
* Thanks to Stefano Zoffoli (https://github.com/stefanozoffoli) for his
* idea (https://github.com/felixgirault/essence/issues/4).
*
* @param string $text Text in which to replace URLs.
* @param callable $callback Templating callback.
* @param array $options Custom options to be interpreted by a provider.
* @return string Text with replaced URLs.
*/
public function replace( $text, $callback = null, array $options = [ ]) {
return preg_replace_callback(
$this->urlPattern,
function ( $matches ) use ( $callback, $options ) {
if ( $Media = $this->embed( $matches['url'], $options )) {
return is_callable( $callback )
? call_user_func( $callback, $Media )
: $Media->get( 'html' );
}
return $matches['url'];
},
$text
);
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use Exception as NativeException;
/**
* The base exception class of the Essence API.
*
* @package Essence
*/
class Exception extends NativeException {
/**
* Wraps a native PHP exception.
*
* @param NativeException Native exception.
* @return Exception Essence exception.
*/
public static function wrap( NativeException $Exception ) {
return new Exception(
$Exception->getMessage( ),
$Exception->getCode( ),
$Exception
);
}
/**
* An alias to fit the Essence coding style.
* I'm probably mad.
*
* @return string The exception message.
*/
public function message( ) {
return $this->getMessage( );
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Http;
/**
* Handles HTTP related operations.
*
* @package Essence.Http
*/
abstract class Client {
/**
* User agent.
*
* @var string
*/
protected $_userAgent = '';
/**
* Retrieves contents from the given URL.
*
* @param string $url The URL fo fetch contents from.
* @return string The contents.
* @throws Essence\Http\Exception
*/
abstract public function get( $url );
/**
* Sets the user agent for HTTP requests.
*
* @param string $userAgent User agent.
*/
public function setUserAgent( $userAgent ) {
$this->_userAgent = $userAgent;
}
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Http\Client;
use Essence\Http\Client;
use Essence\Http\Exception;
/**
* Handles HTTP related operations through cURL.
*
* @package Essence.Http.Client
*/
class Curl extends Client {
/**
* CURL handle.
*
* @var resource
*/
protected $_curl = null;
/**
* Default cURL options, takes precedence over the user options.
*
* @var array
*/
protected $_defaults = [
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true
];
/**
* Initializes cURL with the given options.
*
* @param array cURL options.
*/
public function __construct( array $options = [ ]) {
$this->_curl = curl_init( );
curl_setopt_array(
$this->_curl,
$this->_defaults + $options
);
}
/**
* Closes cURL connexion.
*/
public function __destruct( ) {
curl_close( $this->_curl );
}
/**
* {@inheritDoc}
*/
public function get( $url ) {
curl_setopt( $this->_curl, CURLOPT_URL, $url );
curl_setopt( $this->_curl, CURLOPT_USERAGENT, $this->_userAgent );
$contents = curl_exec( $this->_curl );
if ( $contents === false ) {
throw new Exception(
$url,
curl_getinfo( $this->_curl, CURLINFO_HTTP_CODE )
);
}
return $contents;
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Http\Client;
use Essence\Http\Client;
use Essence\Http\Exception;
/**
* Handles HTTP related operations through file_get_contents( ).
*
* @package Essence.Http.Client
*/
class Native extends Client {
/**
* Default HTTP status code.
*
* @var int
*/
protected $_defaultCode;
/**
* Constructor.
*
* @param int $defaultCode The default HTTP status code to assume if
* response headers cannot be parsed.
*/
public function __construct( $defaultCode = 404 ) {
$this->_defaultCode = $defaultCode;
}
/**
* Retrieves contents from the given URL.
* Thanks to Diije for the hint on $http_response_header
* (http://www.felix-girault.fr/astuces/recuperer-une-page-web-en-php/#comment-1029).
*
* @param string $url The URL fo fetch contents from.
* @return string The fetched contents.
* @throws Essence\Http\Exception
*/
public function get( $url ) {
$options = [
'http' => [
'user_agent' => $this->_userAgent
]
];
$context = stream_context_create( $options );
$reporting = error_reporting( 0 );
$contents = file_get_contents( $url, false, $context );
error_reporting( $reporting );
if ( $contents === false ) {
$code = $this->_defaultCode;
if ( isset( $http_response_header )) {
preg_match(
'#^HTTP/[0-9\.]+\s(?P<code>[0-9]+)#i',
$http_response_header[ 0 ],
$matches
);
if ( isset( $matches['code'])) {
$code = $matches['code'];
}
}
// let's assume the file doesn't exists
throw new Exception( $url, $code );
}
return $contents;
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Http;
use Essence\Exception as EssenceException;
/**
* An HTTP related exception.
*
* @package Essence.Http
*/
class Exception extends EssenceException {
/**
* Error URL.
*
* @var string
*/
protected $_url = '';
/**
* Messages corresponding to HTTP codes.
* Thanks to Hinnerk Brügmann
* (http://www.multiasking.com/2011/05/http-error-codes-as-php-array/).
*
* @var array
*/
protected $_messages = [
// Client errors
400 => 'Bad request',
401 => 'Unauthorized',
402 => 'Payment required',
403 => 'Forbidden',
404 => 'Not found',
405 => 'Method not allowed',
406 => 'Not acceptable',
407 => 'Proxy authentication required',
408 => 'Request timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length required',
412 => 'Precondition failed',
413 => 'Request entity too large',
414 => 'Request-URL too long',
415 => 'Unsupported media type',
416 => 'Requested range not satisfiable',
417 => 'Expectation failed',
// Server errors
500 => 'Internal server error',
501 => 'Not implemented',
502 => 'Bad gateway',
503 => 'Service unavailable',
504 => 'Gateway timeout',
505 => 'HTTP version not supported'
];
/**
* Constructs the exception with the given HTTP status code, and the URL
* that triggered the error.
*
* @param string $url URL.
* @param int $code HTTP status code.
* @param Exception $Previous Previous exception.
*/
public function __construct( $url, $code = 0, Exception $Previous = null ) {
$this->_url = $url;
parent::__construct(
isset( $this->_messages[ $code ])
? $this->_messages[ $code ]
: 'HTTP error',
$code,
$Previous
);
}
/**
* Returns the URL that triggered the error.
*
* @return string URL.
*/
public function url( ) {
return $this->_url;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Log;
/**
* A very basic logger.
* Inspired by PSR log (https://github.com/php-fig/log).
*
* @package Essence.Log
*/
interface Logger {
/**
* Log level for normal but significant events.
*
* @var string
*/
const notice = 'notice';
/**
* Logs a message.
*
* @param mixed $level Level.
* @param string $message Message.
* @param array $context Context.
*/
public function log( $level, $message, array $context = [ ]);
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Log\Logger;
use Essence\Log\Logger;
/**
* Does absolutely nothing.
*
* @package Essence.Log.Logger
*/
class NullClass implements Logger {
/**
* {@inheritDoc}
*/
public function log( $level, $message, array $context = [ ]) { }
}

View File

@@ -0,0 +1,144 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use ArrayIterator;
use IteratorAggregate;
use JsonSerializable;
use Essence\Configurable;
/**
* Stores informations about an embed response.
* This class is useful to ensure that any response from any provider will
* follow the same conventions.
*
* @package Essence
*/
class Media implements IteratorAggregate, JsonSerializable {
use Configurable;
/**
* Embed data, indexed by property name. Providers must try to fill these
* default properties with appropriate data before adding their own, to
* ensure consistency accross the API.
*
* These default properties are gathered from the OEmbed and OpenGraph
* protocols, and provide all the basic informations needed to embed a
* media.
*
* @var array
*/
protected $_properties = [
// OEmbed type
// OG type
'type' => '',
// OEmbed version
'version' => '',
// OEmbed title
// OG title
'title' => '',
// Sometimes provided in OEmbed (i.e. Vimeo)
// OG description
'description' => '',
// OEmbed author_name
'authorName' => '',
// OEmbed author_url
'authorUrl' => '',
// OEmbed provider_name
// OG site_name
'providerName' => '',
// OEmbed provider_url
'providerUrl' => '',
// OEmbed cache_age
'cacheAge' => '',
// OEmbed thumbnail_url
// OG image
// OG image:url
'thumbnailUrl' => '',
// OEmbed thumbnail_width
'thumbnailWidth' => '',
// OEmbed thumbnail_height
'thumbnailHeight' => '',
// OEmbed html
'html' => '',
// OEmbed width
// OG image:width
// OG video:width
'width' => '',
// OEmbed height
// OG image:height
// OG video:height
'height' => '',
// OEmbed url
// OG url
'url' => ''
];
/**
* Constructs a Media from the given dataset.
*
* @see $properties
* @param array $properties An array of media informations.
*/
public function __construct( array $properties ) {
$this->configure( $properties );
}
/**
* Returns an iterator for the media properties.
*
* @return ArrayIterator Iterator.
*/
public function getIterator( ) {
return new ArrayIterator( $this->_properties );
}
/**
* Returns serialized properties.
*
* @return string JSON representation.
*/
public function jsonSerialize( ) {
return $this->_properties;
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Media;
use Essence\Media;
/**
*
*
* @package Essence.Media
*/
class Preparator {
/**
*
*/
protected $_defaults = [
'width' => 640,
'height' => 490
];
/**
* Builds an HTML code from the given media's properties to fill its
* 'html' property.
*
* @param Essence\Media $Media A reference to the Media.
* @param array $options Options.
*/
public function complete( Media $Media, array $options = [ ]) {
if ( $Media->has( 'html' )) {
return;
}
$title = htmlspecialchars( $Media->get( 'title', $Media->url ));
$description = $Media->has( 'description' )
? htmlspecialchars( $Media->description )
: $title;
$options += $this->_defaults;
$width = $Media->setDefault( 'width', $options['width']);
$height = $Media->setDefault( 'height', $options['height']);
switch ( $Media->type ) {
// builds an <img> tag pointing to the photo
case 'photo':
$Media->set( 'html', sprintf(
'<img src="%s" alt="%s" width="%d" height="%d" />',
$Media->url,
$description,
$width,
$height
));
break;
// builds an <iframe> tag pointing to the video
case 'video':
$Media->set( 'html', sprintf(
'<iframe src="%s" width="%d" height="%d" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen />',
$Media->url,
$width,
$height
));
break;
// builds an <a> tag pointing to the original resource
default:
$Media->set( 'html', sprintf(
'<a href="%s" alt="%s">%s</a>',
$Media->url,
$description,
$title
));
break;
}
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Media\Preparator;
use Essence\Media\Preparator;
use Essence\Media;
/**
* Builds an HTML code for the Bandcamp player.
*
* @package Essence.Media.Preparator
*/
class Bandcamp extends Preparator {
/**
* {@inheritDoc}
*/
public function complete( Media $Media, array $options = [ ]) {
parent::complete( $Media, $options );
if (
$Media->has( 'og:video' )
&& ( $Media->get( 'og:video:type') === 'application/x-shockwave-flash' )
&& preg_match( '/((album|track)=\d+)/', $Media->get( 'og:video' ), $matches )
) {
$url = htmlspecialchars( $Media->get( 'url' ));
$title = htmlspecialchars( $Media->get( 'title' ));
$height = ( $matches[ 2 ] == 'album' )
? 470
: 442;
$Media->set( 'html:small', '<iframe style="border: 0; width: 100%; height: 42px;" src="http://bandcamp.com/EmbeddedPlayer/' . $matches[ 1 ] . '/size=small/bgcol=ffffff/linkcol=0687f5/transparent=true/" seamless><a href="' . htmlspecialchars($Media->get('url')) . '">' . $title . '</a></iframe>' );
$Media->set( 'html:medium', '<iframe style="border: 0; width: 100%; height: 120px;" sr="http://bandcamp.com/EmbeddedPlayer/' . $matches[ 1 ] . '/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/artwork=small/transparent=true/" seamless><a href="' . $url . '">' . $title . '</a></iframe>' );
$Media->set( 'html:large', '<iframe style="border: 0; width: 350px; height: ' . $height . 'px;" src="http://bandcamp.com/EmbeddedPlayer/' . $matches[ 1 ] . '/size=large/bgcol=ffffff/linkcol=0687f5/tracklist=false/transparent=true/" seamless><a href="' . $url . '">' . $title . '</a></iframe>' );
$Media->set('html', $Media->get( 'html:small' ));
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Media\Preparator;
use Essence\Media\Preparator;
use Essence\Media;
/**
* Builds an HTML code for the Vine player.
*
* @package Essence.Media.Preparator
*/
class Vine extends Preparator {
/**
* {@inheritDoc}
*/
public function complete( Media $Media, array $options = [ ]) {
parent::complete( $Media, $options );
if (
( $Media->get( 'type' ) === 'vine-app:video' )
&& preg_match( '#https?://vine.co/v/[a-zA-Z0-9]+#i', $Media->get( 'url' ), $matches )
) {
$Media->set( 'html:small', '<iframe class="vine-embed" src="' . $matches[ 0 ] . '/embed/postcard" width="320" height="320" frameborder="0"></iframe><script async src="//platform.vine.co/static/scripts/embed.js" charset="utf-8"></script>' );
$Media->set( 'html:medium', '<iframe class="vine-embed" src="' . $matches[ 0 ] . '/embed/postcard" width="480" height="480" frameborder="0"></iframe><script async src="//platform.vine.co/static/scripts/embed.js" charset="utf-8"></script>' );
$Media->set( 'html:large', '<iframe class="vine-embed" src="' . $matches[ 0 ] . '/embed/postcard" width="600" height="600" frameborder="0"></iframe><script async src="//platform.vine.co/static/scripts/embed.js" charset="utf-8"></script>' );
$Media->set( 'html', $Media->get( 'html:small' ));
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Media\Preparator;
use Essence\Media\Preparator;
use Essence\Media;
/**
* Handles custom thumbnail formats.
*
* @package Essence.Media.Preparator
*/
class Youtube extends Preparator {
/**
* {@inheritDoc}
*
* @param array $options Embed options.
* - 'thumbnailFormat' string
*/
public function complete( Media $Media, array $options = [ ]) {
parent::complete( $Media, $options );
if ( isset( $options['thumbnailFormat'])) {
$url = $Media->get( 'thumbnailUrl' );
switch ( $options['thumbnailFormat']) {
case 'small':
$url = str_replace( 'hqdefault', 'default', $url );
break;
case 'medium':
$url = str_replace( 'hqdefault', 'mqdefault', $url );
break;
// CAUTION!
// this thumbnail format might not be available for all videos
case 'max':
$url = str_replace( 'hqdefault', 'maxresdefault', $url );
break;
case 'large':
default:
// unchanged
break;
}
$Media->set( 'thumbnailUrl', $url );
}
}
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use Essence\Configurable;
use Essence\Exception;
use Essence\Media;
use Essence\Media\Preparator;
use Essence\Log\Logger;
/**
* Base class for a Provider.
*
* @package Essence
*/
abstract class Provider {
use Configurable;
/**
* Internal logger.
*
* @var Essence\Log\Logger
*/
protected $_Logger = null;
/**
* Media preparator.
*
* @var Essence\Media\Preparator
*/
protected $_Preparator = null;
/**
* Configuration options.
*
* ### Options
*
* - 'prepare' callable( string $url ) A function to prepare the given URL.
*
* @var array
*/
protected $_properties = [
'prepare' => 'self::prepareUrl'
];
/**
* Constructor.
*
* @param Essence\Log\Logger $Logger Logger.
* @param Essence\Log\Preparator $Preparator Preparator.
*/
public function __construct( Logger $Logger, Preparator $Preparator = null ) {
$this->_Logger = $Logger;
$this->_Preparator = $Preparator;
}
/**
* Fetches embed information from the given URL.
*
* @param string $url URL to fetch informations from.
* @param array $options Custom options to be interpreted by the provider.
* @return Media|null Embed informations, or null if nothing could be
* fetched.
*/
public final function embed( $url, array $options = [ ]) {
$Media = null;
if ( is_callable( $this->prepare )) {
$url = call_user_func( $this->prepare, $url, $options );
}
try {
$Media = $this->_embed( $url, $options );
$Media->setDefault( 'url', $url );
if ( $this->_Preparator ) {
$this->_Preparator->complete( $Media, $options );
}
} catch ( Exception $Exception ) {
$this->_Logger->log(
Logger::notice,
"Unable to embed $url",
[ 'exception' => $Exception ]
);
}
return $Media;
}
/**
* Does the actual fetching of informations.
*
* @param string $url URL to fetch informations from.
* @param array $options Custom options to be interpreted by the provider.
* @return Media Embed informations.
* @throws Essence\Exception
*/
abstract protected function _embed( $url, array $options );
/**
* Trims and returns the given string.
*
* @param string $url URL.
* @param array $options Embed options.
* @return string Trimmed URL.
*/
public static function prepareUrl( $url, array $options = [ ]) {
return trim( $url );
}
}

View File

@@ -0,0 +1,188 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider;
use Essence\Configurable;
use Essence\Di\Container;
use Essence\Exception;
/**
* A collection of providers which can find the provider of an url.
*
* @package Essence.Provider
*/
class Collection {
use Configurable;
/**
* Dependency injection container.
*
* @var Essence\Di\Container
*/
protected $_Container = null;
/**
* A list of provider configurations.
*
* ### Options
*
* - 'name' string Name of the provider.
* - 'class' string The provider class.
* - 'filter' string|callable A regex or callback to filter URLs
* that will be processed by the provider.
* - ... mixed Provider specific options.
*
* @var array
*/
protected $_properties = [ ];
/**
* A list of providers.
*
* @var array
*/
protected $_providers = [ ];
/**
* Constructor.
*
* @param Essence\Di\Container $Container Dependency injection container
* used to build providers.
*/
public function __construct( Container $Container ) {
$this->_Container = $Container;
}
/**
* Loads configuration from an array or a file.
*
* @throws Essence\Exception If the configuration is not an array.
* @param array|string $config A configuration array, or a configuration
* file returning such an array.
*/
public function load( $config ) {
if ( is_string( $config ) && file_exists( $config )) {
$config = include $config;
}
if ( !is_array( $config )) {
throw new Exception(
'The configuration must be an array.'
);
}
$this->configure( $config );
}
/**
* Tells if a provider was found for the given url.
*
* @param string $url An url which may be embedded.
* @return mixed The url provider if any, otherwise null.
*/
public function hasProvider( $url ) {
foreach ( $this->_properties as $config ) {
if ( $this->_matches( $config['filter'], $url )) {
return true;
}
}
return false;
}
/**
* Finds providers of the given url.
*
* @todo Use PHP generators to yield providers.
* @param string $url An url which may be embedded.
* @return array An array of Essence\Provider.
*/
public function providers( $url ) {
$providers = [ ];
foreach ( $this->_properties as $name => $config ) {
if ( $this->_matches( $config['filter'], $url )) {
$providers[ ] = $this->_provider( $name, $config );
}
}
return $providers;
}
/**
* Tells if an URL matches a filter.
*
* @param string|callable $filter Regex or callback to filter URL.
* @param string $url URL to filter.
* @return Whether the URL matches the filter or not.
*/
protected function _matches( $filter, $url ) {
return is_callable( $filter )
? call_user_func( $filter, $url )
: preg_match( $filter, $url );
}
/**
* Lazy loads a provider given its name and configuration.
*
* @param string $name Name.
* @param string $config Configuration.
* @return Provider Instance.
*/
protected function _provider( $name, $config ) {
if ( !isset( $this->_providers[ $name ])) {
$class = $config['class'];
$Provider = $this->_Container->has( $class )
? $this->_Container->get( $class )
: new $class( );
$Provider->configure( $config );
$this->_providers[ $name ] = $Provider;
}
return $this->_providers[ $name ];
}
}

View File

@@ -0,0 +1,267 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider;
use Essence\Exception;
use Essence\Media;
use Essence\Media\Preparator;
use Essence\Provider;
use Essence\Dom\Parser as DomParser;
use Essence\Http\Client as HttpClient;
use Essence\Log\Logger;
use Essence\Utility\Hash;
use Essence\Utility\Json;
use Essence\Utility\Xml;
/**
* Base class for an OEmbed provider.
* This kind of provider extracts embed informations through the OEmbed protocol.
*
* @package Essence.Provider
*/
class OEmbed extends Provider {
/**
* JSON response format.
*
* @var string
*/
const json = 'json';
/**
* XML response format.
*
* @var string
*/
const xml = 'xml';
/**
* Internal HTTP client.
*
* @var Essence\Http\Client
*/
protected $_Http = null;
/**
* Internal DOM parser.
*
* @var Essence\Dom\Parser
*/
protected $_Dom = null;
/**
* ### Options
*
* - 'endpoint' string The OEmbed endpoint.
* - 'format' string The expected response format.
*/
protected $_properties = [
'prepare' => 'static::prepareUrl',
'endpoint' => '',
'format' => self::json
];
/**
* Constructor.
*
* @param Essence\Http\Client $Http HTTP client.
* @param Essence\Dom\Parser $Dom DOM parser.
* @param Essence\Log\Logger $Log Logger.
* @param Essence\Log\Preparator $Preparator Preparator.
*/
public function __construct(
HttpClient $Http,
DomParser $Dom,
Logger $Log,
Preparator $Preparator = null
) {
$this->_Http = $Http;
$this->_Dom = $Dom;
parent::__construct( $Log, $Preparator );
}
/**
* Strips arguments and anchors from the given URL.
*
* @param string $url Url to prepare.
* @return string Prepared url.
*/
public static function prepareUrl( $url, array $options = [ ]) {
$url = trim( $url );
if ( !self::strip( $url, '?' )) {
self::strip( $url, '#' );
}
return $url;
}
/**
* Strips the end of a string after a delimiter.
*
* @param string $string The string to strip.
* @param string $delimiter The delimiter from which to strip the string.
* @return boolean True if the string was modified, otherwise false.
*/
public static function strip( &$string, $delimiter ) {
$position = strrpos( $string, $delimiter );
$found = ( $position !== false );
if ( $found ) {
$string = substr( $string, 0, $position );
}
return $found;
}
/**
* {@inheritDoc}
*
* @note If no endpoint was specified in the configuration, the page at
* the given URL will be parsed to find one.
* @throws Essence\Exception If the parsed page doesn't provide any endpoint.
*/
protected function _embed( $url, array $options ) {
if ( $this->endpoint ) {
$endpoint = sprintf( $this->endpoint, urlencode( $url ));
$format = $this->format;
} else if ( !$this->_extractEndpoint( $url, $endpoint, $format )) {
throw new Exception(
"Unable to extract any endpoint from '$url'."
);
}
if ( $options ) {
$this->_completeEndpoint( $endpoint, $options );
}
return $this->_embedEndpoint( $endpoint, $format );
}
/**
* Extracts an oEmbed endpoint from the given URL.
*
* @param string $url URL from which to extract an endpoint.
* @param string $endpoint The extracted endpoint.
* @param string $format The extracted format.
* @return boolean If an endpoint was extracted.
*/
protected function _extractEndpoint( $url, &$endpoint, &$format ) {
$attributes = $this->_Dom->extractAttributes( $this->_Http->get( $url ), [
'link' => [
'rel' => '#alternate#i',
'type',
'href'
]
]);
foreach ( $attributes['link'] as $link ) {
if ( preg_match( '#(?<format>json|xml)#i', $link['type'], $matches )) {
$endpoint = $link['href'];
$format = $matches['format'];
return true;
}
}
return false;
}
/**
* Appends a set of options as parameters to the given endpoint URL.
*
* @param string $endpoint Endpoint URL.
* @param array $options Options to append.
*/
protected function _completeEndpoint( &$endpoint, $options ) {
if ( $options ) {
$endpoint .= ( strrpos( $endpoint, '?' ) === false ) ? '?' : '&';
$endpoint .= http_build_query( $options );
}
}
/**
* Fetches embed information from the given endpoint.
*
* @param string $endpoint Endpoint to fetch informations from.
* @param string $format Response format.
* @return Media Embed informations.
*/
protected function _embedEndpoint( $endpoint, $format ) {
$response = $this->_Http->get( $endpoint );
switch ( $format ) {
case self::json:
$data = Json::parse( $response );
break;
case self::xml:
$data = Xml::parse( $response );
break;
default:
throw new Exception( 'Unsupported response format.' );
}
return new Media(
Hash::reindex( $data, [
'author_name' => 'authorName',
'author_url' => 'authorUrl',
'provider_name' => 'providerName',
'provider_url' => 'providerUrl',
'cache_age' => 'cacheAge',
'thumbnail_url' => 'thumbnailUrl',
'thumbnail_width' => 'thumbnailWidth',
'thumbnail_height' => 'thumbnailHeight'
])
);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider\OEmbed;
use Essence\Provider\OEmbed;
/**
*
*
* @package Essence.Provider.OEmbed
*/
class Vimeo extends OEmbed {
/**
* Refactors URLs like these:
* - http://player.vimeo.com/video/20830433
*
* in such form:
* - http://www.vimeo.com/20830433
*
* @param string $url Url to prepare.
* @return string Prepared url.
*/
public static function prepareUrl( $url, array $options = [ ]) {
$url = parent::prepareUrl( $url );
if ( preg_match( '#player\.vimeo\.com/video/(?<id>[0-9]+)#i', $url, $matches )) {
$url = 'http://www.vimeo.com/' . $matches['id'];
}
return $url;
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider\OEmbed;
use Essence\Media;
use Essence\Provider\OEmbed;
/**
*
* @package Essence.Provider.OEmbed
*/
class Youtube extends OEmbed {
/**
* Refactors URLs like these:
* - http://www.youtube.com/watch?v=oHg5SJYRHA0&noise=noise
* - http://www.youtube.com/v/oHg5SJYRHA0
* - http://www.youtube.com/embed/oHg5SJYRHA0
* - http://youtu.be/oHg5SJYRHA0
*
* in such form:
* - http://www.youtube.com/watch?v=oHg5SJYRHA0
*
* @param string $url Url to prepare.
* @return string Prepared url.
*/
public static function prepareUrl( $url, array $options = [ ]) {
$url = trim( $url );
if ( preg_match( '#(?:v=|v/|embed/|youtu\.be/)(?<id>[a-z0-9_-]+)#i', $url, $matches )) {
$url = 'http://www.youtube.com/watch?v=' . $matches['id'];
}
return $url;
}
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @author Laughingwithu <laughingwithu@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider;
use Essence\Exception;
use Essence\Media;
use Essence\Media\Preparator;
use Essence\Provider;
use Essence\Dom\Parser as DomParser;
use Essence\Http\Client as HttpClient;
use Essence\Log\Logger;
use Essence\Utility\Hash;
/**
* Base class for an OpenGraph provider.
* This kind of provider extracts embed informations from OpenGraph meta tags.
*
* @package Essence.Provider
*/
class OpenGraph extends Provider {
/**
* Internal HTTP client.
*
* @var Essence\Http\Client
*/
protected $_Http = null;
/**
* Internal DOM parser.
*
* @var Essence\Dom\Parser
*/
protected $_Dom = null;
/**
* Constructor.
*
* @param Essence\Http\Client $Http HTTP client.
* @param Essence\Dom\Parser $Dom DOM parser.
* @param Essence\Log\Logger $Log Logger.
* @param Essence\Log\Preparator $Preparator Preparator.
*/
public function __construct(
HttpClient $Http,
DomParser $Dom,
Logger $Log,
Preparator $Preparator = null
) {
$this->_Http = $Http;
$this->_Dom = $Dom;
parent::__construct( $Log, $Preparator );
}
/**
* {@inheritDoc}
*/
protected function _embed( $url, array $options ) {
return new Media(
Hash::reindex( $this->_extractInformations( $url ), [
'og:type' => 'type',
'og:title' => 'title',
'og:description' => 'description',
'og:site_name' => 'providerName',
'og:image' => 'thumbnailUrl',
'og:image:url' => 'thumbnailUrl',
'og:image:width' => 'width',
'og:image:height' => 'height',
'og:video:width' => 'width',
'og:video:height' => 'height',
'og:url' => 'url'
])
);
}
/**
* Extracts OpenGraph informations from the given URL.
*
* @param string $url URL to fetch informations from.
* @return array Extracted informations.
*/
protected function _extractInformations( $url ) {
$attributes = $this->_Dom->extractAttributes( $this->_Http->get( $url ), [
'meta' => [
'property' => '#^og:.+#i',
'content'
]
]);
$og = [ ];
if ( empty( $attributes['meta'])) {
throw new Exception(
"Unable to extract OpenGraph data from '$url'."
);
} else {
foreach ( $attributes['meta'] as $meta ) {
if ( !isset( $og[ $meta['property']])) {
$og[ $meta['property']] = trim( $meta['content']);
}
}
}
return $og;
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
/**
* A simple PSR-0 compliant class loader.
*
* @package Essence.Utility
*/
class Autoload {
/**
* Sets autoload up on the given path.
*
* @param string $basePath Base include path for all class files.
*/
public static function setup( $basePath ) {
$basePath = rtrim( $basePath, DIRECTORY_SEPARATOR );
spl_autoload_register( function( $className ) use ( $basePath ) {
if (strpos($className, 'Essence\\') === false) {
return;
}
$path = $basePath
. DIRECTORY_SEPARATOR
. str_replace( '\\', DIRECTORY_SEPARATOR, $className )
. '.php';
if ( file_exists( $path )) {
require_once $path;
}
});
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
/**
* An utility class to manipulate data sets.
*
* @package Essence.Utility
*/
class Hash {
/**
* Reindexes an array, according to the given correspondances.
*
* @param array $data The data to be reindexed.
* @param array $correspondances An array of index correspondances of the
* form `array( 'currentIndex' => 'newIndex' )`.
* @return array Reindexed array.
*/
public static function reindex( array $data, array $correspondances ) {
$result = $data;
foreach ( $correspondances as $from => $to ) {
if ( isset( $data[ $from ])) {
$result[ $to ] = $data[ $from ];
}
}
return $result;
}
/**
* Every element that is numerically indexed becomes a key, given
* $default as value.
*
* @param array $data The array to normalize.
* @param mixed $default Default value.
* @return array The normalized array.
*/
public static function normalize( array $data, $default ) {
$normalized = [ ];
foreach ( $data as $key => $value ) {
if ( is_numeric( $key )) {
$key = $value;
$value = $default;
}
$normalized[ $key ] = $value;
}
return $normalized;
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
use Essence\Exception;
/**
* A simple JSON parser.
*
* @package Essence.Utility
*/
class Json {
/**
* JSON error messages.
*
* @var array
*/
protected static $_errors = [
JSON_ERROR_NONE => 'no error',
JSON_ERROR_DEPTH => 'depth error',
JSON_ERROR_STATE_MISMATCH => 'state mismatch error',
JSON_ERROR_CTRL_CHAR => 'control character error',
JSON_ERROR_SYNTAX => 'syntax error',
JSON_ERROR_UTF8 => 'UTF-8 error'
];
/**
* Parses a JSON document and returns an array of data.
*
* @param string $json JSON document.
* @return array Data.
*/
public static function parse( $json ) {
$data = json_decode( $json, true );
if ( $data === null ) {
throw new Exception(
'Error parsing JSON response: '
. self::$_errors[ json_last_error( )]
. '.'
);
}
return $data;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
use Essence\Exception;
use Exception as NativeException;
use SimpleXmlIterator;
/**
* A simple XML parser.
*
* @package Essence.Utility
*/
class Xml {
/**
* Parses an XML document and returns an array of data.
*
* @param string $xml XML document.
* @return array Data.
*/
public static function parse( $xml ) {
$internal = libxml_use_internal_errors( true );
$data = [ ];
try {
$iterator = new SimpleXmlIterator( $xml );
} catch ( NativeException $Exception ) {
throw Exception::wrap( $Exception );
}
foreach ( $iterator as $key => $value ) {
$data[ $key ] = strval( $value );
}
libxml_use_internal_errors( $internal );
return $data;
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
use Essence\Utility\Autoload;
require_once dirname( __FILE__ )
. DIRECTORY_SEPARATOR . 'Essence'
. DIRECTORY_SEPARATOR . 'Utility'
. DIRECTORY_SEPARATOR . 'Autoload.php';
/**
* Definitions
*/
if ( !defined( 'ESSENCE_LIB' )) {
define( 'ESSENCE_LIB', dirname( __FILE__ ) . DIRECTORY_SEPARATOR );
}
if ( !defined( 'ESSENCE_DEFAULT_PROVIDERS' )) {
define( 'ESSENCE_DEFAULT_PROVIDERS', ESSENCE_LIB . 'providers.php' );
}
/**
* Autoload.
*/
Autoload::setup( ESSENCE_LIB );

380
vendor/essence/essence/lib/providers.php vendored Normal file
View File

@@ -0,0 +1,380 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
/**
* Default providers configuration.
*
* @see Essence\Provider\Collection::$_properties
* @var array
*/
return [
'23hq' => [
'class' => 'OEmbed',
'filter' => '#23hq\.com/.+/photo/.+#i',
'endpoint' => 'http://www.23hq.com/23/oembed?format=json&url=%s'
],
'Animoto' => [
'class' => 'OEmbed',
'filter' => '#animoto\.com/play/.+#i',
'endpoint' => 'http://animoto.com/oembeds/create?format=json&url=%s'
],
'Aol' => [
'class' => 'OEmbed',
'filter' => '#on\.aol\.com/video/.+#i',
'endpoint' => 'http://on.aol.com/api?format=json&url=%s'
],
'App.net' => [
'class' => 'OEmbed',
'filter' => '#(alpha|photo)\.app\.net/.+(/post)?/.+#i',
'endpoint' => 'https://alpha-api.app.net/oembed?format=json&url=%s'
],
'Bambuser' => [
'class' => 'OEmbed',
'filter' => '#bambuser\.com/(v|channel)/.+#i',
'endpoint' => 'http://api.bambuser.com/oembed.json?url=%s'
],
'Bandcamp' => [
'class' => 'Bandcamp',
// OpenGraph subclasses should strictly match the start of the URL
// to prevent spoofing.
'filter' => '#^https?://(?:[^\.]+\.)?bandcamp\.com/(album|track)/#i'
],
'Blip.tv' => [
'class' => 'OEmbed',
'filter' => '#blip\.tv/.+#i',
'endpoint' => 'http://blip.tv/oembed?format=json&url=%s'
],
'Cacoo' => [
'class' => 'OEmbed',
'filter' => '#cacoo\.com/.+#i',
'endpoint' => 'http://cacoo.com/oembed.json?url=%s'
],
'CanalPlus' => [
'class' => 'OpenGraph',
'filter' => '#canalplus\.fr#i'
],
'Chirb.it' => [
'class' => 'OEmbed',
'filter' => '#chirb\.it/.+#i',
'endpoint' => 'http://chirb.it/oembed.json?url=%s'
],
'CircuitLab' => [
'class' => 'OEmbed',
'filter' => '#circuitlab\.com/circuit/.+#i',
'endpoint' => 'https://www.circuitlab.com/circuit/oembed?format=json&url=%s'
],
'Clikthrough' => [
'class' => 'OEmbed',
'filter' => '#clikthrough\.com/theater/video/\d+#i',
'endpoint' => 'http://clikthrough.com/services/oembed?format=json&url=%s'
],
'CollegeHumorOEmbed' => [
'class' => 'OEmbed',
'filter' => '#collegehumor\.com/(video|embed)/.+#i',
'endpoint' => 'http://www.collegehumor.com/oembed.json?url=%s'
],
'CollegeHumorOpenGraph' => [
'class' => 'OpenGraph',
'filter' => '#collegehumor\.com/(picture|article)/.+#i'
],
'Coub' => [
'class' => 'OEmbed',
'filter' => '#coub\.com/(view|embed)/.+#i',
'endpoint' => 'http://coub.com/api/oembed.json?url=%s'
],
'CrowdRanking' => [
'class' => 'OEmbed',
'filter' => '#crowdranking\.com/.+/.+#i',
'endpoint' => 'http://crowdranking.com/api/oembed.json?url=%s'
],
'DailyMile' => [
'class' => 'OEmbed',
'filter' => '#dailymile\.com/people/.+/entries/.+#i',
'endpoint' => 'http://api.dailymile.com/oembed?format=json&url=%s'
],
'Dailymotion' => [
'class' => 'OEmbed',
'filter' => '#dailymotion\.com#i',
'endpoint' => 'http://www.dailymotion.com/services/oembed?format=json&url=%s'
],
'Deviantart' => [
'class' => 'OEmbed',
'filter' => '#deviantart\.com/.+#i',
'endpoint' => 'http://backend.deviantart.com/oembed?format=json&url=%s'
],
'Dipity' => [
'class' => 'OEmbed',
'filter' => '#dipity\.com/.+#i',
'endpoint' => 'http://www.dipity.com/oembed/timeline?format=json&url=%s'
],
'Dotsub' => [
'class' => 'OEmbed',
'filter' => '#dotsub\.com/view/.+#i',
'endpoint' => 'http://dotsub.com/services/oembed?format=json&url=%s'
],
'Edocr' => [
'class' => 'OEmbed',
'filter' => '#edocr\.com/doc/[0-9]+/.+#i',
'endpoint' => 'http://www.edocr.com/api/oembed?format=json&url=%s'
],
'Flickr' => [
'class' => 'OEmbed',
'filter' => '#flickr\.com/photos/[a-zA-Z0-9@\\._]+/[0-9]+#i',
'endpoint' => 'http://flickr.com/services/oembed?format=json&url=%s'
],
'FunnyOrDie' => [
'class' => 'OEmbed',
'filter' => '#funnyordie\.com/videos/.+#i',
'endpoint' => 'http://www.funnyordie.com/oembed?format=json&url=%s'
],
'Gist' => [
'class' => 'OEmbed',
'filter' => '#gist\.github\.com/.+/[0-9]+#i',
'endpoint' => 'https://github.com/api/oembed?format=json&url=%s'
],
'Gmep' => [
'class' => 'OEmbed',
'filter' => '#gmep\.org/media/.+#i',
'endpoint' => 'https://gmep.org/oembed.json?url=%s'
],
'HowCast' => [
'class' => 'OpenGraph',
'filter' => '#howcast\.com/.+/.+#i'
],
'Huffduffer' => [
'class' => 'OEmbed',
'filter' => '#huffduffer\.com/[-.\w@]+/\d+#i',
'endpoint' => 'http://huffduffer.com/oembed?format=json&url=%s'
],
'Hulu' => [
'class' => 'OEmbed',
'filter' => '#hulu\.com/watch/.+#i',
'endpoint' => 'http://www.hulu.com/api/oembed.json?url=%s'
],
'Ifixit' => [
'class' => 'OEmbed',
'filter' => '#ifixit\.com/.+#i',
'endpoint' => 'http://www.ifixit.com/Embed?format=json&url=%s'
],
'Ifttt' => [
'class' => 'OEmbed',
'filter' => '#ifttt\.com/recipes/.+#i',
'endpoint' => 'http://www.ifttt.com/oembed?format=json&url=%s'
],
'Imgur' => [
'class' => 'OEmbed',
'filter' => '#(imgur\.com/(gallery|a)/.+|imgur\.com/.+)#i',
'endpoint' => 'http://api.imgur.com/oembed?format=json&url=%s'
],
'Instagram' => [
'class' => 'OEmbed',
'filter' => '#instagr(\.am|am\.com)/p/.+#i',
'endpoint' => 'http://api.instagram.com/oembed?format=json&url=%s'
],
'Jest' => [
'class' => 'OEmbed',
'filter' => '#jest\.com/video/.+#i',
'endpoint' => 'http://www.jest.com/oembed.json?url=%s'
],
'Justin.tv' => [
'class' => 'OEmbed',
'filter' => '#justin\.tv/.+#i',
'endpoint' => 'http://api.justin.tv/api/embed/from_url.json?url=%s'
],
'Kickstarter' => [
'class' => 'OEmbed',
'filter' => '#kickstarter\.com/projects/.+#i',
'endpoint' => 'http://www.kickstarter.com/services/oembed?format=json&url=%s'
],
'Meetup' => [
'class' => 'OEmbed',
'filter' => '#meetup\.(com|ps)/.+#i',
'endpoint' => 'https://api.meetup.com/oembed?format=json&url=%s'
],
'Mixcloud' => [
'class' => 'OEmbed',
'filter' => '#mixcloud\.com/.+/.+#i',
'endpoint' => 'http://www.mixcloud.com/oembed?format=json&url=%s'
],
'Mobypicture' => [
'class' => 'OEmbed',
'filter' => '#(moby.to|mobypicture\.com/user/.+/view)/.+#i',
'endpoint' => 'http://api.mobypicture.com/oEmbed?format=json&url=%s'
],
'Nfb' => [
'class' => 'OEmbed',
'filter' => '#nfb\.ca/films/.+#i',
'endpoint' => 'http://www.nfb.ca/remote/services/oembed?format=json&url=%s'
],
'Official.fm' => [
'class' => 'OEmbed',
'filter' => '#official\.fm/.+#i',
'endpoint' => 'http://official.fm/services/oembed?format=json&url=%s'
],
'Polldaddy' => [
'class' => 'OEmbed',
'filter' => '#polldaddy\.com/.+#i',
'endpoint' => 'http://polldaddy.com/oembed?format=json&url=%s'
],
'PollEverywhere' => [
'class' => 'OEmbed',
'filter' => '#polleverywhere\.com/(polls|multiple_choice_polls|free_text_polls)/.+#i',
'endpoint' => 'http://www.polleverywhere.com/services/oembed?format=json&url=%s'
],
'Prezi' => [
'class' => 'OpenGraph',
'filter' => '#prezi\.com/.+/.+#i'
],
'Qik' => [
'class' => 'OEmbed',
'filter' => '#qik\.com/\w+#i',
'endpoint' => 'http://qik.com/api/oembed.json?url=%s'
],
'Rdio' => [
'class' => 'OEmbed',
'filter' => '#rdio\.com/(artist|people)/.+#i',
'endpoint' => 'http://www.rdio.com/api/oembed?format=json&url=%s'
],
'Revision3' => [
'class' => 'OEmbed',
'filter' => '#revision3\.com/[a-z0-9]+/.+#i',
'endpoint' => 'http://revision3.com/api/oembed?format=json&url=%s'
],
'Roomshare' => [
'class' => 'OEmbed',
'filter' => '#roomshare\.jp(/en)?/post/.+#i',
'endpoint' => 'http://roomshare.jp/en/oembed.json?&url=%s'
],
'Sapo' => [
'class' => 'OEmbed',
'filter' => '#videos\.sapo\.pt/.+#i',
'endpoint' => 'http://videos.sapo.pt/oembed?format=json&url=%s'
],
'Screenr' => [
'class' => 'OEmbed',
'filter' => '#screenr\.com/.+#i',
'endpoint' => 'http://www.screenr.com/api/oembed.json?url=%s'
],
'Scribd' => [
'class' => 'OEmbed',
'filter' => '#scribd\.com/doc/[0-9]+/.+#i',
'endpoint' => 'http://www.scribd.com/services/oembed?format=json&url=%s'
],
'Shoudio' => [
'class' => 'OEmbed',
'filter' => '#(shoudio\.com|shoud\.io)/.+#i',
'endpoint' => 'http://shoudio.com/api/oembed?format=json&url=%s'
],
'Sketchfab' => [
'class' => 'OEmbed',
'filter' => '#sketchfab\.com/show/.+#i',
'endpoint' => 'http://sketchfab.com/oembed?format=json&url=%s'
],
'SlideShare' => [
'class' => 'OEmbed',
'filter' => '#slideshare\.net/.+/.+#i',
'endpoint' => 'http://www.slideshare.net/api/oembed/2?format=json&url=%s'
],
'SoundCloud' => [
'class' => 'OEmbed',
'filter' => '#soundcloud\.com/[a-zA-Z0-9-_]+/[a-zA-Z0-9-]+#i',
'endpoint' => 'http://soundcloud.com/oembed?format=json&url=%s'
],
'SpeakerDeck' => [
'class' => 'OEmbed',
'filter' => '#speakerdeck\.com/.+/.+#i',
'endpoint' => 'https://speakerdeck.com/oembed.json?url=%s'
],
'Spotify' => [
'class' => 'OEmbed',
'filter' => '#(open|play)\.spotify\.com/.+#i',
'endpoint' => 'https://embed.spotify.com/oembed?format=json&url=%s'
],
'TedOEmbed' => [
'class' => 'OEmbed',
'filter' => '#ted\.com/talks/.+#i',
'endpoint' => 'http://www.ted.com/talks/oembed.json?url=%s'
],
'TedOpenGraph' => [
'class' => 'OpenGraph',
'filter' => '#ted\.com/talks#i'
],
'Twitter' => [
'class' => 'OEmbed',
'filter' => '#twitter\.com/[a-zA-Z0-9_]+/status(es)?/.+#i',
'endpoint' => 'https://api.twitter.com/1/statuses/oembed.json?url=%s'
],
'Ustream' => [
'class' => 'OEmbed',
'filter' => '#ustream\.(tv|com)/.+#i',
'endpoint' => 'http://www.ustream.tv/oembed?format=json&url=%s'
],
'Vhx' => [
'class' => 'OEmbed',
'filter' => '#vhx\.tv/.+#i',
'endpoint' => 'http://vhx.tv/services/oembed.json?url=%s'
],
'Viddler' => [
'class' => 'OEmbed',
'filter' => '#viddler\.com/.+#i',
'endpoint' => 'http://www.viddler.com/oembed/?url=%s'
],
'Videojug' => [
'class' => 'OEmbed',
'filter' => '#videojug\.com/(film|interview)/.+#i',
'endpoint' => 'http://www.videojug.com/oembed.json?url=%s'
],
'Vimeo' => [
'class' => 'Vimeo',
'filter' => '#vimeo\.com#i',
'endpoint' => 'http://vimeo.com/api/oembed.json?url=%s'
],
'Vine' => [
'class' => 'Vine',
// OpenGraph subclasses should strictly match the start of the URL
// to prevent spoofing.
'filter' => '#^https?://vine.co/v/[a-zA-Z0-9]+#i'
],
'Wistia' => [
'class' => 'OEmbed',
'filter' => '#https?://(.+)?(wistia.com|wi.st)/.*#i',
'endpoint' => 'http://fast.wistia.com/oembed?format=json&url=%s',
],
'WordPress' => [
'class' => 'OEmbed',
'filter' => '#wordpress\\.com/.+#i',
'endpoint' => 'http://public-api.wordpress.com/oembed/1.0?format=json&for=me&url=%s'
],
'Yfrog' => [
'class' => 'OEmbed',
'filter' => '#yfrog\.(com|ru|com\.tr|it|fr|co\.il|co\.uk|com\.pl|pl|eu|us)/.+#i',
'endpoint' => 'http://www.yfrog.com/api/oembed?format=json&url=%s'
],
'Youtube' => [
'class' => 'Youtube',
'filter' => '#youtube\.com|youtu\.be#i',
'endpoint' => 'http://www.youtube.com/oembed?format=json&url=%s'
]
/**
* The following providers will try to embed any URL.
*/
/*
'OEmbed' => [
'class' => 'OEmbed',
'filter' => '#.+#'
],
'OpenGraph' => [
'class' => 'OpenGraph',
'filter' => '#.+#'
],
*/
];

26
vendor/essence/essence/phpunit.xml vendored Normal file
View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="tests/bootstrap.php"
backupGlobals="false"
backupStaticAttributes="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
colors="true"
>
<testsuites>
<testsuite name="Essence test suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<blacklist>
<directory>http</directory>
</blacklist>
</filter>
</phpunit>

View File

@@ -0,0 +1,65 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Cache\Engine;
use PHPUnit_Framework_TestCase;
/**
* Test case for Volatile.
*/
class VolatileTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Volatile = null;
/**
*
*/
public function setUp( ) {
$this->Volatile = new Volatile( );
}
/**
*
*/
public function testHas( ) {
$this->assertFalse( $this->Volatile->has( 'key' ));
$this->Volatile->set( 'key', 'value' );
$this->assertTrue( $this->Volatile->has( 'key' ));
}
/**
*
*/
public function testGetSet( ) {
$this->assertNull( $this->Volatile->get( 'key' ));
$this->assertEquals( 'value', $this->Volatile->get( 'key', 'value' ));
$this->Volatile->set( 'key', 'value' );
$this->assertEquals( 'value', $this->Volatile->get( 'key' ));
}
}

View File

@@ -0,0 +1,115 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use PHPUnit_Framework_TestCase;
use Essence\Cache\Engine;
use Essence\Cache\Engine\Volatile;
/**
*
*/
class CacheableImplementation {
use Cacheable;
/**
*
*/
public function __construct( Engine $Engine ) {
$this->_Cache = $Engine;
}
/**
*
*/
protected function _cacheKey( $signature ) {
return 'key';
}
/**
*
*/
public function cachedMethod( $arg ) {
return $this->_cached( '_cachedMethod', $arg );
}
/**
*
*/
public function _cachedMethod( $arg ) {
return $arg;
}
}
/**
* Test case for Cacheable.
*/
class CacheableTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Engine = null;
/**
*
*/
public $Cacheable = null;
/**
*
*/
public function setUp( ) {
$this->Engine = new Volatile( );
$this->Cacheable = new CacheableImplementation( $this->Engine );
}
/**
*
*/
public function testCached( ) {
$this->assertFalse( $this->Engine->has( 'key' ));
$this->assertEquals( 'result', $this->Cacheable->cachedMethod( 'result' ));
$this->assertEquals( 'result', $this->Engine->get( 'key' ));
}
}

View File

@@ -0,0 +1,161 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use PHPUnit_Framework_TestCase;
/**
*
*/
class ConfigurableImplementation {
use Configurable;
/**
*
*/
protected $_properties = [
'one' => 1,
'two' => 2
];
}
/**
* Test case for Configurable.
*/
class ConfigurableTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Configurable = null;
/**
*
*/
public function setUp( ) {
$this->Configurable = new ConfigurableImplementation( );
}
/**
*
*/
public function testMagicIsSet( ) {
$this->assertTrue( isset( $this->Configurable->one ));
$this->assertFalse( isset( $this->Configurable->unset ));
}
/**
*
*/
public function testMagicGet( ) {
$this->assertEquals( 1, $this->Configurable->one );
}
/**
*
*/
public function testMagicSet( ) {
$this->Configurable->foo = 'bar';
$this->assertEquals( 'bar', $this->Configurable->foo );
}
/**
*
*/
public function testHas( ) {
$this->assertTrue( $this->Configurable->has( 'one' ));
$this->assertFalse( $this->Configurable->has( 'unset' ));
}
/**
*
*/
public function testGet( ) {
$this->assertEquals( 1, $this->Configurable->get( 'one' ));
$this->assertEmpty( $this->Configurable->get( 'unset' ));
}
/**
*
*/
public function testSet( ) {
$this->Configurable->set( 'foo', 'bar' );
$this->assertEquals( 'bar', $this->Configurable->foo );
}
/**
*
*/
public function testSetDefault( ) {
$this->Configurable->setDefault( 'one', 2 );
$this->assertEquals( 1, $this->Configurable->get( 'one' ));
$this->Configurable->setDefault( 'three', 3 );
$this->assertEquals( 3, $this->Configurable->get( 'three' ));
}
/**
*
*/
public function testSetDefaults( ) {
$this->Configurable->setDefaults([
'one' => 2,
'three' => 3
]);
$this->assertEquals( 1, $this->Configurable->get( 'one' ));
$this->assertEquals( 3, $this->Configurable->get( 'three' ));
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Di;
use PHPUnit_Framework_TestCase;
/**
*
*/
class Containable { }
/**
* Test case for Container.
*/
class ContainerTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Container = null;
/**
*
*/
public function setUp( ) {
$this->Container = new Container( );
}
/**
*
*/
public function testGet( ) {
$this->Container->set( 'integer', 12 );
$this->assertEquals( 12, $this->Container->get( 'integer' ));
}
/**
*
*/
public function testGetClosureResult( ) {
$this->Container->set( 'Containable', function( $Container ) {
return new Containable( );
});
$this->assertEquals( new Containable( ), $this->Container->get( 'Containable' ));
$this->assertNotSame( new Containable( ), $this->Container->get( 'Containable' ));
}
/**
*
*/
public function testGetUnique( ) {
$unique = Container::unique( function( $Container ) {
return new Containable( );
});
$first = $unique( $this->Container );
$second = $unique( $this->Container );
$this->assertSame( $first, $second );
}
}

View File

@@ -0,0 +1,159 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Dom\Parser;
use PHPUnit_Framework_TestCase;
/**
* Test case for Native.
*/
class NativeTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Native = null;
/**
*
*/
public $html = <<<'HTML'
<meta name="description" content="Description." />
<meta name="ns:custom" content="Custom namespace." />
<a href="http://www.test.com" title="Link">
<a href="http://www.othertest.com" title="Other link" target="_blank">
HTML;
/**
*
*/
public function setUp( ) {
$this->Native = new Native( );
}
/**
*
*/
public function testExtractAttributes( ) {
$this->setExpectedException( '\\Essence\\Exception' );
$this->Native->extractAttributes( '', [ ]);
}
/**
*
*/
public function testExtractAttributesFromUnknownTag( ) {
$this->assertEquals(
[ 'unknown' => [ ]],
$this->Native->extractAttributes( $this->html, [ 'unknown' ])
);
}
/**
*
*/
public function testExtractAllAttributesFromTag( ) {
$this->assertEquals([
'a' => [[
'href' => 'http://www.test.com',
'title' => 'Link'
], [
'href' => 'http://www.othertest.com',
'title' => 'Other link',
'target' => '_blank'
]]
], $this->Native->extractAttributes( $this->html, [ 'a' ]));
}
/**
*
*/
public function testExtractSomeAttributesFromTag( ) {
$this->assertEquals([
'a' => [[
'href' => 'http://www.othertest.com',
'target' => '_blank'
]]
], $this->Native->extractAttributes( $this->html, [
'a' => [ 'href', 'target' ]
]));
}
/**
*
*/
public function testExtractFilteredAttributesFromTag( ) {
$this->assertEquals([
'meta' => [[
'name' => 'ns:custom',
'content' => 'Custom namespace.'
]]
], $this->Native->extractAttributes( $this->html, [
'meta' => [ 'name' => '#^ns:.+#', 'content' ]
]));
}
/**
*
*/
public function testExtractAllAttributesFromMultipleTags( ) {
$this->assertEquals([
'meta' => [[
'name' => 'description',
'content' => 'Description.'
], [
'name' => 'ns:custom',
'content' => 'Custom namespace.'
]],
'a' => [[
'href' => 'http://www.test.com',
'title' => 'Link'
], [
'href' => 'http://www.othertest.com',
'title' => 'Other link',
'target' => '_blank'
]]
], $this->Native->extractAttributes( $this->html, [ 'meta', 'a' ]));
}
}

View File

@@ -0,0 +1,221 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use PHPUnit_Framework_TestCase;
use Essence\Di\Container\Standard as StandardContainer;
use Essence\Cache\Engine\Null as NullCacheEngine;
use Essence\Dom\Parser\Native as NativeDomParser;
use Essence\Http\Client\Native as NativeHttpClient;
use Essence\Log\Logger\NullClass as NullLogger;
/**
* Test case for Essence.
*/
class EssenceTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Essence = null;
/**
*
*/
public function setUp( ) {
$Container = new StandardContainer([
'Cache' => new NullCacheEngine( ),
'Http' => new NativeHttpClient( ),
'Dom' => new NativeDomParser( ),
'Log' => new NullLogger( ),
'Media' => new Media([
'title' => 'Title',
'html' => 'HTML'
]),
'Provider' => function( $C ) {
$Provider = $this->getMockForAbstractClass(
'\\Essence\\Provider',
[ $C->get( 'Log' )]
);
$Provider
->expects( $this->any( ))
->method( '_embed' )
->will( $this->returnValue( $C->get( 'Media' )));
return $Provider;
},
'providers' => [
'provider' => [
'class' => 'Provider',
'filter' => '#pass#i'
]
]
]);
$this->Essence = $Container->get( 'Essence' );
}
/**
*
*/
public function testExtract( ) {
$this->assertEquals([
'http://pass.foo.com',
'http://pass.embed.com',
'http://pass.iframe.com'
], $this->Essence->extract( 'file://' . ESSENCE_HTTP . 'valid.html' ));
}
/**
*
*/
public function testExtractHtml( ) {
$html = <<<HTML
<a href="http://pass.foo.com">Foo</a>
<a href="http://fail.bar.com">Bar</a>
<embed src="http://pass.embed.com"></embed>
<iframe src="http://pass.iframe.com"></iframe>
HTML;
$this->assertEquals([
'http://pass.foo.com',
'http://pass.embed.com',
'http://pass.iframe.com'
], $this->Essence->extract( $html ));
}
/**
*
*/
public function testEmbed( ) {
$this->assertNotNull( $this->Essence->embed( 'http://pass.foo.com/bar' ));
}
/**
*
*/
public function testEmbedAll( ) {
$urls = [ 'one', 'two' ];
$medias = $this->Essence->embedAll( $urls );
$this->assertEquals( $urls, array_keys( $medias ));
}
/**
*
*/
public function testReplace( ) {
$this->assertEquals(
'foo HTML bar',
$this->Essence->replace( 'foo http://pass.example.com bar' )
);
}
/**
*
*/
public function testReplaceSingleUrl( ) {
$this->assertEquals(
'HTML',
$this->Essence->replace( 'http://pass.example.com' )
);
}
/**
*
*/
public function testReplaceTagSurroundedUrl( ) {
$this->assertEquals(
'<span>HTML</span>',
$this->Essence->replace( '<span>http://pass.example.com</span>' )
);
}
/**
*
*/
public function testReplaceWithTemplate( ) {
$this->assertEquals(
'foo <h1>Title</h1> bar',
$this->Essence->replace( 'foo http://pass.example.com bar', function( $Media ) {
return '<h1>' . $Media->title . '</h1>';
})
);
}
/**
*
*/
public function testDontReplaceLinks( ) {
$link = '<a href="http://pass.com">baz</a>';
$this->assertEquals( $link, $this->Essence->replace( $link ));
$link = '<a href="http://www.pass.com/watch?v=emgJtr9tIME">baz</a>';
$this->assertEquals( $link, $this->Essence->replace( $link ));
$link = "<a href='http://pass.com'>baz</a>";
$this->assertEquals( $link, $this->Essence->replace( $link ));
}
/**
*
*/
public function testReplaceQuotesSurroundedUrl( ) {
$this->assertEquals( '"HTML"', $this->Essence->replace( '"http://pass.com"' ));
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Http\Client;
use PHPUnit_Framework_TestCase;
/**
* Test case for Native.
*/
class NativeTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Native = null;
/**
*
*/
public function setUp( ) {
$this->Native = new Native( );
}
/**
*
*/
public function testGet( ) {
$this->assertNotEmpty( $this->Native->get( 'file://' . __FILE__ ));
}
/**
*
*/
public function testGetUnreachable( ) {
$this->setExpectedException( '\\Essence\\Http\\Exception' );
$this->Native->get( 'file://' . __FILE__ . '.unreachable' );
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Media;
use PHPUnit_Framework_TestCase;
/**
* Test case for Preparator.
*/
class PreparatorTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Preparator = null;
public $Media = null;
/**
*
*/
public function setup( ) {
$this->Media = new Media([
'url' => 'http://foo.bar.com/resource',
'title' => 'Title',
'description' => 'Description',
'width' => 800,
'height' => 600
]);
$this->Preparator = new Preparator( );
}
/**
*
*/
public function testCompletePhoto( ) {
$this->Media->set( 'type', 'photo' );
$this->Preparator->completeMedia( $this->Media );
$this->assertEquals(
'<img src="http://foo.bar.com/resource" alt="Description" width="800" height="600" />',
$this->Media->html
);
}
/**
*
*/
public function testCompleteVideo( ) {
$this->Media->set( 'type', 'video' );
$this->Preparator->completeMedia( $this->Media );
$this->assertEquals(
'<iframe src="http://foo.bar.com/resource" width="800" height="600" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen />',
$this->Media->html
);
}
/**
*
*/
public function testCompleteDefault( ) {
$this->Preparator->completeMedia( $this->Media );
$this->assertEquals(
'<a href="http://foo.bar.com/resource" alt="Description">Title</a>',
$this->Media->html
);
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Media\Preparator;
use PHPUnit_Framework_TestCase;
use Essence\Media;
/**
* Test case for Youtube.
*/
class YoutubeTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Youtube = null;
public $Media = null;
/**
*
*/
public function setup( ) {
$this->Media = new Media([
'thumbnailUrl' => 'http://i1.ytimg.com/vi/r0dBPI4etvI/hqdefault.jpg'
]);
$this->Youtube = new Youtube( );
}
/**
* @dataProvider thumbnailFormatProvider
*/
public function testCompleteWithThumbnailUrl( $format, $file ) {
$this->Youtube->complete( $this->Media, [
'thumbnailFormat' => $format
]);
$this->assertEquals(
"http://i1.ytimg.com/vi/r0dBPI4etvI/$file.jpg",
$this->Media->get( 'thumbnailUrl' )
);
}
/**
*
*/
public function thumbnailFormatProvider( ) {
return [
['small', 'default'],
['medium', 'mqdefault'],
['large', 'hqdefault'],
['max', 'maxresdefault']
];
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use PHPUnit_Framework_TestCase;
/**
* Test case for Media.
*/
class MediaTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Media = null;
/**
*
*/
public function setUp( ) {
$this->Media = new Media( [
'property' => 'value'
]);
}
/**
*
*/
public function testConstruct( ) {
$this->assertTrue( $this->Media->has( 'property' ));
}
/**
*
*/
public function testIterator( ) {
foreach ( $this->Media as $property => $value ) { }
}
/**
*
*/
public function testSerialize( ) {
$this->assertEquals(
json_encode( $this->Media->properties( )),
json_encode( $this->Media )
);
}
}

View File

@@ -0,0 +1,108 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider;
use PHPUnit_Framework_TestCase;
use Essence\Provider;
use Essence\Provider\OEmbed;
use Essence\Di\Container;
use Essence\Log\Logger\NullClass as NullLogger;
/**
*
*/
class ProviderImplementation extends Provider {
/**
*
*/
protected function _embed( $url, array $options ) { }
}
/**
* Test case for Collection.
*/
class CollectionTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Provider = null;
/**
*
*/
public $Collection = null;
/**
*
*/
public function setUp( ) {
$this->Provider = new ProviderImplementation( new NullLogger( ));
$Container = new Container( );
$Container->set( 'OEmbed', $this->Provider );
$this->Collection = new Collection( $Container );
$this->Collection->setProperties([
'Foo' => [
'class' => 'OEmbed',
'filter' => '#^foo$#'
],
'Bar' => [
'class' => 'OpenGraph',
'filter' => function ( $url ) {
return ( $url === 'bar' );
}
]
]);
}
/**
*
*/
public function testHasProvider( ) {
$this->assertTrue( $this->Collection->hasProvider( 'foo' ));
$this->assertTrue( $this->Collection->hasProvider( 'bar' ));
$this->assertFalse( $this->Collection->hasProvider( 'baz' ));
}
/**
*
*/
public function testProviders( ) {
$this->assertEquals(
[ $this->Provider ],
$this->Collection->providers( 'foo' )
);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider\OEmbed;
use PHPUnit_Framework_TestCase;
/**
* Test case for Vimeo.
*/
class VimeoTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public function testPrepareUrl( ) {
$this->assertEquals(
'http://www.vimeo.com/20830433',
Vimeo::prepareUrl( 'http://player.vimeo.com/video/20830433' )
);
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider\OEmbed;
use PHPUnit_Framework_TestCase;
use Essence\Media;
/**
* Test case for Youtube.
*/
class YoutubeTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public function testPrepareUrl( ) {
$this->assertEquals(
'http://www.youtube.com/watch?v=oHg5SJYRHA0',
Youtube::prepareUrl( 'http://www.youtube.com/watch?v=oHg5SJYRHA0&noise=noise' )
);
$this->assertEquals(
'http://www.youtube.com/watch?v=oHg5SJYRHA0',
Youtube::prepareUrl( 'http://www.youtube.com/v/oHg5SJYRHA0' )
);
$this->assertEquals(
'http://www.youtube.com/watch?v=oHg5SJYRHA0',
Youtube::prepareUrl( 'http://www.youtube.com/embed/oHg5SJYRHA0' )
);
$this->assertEquals(
'http://www.youtube.com/watch?v=oHg5SJYRHA0',
Youtube::prepareUrl( 'http://youtu.be/oHg5SJYRHA0' )
);
}
}

View File

@@ -0,0 +1,182 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider;
use PHPUnit_Framework_TestCase;
use Essence\Dom\Parser\Native as NativeDomParser;
use Essence\Http\Client\Native as NativeHttpClient;
use Essence\Log\Logger\NullClass as NullLogger;
/**
*
*/
class TestableOEmbed extends OEmbed {
/**
*
*/
public function completeEndpoint( $endpoint, $options ) {
$this->_completeEndpoint( $endpoint, $options );
return $endpoint;
}
}
/**
* Test case for OEmbed.
*/
class OEmbedTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $OEmbed = null;
/**
*
*/
public function setup( ) {
$this->OEmbed = new TestableOEmbed(
new NativeHttpClient( ),
new NativeDomParser( ),
new NullLogger( )
);
$this->OEmbed->configure([
'endpoint' => 'file://' . ESSENCE_HTTP . '%s.json',
'format' => OEmbed::json
]);
}
/**
*
*/
public function testPrepare( ) {
$this->assertEquals( 'valid', OEmbed::prepareUrl( 'valid#anchor' ));
$this->assertEquals( 'valid', OEmbed::prepareUrl( 'valid?argument=value' ));
$this->assertEquals( 'valid', OEmbed::prepareUrl( 'valid?argument=value#anchor' ));
}
/**
*
*/
public function testCompleteEndpoint( ) {
$this->assertEquals(
'url?maxwidth=120&maxheight=60',
$this->OEmbed->completeEndpoint( 'url', [
'maxwidth' => 120,
'maxheight' => 60
])
);
$this->assertEquals(
'url?param=value&maxwidth=120',
$this->OEmbed->completeEndpoint( 'url?param=value', [
'maxwidth' => 120
])
);
}
/**
*
*/
public function testEmbedJson( ) {
$this->assertNotNull( $this->OEmbed->embed( 'valid' ));
}
/**
*
*/
public function testEmbedInvalidJson( ) {
$this->assertNull( $this->OEmbed->embed( 'invalid' ));
}
/**
*
*/
public function testEmbedXml( ) {
$this->OEmbed->set( 'endpoint', 'file://' . ESSENCE_HTTP . '%s.xml' );
$this->OEmbed->set( 'format', OEmbed::xml );
$this->assertNotNull( $this->OEmbed->embed( 'valid' ));
}
/**
*
*/
public function testEmbedInvalidXml( ) {
$this->OEmbed->set( 'endpoint', 'file://' . ESSENCE_HTTP . '%s.xml' );
$this->OEmbed->set( 'format', OEmbed::xml );
$this->assertNull( $this->OEmbed->embed( 'invalid' ));
}
/**
*
*/
public function testEmbedUnsupportedFormat( ) {
$this->OEmbed->set( 'format', 'unsupported' );
$this->assertNull( $this->OEmbed->embed( 'valid' ));
}
/**
*
*/
public function testEmbedGeneric( ) {
$this->OEmbed->set( 'endpoint', '' );
$this->assertNotNull(
$this->OEmbed->embed( 'file://' . ESSENCE_HTTP . 'valid.html' )
);
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Provider;
use PHPUnit_Framework_TestCase;
use Essence\Dom\Parser\Native as NativeDomParser;
use Essence\Http\Client\Native as NativeHttpClient;
use Essence\Log\Logger\NullClass as NullLogger;
/**
* Test case for OpenGraph.
*/
class OpenGraphTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $OpenGraph = null;
/**
*
*/
public function setUp( ) {
$this->OpenGraph = new OpenGraph(
new NativeHttpClient( ),
new NativeDomParser( ),
new NullLogger( )
);
}
/**
*
*/
public function testEmbed( ) {
$this->assertNotNull(
$this->OpenGraph->embed( 'file://' . ESSENCE_HTTP . 'valid.html' )
);
}
/**
* @todo fix it for travis
*/
/*
public function testEmbedInvalid( ) {
$this->setExpectedException( '\\Essence\\Exception' );
$this->OpenGraph->embed( 'file://' . ESSENCE_HTTP . 'invalid.html' );
}
*/
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence;
use PHPUnit_Framework_TestCase;
use Essence\Log\Logger\NullClass as NullLogger;
/**
* Test case for Provider.
*/
class ProviderTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $Provider = null;
public $Media = null;
/**
*
*/
public function setup( ) {
$this->Media = new Media([
'url' => 'http://foo.bar.com/resource',
'title' => 'Title',
'description' => 'Description',
'width' => 800,
'height' => 600
]);
$this->Provider = $this->getMockForAbstractClass(
'\\Essence\\Provider',
[ new NullLogger( )]
);
}
/**
*
*/
public function testEmbed( ) {
$this->Provider
->expects( $this->any( ))
->method( '_embed' )
->will( $this->returnValue( $this->Media ));
$this->assertEquals(
$this->Media,
$this->Provider->embed( ' http://foo.bar ' )
);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
use PHPUnit_Framework_TestCase;
/**
* Test case for Autoload.
*/
class AutoloadTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public function testSetup( ) {
$this->assertTrue( class_exists( '\\Essence\\Provider\\OEmbed' ));
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
use PHPUnit_Framework_TestCase;
/**
* Test case for Hash.
*/
class HashTest {
/**
*
*/
public function testReindex( ) {
$data = Hash::reindex(
[ 'one' => 'value' ],
[ 'one' => 'two' ]
);
$this->assertEquals(
[ 'two' => 'value' ],
$data
);
}
/**
*
*/
public function testNormalize( ) {
$data = Hash::normalize([
'one',
'two' => 'three',
'four'
], 'default' );
$this->assertEquals([
'one' => 'default',
'two' => 'three',
'four' => 'default'
], $data );
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
use PHPUnit_Framework_TestCase;
/**
* Test case for Json.
*/
class JsonTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $valid = <<<VALID
{
"title": "Title",
"type": "video"
}
VALID;
/**
*
*/
public $invalid = <<<VALID
{
"title" "Title",
"type": "video"
VALID;
/**
*
*/
public function testParse( ) {
$this->assertEquals([
'title' => 'Title',
'type' => 'video'
], Json::parse( $this->valid ));
}
/**
*
*/
public function testParseInvalid( ) {
$this->setExpectedException( 'Essence\\Exception' );
Json::parse( $this->invalid );
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
namespace Essence\Utility;
use PHPUnit_Framework_TestCase;
/**
* Test case for Xml.
*/
class XmlTest extends PHPUnit_Framework_TestCase {
/**
*
*/
public $valid =
'<?xml version="1.0" encoding="utf-8"?>
<oembed>
<title>Title</title>
<type>video</type>
</oembed>';
/**
*
*/
public $invalid =
'<oembed>
<title>Title
<type>video</type>';
/**
*
*/
public function testParse( ) {
$this->assertEquals([
'title' => 'Title',
'type' => 'video'
], Xml::parse( $this->valid ));
}
/**
*
*/
public function testParseInvalid( ) {
$this->setExpectedException( 'Essence\\Exception' );
Xml::parse( $this->invalid );
}
}

View File

@@ -0,0 +1,24 @@
<?php
/**
* @author Félix Girault <felix.girault@gmail.com>
* @license FreeBSD License (http://opensource.org/licenses/BSD-2-Clause)
*/
require_once dirname( dirname( __FILE__ ))
. DIRECTORY_SEPARATOR . 'lib'
. DIRECTORY_SEPARATOR . 'bootstrap.php';
/**
* Definitions
*/
if ( !defined( 'ESSENCE_TEST' )) {
define( 'ESSENCE_TEST', dirname( __FILE__ ) . DIRECTORY_SEPARATOR );
}
if ( !defined( 'ESSENCE_HTTP' )) {
define( 'ESSENCE_HTTP', ESSENCE_TEST . 'http' . DIRECTORY_SEPARATOR );
}

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr" >
<head>
<title></title>
<link rel="search" type="application/opensearchdescription+xml" href="http://www.youtube.com/opensearch?locale=fr_FR" title="Recherche de vidéos YouTube">
<link rel="icon" href="http://s.ytimg.com/yt/favicon-vfldLzJxy.ico" type="image/x-icon">
<link rel="shortcut icon" href="http://s.ytimg.com/yt/favicon-vfldLzJxy.ico" type="image/x-icon">
<link rel="canonical" href="/watch?v=M79KsXmsvec">
<link rel="alternate" media="handheld" href="http://m.youtube.com/watch?desktop_uri=%2Fwatch%3Fv%3DM79KsXmsvec&amp;v=M79KsXmsvec&amp;gl=FR">
<link rel="shortlink" href="http://youtu.be/M79KsXmsvec">
<link id="www-core-css" rel="stylesheet" href="http://s.ytimg.com/yt/cssbin/www-core-vflQNVkcc.css">
</head>
</html>

View File

@@ -0,0 +1,15 @@
{
"type" "video",
"version" : "1.0",
"provider_name" : "Dailymotion",
"provider_url" : "http:\/\/www.dailymotion.com",
"title" : "La Strat\u00e9gie de l'Echec - Les Aliments de l'echec",
"author_name" : "Benjamin",
"author_url" : "http:\/\/www.dailymotion.com\/thierrybenji", // comment
"width" : 480
"height" : 360,
"html" : "<iframe src=\"http:\/\/www.dailymotion.com\/embed\/video\/x42q5e\" width=\"480\" height=\"360\" frameborder=\"0\"><\/iframe>",
"thumbnail_url" : "http:\/\/static2.dmcdn.net\/static\/video\/666\/548\/6845666:jpeg_preview_large.jpg?20110916130708",
"thumbnail_width" : 319.99920845,
"thumbnail_height" : 240,
}

View File

@@ -0,0 +1,14 @@
<oembed>
<provider_url>http://www.youtube.com/
<thumbnail_url>http://i3.ytimg.com/vi/zGt3-fxOvug/hqdefault.jpg</thumbnail_url>
<title>JOHN CLEESE WCF</title>
<html>&lt;iframe width="480" height="270" src="http://www.youtube.com/embed/zGt3-fxOvug?fs=1&amp;feature=oembed" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;</html>
<author_name>zeekomkommers</author_name>
<height>270</height>
<thumbnail_width>480</thumbnail_width>
<width>480</width>
<version>1.0</version>
http://www.youtube.com/user/zeekomkommers</author_url>
<provider_name>YouTube</provider_name>
<type>video</type>
<thumbnail_height>360</thumbnail_height>

View File

@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="fr" dir="ltr" >
<head>
<title>Stephen Marley feat. Damian Marley &amp; Buju Banton - Jah Army (DJ Res-Q Video Edit) - YouTube</title>
<link rel="search" type="application/opensearchdescription+xml" href="http://www.youtube.com/opensearch?locale=fr_FR" title="Recherche de vidéos YouTube">
<link rel="icon" href="http://s.ytimg.com/yt/favicon-vfldLzJxy.ico" type="image/x-icon">
<link rel="shortcut icon" href="http://s.ytimg.com/yt/favicon-vfldLzJxy.ico" type="image/x-icon">
<link rel="canonical" href="/watch?v=M79KsXmsvec">
<link rel="alternate" media="handheld" href="http://m.youtube.com/watch?desktop_uri=%2Fwatch%3Fv%3DM79KsXmsvec&amp;v=M79KsXmsvec&amp;gl=FR">
<link rel="shortlink" href="http://youtu.be/M79KsXmsvec">
<meta name="title" content="Stephen Marley feat. Damian Marley &amp; Buju Banton - Jah Army (DJ Res-Q Video Edit)">
<meta name="description" content="---Exclusive DJ Res-Q Video Edit ---This is a &quot;One in the World&quot; Video--- Stephen Marley feat. Damian Marley &amp; Buju Banton - Jah Army http://www.djresqvideom...">
<meta name="keywords" content="carivibez, tv, dancehall, reggae, bob, marley, roots, dub, jamaica, remix, video, buju, banton, damian, stephen, sound, system, dubplate, 2011, riddim, VJ, V...">
<link rel="alternate" type="application/json+oembed" href="http://www.youtube.com/oembed?url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DM79KsXmsvec&amp;format=json" title="Stephen Marley feat. Damian Marley &amp; Buju Banton - Jah Army (DJ Res-Q Video Edit)">
<link rel="alternate" type="text/xml+oembed" href="http://www.youtube.com/oembed?url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DM79KsXmsvec&amp;format=xml" title="Stephen Marley feat. Damian Marley &amp; Buju Banton - Jah Army (DJ Res-Q Video Edit)">
<meta property="og:url" content="http://www.youtube.com/watch?v=M79KsXmsvec">
<meta property="og:title" content="Stephen Marley feat. Damian Marley &amp; Buju Banton - Jah Army (DJ Res-Q Video Edit)">
<meta property="og:description" content="---Exclusive DJ Res-Q Video Edit ---This is a &quot;One in the World&quot; Video--- Stephen Marley feat. Damian Marley &amp; Buju Banton - Jah Army http://www.djresqvideom...">
<meta property="og:type" content="video">
<meta property="og:image" content="http://i2.ytimg.com/vi/M79KsXmsvec/mqdefault.jpg">
<meta property="og:video" content="http://www.youtube.com/v/M79KsXmsvec?version=3&amp;autohide=1">
<meta property="og:video:type" content="application/x-shockwave-flash">
<meta property="og:video:width" content="640">
<meta property="og:video:height" content="360">
<meta property="og:site_name" content="YouTube">
<meta property="fb:app_id" content="87741124305">
<meta name="twitter:card" value="player">
<meta name="twitter:site" value="@youtube">
<meta name="twitter:player" value="https://www.youtube.com/embed/M79KsXmsvec">
<meta property="twitter:player:width" content="640">
<meta property="twitter:player:height" content="360">
<meta name=attribution content=youtube_multi/>
<link id="www-core-css" rel="stylesheet" href="http://s.ytimg.com/yt/cssbin/www-core-vflQNVkcc.css">
<script>
var gYouTubePlayerReady = false;
if ( !window['onYouTubePlayerReady']) {
window['onYouTubePlayerReady'] = function( ) {
gYouTubePlayerReady = true;
};
}
</script>
<script>
if ( window.yt.timing ) {
yt.timing.tick( 'ct' );
}
</script>
</head>
<body>
<h1>Red is dead.</h1>
<a href="http://pass.foo.com">Foo</a>
<a href="http://fail.bar.com">Bar</a>
<embed src="http://pass.embed.com"></embed>
<iframe src="http://pass.iframe.com"></iframe>
</body>
</html>

View File

@@ -0,0 +1,15 @@
{
"type" : "video",
"version" : "1.0",
"provider_name" : "Dailymotion",
"provider_url" : "http:\/\/www.dailymotion.com",
"title" : "La Strat\u00e9gie de l'Echec - Les Aliments de l'echec",
"author_name" : "Benjamin",
"author_url" : "http:\/\/www.dailymotion.com\/thierrybenji",
"width" : 480,
"height" : 360,
"html" : "<iframe src=\"http:\/\/www.dailymotion.com\/embed\/video\/x42q5e\" width=\"480\" height=\"360\" frameborder=\"0\"><\/iframe>",
"thumbnail_url" : "http:\/\/static2.dmcdn.net\/static\/video\/666\/548\/6845666:jpeg_preview_large.jpg?20110916130708",
"thumbnail_width" : 319.99920845,
"thumbnail_height" : 240
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<oembed>
<provider_url>http://www.youtube.com/</provider_url>
<thumbnail_url>http://i3.ytimg.com/vi/zGt3-fxOvug/hqdefault.jpg</thumbnail_url>
<title>JOHN CLEESE WCF</title>
<html>&lt;iframe width="480" height="270" src="http://www.youtube.com/embed/zGt3-fxOvug?fs=1&amp;feature=oembed" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;</html>
<author_name>zeekomkommers</author_name>
<height>270</height>
<thumbnail_width>480</thumbnail_width>
<width>480</width>
<version>1.0</version>
<author_url>http://www.youtube.com/user/zeekomkommers</author_url>
<provider_name>YouTube</provider_name>
<type>video</type>
<thumbnail_height>360</thumbnail_height>
</oembed>