Fix undefined oembed properties
- Add Object\OEmbed class
This commit is contained in:
		
					parent
					
						
							
								adc47fc8ea
							
						
					
				
			
			
				commit
				
					
						df917251ff
					
				
			
		
					 2 changed files with 134 additions and 89 deletions
				
			
		|  | @ -19,7 +19,6 @@ use Friendica\Database\DBA; | |||
| use Friendica\Util\DateTimeFormat; | ||||
| use Friendica\Util\Network; | ||||
| use Friendica\Util\ParseUrl; | ||||
| use stdClass; | ||||
| 
 | ||||
| require_once 'include/dba.php'; | ||||
| require_once 'mod/proxy.php'; | ||||
|  | @ -48,132 +47,128 @@ class OEmbed | |||
| 	/** | ||||
| 	 * @brief Get data from an URL to embed its content. | ||||
| 	 * | ||||
| 	 * @param string $embedurl The URL from which the data should be fetched. | ||||
| 	 * @param bool $no_rich_type If set to true rich type content won't be fetched. | ||||
| 	 * @param string $embedurl     The URL from which the data should be fetched. | ||||
| 	 * @param bool   $no_rich_type If set to true rich type content won't be fetched. | ||||
| 	 * | ||||
| 	 * @return bool|object Returns object with embed content or false if no embeddable | ||||
| 	 * 	                   content exists | ||||
| 	 * @return \Friendica\Object\OEmbed | ||||
| 	 */ | ||||
| 	public static function fetchURL($embedurl, $no_rich_type = false) | ||||
| 	{ | ||||
| 		$embedurl = trim($embedurl, "'"); | ||||
| 		$embedurl = trim($embedurl, '"'); | ||||
| 		$embedurl = trim($embedurl, '\'"'); | ||||
| 
 | ||||
| 		$a = get_app(); | ||||
| 
 | ||||
| 		$cache_key = 'oembed:' . $a->videowidth . ':' . $embedurl; | ||||
| 
 | ||||
| 		$condition = ['url' => normalise_link($embedurl), 'maxwidth' => $a->videowidth]; | ||||
| 		$oembed = DBA::selectFirst('oembed', ['content'], $condition); | ||||
| 		if (DBA::isResult($oembed)) { | ||||
| 			$txt = $oembed["content"]; | ||||
| 		$oembed_record = DBA::selectFirst('oembed', ['content'], $condition); | ||||
| 		if (DBA::isResult($oembed_record)) { | ||||
| 			$json_string = $oembed_record['content']; | ||||
| 		} else { | ||||
| 			$txt = Cache::get($a->videowidth . $embedurl); | ||||
| 			$json_string = Cache::get($cache_key); | ||||
| 		} | ||||
| 
 | ||||
| 		// These media files should now be caught in bbcode.php
 | ||||
| 		// left here as a fallback in case this is called from another source
 | ||||
| 
 | ||||
| 		$noexts = ["mp3", "mp4", "ogg", "ogv", "oga", "ogm", "webm"]; | ||||
| 		$noexts = ['mp3', 'mp4', 'ogg', 'ogv', 'oga', 'ogm', 'webm']; | ||||
| 		$ext = pathinfo(strtolower($embedurl), PATHINFO_EXTENSION); | ||||
| 
 | ||||
| 		$oembed = new \Friendica\Object\OEmbed($embedurl); | ||||
| 
 | ||||
| 		if (is_null($txt)) { | ||||
| 			$txt = ""; | ||||
| 		if ($json_string) { | ||||
| 			$oembed->parseJSON($json_string); | ||||
| 		} else { | ||||
| 			$json_string = ''; | ||||
| 
 | ||||
| 			if (!in_array($ext, $noexts)) { | ||||
| 				// try oembed autodiscovery
 | ||||
| 				$redirects = 0; | ||||
| 				$html_text = Network::fetchUrl($embedurl, false, $redirects, 15, "text/*"); | ||||
| 				$html_text = Network::fetchUrl($embedurl, false, $redirects, 15, 'text/*'); | ||||
| 				if ($html_text) { | ||||
| 					$dom = @DOMDocument::loadHTML($html_text); | ||||
| 					if ($dom) { | ||||
| 						$xpath = new DOMXPath($dom); | ||||
| 						$entries = $xpath->query("//link[@type='application/json+oembed']"); | ||||
| 						foreach ($entries as $e) { | ||||
| 							$href = $e->getAttributeNode("href")->nodeValue; | ||||
| 							$txt = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); | ||||
| 							$href = $e->getAttributeNode('href')->nodeValue; | ||||
| 							$json_string = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); | ||||
| 							break; | ||||
| 						} | ||||
| 
 | ||||
| 						$entries = $xpath->query("//link[@type='text/json+oembed']"); | ||||
| 						foreach ($entries as $e) { | ||||
| 							$href = $e->getAttributeNode("href")->nodeValue; | ||||
| 							$txt = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); | ||||
| 							$href = $e->getAttributeNode('href')->nodeValue; | ||||
| 							$json_string = Network::fetchUrl($href . '&maxwidth=' . $a->videowidth); | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			$txt = trim($txt); | ||||
| 			$json_string = trim($json_string); | ||||
| 
 | ||||
| 			if (!$txt || $txt[0] != "{") { | ||||
| 				$txt = '{"type":"error"}'; | ||||
| 			} else { //save in cache
 | ||||
| 				$j = json_decode($txt); | ||||
| 				if (!empty($j->type) && $j->type != "error") { | ||||
| 					DBA::insert('oembed', [ | ||||
| 						'url' => normalise_link($embedurl), | ||||
| 						'maxwidth' => $a->videowidth, | ||||
| 						'content' => $txt, | ||||
| 						'created' => DateTimeFormat::utcNow() | ||||
| 					], true); | ||||
| 				} | ||||
| 
 | ||||
| 				Cache::set($a->videowidth . $embedurl, $txt, CACHE_DAY); | ||||
| 			if (!$json_string || $json_string[0] != '{') { | ||||
| 				$json_string = '{"type":"error"}'; | ||||
| 			} | ||||
| 
 | ||||
| 			$oembed->parseJSON($json_string); | ||||
| 			if (!empty($oembed->type) && $oembed->type != 'error') { | ||||
| 				DBA::insert('oembed', [ | ||||
| 					'url' => normalise_link($embedurl), | ||||
| 					'maxwidth' => $a->videowidth, | ||||
| 					'content' => $json_string, | ||||
| 					'created' => DateTimeFormat::utcNow() | ||||
| 				], true); | ||||
| 			} | ||||
| 
 | ||||
| 			Cache::set($cache_key, $json_string, CACHE_DAY); | ||||
| 		} | ||||
| 
 | ||||
| 		$j = json_decode($txt); | ||||
| 
 | ||||
| 		if (!is_object($j)) { | ||||
| 			return false; | ||||
| 		if ($oembed->type == 'error') { | ||||
| 			return $oembed; | ||||
| 		} | ||||
| 
 | ||||
| 		// Always embed the SSL version
 | ||||
| 		if (isset($j->html)) { | ||||
| 			$j->html = str_replace(["http://www.youtube.com/", "http://player.vimeo.com/"], ["https://www.youtube.com/", "https://player.vimeo.com/"], $j->html); | ||||
| 		} | ||||
| 
 | ||||
| 		$j->embedurl = $embedurl; | ||||
| 		$oembed->html = str_replace(['http://www.youtube.com/', 'http://player.vimeo.com/'], ['https://www.youtube.com/', 'https://player.vimeo.com/'], $oembed->html); | ||||
| 
 | ||||
| 		// If fetching information doesn't work, then improve via internal functions
 | ||||
| 		if ($no_rich_type && ($j->type == "rich")) { | ||||
| 		if ($no_rich_type && ($oembed->type == 'rich')) { | ||||
| 			$data = ParseUrl::getSiteinfoCached($embedurl, true, false); | ||||
| 			$j->type = $data["type"]; | ||||
| 			$oembed->type = $data['type']; | ||||
| 
 | ||||
| 			if ($j->type == "photo") { | ||||
| 				$j->url = $data["url"]; | ||||
| 			if ($oembed->type == 'photo') { | ||||
| 				$oembed->url = $data['url']; | ||||
| 			} | ||||
| 
 | ||||
| 			if (isset($data["title"])) { | ||||
| 				$j->title = $data["title"]; | ||||
| 			if (isset($data['title'])) { | ||||
| 				$oembed->title = $data['title']; | ||||
| 			} | ||||
| 
 | ||||
| 			if (isset($data["text"])) { | ||||
| 				$j->description = $data["text"]; | ||||
| 			if (isset($data['text'])) { | ||||
| 				$oembed->description = $data['text']; | ||||
| 			} | ||||
| 
 | ||||
| 			if (is_array($data["images"])) { | ||||
| 				$j->thumbnail_url = $data["images"][0]["src"]; | ||||
| 				$j->thumbnail_width = $data["images"][0]["width"]; | ||||
| 				$j->thumbnail_height = $data["images"][0]["height"]; | ||||
| 			if (is_array($data['images'])) { | ||||
| 				$oembed->thumbnail_url = $data['images'][0]['src']; | ||||
| 				$oembed->thumbnail_width = $data['images'][0]['width']; | ||||
| 				$oembed->thumbnail_height = $data['images'][0]['height']; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		Addon::callHooks('oembed_fetch_url', $embedurl, $j); | ||||
| 		Addon::callHooks('oembed_fetch_url', $embedurl, $oembed); | ||||
| 
 | ||||
| 		return $j; | ||||
| 		return $oembed; | ||||
| 	} | ||||
| 
 | ||||
| 	private static function formatObject(stdClass $j) | ||||
| 	private static function formatObject(\Friendica\Object\OEmbed $oembed) | ||||
| 	{ | ||||
| 		$embedurl = $j->embedurl; | ||||
| 		$jhtml = $j->html; | ||||
| 		$ret = '<div class="oembed ' . $j->type . '">'; | ||||
| 		$ret = '<div class="oembed ' . $oembed->type . '">'; | ||||
| 
 | ||||
| 		switch ($j->type) { | ||||
| 		switch ($oembed->type) { | ||||
| 			case "video": | ||||
| 				if (isset($j->thumbnail_url)) { | ||||
| 					$tw = (isset($j->thumbnail_width) && intval($j->thumbnail_width)) ? $j->thumbnail_width : 200; | ||||
| 					$th = (isset($j->thumbnail_height) && intval($j->thumbnail_height)) ? $j->thumbnail_height : 180; | ||||
| 				if ($oembed->thumbnail_url) { | ||||
| 					$tw = (isset($oembed->thumbnail_width) && intval($oembed->thumbnail_width)) ? $oembed->thumbnail_width : 200; | ||||
| 					$th = (isset($oembed->thumbnail_height) && intval($oembed->thumbnail_height)) ? $oembed->thumbnail_height : 180; | ||||
| 					// make sure we don't attempt divide by zero, fallback is a 1:1 ratio
 | ||||
| 					$tr = (($th) ? $tw / $th : 1); | ||||
| 
 | ||||
|  | @ -182,63 +177,63 @@ class OEmbed | |||
| 					$tpl = get_markup_template('oembed_video.tpl'); | ||||
| 					$ret .= replace_macros($tpl, [ | ||||
| 						'$baseurl' => System::baseUrl(), | ||||
| 						'$embedurl' => $embedurl, | ||||
| 						'$escapedhtml' => base64_encode($jhtml), | ||||
| 						'$embedurl' => $oembed->embed_url, | ||||
| 						'$escapedhtml' => base64_encode($oembed->html), | ||||
| 						'$tw' => $tw, | ||||
| 						'$th' => $th, | ||||
| 						'$turl' => $j->thumbnail_url, | ||||
| 						'$turl' => $oembed->thumbnail_url, | ||||
| 					]); | ||||
| 				} else { | ||||
| 					$ret = $jhtml; | ||||
| 					$ret = $oembed->html; | ||||
| 				} | ||||
| 				break; | ||||
| 			case "photo": | ||||
| 				$ret .= '<img width="' . $j->width . '" src="' . proxy_url($j->url) . '">'; | ||||
| 				$ret .= '<img width="' . $oembed->width . '" src="' . proxy_url($oembed->url) . '">'; | ||||
| 				break; | ||||
| 			case "link": | ||||
| 				break; | ||||
| 			case "rich": | ||||
| 				$ret .= proxy_parse_html($jhtml); | ||||
| 				$ret .= proxy_parse_html($oembed->html); | ||||
| 				break; | ||||
| 		} | ||||
| 
 | ||||
| 		// add link to source if not present in "rich" type
 | ||||
| 		if ($j->type != 'rich' || !strpos($j->html, $embedurl)) { | ||||
| 		if ($oembed->type != 'rich' || !strpos($oembed->html, $oembed->embed_url)) { | ||||
| 			$ret .= '<h4>'; | ||||
| 			if (!empty($j->title)) { | ||||
| 				if (!empty($j->provider_name)) { | ||||
| 					$ret .= $j->provider_name . ": "; | ||||
| 			if (!empty($oembed->title)) { | ||||
| 				if (!empty($oembed->provider_name)) { | ||||
| 					$ret .= $oembed->provider_name . ": "; | ||||
| 				} | ||||
| 
 | ||||
| 				$ret .= '<a href="' . $embedurl . '" rel="oembed">' . $j->title . '</a>'; | ||||
| 				if (!empty($j->author_name)) { | ||||
| 					$ret .= ' (' . $j->author_name . ')'; | ||||
| 				$ret .= '<a href="' . $oembed->embed_url . '" rel="oembed">' . $oembed->title . '</a>'; | ||||
| 				if (!empty($oembed->author_name)) { | ||||
| 					$ret .= ' (' . $oembed->author_name . ')'; | ||||
| 				} | ||||
| 			} elseif (!empty($j->provider_name) || !empty($j->author_name)) { | ||||
| 			} elseif (!empty($oembed->provider_name) || !empty($oembed->author_name)) { | ||||
| 				$embedlink = ""; | ||||
| 				if (!empty($j->provider_name)) { | ||||
| 					$embedlink .= $j->provider_name; | ||||
| 				if (!empty($oembed->provider_name)) { | ||||
| 					$embedlink .= $oembed->provider_name; | ||||
| 				} | ||||
| 
 | ||||
| 				if (!empty($j->author_name)) { | ||||
| 				if (!empty($oembed->author_name)) { | ||||
| 					if ($embedlink != "") { | ||||
| 						$embedlink .= ": "; | ||||
| 					} | ||||
| 
 | ||||
| 					$embedlink .= $j->author_name; | ||||
| 					$embedlink .= $oembed->author_name; | ||||
| 				} | ||||
| 				if (trim($embedlink) == "") { | ||||
| 					$embedlink = $embedurl; | ||||
| 					$embedlink = $oembed->embed_url; | ||||
| 				} | ||||
| 
 | ||||
| 				$ret .= '<a href="' . $embedurl . '" rel="oembed">' . $embedlink . '</a>'; | ||||
| 				$ret .= '<a href="' . $oembed->embed_url . '" rel="oembed">' . $embedlink . '</a>'; | ||||
| 			} else { | ||||
| 				$ret .= '<a href="' . $embedurl . '" rel="oembed">' . $embedurl . '</a>'; | ||||
| 				$ret .= '<a href="' . $oembed->embed_url . '" rel="oembed">' . $oembed->embed_url . '</a>'; | ||||
| 			} | ||||
| 			$ret .= "</h4>"; | ||||
| 		} elseif (!strpos($j->html, $embedurl)) { | ||||
| 		} elseif (!strpos($oembed->html, $oembed->embed_url)) { | ||||
| 			// add <a> for html2bbcode conversion
 | ||||
| 			$ret .= '<a href="' . $embedurl . '" rel="oembed">' . $j->title . '</a>'; | ||||
| 			$ret .= '<a href="' . $oembed->embed_url . '" rel="oembed">' . $oembed->title . '</a>'; | ||||
| 		} | ||||
| 
 | ||||
| 		$ret .= '</div>'; | ||||
|  |  | |||
							
								
								
									
										50
									
								
								src/Object/OEmbed.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/Object/OEmbed.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Friendica\Object; | ||||
| 
 | ||||
| /** | ||||
|  * OEmbed data object | ||||
|  * | ||||
|  * @see https://oembed.com/#section2.3
 | ||||
|  * | ||||
|  * @author Hypolite Petovan <mrpetovan@gmail.com> | ||||
|  */ | ||||
| class OEmbed | ||||
| { | ||||
| 	public $embed_url        = ''; | ||||
| 
 | ||||
| 	public $type             = ''; | ||||
| 	public $title            = ''; | ||||
| 	public $author_name      = ''; | ||||
| 	public $author_url       = ''; | ||||
| 	public $provider_name    = ''; | ||||
| 	public $provider_url     = ''; | ||||
| 	public $cache_age        = ''; | ||||
| 	public $thumbnail_url    = ''; | ||||
| 	public $thumbnail_width  = ''; | ||||
| 	public $thumbnail_height = ''; | ||||
| 	public $html             = ''; | ||||
| 	public $url              = ''; | ||||
| 	public $width            = ''; | ||||
| 	public $height           = ''; | ||||
| 
 | ||||
| 	public function __construct($embed_url) | ||||
| 	{ | ||||
| 		$this->embed_url = $embed_url; | ||||
| 	} | ||||
| 
 | ||||
| 	public function parseJSON($json_string) | ||||
| 	{ | ||||
| 		$properties = json_decode($json_string, true); | ||||
| 
 | ||||
| 		if (empty($properties)) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		foreach ($properties as $key => $value) { | ||||
| 			if (property_exists(__CLASS__, $key)) { | ||||
| 				$this->{$key} = $value; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue