From c62c0602feb720fb8c198ea0362c3292bab38415 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Tue, 3 Feb 2009 21:29:06 +0000 Subject: Added PEAR Services/oEmbed and its dependencies for multimedia integration. --- extlib/Services/oEmbed.php | 357 +++++++++++++++++++++++++ extlib/Services/oEmbed/Exception.php | 65 +++++ extlib/Services/oEmbed/Exception/NoSupport.php | 63 +++++ extlib/Services/oEmbed/Object.php | 126 +++++++++ extlib/Services/oEmbed/Object/Common.php | 139 ++++++++++ extlib/Services/oEmbed/Object/Exception.php | 65 +++++ extlib/Services/oEmbed/Object/Link.php | 73 +++++ extlib/Services/oEmbed/Object/Photo.php | 89 ++++++ extlib/Services/oEmbed/Object/Rich.php | 82 ++++++ extlib/Services/oEmbed/Object/Video.php | 82 ++++++ 10 files changed, 1141 insertions(+) create mode 100644 extlib/Services/oEmbed.php create mode 100644 extlib/Services/oEmbed/Exception.php create mode 100644 extlib/Services/oEmbed/Exception/NoSupport.php create mode 100644 extlib/Services/oEmbed/Object.php create mode 100644 extlib/Services/oEmbed/Object/Common.php create mode 100644 extlib/Services/oEmbed/Object/Exception.php create mode 100644 extlib/Services/oEmbed/Object/Link.php create mode 100644 extlib/Services/oEmbed/Object/Photo.php create mode 100644 extlib/Services/oEmbed/Object/Rich.php create mode 100644 extlib/Services/oEmbed/Object/Video.php (limited to 'extlib/Services') diff --git a/extlib/Services/oEmbed.php b/extlib/Services/oEmbed.php new file mode 100644 index 000000000..5d38ed883 --- /dev/null +++ b/extlib/Services/oEmbed.php @@ -0,0 +1,357 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'Validate.php'; +require_once 'Net/URL2.php'; +require_once 'HTTP/Request.php'; +require_once 'Services/oEmbed/Exception.php'; +require_once 'Services/oEmbed/Exception/NoSupport.php'; +require_once 'Services/oEmbed/Object.php'; + +/** + * Base class for consuming oEmbed objects + * + * + * 'http://www.flickr.com/services/oembed/' + * )); + * $object = $oEmbed->getObject(); + * + * // All of the objects have somewhat sane __toString() methods that allow + * // you to output them directly. + * echo (string)$object; + * + * ?> + * + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed +{ + /** + * HTTP timeout in seconds + * + * All HTTP requests made by Services_oEmbed will respect this timeout. + * This can be passed to {@link Services_oEmbed::setOption()} or to the + * options parameter in {@link Services_oEmbed::__construct()}. + * + * @var string OPTION_TIMEOUT Timeout in seconds + */ + const OPTION_TIMEOUT = 'http_timeout'; + + /** + * HTTP User-Agent + * + * All HTTP requests made by Services_oEmbed will be sent with the + * string set by this option. + * + * @var string OPTION_USER_AGENT The HTTP User-Agent string + */ + const OPTION_USER_AGENT = 'http_user_agent'; + + /** + * The API's URI + * + * If the API is known ahead of time this option can be used to explicitly + * set it. If not present then the API is attempted to be discovered + * through the auto-discovery mechanism. + * + * @var string OPTION_API + */ + const OPTION_API = 'oembed_api'; + + /** + * Options for oEmbed requests + * + * @var array $options The options for making requests + */ + protected $options = array( + self::OPTION_TIMEOUT => 3, + self::OPTION_API => null, + self::OPTION_USER_AGENT => 'Services_oEmbed 0.1.0' + ); + + /** + * URL of object to get embed information for + * + * @var object $url {@link Net_URL2} instance of URL of object + */ + protected $url = null; + + /** + * Constructor + * + * @param string $url The URL to fetch an oEmbed for + * @param array $options A list of options for the oEmbed lookup + * + * @throws {@link Services_oEmbed_Exception} if the $url is invalid + * @throws {@link Services_oEmbed_Exception} when no valid API is found + * @return void + */ + public function __construct($url, array $options = array()) + { + if (Validate::uri($url)) { + $this->url = new Net_URL2($url); + } else { + throw new Services_oEmbed_Exception('URL is invalid'); + } + + if (count($options)) { + foreach ($options as $key => $val) { + $this->setOption($key, $val); + } + } + + if ($this->options[self::OPTION_API] === null) { + $this->options[self::OPTION_API] = $this->discover(); + } + } + + /** + * Set an option for the oEmbed request + * + * @param mixed $option The option name + * @param mixed $value The option value + * + * @see Services_oEmbed::OPTION_API, Services_oEmbed::OPTION_TIMEOUT + * @throws {@link Services_oEmbed_Exception} on invalid option + * @access public + * @return void + */ + public function setOption($option, $value) + { + switch ($option) { + case self::OPTION_API: + case self::OPTION_TIMEOUT: + break; + default: + throw new Services_oEmbed_Exception( + 'Invalid option "' . $option . '"' + ); + } + + $func = '_set_' . $option; + if (method_exists($this, $func)) { + $this->options[$option] = $this->$func($value); + } else { + $this->options[$option] = $value; + } + } + + /** + * Set the API option + * + * @param string $value The API's URI + * + * @throws {@link Services_oEmbed_Exception} on invalid API URI + * @see Validate::uri() + * @return string + */ + protected function _set_oembed_api($value) + { + if (!Validate::uri($value)) { + throw new Services_oEmbed_Exception( + 'API URI provided is invalid' + ); + } + + return $value; + } + + /** + * Get the oEmbed response + * + * @param array $params Optional parameters for + * + * @throws {@link Services_oEmbed_Exception} on cURL errors + * @throws {@link Services_oEmbed_Exception} on HTTP errors + * @throws {@link Services_oEmbed_Exception} when result is not parsable + * @return object The oEmbed response as an object + */ + public function getObject(array $params = array()) + { + $params['url'] = $this->url->getURL(); + if (!isset($params['format'])) { + $params['format'] = 'json'; + } + + $sets = array(); + foreach ($params as $var => $val) { + $sets[] = $var . '=' . urlencode($val); + } + + $url = $this->options[self::OPTION_API] . '?' . implode('&', $sets); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->options[self::OPTION_TIMEOUT]); + $result = curl_exec($ch); + + if (curl_errno($ch)) { + throw new Services_oEmbed_Exception( + curl_error($ch), curl_errno($ch) + ); + } + + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if (substr($code, 0, 1) != '2') { + throw new Services_oEmbed_Exception('Non-200 code returned'); + } + + curl_close($ch); + + switch ($params['format']) { + case 'json': + $res = json_decode($result); + if (!is_object($res)) { + throw new Services_oEmbed_Exception( + 'Could not parse JSON response' + ); + } + break; + case 'xml': + libxml_use_internal_errors(true); + $res = simplexml_load_string($result); + if (!$res instanceof SimpleXMLElement) { + $errors = libxml_get_errors(); + $err = array_shift($errors); + libxml_clear_errors(); + libxml_use_internal_errors(false); + throw new Services_oEmbed_Exception( + $err->message, $error->code + ); + } + break; + } + + return Services_oEmbed_Object::factory($res); + } + + /** + * Discover an oEmbed API + * + * @param string $url The URL to attempt to discover oEmbed for + * + * @throws {@link Services_oEmbed_Exception} if the $url is invalid + * @return string The oEmbed API endpoint discovered + */ + protected function discover($url) + { + $body = $this->sendRequest($url); + + // Find all tags that have a valid oembed type set. We then + // extract the href attribute for each type. + $regexp = '#]*)type="' . + '(application/json|text/xml)\+oembed"([^>]*)>#i'; + + $m = $ret = array(); + if (!preg_match_all($regexp, $body, $m)) { + throw new Services_oEmbed_Exception_NoSupport( + 'No valid oEmbed links found on page' + ); + } + + foreach ($m[0] as $i => $link) { + $h = array(); + if (preg_match('/href="([^"]+)"/i', $link, $h)) { + $ret[$m[2][$i]] = $h[1]; + } + } + + return (isset($ret['json']) ? $ret['json'] : array_pop($ret)); + } + + /** + * Send a GET request to the provider + * + * @param mixed $url The URL to send the request to + * + * @throws {@link Services_oEmbed_Exception} on HTTP errors + * @return string The contents of the response + */ + private function sendRequest($url) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->options[self::OPTION_TIMEOUT]); + curl_setopt($ch, CURLOPT_USERAGENT, $this->options[self::OPTION_USER_AGENT]); + $result = curl_exec($ch); + if (curl_errno($ch)) { + throw new Services_oEmbed_Exception( + curl_error($ch), curl_errno($ch) + ); + } + + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if (substr($code, 0, 1) != '2') { + throw new Services_oEmbed_Exception('Non-200 code returned'); + } + + return $result; + } +} + +?> diff --git a/extlib/Services/oEmbed/Exception.php b/extlib/Services/oEmbed/Exception.php new file mode 100644 index 000000000..446ac2a70 --- /dev/null +++ b/extlib/Services/oEmbed/Exception.php @@ -0,0 +1,65 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'PEAR/Exception.php'; + +/** + * Base exception class for {@link Services_oEmbed} + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed_Exception extends PEAR_Exception +{ + +} + +?> diff --git a/extlib/Services/oEmbed/Exception/NoSupport.php b/extlib/Services/oEmbed/Exception/NoSupport.php new file mode 100644 index 000000000..384c7191f --- /dev/null +++ b/extlib/Services/oEmbed/Exception/NoSupport.php @@ -0,0 +1,63 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +/** + * Exception class when no oEmbed support is discovered + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed_Exception_NoSupport extends Services_oEmbed_Exception +{ + +} + +?> diff --git a/extlib/Services/oEmbed/Object.php b/extlib/Services/oEmbed/Object.php new file mode 100644 index 000000000..9eedd7efb --- /dev/null +++ b/extlib/Services/oEmbed/Object.php @@ -0,0 +1,126 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'Services/oEmbed/Object/Exception.php'; + +/** + * Base class for consuming oEmbed objects + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +abstract class Services_oEmbed_Object +{ + + /** + * Valid oEmbed object types + * + * @var array $types Array of valid object types + * @see Services_oEmbed_Object::factory() + */ + static protected $types = array( + 'photo' => 'Photo', + 'video' => 'Video', + 'link' => 'Link', + 'rich' => 'Rich' + ); + + /** + * Create an oEmbed object from result + * + * @param object $object Raw object returned from API + * + * @throws {@link Services_oEmbed_Object_Exception} on object error + * @return object Instance of object driver + * @see Services_oEmbed_Object_Link, Services_oEmbed_Object_Photo + * @see Services_oEmbed_Object_Rich, Services_oEmbed_Object_Video + */ + static public function factory($object) + { + if (!isset($object->type)) { + throw new Services_oEmbed_Object_Exception( + 'Object has no type' + ); + } + + $type = (string)$object->type; + if (!isset(self::$types[$type])) { + throw new Services_oEmbed_Object_Exception( + 'Object type is unknown or invalid: ' . $type + ); + } + + $file = 'Services/oEmbed/Object/' . self::$types[$type] . '.php'; + include_once $file; + + $class = 'Services_oEmbed_Object_' . self::$types[$type]; + if (!class_exists($class)) { + throw new Services_oEmbed_Object_Exception( + 'Object class is invalid or not present' + ); + } + + $instance = new $class($object); + return $instance; + } + + /** + * Instantiation is not allowed + * + * @return void + */ + private function __construct() + { + + } +} + +?> diff --git a/extlib/Services/oEmbed/Object/Common.php b/extlib/Services/oEmbed/Object/Common.php new file mode 100644 index 000000000..f568ec89f --- /dev/null +++ b/extlib/Services/oEmbed/Object/Common.php @@ -0,0 +1,139 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +/** + * Base class for oEmbed objects + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +abstract class Services_oEmbed_Object_Common +{ + /** + * Raw object returned from API + * + * @var object $object The raw object from the API + */ + protected $object = null; + + /** + * Required fields per the specification + * + * @var array $required Array of required fields + * @link http://oembed.com + */ + protected $required = array(); + + /** + * Constructor + * + * @param object $object Raw object returned from the API + * + * @throws {@link Services_oEmbed_Object_Exception} on missing fields + * @return void + */ + public function __construct($object) + { + $this->object = $object; + + $this->required[] = 'version'; + foreach ($this->required as $field) { + if (!isset($this->$field)) { + throw new Services_oEmbed_Object_Exception( + 'Object is missing required ' . $field . ' attribute' + ); + } + } + } + + /** + * Get object variable + * + * @param string $var Variable to get + * + * @see Services_oEmbed_Object_Common::$object + * @return mixed Attribute's value or null if it's not set/exists + */ + public function __get($var) + { + if (property_exists($this->object, $var)) { + return $this->object->$var; + } + + return null; + } + + /** + * Is variable set? + * + * @param string $var Variable name to check + * + * @return boolean True if set, false if not + * @see Services_oEmbed_Object_Common::$object + */ + public function __isset($var) + { + if (property_exists($this->object, $var)) { + return (isset($this->object->$var)); + } + + return false; + } + + /** + * Require a sane __toString for all objects + * + * @return string + */ + abstract public function __toString(); +} + +?> diff --git a/extlib/Services/oEmbed/Object/Exception.php b/extlib/Services/oEmbed/Object/Exception.php new file mode 100644 index 000000000..6025ffd49 --- /dev/null +++ b/extlib/Services/oEmbed/Object/Exception.php @@ -0,0 +1,65 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'Services/oEmbed/Exception.php'; + +/** + * Exception for {@link Services_oEmbed_Object} + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed_Object_Exception extends Services_oEmbed_Exception +{ + +} + +?> diff --git a/extlib/Services/oEmbed/Object/Link.php b/extlib/Services/oEmbed/Object/Link.php new file mode 100644 index 000000000..9b627a89a --- /dev/null +++ b/extlib/Services/oEmbed/Object/Link.php @@ -0,0 +1,73 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'Services/oEmbed/Object/Common.php'; + +/** + * Link object for {@link Services_oEmbed} + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed_Object_Link extends Services_oEmbed_Object_Common +{ + /** + * Output a sane link + * + * @return string An HTML link of the object + */ + public function __toString() + { + return '' . $this->title . ''; + } +} + +?> diff --git a/extlib/Services/oEmbed/Object/Photo.php b/extlib/Services/oEmbed/Object/Photo.php new file mode 100644 index 000000000..5fbf4292f --- /dev/null +++ b/extlib/Services/oEmbed/Object/Photo.php @@ -0,0 +1,89 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'Services/oEmbed/Object/Common.php'; + +/** + * Photo object for {@link Services_oEmbed} + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed_Object_Photo extends Services_oEmbed_Object_Common +{ + /** + * Required fields for photo objects + * + * @var array $required Required fields + */ + protected $required = array( + 'url', 'width', 'height' + ); + + /** + * Output a valid HTML tag for image + * + * @return string HTML tag for Photo + */ + public function __toString() + { + $img = 'title)) { + $img .= ' alt="' . $this->title . '"'; + } + + return $img . ' />'; + } +} + +?> diff --git a/extlib/Services/oEmbed/Object/Rich.php b/extlib/Services/oEmbed/Object/Rich.php new file mode 100644 index 000000000..dbf6933ac --- /dev/null +++ b/extlib/Services/oEmbed/Object/Rich.php @@ -0,0 +1,82 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'Services/oEmbed/Object/Common.php'; + +/** + * Photo object for {@link Services_oEmbed} + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed_Object_Rich extends Services_oEmbed_Object_Common +{ + /** + * Required fields for rich objects + * + * @var array $required Required fields + */ + protected $required = array( + 'html', 'width', 'height' + ); + + /** + * Output a the HTML tag for rich object + * + * @return string HTML for rich object + */ + public function __toString() + { + return $this->html; + } +} + +?> diff --git a/extlib/Services/oEmbed/Object/Video.php b/extlib/Services/oEmbed/Object/Video.php new file mode 100644 index 000000000..746108115 --- /dev/null +++ b/extlib/Services/oEmbed/Object/Video.php @@ -0,0 +1,82 @@ + + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version SVN: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ + +require_once 'Services/oEmbed/Object/Common.php'; + +/** + * Photo object for {@link Services_oEmbed} + * + * @category Services + * @package Services_oEmbed + * @author Joe Stump + * @copyright 2008 Digg.com, Inc. + * @license http://tinyurl.com/42zef New BSD License + * @version Release: @version@ + * @link http://code.google.com/p/digg + * @link http://oembed.com + */ +class Services_oEmbed_Object_Video extends Services_oEmbed_Object_Common +{ + /** + * Required fields for video objects + * + * @var array $required Required fields + */ + protected $required = array( + 'html', 'width', 'height' + ); + + /** + * Output a valid embed tag for video + * + * @return string HTML for video + */ + public function __toString() + { + return $this->html; + } +} + +?> -- cgit v1.2.3-54-g00ecf