123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 |
- <?php
- namespace Grav\Plugin\MediaEmbed;
- use Grav\Common\Grav;
- use Grav\Common\GravTrait;
- use Grav\Plugin\MediaEmbed\Service;
- use RocketTheme\Toolbox\Event\Event;
- class MediaEmbed
- {
-
- use GravTrait;
-
-
- protected $id;
-
- protected $hashes;
-
- protected $config;
-
- protected $assets = [];
-
- protected $service;
-
-
- public function __construct($config)
- {
-
- $this->service = new Service();
- $this->config = $config;
- $this->hashes = [];
- $services = $this->config->get('plugins.mediaembed.services', []);
- foreach ($services as $name => $config) {
- if (!$config['enabled']) {
- continue;
- }
-
- $class = __NAMESPACE__ . "\\Services\\$name";
- if (!class_exists($class)) {
-
- $type = isset($config['type']) ? $config['type'] : '';
- $class = __NAMESPACE__."\\OEmbed\\OEmbed".ucfirst($type);
- }
-
- $config['media'] = $this->config->get('plugins.mediaembed.media', []);
- $config['name'] = $name;
- if (class_exists($class)) {
-
- $provider = new $class($config);
-
- $this->service->register($provider);
- }
- }
- }
-
- public function id($var = null)
- {
- if ($var !== null) {
- $this->id = $var;
- }
- return $this->id;
- }
- public function prepare($content, $id = '')
- {
-
- $this->id(md5(time() . $id . md5($content)));
-
- $this->reset();
- $regex = "~
- ( # wrap whole match in $1
- !\\[
- (?P<alt>.*?) # alt text = $2
- \\]
- \\( # literal paren
- [ \\t]*
- <?(?P<src>\S+?)>? # src url = $3
- [ \\t]*
- ( # $4
- (['\"]) # quote char = $5
- (?<title>.*?) # title = $6
- \\5 # matching quote
- [ \\t]*
- )? # title is optional
- \\)
- )
- ~xs";
-
- $content = preg_replace_callback($regex, function($matches) {
-
- $url = parse_url(htmlspecialchars_decode($matches[3]));
-
- if (!isset($url['host']) && isset($url['path'])) {
- return $matches[0];
- }
- if (!isset($matches['title'])) {
- $matches['title'] = '';
- }
- return $this->hash($matches[0], $matches);
- }, $content);
- return $content;
- }
- public function process($content, $config = [])
- {
-
- $twig = self::getGrav()['twig'];
-
- $uid = 1;
-
-
- $content = preg_replace_callback(
- '~mediaembed::([0-9a-z]+)::([0-9]+)::M~i',
- function($match) use ($twig, &$uid, $config) {
- list($embed, $data) = $this->hashes[$match[0]];
-
- if ($this->service->match($data['src'])) {
- $mediaembed = [
- 'uid' => $uid++,
- 'service' => null,
- 'config' => $config,
- 'raw' => [
- 'alt' => $data['alt'],
- 'title' => $data['title'],
- 'src' => html_entity_decode($data['src']),
- ],
- 'success' => true,
- 'message' => '',
- ];
-
- try {
- $provider = $this->service->embed($data['src']);
- } catch (\Exception $e) {
- $mediaembed['message'] = $e->getMessage();
- $mediaembed['success'] = false;
- }
-
- if ($mediaembed['success']) {
-
- $assets = $provider->onTwigTemplateVariables(
- new Event(['service' => $this->service, 'mediaembed' => $this])
- );
-
- if (is_array($assets)) {
- $this->addAssets($assets);
- }
-
- $mediaembed['service'] = $provider;
-
- }
-
- $vars = ['mediaembed' => $mediaembed];
- $template = 'partials/mediaembed' . TEMPLATE_EXT;
- $embed = $twig->processTemplate($template, $vars);
- } else {
- $text = (strlen($data['alt']) > 0) ? $data['alt'] : $data['src'];
-
- $link = $config->get('link');
- if($link == true) {
- $attributes = [
- 'href' => $data['src'],
- 'title' => $data['title'],
- ];
- $format = '<a%s>%s</a>';
- } else {
- $attributes = [
- 'src' => $data['src'],
- 'title' => $data['title'],
- 'alt' => $data['alt'],
- ];
- $format = '<img%s>';
- }
- foreach ($attributes as $key => $value) {
- if (strlen($value) == 0) {
- unset($attributes[$key]);
- } else {
- $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
- $attributes[$key] = $key . '="' . $value . '"';
- }
- }
- $attributes = $attributes ? ' ' . implode(' ', $attributes) : '';
-
- $embed = sprintf($format, $attributes, $text);
- }
- return $embed;
- }, $content);
- $this->reset();
-
- return $content;
- }
-
- public function fireEvent($eventName, Event $event = null)
- {
-
- return $this->service->call($eventName, $event);
- }
-
- public function getAssets($reset = true)
- {
- $assets = $this->assets;
- if ($reset) {
- $this->assets = [];
- }
- return $assets;
- }
-
- public function addAssets($assets, $append = true)
- {
-
- if (!$append) {
- $this->assets = [];
- }
-
- if (!is_array($assets)) {
- $assets = array($assets);
- }
-
- $assets = array_merge($this->assets, $assets);
-
- $this->assets = array_keys(array_flip($assets));
- }
-
- public function add($assets, $append = true)
- {
- return $this->addAssets($assets, $append);
- }
-
- public function addCss($assets, $append = true)
- {
- return $this->addAssets($assets, $append);
- }
-
- public function addJs($assets, $append = true)
- {
- return $this->addAssets($assets, $append);
- }
-
-
- protected function getCachedMedia($key)
- {
-
- $cache = $grav['cache'];
-
- if ($this->config->get('cache.enabled')) {
-
- $cache_id = md5('mediaembed' . $key . $cache->getKey());
- $data = $cache->fetch($cache_id);
- if ((false === $data) || (time() > $data['expire'])) {
-
- $data = array(
- 'content' => $this->service->embed($key),
- 'expire' => time() + $this->config->get('cache.lifetime'),
- );
- $cache->save($cache_id, $data);
- }
-
- $content = $data['content'];
- } else {
-
- $content = $this->service->embed($key);
- }
- return $content;
- }
- protected function parseUrl($url)
- {
- if (!filter_var($url, FILTER_VALIDATE_URL)) {
- return [];
- }
-
- $url = html_entity_decode($url, ENT_COMPAT | ENT_HTML401, 'UTF-8');
- $parts = parse_url($url);
- $parts['url'] = $url;
-
- $parts['domain'] = isset($parts['host']) ? $parts['host'] : '';
- if ( preg_match('~(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$~i', $parts['domain'], $match) ) {
- $parts['domain'] = $match['domain'];
- }
- if (isset($parts['query'])) {
- parse_str(urldecode($parts['query']), $parts['query']);
- }
- $parts['query'] = [];
- return $parts;
- }
-
- protected function reset()
- {
- $this->hashes = [];
- }
-
- protected function hash($text, $data = [])
- {
- static $counter = 0;
-
-
- $text = $this->unhash($text);
-
- $key = implode('::', array('mediaembed', $this->id, ++$counter, 'M'));
- $this->hashes[$key] = [$text, $data];
-
- return $key;
- }
-
- protected function unhash($text)
- {
- $text = preg_replace_callback(
- '~mediaembed::([0-9a-z]+)::([0-9]+)::M~i', function($atches) {
- return $this->hashes[$matches[0]][0];
- }, $text);
- return $text;
- }
- }
|