]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Super-basic OpenGraph image preview support, "works for me"
authorMikael Nordfeldth <mmn@hethane.se>
Tue, 12 Jan 2016 14:29:03 +0000 (15:29 +0100)
committerMikael Nordfeldth <mmn@hethane.se>
Tue, 12 Jan 2016 14:29:03 +0000 (15:29 +0100)
plugins/Oembed/OembedPlugin.php
plugins/Oembed/lib/opengraphhelper.php [new file with mode: 0644]

index 7d66bdebefac568c7148392decc56b9693e523b7..4adf6d35c17eeee1eb13fb570e55cedd9e2b156e 100644 (file)
@@ -40,16 +40,16 @@ class OembedPlugin extends Plugin
         try {
             common_log(LOG_INFO, 'Trying to discover an oEmbed endpoint using link headers.');
             $api = oEmbedHelper::oEmbedEndpointFromHTML($dom);
-            common_log(LOG_INFO, 'Found API endpoint ' . $api . ' for URL ' . $url);
+            common_log(LOG_INFO, 'Found oEmbed API endpoint ' . $api . ' for URL ' . $url);
             $params = array(
                 'maxwidth' => common_config('thumbnail', 'width'),
                 'maxheight' => common_config('thumbnail', 'height'),
             );
             $metadata = oEmbedHelper::getOembedFrom($api, $url, $params);
-
         } catch (Exception $e) {
-            common_log(LOG_INFO, 'Could not find an oEmbed endpoint using link headers.');
+            common_log(LOG_INFO, 'Could not find an oEmbed endpoint using link headers, trying OpenGraph from HTML.');
             // Just ignore it!
+            $metadata = OpenGraphHelper::ogFromHtml($dom);
         }
     }
 
diff --git a/plugins/Oembed/lib/opengraphhelper.php b/plugins/Oembed/lib/opengraphhelper.php
new file mode 100644 (file)
index 0000000..07b5cf5
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+
+/**
+ * Utility class to get OpenGraph data from HTML DOMs etc.
+ */
+class OpenGraphHelper
+{
+    const KEY_REGEX = '/^og\:(\w+)(?:\:(\w+))?/';
+    protected static $property_map = [
+                            'site_name'      => 'provider_name',
+                            'title'          => 'title',
+                            'description'    => 'html',
+                            'type'           => 'type',
+                            'url'            => 'url',
+                            'image'          => 'thumbnail_url',
+                            ];
+
+    // This regex map has:    /pattern(match)/ => matchindex | string
+    protected static $type_regex_map = [
+                            '/^(video)/'   => 1,
+                            '/^image/'     => 'photo',
+                            ];
+
+    static function ogFromHtml(DOMDocument $dom) {
+        $obj = new stdClass();
+        $nodes = $dom->getElementsByTagName('meta');
+        for ($i = 0; $i < $nodes->length; $i++) {
+            $node = $nodes->item($i);
+            if (!$node->hasAttributes()) {
+                continue;
+            }
+            $property = $node->attributes->getNamedItem('property');
+            $matches = array();
+            if (!preg_match(self::KEY_REGEX, $property->value, $matches)) {
+                // not property="og:something"
+                continue;
+            }
+            if (!isset(self::$property_map[$matches[1]])) {
+                // unknown metadata property, nothing we would care about anyway
+                continue;
+            }
+
+            $prop = self::$property_map[$matches[1]];
+            $obj->{$prop} = $node->attributes->getNamedItem('content')->value;
+            // I don't care right now if they're empty
+        }
+        if (isset($obj->type)) {
+            // Loop through each known OpenGraph type where we have a match in oEmbed
+            foreach (self::$type_regex_map as $pattern=>$replacement) {
+                $matches = array();
+                if (preg_match($pattern, $obj->type, $matches)) {
+                    $obj->type = is_int($replacement)
+                                    ? $matches[$replacement]
+                                    : $replacement;
+                    break;
+                }
+            }
+            // If it's not known to our type map, we just pass it through in hopes of it getting handled anyway
+        } elseif (isset($obj->url)) {
+            // If no type is set but we have a URL, let's set type=link
+            $obj->type = 'link';
+        }
+        return $obj;
+    }
+}