Source of file Embedder.php
Size: 9,002 Bytes - Last Modified: 2021-12-23T10:19:05+00:00
/var/www/docs.ssmods.com/process/src/code/Embedder.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 | <?php namespace RichardsJoqvist\silverstripeEmbedder; use RichardsJoqvist\silverstripeEmbedder\Youtube; use RichardsJoqvist\silverstripeEmbedder\Vimeo; use SilverStripe\ORM\DataExtension; use SilverStripe\Core\Injector\Injector; /** * Extend {@link DataExtension} with methods to render embedded media from links in content */ class Embedder extends DataExtension { /** * Exact width of embedded media * If set then media embedded from links will have this exact width. Media embedded from tags is not affected. * * @var int $width */ private $width = null; /** * Exact height of embedded media * If set then media embedded from links will have this exact width. Media embedded from tags is not affected. * * @var int $height */ private $height = null; /** * Max width of embedded media * * @var int $width */ private $maxWidth = null; /** * Max height of embedded media * * @var int $height */ private $maxHeight = null; /** * Fields to execute embedder on * * @var array */ private $fields = []; /** * List of ClassNames that implement IEmbedderProvider * * @var array */ private $providers = []; /** * Element tags to render * * @var array */ private $tags = []; private static $dependencies = [ 'cache' => '%$Psr\SimpleCache\CacheInterface.silverstripeEmbedder' // see _config/cache.yml ]; /** * @var Psr\SimpleCache\CacheInterface */ public $cache; /** * Render HTML from oEmbed response * * @param string $url to oEmbed service * @return string HTML or boolean false on failure */ public function renderHTML($url) { $width = $this->owner->config()->get('width'); $maxWidth = $this->owner->config()->get('maxWidth'); $height = $this->owner->config()->get('height'); $maxHeight = $this->owner->config()->get('maxHeight'); // Get json $url .= '&format=json'; if ($width || $maxWidth) { $urlWidth = ($maxWidth) ? $maxWidth : $width; $url .= '&maxwidth=' . $urlWidth; } if ($height || $maxHeight) { $urlHeight = ($maxHeight) ? $maxHeight : $height; $url .= '&maxheight=' . $urlHeight; } $fileName = md5($url) . '.json'; if (!$json = $this->loadJson($url)) { return false; } // Decode json to an object if ($json->type == 'video') { $html = $json->html; // Calculate size if ($size = $this->calculateSize($json->width, $json->height)) { $resize = []; if (isset($json->width) && $size['width']) { $resize['width="' . $json->width . '"'] = 'width="' . $size['width'] . '"'; } if (isset($json->height) && $size['height']) { $resize['height="' . $json->height . '"'] = 'height="' . $size['height'] . '"'; } if ($resize) { $html = str_replace(array_keys($resize), array_values($resize), $html); } } return $html; } if ($json->type == 'photo') { // Image template $template = '<img src="%s" width="%d" height="%d" class="embed-%s" title="%s"/>'; // Calculate size if ($size = $this->calculateSize($json->width, $json->height)) { $json->width = $size['width']; $json->height = $size['height']; } $title = strip_tags($json->title); if (empty($title)) { $title = $json->provider_name; } return sprintf($template, $json->url, $json->width, $json->height, strtolower($json->provider_name), $title); } if($json->type === 'rich' && $json->html) // Instagram type { return $json->html; } return false; } /** * Calculate embed size (maintaining aspect ratio) * * @param int $width original width of media * @param int $height original height of media * @return array */ public function calculateSize($mediaWidth, $mediaHeight) { try { $mediaWidth = (int) $mediaWidth; $mediaHeight = (int) $mediaHeight; $width = $this->owner->config()->get('width'); $maxWidth = $this->owner->config()->get('maxWidth'); $height = $this->owner->config()->get('height'); $maxHeight = $this->owner->config()->get('maxHeight'); if ($width) { if (!$height) { $mediaHeight = round($mediaHeight * ($width / $mediaWidth)); } $mediaWidth = $width; } elseif ($maxWidth) { if ($mediaWidth > $maxWidth) { $mediaHeight = round($mediaHeight * ($maxWidth / $mediaWidth)); $mediaWidth = $maxWidth; } } if ($height) { if (!$width) { $mediaWidth = round($mediaWidth * ($height / $mediaHeight)); } $mediaHeight = $height; } elseif ($maxHeight) { if ($mediaHeight > $maxHeight) { $mediaWidth = round($mediaWidth * ($maxHeight / $mediaHeight)); $mediaHeight = $maxHeight; } } return ['width' => $mediaWidth, 'height' => $mediaHeight]; } catch (Exception $e) { return false; } } /** * Load oEmbed json and return it as stdclass object * * @param string $url * @param bool $refresh * @return bool|stdclass */ private function loadJson($url, $refresh = false) { $cacheKey = md5($url); // Unless force refreshing, try loading from cache if (!$refresh) { if ($json = $this->cache->get($cacheKey)) { return json_decode($json); } } // Load json and cache it $json = file_get_contents($url); if (!empty($json)) { try { $jsonObj = json_decode($json); } catch (Exception $e) { return false; } if ($jsonObj) { $this->cache->set($cacheKey,$json); return $jsonObj; } } return false; } /** * Render embeds * * @param Controller $controller */ public function contentcontrollerInit($controller) { $configFields =$this->owner->config()->get('fields'); if (!is_array($configFields)) { user_error('Fields Not Set, Content Fields need to be set in a yml config file. See Readme for details ', E_USER_ERROR); } $className = $this->owner->data()->className; // Get the Wild Fields that apply to all SiteTree Models $fieldsToApplyEmbeddersTo = $this->convertToArray('all', $configFields); // Get the Fields set to apply to this controllers SiteTree object $fieldsToApplyEmbeddersTo = array_merge( $fieldsToApplyEmbeddersTo, $this->convertToArray($className, $configFields) ); if (empty($fieldsToApplyEmbeddersTo)) { return; } $providers = $this->owner->config()->get('providers'); $tags = $this->owner->config()->get('tags'); foreach ($fieldsToApplyEmbeddersTo as $field) { $content = $controller->data()->$field; if (!$content || empty($content)) { continue; } foreach ($providers as $providerClassName) { $provider = new $providerClassName($this); $content = preg_replace_callback( $provider->pattern(), function($matches) use ($provider) { return $provider->render($matches); }, $content); } if($tags && is_array($tags)) { foreach ($tags as $tag) { preg_match_all("/(\<{$tag}\s)(.*)(\/{$tag}\>)/isU", $content, $m); $m = array_unique($m[0]); foreach ($m as $match) { $content = str_replace($match, html_entity_decode($match), $content); } } } $controller->data()->$field = $content; } } private function convertToArray($key, $array) { if (!isset($array[$key])) { return []; } $value = $array[$key]; if (is_string($value)) { return [$value]; } elseif (is_array($value)) { return $value; } user_error('Config value needs to be a string or Array', E_USER_ERROR); } } |