opengraphhelper.php 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <?php
  2. if (!defined('GNUSOCIAL')) { exit(1); }
  3. /**
  4. * Utility class to get OpenGraph data from HTML DOMs etc.
  5. */
  6. class OpenGraphHelper
  7. {
  8. const KEY_REGEX = '/^og\:(\w+(?:\:\w+)?)/';
  9. protected static $property_map = [
  10. 'site_name' => 'provider_name',
  11. 'title' => 'title',
  12. 'description' => 'html',
  13. 'type' => 'type',
  14. 'url' => 'url',
  15. 'image' => 'thumbnail_url',
  16. 'image:height' => 'thumbnail_height',
  17. 'image:width' => 'thumbnail_width',
  18. ];
  19. // This regex map has: /pattern(match)/ => matchindex | string
  20. protected static $type_regex_map = [
  21. '/^(video)/' => 1,
  22. '/^image/' => 'photo',
  23. ];
  24. static function ogFromHtml(DOMDocument $dom) {
  25. $obj = new stdClass();
  26. $obj->version = '1.0'; // fake it til u make it
  27. $nodes = $dom->getElementsByTagName('meta');
  28. for ($i = 0; $i < $nodes->length; $i++) {
  29. $node = $nodes->item($i);
  30. if (!$node->hasAttributes()) {
  31. continue;
  32. }
  33. $property = $node->attributes->getNamedItem('property');
  34. $matches = array();
  35. if ($property === null || !preg_match(self::KEY_REGEX, $property->value, $matches)) {
  36. // not property="og:something"
  37. continue;
  38. }
  39. if (!isset(self::$property_map[$matches[1]])) {
  40. // unknown metadata property, nothing we would care about anyway
  41. continue;
  42. }
  43. $prop = self::$property_map[$matches[1]];
  44. $obj->{$prop} = $node->attributes->getNamedItem('content')->value;
  45. // I don't care right now if they're empty
  46. }
  47. if (isset($obj->type)) {
  48. // Loop through each known OpenGraph type where we have a match in oEmbed
  49. foreach (self::$type_regex_map as $pattern=>$replacement) {
  50. $matches = array();
  51. if (preg_match($pattern, $obj->type, $matches)) {
  52. $obj->type = is_int($replacement)
  53. ? $matches[$replacement]
  54. : $replacement;
  55. break;
  56. }
  57. }
  58. // If it's not known to our type map, we just pass it through in hopes of it getting handled anyway
  59. } elseif (isset($obj->url)) {
  60. // If no type is set but we have a URL, let's set type=link
  61. $obj->type = 'link';
  62. }
  63. return $obj;
  64. }
  65. }