diff --git a/lib/classes/local/url_unfurl.php b/lib/classes/local/url_unfurl.php new file mode 100644 index 0000000000..37d3d3fec9 --- /dev/null +++ b/lib/classes/local/url_unfurl.php @@ -0,0 +1,130 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +/** + * Receives Open Graph protocol metadata (a.k.a social media metadata) from link + * + * @package core + * @copyright 2021 Jon Green + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class unfurl { + public $title = ''; + public $site_name = ''; + public $image = ''; + public $description = ''; + public $canonical_url = ''; + public $no_og_metadata = true; + + function __construct($url) { + $html = file_get_contents($url); + + $doc = new DOMDocument(); + @$doc->loadHTML('' . $html); + $meta_tag_list = $doc->getElementsByTagName('meta'); + + foreach($meta_tag_list as $meta_tag) { + $property_attribute = strtolower(s($meta_tag->getAttribute('property'))); + if ( + !empty($property_attribute) && + preg_match ('/^og:\w+/i', $property_attribute) === 1 + ) { + $this->no_og_metadata = false; + break; + } + } + + if ($this->no_og_metadata) { + return; + } + + foreach($meta_tag_list as $meta_tag) { + $property_attribute = strtolower(s($meta_tag->getAttribute('property'))); + $content_attribute = s($meta_tag->getAttribute('content')); + if ( + !empty($property_attribute) && + !empty($content_attribute) && + preg_match ('/^og:\w+/i', $property_attribute) === 1 + ) { + switch ($property_attribute) { + case 'og:title': + $this->title = $content_attribute; + break; + case 'og:site_name': + $this->site_name = $content_attribute; + break; + case 'og:image': + $imageurl_parts = parse_url($content_attribute); + // Some websites only give the path + if (empty($imageurl_parts['host']) && !empty($imageurl_parts['path'])) { + $url_parts = parse_url($url); + $this->image = $url_parts['scheme'].'://'.$url_parts['host'].$imageurl_parts['path']; + } else { + $this->image = $content_attribute; + } + break; + case 'og:description': + $this->description = $content_attribute; + break; + case 'og:url': + $this->canonical_url = $content_attribute; + break; + default: + break; + } + } + } + } +} + +/** + * Receives and stores unfurled link meta data + * + * @package core + * @copyright 2021 Jon Green + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class unfurl_store { + private static $instance = null; + private $cache; + + private function __construct() { + $this->cache = cache::make('core', 'unfurl'); + } + + public static function get_instance() { + if (self::$instance == null) { + self::$instance = new unfurl_store(); + } + + return self::$instance; + } + + public function get_unfurl($url) { + $data = $this->cache->get($url); + + if ($data) { + return $data; + } + + $new_data = new unfurl($url); + $this->cache->set($url, $new_data); + + return $new_data; + } +} \ No newline at end of file