/** * Process an image excerpt * * @param $excerpt * @param $page * @return mixed */ public static function processImageExcerpt($excerpt, $page) { $url = $excerpt['element']['attributes']['src']; $url_parts = parse_url(htmlspecialchars_decode(urldecode($url))); if (isset($url_parts['scheme']) && !Utils::startsWith($url_parts['scheme'], 'http')) { $stream_path = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path']; $url_parts['path'] = $stream_path; unset($url_parts['host']); unset($url_parts['scheme']); } $this_host = isset($url_parts['host']) && $url_parts['host'] == Grav::instance()['uri']->host(); // if there is no host set but there is a path, the file is local if ((!isset($url_parts['host']) || $this_host) && isset($url_parts['path'])) { $path_parts = pathinfo($url_parts['path']); $media = null; // get the local path to page media if possible if ($path_parts['dirname'] == $page->url(false, false, false)) { // get the media objects for this page $media = $page->media(); } else { // see if this is an external page to this one $base_url = rtrim(Grav::instance()['base_url_relative'] . Grav::instance()['pages']->base(), '/'); $page_route = '/' . ltrim(str_replace($base_url, '', $path_parts['dirname']), '/'); $ext_page = Grav::instance()['pages']->dispatch($page_route, true); if ($ext_page) { $media = $ext_page->media(); } else { Grav::instance()->fireEvent('onMediaLocate', new Event(['route' => $page_route, 'media' => &$media])); } } // if there is a media file that matches the path referenced.. if ($media && isset($media->all()[$path_parts['basename']])) { // get the medium object /** @var Medium $medium */ $medium = $media->all()[$path_parts['basename']]; // Process operations $medium = static::processMediaActions($medium, $url_parts); $alt = isset($excerpt['element']['attributes']['alt']) ? $excerpt['element']['attributes']['alt'] : ''; $title = isset($excerpt['element']['attributes']['title']) ? $excerpt['element']['attributes']['title'] : ''; $class = isset($excerpt['element']['attributes']['class']) ? $excerpt['element']['attributes']['class'] : ''; $id = isset($excerpt['element']['attributes']['id']) ? $excerpt['element']['attributes']['id'] : ''; $excerpt['element'] = $medium->parseDownElement($title, $alt, $class, $id, true); } else { // not a current page media file, see if it needs converting to relative $excerpt['element']['attributes']['src'] = Uri::buildUrl($url_parts); } } return $excerpt; }
protected function inlineLink($excerpt) { if (isset($excerpt['type'])) { $type = $excerpt['type']; } else { $type = 'link'; } // do some trickery to get around Parsedown requirement for valid URL if its Twig in there if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) { $excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']); $excerpt = parent::inlineLink($excerpt); $excerpt['element']['attributes']['href'] = $matches[1]; $excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1; return $excerpt; } else { $excerpt = parent::inlineLink($excerpt); } // if this is a link if (isset($excerpt['element']['attributes']['href'])) { $url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href'])); // if there is a query, then parse it and build action calls if (isset($url['query'])) { $actions = array_reduce(explode('&', $url['query']), function ($carry, $item) { $parts = explode('=', $item, 2); $value = isset($parts[1]) ? $parts[1] : true; $carry[$parts[0]] = $value; return $carry; }, []); // valid attributes supported $valid_attributes = ['rel', 'target', 'id', 'class', 'classes']; // Unless told to not process, go through actions if (array_key_exists('noprocess', $actions)) { unset($actions['noprocess']); } else { // loop through actions for the image and call them foreach ($actions as $attrib => $value) { $key = $attrib; if (in_array($attrib, $valid_attributes)) { // support both class and classes if ($attrib == 'classes') { $attrib = 'class'; } $excerpt['element']['attributes'][$attrib] = str_replace(',', ' ', $value); unset($actions[$key]); } } } $url['query'] = http_build_query($actions, null, '&', PHP_QUERY_RFC3986); } // if no query elements left, unset query if (empty($url['query'])) { unset($url['query']); } // if there is no scheme, the file is local and we'll need to convert that URL if (!isset($url['scheme']) && count($url) > 0) { $excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type, true); } else { $excerpt['element']['attributes']['href'] = Uri::buildUrl($url); } } return $excerpt; }
protected function inlineLink($excerpt) { if (isset($excerpt['type'])) { $type = $excerpt['type']; } else { $type = 'link'; } // do some trickery to get around Parsedown requirement for valid URL if its Twig in there if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) { $excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']); $excerpt = parent::inlineLink($excerpt); $excerpt['element']['attributes']['href'] = $matches[1]; $excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1; return $excerpt; } else { $excerpt = parent::inlineLink($excerpt); } // if this is a link if (isset($excerpt['element']['attributes']['href'])) { $url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href'])); // if there is no scheme, the file is local if (!isset($url['scheme']) && count($url) > 0) { // convert the URl is required $excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type); } } return $excerpt; }
/** * Converts links from absolute '/' or relative (../..) to a grav friendly format * * @param $page the current page to use as reference * @param string $markdown_url the URL as it was written in the markdown * * @return string the more friendly formatted url */ public static function convertUrl(Page $page, $markdown_url) { $grav = Grav::instance(); $pages_dir = $grav['locator']->findResource('page://'); $base_url = rtrim($grav['base_url'] . $grav['pages']->base(), '/'); // if absolute and starts with a base_url move on if (pathinfo($markdown_url, PATHINFO_DIRNAME) == '.' && $page->url() == '/') { return '/' . $markdown_url; // no path to convert } elseif ($base_url != '' && Utils::startsWith($markdown_url, $base_url)) { return $markdown_url; // if contains only a fragment } elseif (Utils::startsWith($markdown_url, '#')) { return $markdown_url; } else { $target = null; // see if page is relative to this or absolute if (Utils::startsWith($markdown_url, '/')) { $normalized_url = Utils::normalizePath($base_url . $markdown_url); $normalized_path = Utils::normalizePath($pages_dir . $markdown_url); } else { $normalized_url = $base_url . Utils::normalizePath($page->route() . '/' . $markdown_url); $normalized_path = Utils::normalizePath($page->path() . '/' . $markdown_url); } // special check to see if path checking is required. $just_path = str_replace($normalized_url, '', $normalized_path); if ($just_path == $page->path()) { return $normalized_url; } $url_bits = parse_url($normalized_path); $full_path = $url_bits['path']; if (file_exists($full_path)) { // do nothing } elseif (file_exists(urldecode($full_path))) { $full_path = urldecode($full_path); } else { return $normalized_url; } $path_info = pathinfo($full_path); $page_path = $path_info['dirname']; $filename = ''; if ($markdown_url == '..') { $page_path = $full_path; } else { // save the filename if a file is part of the path if (is_file($full_path)) { if ($path_info['extension'] != 'md') { $filename = '/' . $path_info['basename']; } } else { $page_path = $full_path; } } // get page instances and try to find one that fits $instances = $grav['pages']->instances(); if (isset($instances[$page_path])) { $target = $instances[$page_path]; $url_bits['path'] = $base_url . $target->route() . $filename; return Uri::buildUrl($url_bits); } return $normalized_url; } }
public function testBuildUrl() { $parsed_url = ['scheme' => 'http', 'host' => 'localhost', 'port' => '8080']; $this->assertSame('http://*****:*****@localhost:8080/test?x=2#xxx', Uri::buildUrl($parsed_url)); }