]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/Oembed/lib/oembedhelper.php
Oembed slimmed to only do discovery (soon we get og: discovery too)
[quix0rs-gnu-social.git] / plugins / Oembed / lib / oembedhelper.php
index 34a4923c484aa552e70ca7149b568a48fb6306b4..7abd76109a0e488f4cd8cb31fc6f5b063fcb8a01 100644 (file)
@@ -17,9 +17,7 @@
  * along with this program.     If not, see <http://www.gnu.org/licenses/>.
  */
 
-if (!defined('STATUSNET')) {
-    exit(1);
-}
+if (!defined('GNUSOCIAL')) { exit(1); }
 
 
 /**
@@ -47,9 +45,6 @@ class oEmbedHelper
         'revision3.com' => 'https://revision3.com/api/oembed/',
         'vimeo.com' => 'https://vimeo.com/api/oembed.json',
     );
-    protected static $functionMap = array(
-        'twitpic.com' => 'oEmbedHelper::twitPic',
-    );
 
     /**
      * Perform or fake an oEmbed lookup for the given resource.
@@ -72,77 +67,31 @@ class oEmbedHelper
      */
     public static function getObject($url, $params=array())
     {
-        $host = parse_url($url, PHP_URL_HOST);
-        if (substr($host, 0, 4) == 'www.') {
-            $host = substr($host, 4);
-        }
-
-        common_log(LOG_INFO, 'Checking for oEmbed data for ' . $url);
+        common_log(LOG_INFO, 'Checking for remote URL metadata for ' . $url);
 
-        // You can fiddle with the order of discovery -- either skipping
-        // some types or re-ordering them.
+        // TODO: Make this class something like UrlMetadata, or use a dataobject?
+        $metadata = new stdClass();
 
-        $order = common_config('oembed', 'order');
+        if (Event::handle('GetRemoteUrlMetadata', array($url, &$metadata))) {
+            // If that event didn't return anything, try downloading the body and parse it
+            $body = HTTPClient::quickGet($url);
 
-        foreach ($order as $method) {
+            // DOMDocument::loadHTML may throw warnings on unrecognized elements,
+            // and notices on unrecognized namespaces.
+            $old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE));
+            $dom = new DOMDocument();
+            $ok = $dom->loadHTML($body);
+            unset($body);   // storing the DOM in memory is enough...
+            error_reporting($old);
 
-            switch ($method) {
-            case 'built-in':
-                common_log(LOG_INFO, 'Considering built-in oEmbed methods...');
-                // Blacklist: systems with no oEmbed API of their own, which are
-                // either missing from or broken on noembed.com's proxy.
-                // we know how to look data up in another way...
-                if (array_key_exists($host, self::$functionMap)) {
-                    common_log(LOG_INFO, 'We have a built-in method for ' . $host);
-                    $func = self::$functionMap[$host];
-                    return call_user_func($func, $url, $params);
-                }
-                break;
-            case 'well-known':
-                common_log(LOG_INFO, 'Considering well-known oEmbed endpoints...');
-                // Whitelist: known API endpoints for sites that don't provide discovery...
-                if (array_key_exists($host, self::$apiMap)) {
-                    $api = self::$apiMap[$host];
-                    common_log(LOG_INFO, 'Using well-known endpoint "' . $api . '" for "' . $host . '"');
-                    break 2;
-                }
-                break;
-            case 'discovery':
-                try {
-                    common_log(LOG_INFO, 'Trying to discover an oEmbed endpoint using link headers.');
-                    $api = self::discover($url);
-                    common_log(LOG_INFO, 'Found API endpoint ' . $api . ' for URL ' . $url);
-                    break 2;
-                } catch (Exception $e) {
-                    common_log(LOG_INFO, 'Could not find an oEmbed endpoint using link headers.');
-                    // Just ignore it!
-                }
-                break;
-            case 'service':
-                $api = common_config('oembed', 'endpoint');
-                common_log(LOG_INFO, 'Using service API endpoint ' . $api);
-                break 2;
-                break;
+            if (!$ok) {
+                throw new oEmbedHelper_BadHtmlException();
             }
-        }
 
-        if (empty($api)) {
-            // TRANS: Server exception thrown in oEmbed action if no API endpoint is available.
-            throw new ServerException(_('No oEmbed API endpoint available.'));
+            Event::handle('GetRemoteUrlMetadataFromDom', array($url, $dom, &$metadata));
         }
 
-        return self::getObjectFrom($api, $url, $params);
-    }
-
-    /**
-     * Perform basic discovery.
-     * @return string
-     */
-    static function discover($url)
-    {
-        // @fixme ideally skip this for non-HTML stuff!
-        $body = self::http($url);
-        return self::discoverFromHTML($url, $body);
+        return self::normalize($metadata);
     }
 
     /**
@@ -152,19 +101,8 @@ class oEmbedHelper
      * @param string $body HTML body text
      * @return mixed string with URL or false if no target found
      */
-    static function discoverFromHTML($url, $body)
+    static function oEmbedEndpointFromHTML(DOMDocument $dom)
     {
-        // DOMDocument::loadHTML may throw warnings on unrecognized elements,
-        // and notices on unrecognized namespaces.
-        $old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE));
-        $dom = new DOMDocument();
-        $ok = $dom->loadHTML($body);
-        error_reporting($old);
-
-        if (!$ok) {
-            throw new oEmbedHelper_BadHtmlException();
-        }
-
         // Ok... now on to the links!
         $feeds = array(
             'application/json+oembed' => false,
@@ -208,16 +146,19 @@ class oEmbedHelper
      * @param array $params
      * @return object
      */
-    static function getObjectFrom($api, $url, $params=array())
+    static function getOembedFrom($api, $url, $params=array())
     {
+        if (empty($api)) {
+            // TRANS: Server exception thrown in oEmbed action if no API endpoint is available.
+            throw new ServerException(_('No oEmbed API endpoint available.'));
+        }
         $params['url'] = $url;
         $params['format'] = 'json';
         $key=common_config('oembed','apikey');
         if(isset($key)) {
             $params['key'] = common_config('oembed','apikey');
         }
-        $data = self::json($api, $params);
-        return self::normalize($data);
+        return HTTPClient::quickGetJson($api, $params);
     }
 
     /**
@@ -226,14 +167,11 @@ class oEmbedHelper
      * @param object $orig
      * @return object
      */
-    static function normalize($orig)
+    static function normalize(stdClass $data)
     {
-        $data = clone($orig);
-
         if (empty($data->type)) {
             throw new Exception('Invalid oEmbed data: no type field.');
         }
-
         if ($data->type == 'image') {
             // YFrog does this.
             $data->type = 'photo';
@@ -249,89 +187,6 @@ class oEmbedHelper
 
         return $data;
     }
-
-    /**
-     * Using a local function for twitpic lookups, as oohembed's adapter
-     * doesn't return a valid result:
-     * http://code.google.com/p/oohembed/issues/detail?id=19
-     *
-     * This code fetches metadata from Twitpic's own API, and attempts
-     * to guess proper thumbnail size from the original's size.
-     *
-     * @todo respect maxwidth and maxheight params
-     *
-     * @param string $url
-     * @param array $params
-     * @return object
-     */
-    static function twitPic($url, $params=array())
-    {
-        $matches = array();
-        if (preg_match('!twitpic\.com/(\w+)!', $url, $matches)) {
-            $id = $matches[1];
-        } else {
-            throw new Exception("Invalid twitpic URL");
-        }
-
-        // Grab metadata from twitpic's API...
-        // http://dev.twitpic.com/docs/2/media_show
-        $data = self::json('http://api.twitpic.com/2/media/show.json',
-                array('id' => $id));
-        $oembed = (object)array('type' => 'photo',
-                                'url' => 'http://twitpic.com/show/full/' . $data->short_id,
-                                'width' => $data->width,
-                                'height' => $data->height);
-        if (!empty($data->message)) {
-            $oembed->title = $data->message;
-        }
-
-        // Thumbnail is cropped and scaled to 150x150 box:
-        // http://dev.twitpic.com/docs/thumbnails/
-        $thumbSize = 150;
-        $oembed->thumbnail_url = 'http://twitpic.com/show/thumb/' . $data->short_id;
-        $oembed->thumbnail_width = $thumbSize;
-        $oembed->thumbnail_height = $thumbSize;
-
-        return $oembed;
-    }
-
-    /**
-     * Fetch some URL and return JSON data.
-     *
-     * @param string $url
-     * @param array $params query-string params
-     * @return object
-     */
-    static protected function json($url, $params=array())
-    {
-        $data = self::http($url, $params);
-        return json_decode($data);
-    }
-
-    /**
-     * Hit some web API and return data on success.
-     * @param string $url
-     * @param array $params
-     * @return string
-     */
-    static protected function http($url, $params=array())
-    {
-        $client = HTTPClient::start();
-        if ($params) {
-            $query = http_build_query($params, null, '&');
-            if (strpos($url, '?') === false) {
-                $url .= '?' . $query;
-            } else {
-                $url .= '&' . $query;
-            }
-        }
-        $response = $client->get($url);
-        if ($response->isOk()) {
-            return $response->getBody();
-        } else {
-            throw new Exception('Bad HTTP response code: ' . $response->getStatus());
-        }
-    }
 }
 
 class oEmbedHelper_Exception extends Exception