public function init() { $this->shortcode->getHandlers()->add('fa', function (ShortcodeInterface $sc) { // Load assets if required if ($this->config->get('plugins.shortcode-core.fontawesome.load', false)) { $this->shortcode->addAssets('css', $this->config->get('plugins.shortcode-core.fontawesome.url')); } // Get shortcode content and parameters $str = $sc->getContent(); $icon = $sc->getParameter('icon', false); if (!$icon) { $icon = $sc->getParameter('fa', trim($sc->getParameterAt(0), '=')); } if (!Utils::startsWith($icon, 'fa-')) { $icon = 'fa-' . $icon; } $extras = explode(',', $sc->getParameter('extras', '')); foreach ($extras as $extra) { if (!Utils::startsWith($extra, 'fa-')) { $extra = 'fa-' . $extra; } $icon .= ' ' . $extra; } $output = '<i class="fa ' . $icon . '">' . $str . '</i>'; return $output; }); }
/** * If the admin path matches, initialize the Login plugin configuration and set the admin * as active. */ public function setup() { // Autoloader spl_autoload_register(function ($class) { if (Utils::startsWith($class, 'Grav\\Plugin\\Admin')) { require_once __DIR__ . '/classes/' . strtolower(basename(str_replace("\\", "/", $class))) . '.php'; } }); $route = $this->config->get('plugins.admin.route'); if (!$route) { return; } $this->base = '/' . trim($route, '/'); $this->admin_route = rtrim($this->grav['pages']->base(), '/') . $this->base; $this->uri = $this->grav['uri']; // check for existence of a user account $account_dir = $file_path = $this->grav['locator']->findResource('account://'); $user_check = glob($account_dir . '/*.yaml'); // If no users found, go to register if ($user_check == false || count((array) $user_check) == 0) { if (!$this->isAdminPath()) { $this->grav->redirect($this->admin_route); } $this->template = 'register'; } // Only activate admin if we're inside the admin path. if ($this->isAdminPath()) { $this->active = true; // Set cache based on admin_cache option if (method_exists($this->grav['cache'], 'setEnabled')) { $this->grav['cache']->setEnabled($this->config->get('plugins.admin.cache_enabled')); } } }
public function testStartsWith() { $this->assertTrue(Utils::startsWith('english', 'en')); $this->assertTrue(Utils::startsWith('English', 'En')); $this->assertTrue(Utils::startsWith('ENGLISH', 'EN')); $this->assertTrue(Utils::startsWith('ENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISH', 'EN')); $this->assertFalse(Utils::startsWith('english', 'En')); $this->assertFalse(Utils::startsWith('English', 'EN')); $this->assertFalse(Utils::startsWith('ENGLISH', 'en')); $this->assertFalse(Utils::startsWith('ENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISHENGLISH', 'e')); }
public function filecontent($path) { $path_info = pathinfo($path); $config = Grav::instance()['config']->get('plugins.file-content'); if (in_array($path_info['extension'], $config['allowed_extensions'])) { if (Utils::startsWith($path, '/')) { if ($config['allow_in_grav'] && file_exists(GRAV_ROOT . $path)) { return file_get_contents(GRAV_ROOT . $path); } elseif ($config['allow_in_filesystem'] && file_exists($path)) { return file_get_contents($path); } } else { $page_path = Grav::instance()['page']->path() . '/' . $path; if ($config['allow_in_page'] && file_exists($page_path)) { return file_get_contents($page_path); } } } return $path; }
/** * Build search results. */ public function onPagesInitialized() { $page = $this->grav['page']; // If a page exists merge the configs if ($page) { $this->config->set('plugins.simplesearch', $this->mergeConfig($page)); } /** @var Uri $uri */ $uri = $this->grav['uri']; $query = $uri->param('query') ?: $uri->query('query'); $route = $this->config->get('plugins.simplesearch.route'); // performance check if ($route && $query && $route == $uri->path()) { $this->enable(['onTwigSiteVariables' => ['onTwigSiteVariables', 0]]); } else { return; } $this->query = explode(',', $query); /** @var Taxonomy $taxonomy_map */ $taxonomy_map = $this->grav['taxonomy']; $taxonomies = []; $filters = (array) $this->config->get('plugins.simplesearch.filters'); $operator = $this->config->get('plugins.simplesearch.filter_combinator', 'and'); // see if the filter uses the new 'items-type' syntax $new_approach = false; foreach ($filters as $filter) { $filter_saved = $filter; if (is_array($filter)) { $filter = key($filter); } if (Utils::startsWith($filter, '@')) { if ($filter == '@self') { $new_approach = true; } if ($filter == '@taxonomy') { $taxonomies = $filter_saved[$filter]; } } } if ($new_approach) { $params = $page->header()->content; $params['query'] = $this->config->get('plugins.simplesearch.query'); $this->collection = $page->collection($params, false); } else { $this->collection = new Collection(); $this->collection->append($taxonomy_map->findTaxonomy($filters, $operator)->toArray()); } $extras = []; /** @var Page $cpage */ foreach ($this->collection as $cpage) { foreach ($this->query as $query) { $query = trim($query); $taxonomy_match = false; if (!empty($taxonomies)) { $page_taxonomies = $cpage->taxonomy(); foreach ((array) $taxonomies as $taxonomy) { if (array_key_exists($taxonomy, $page_taxonomies)) { $taxonomy_values = implode('|', $page_taxonomies[$taxonomy]); if (stripos($taxonomy_values, $query) !== false) { $taxonomy_match = true; break; } } } } if ($taxonomy_match === false && stripos($cpage->content(), $query) === false && stripos($cpage->title(), $query) === false) { $this->collection->remove($cpage); continue; } if ($cpage->modular()) { $this->collection->remove($cpage); $parent = $cpage->parent(); $extras[$parent->path()] = ['slug' => $parent->slug()]; } } } if (!empty($extras)) { $this->collection->append($extras); } // use a configured sorting order if not already done if (!$new_approach) { $this->collection = $this->collection->order($this->config->get('plugins.simplesearch.order.by'), $this->config->get('plugins.simplesearch.order.dir')); } // if page doesn't have settings set, create a page if (!isset($page->header()->simplesearch)) { // create the search page $page = new Page(); $page->init(new \SplFileInfo(__DIR__ . '/pages/simplesearch.md')); // override the template is set in the config $template_override = $this->config->get('plugins.simplesearch.template'); if ($template_override) { $page->template($template_override); } // fix RuntimeException: Cannot override frozen service "page" issue unset($this->grav['page']); $this->grav['page'] = $page; } }
/** * 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; }
/** * Test if a URL is external * * @param string $url The URL to test. * @param array $domains An array of domains to be seen as internal. * * @return boolean Returns true, if the URL is external, * false otherwise. */ protected function isExternalUrl($url, $domains = []) { static $allowed_protocols; static $pattern; // Statically store allowed protocols if (!isset($allowed_protocols)) { $allowed_protocols = array_flip(array('ftp', 'http', 'https', 'irc', 'mailto', 'news', 'nntp', 'rtsp', 'sftp', 'ssh', 'tel', 'telnet', 'webcal')); } // Statically store internal domains as a PCRE pattern. if (!isset($pattern) || count($domains) > 0) { $domains = array_merge($domains, array(self::getGrav()['base_url_absolute'])); foreach ($domains as $domain) { $domains[] = preg_quote($domain, '#'); } $pattern = '#(' . str_replace(array('\\*', '/*'), '.*?', implode('|', $domains)) . ')#i'; } $external = false; if (!preg_match($pattern, $url)) { // Check if URL is external by extracting colon position $colonpos = strpos($url, ':'); if ($colonpos > 0) { // We found a colon, possibly a protocol. Verify. $protocol = strtolower(substr($url, 0, $colonpos)); if (isset($allowed_protocols[$protocol])) { // The protocol turns out be an allowed protocol $external = true; } } elseif (Utils::startsWith($url, 'www.')) { // We found an url without protocol, but with starting // 'www' (sub-)domain $external = true; } } // Only if a colon and a valid protocol was found return true return $colonpos !== false && $external; }
/** * Redirect to the route stored in $this->redirect */ public function redirect() { if (!$this->redirect) { return; } $base = $this->admin->base; $this->redirect = '/' . ltrim($this->redirect, '/'); $multilang = $this->isMultilang(); $redirect = ''; if ($multilang) { // if base path does not already contain the lang code, add it $langPrefix = '/' . $this->grav['session']->admin_lang; if (!Utils::startsWith($base, $langPrefix . '/')) { $base = $langPrefix . $base; } // now the first 4 chars of base contain the lang code. // if redirect path already contains the lang code, and is != than the base lang code, then use redirect path as-is if (Utils::pathPrefixedByLangCode($base) && Utils::pathPrefixedByLangCode($this->redirect) && substr($base, 0, 4) != substr($this->redirect, 0, 4)) { $redirect = $this->redirect; } else { if (!Utils::startsWith($this->redirect, $base)) { $this->redirect = $base . $this->redirect; } } } else { if (!Utils::startsWith($this->redirect, $base)) { $this->redirect = $base . $this->redirect; } } if (!$redirect) { $redirect = $this->redirect; } $this->grav->redirect($redirect, $this->redirectCode); }
/** * Recursive function to load & build page relationships. * * @param string $directory * @param Page|null $parent * @return Page * @throws \RuntimeException * @internal */ protected function recurse($directory, Page &$parent = null) { $directory = rtrim($directory, DS); $iterator = new \DirectoryIterator($directory); $page = new Page(); /** @var Config $config */ $config = $this->grav['config']; $page->path($directory); if ($parent) { $page->parent($parent); } $page->orderDir($config->get('system.pages.order.dir')); $page->orderBy($config->get('system.pages.order.by')); // Add into instances if (!isset($this->instances[$page->path()])) { $this->instances[$page->path()] = $page; if ($parent && $page->path()) { $this->children[$parent->path()][$page->path()] = array('slug' => $page->slug()); } } else { throw new \RuntimeException('Fatal error when creating page instances.'); } // set current modified of page $last_modified = $page->modified(); // flat for content availability $content_exists = false; /** @var \DirectoryIterator $file */ foreach ($iterator as $file) { if ($file->isDot()) { continue; } $name = $file->getFilename(); if ($file->isFile()) { // Update the last modified if it's newer than already found if ($file->getBasename() !== '.DS_Store' && ($modified = $file->getMTime()) > $last_modified) { $last_modified = $modified; } if (preg_match('/^[^.].*' . CONTENT_EXT . '$/', $name)) { $page->init($file); $content_exists = true; if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onPageProcessed', new Event(['page' => $page])); } } } elseif ($file->isDir()) { if (!$page->path()) { $page->path($file->getPath()); } $path = $directory . DS . $name; $child = $this->recurse($path, $page); if (Utils::startsWith($name, '_')) { $child->routable(false); } $this->children[$page->path()][$child->path()] = array('slug' => $child->slug()); if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onFolderProcessed', new Event(['page' => $page])); } } } // Set routability to false if no page found if (!$content_exists) { $page->routable(false); } // Override the modified and ID so that it takes the latest change into account $page->modified($last_modified); $page->id($last_modified . md5($page->filePath())); // Sort based on Defaults or Page Overridden sort order $this->children[$page->path()] = $this->sort($page); return $page; }
/** * Return the languages available in the admin * * @return array */ public static function adminLanguages() { $languages = []; $path = Grav::instance()['locator']->findResource('plugins://admin/languages'); /** @var \DirectoryIterator $directory */ foreach (new \DirectoryIterator($path) as $file) { if ($file->isDir() || $file->isDot() || Utils::startsWith($file->getBasename(), '.')) { continue; } $lang = basename($file->getBasename(), '.yaml'); $languages[$lang] = LanguageCodes::getNativeName($lang); } return $languages; }
private function cleanFilesData($key, $file) { /** @var Page $page */ $page = null; $blueprint = $this->items['fields'][$key]['files']; $cleanFiles[$key] = []; if (!isset($blueprint)) { return false; } $cleanFiles = [$key => []]; foreach ((array) $file['error'] as $index => $error) { if ($error == UPLOAD_ERR_OK) { $tmp_name = $file['tmp_name'][$index]; $name = $file['name'][$index]; $type = $file['type'][$index]; $destination = Folder::getRelativePath(rtrim($blueprint['destination'], '/')); if (!$this->match_in_array($type, $blueprint['accept'])) { throw new \RuntimeException('File "' . $name . '" is not an accepted MIME type.'); } if (Utils::startsWith($destination, '@page:')) { $parts = explode(':', $destination); $route = $parts[1]; $page = self::getGrav()['page']->find($route); if (!$page) { throw new \RuntimeException('Unable to upload file to destination. Page route not found.'); } $destination = $page->relativePagePath(); } else { if ($destination == '@self') { $page = self::getGrav()['page']; $destination = $page->relativePagePath(); } else { Folder::mkdir($destination); } } if (move_uploaded_file($tmp_name, "{$destination}/{$name}")) { $path = $page ? self::getGrav()['uri']->convertUrl($page, $page->route() . '/' . $name) : $destination . '/' . $name; $cleanFiles[$key][$path] = ['name' => $file['name'][$index], 'type' => $file['type'][$index], 'size' => $file['size'][$index], 'file' => $destination . '/' . $name, 'route' => $page ? $path : null]; } else { throw new \RuntimeException('Unable to upload file(s). Error Code: ' . $error); } } } return $cleanFiles[$key]; }
/** * Test if a URL is external * * @param string $url The URL to test. * @param array $domains An array of domains to be seen as internal. * @param null|Page $page Null or an instance of \Grav\Common\Page. * * @return mixed Returns the URL as a string, if it is external, * false otherwise. */ protected function isExternalUrl($url, $domains = [], $page = null) { static $allowed_protocols; static $pattern; /** @var Config $config */ $config = self::getGrav()['config']; /** @var Page $page */ $page = $page ?: self::getGrav()['page']; // Statically store allowed protocols if (!isset($allowed_protocols)) { $allowed_protocols = array_flip($config->get('plugins.external_links.links.schemes', ['http', 'https'])); } // Statically store internal domains as a PCRE pattern. if (!isset($pattern) || count($domains) > 0) { $domains = array_merge($domains, array(self::getGrav()['base_url_absolute'])); foreach ($domains as $domain) { $domains[] = preg_quote($domain, '#'); } $pattern = '#(' . str_replace(array('\\*', '/*'), '.*?', implode('|', $domains)) . ')#i'; } $external = false; // Check for URLs that don't match any excluded domain if (!preg_match($pattern, $url)) { // Check if URL is external by extracting colon position $colonpos = strpos($url, ':'); if ($colonpos > 0) { // We found a colon, possibly a protocol. Verify. $protocol = strtolower(substr($url, 0, $colonpos)); if (isset($allowed_protocols[$protocol])) { // The protocol turns out be an allowed protocol $external = $url; } } elseif ($config->get('plugins.external_links.links.www')) { // Remove possible path duplicate $route = self::getGrav()['base_url'] . $page->route(); $href = Utils::startsWith($url, $route) ? ltrim(mb_substr($url, mb_strlen($route)), '/') : $url; // We found an url without protocol, but with starting 'www' (sub-)domain if (Utils::startsWith($url, 'www.')) { $external = 'http://' . $url; } elseif (Utils::startsWith($href, 'www.')) { $external = 'http://' . $href; } } } // Only if a valid protocol or an URL starting with 'www.' was found return true return $external; }
/** * Recursive function to load & build page relationships. * * @param string $directory * @param null $parent * @return Page * @throws \RuntimeException * @internal */ protected function recurse($directory = PAGES_DIR, Page &$parent = null) { $directory = rtrim($directory, DS); $iterator = new \DirectoryIterator($directory); $page = new Page(); $config = $this->grav['config']; $page->path($directory); if ($parent) { $page->parent($parent); } $page->orderDir($config->get('system.pages.order.dir')); $page->orderBy($config->get('system.pages.order.by')); // Add into instances if (!isset($this->instances[$page->path()])) { $this->instances[$page->path()] = $page; if ($parent && $page->path()) { $this->children[$parent->path()][$page->path()] = array('slug' => $page->slug()); } } else { throw new \RuntimeException('Fatal error when creating page instances.'); } $last_modified = 0; /** @var \DirectoryIterator $file */ foreach ($iterator as $file) { $name = $file->getFilename(); $date = $file->getMTime(); if ($date > $last_modified) { $last_modified = $date; } if ($file->isFile() && Utils::endsWith($name, CONTENT_EXT)) { $page->init($file); if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onPageProcessed', new Event(['page' => $page])); } } elseif ($file->isDir() && !$file->isDot()) { if (!$page->path()) { $page->path($file->getPath()); } $path = $directory . DS . $name; $child = $this->recurse($path, $page); if (Utils::startsWith($name, '_')) { $child->routable(false); } $this->children[$page->path()][$child->path()] = array('slug' => $child->slug()); // set the modified time if not already set if (!$page->date()) { $page->date($file->getMTime()); } // set the last modified time on pages $this->lastModified($file->getMTime()); if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onFolderProcessed', new Event(['page' => $page])); } } } // Override the modified and ID so that it takes the latest change // into account $page->modified($last_modified); $page->id($last_modified . md5($page->filePath())); // Sort based on Defaults or Page Overridden sort order $this->children[$page->path()] = $this->sort($page); return $page; }
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]) ? rawurldecode($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']); } // set path to / if not set if (empty($url['path'])) { $url['path'] = ''; } // if special scheme, just return if (isset($url['scheme']) && !Utils::startsWith($url['scheme'], 'http')) { return $excerpt; } // handle paths and such $url = Uri::convertUrl($this->page, $url, $type); // build the URL from the component parts and set it on the element $excerpt['element']['attributes']['href'] = Uri::buildUrl($url); } return $excerpt; }
/** * Determine whether a link is local or remote. * * Understands both "http://" and "https://" as well as protocol agnostic links "//" * * @param string $link * * @return bool */ protected function isRemoteLink($link) { $base = Grav::instance()['uri']->rootUrl(true); // sanity check for local URLs with absolute URL's enabled if (Utils::startsWith($link, $base)) { return false; } return 'http://' === substr($link, 0, 7) || 'https://' === substr($link, 0, 8) || '//' === substr($link, 0, 2); }
/** * Return URL to image. * * @param bool $reset * @return string */ public function url($reset = true) { $image_path = self::$grav['locator']->findResource('cache://images', true); $image_dir = self::$grav['locator']->findResource('cache://images', false); $saved_image_path = $this->saveImage(); $output = preg_replace('|^' . preg_quote(GRAV_ROOT) . '|', '', $saved_image_path); if (Utils::startsWith($output, $image_path)) { $output = '/' . $image_dir . preg_replace('|^' . preg_quote($image_path) . '|', '', $output); } if ($reset) { $this->reset(); } return self::$grav['base_url'] . $output . $this->querystring() . $this->urlHash(); }
/** * Recursive function to load & build page relationships. * * @param string $directory * @param Page|null $parent * @return Page * @throws \RuntimeException * @internal */ protected function recurse($directory, Page &$parent = null) { $directory = rtrim($directory, DS); $page = new Page(); /** @var Config $config */ $config = $this->grav['config']; /** @var Language $language */ $language = $this->grav['language']; // stuff to do at root page if ($parent === null) { // Fire event for memory and time consuming plugins... if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onBuildPagesInitialized'); } } $page->path($directory); if ($parent) { $page->parent($parent); } $page->orderDir($config->get('system.pages.order.dir')); $page->orderBy($config->get('system.pages.order.by')); // Add into instances if (!isset($this->instances[$page->path()])) { $this->instances[$page->path()] = $page; if ($parent && $page->path()) { $this->children[$parent->path()][$page->path()] = array('slug' => $page->slug()); } } else { throw new \RuntimeException('Fatal error when creating page instances.'); } $content_exists = false; $pages_found = glob($directory . '/*' . CONTENT_EXT); $page_extensions = $language->getFallbackPageExtensions(); if ($pages_found) { foreach ($page_extensions as $extension) { foreach ($pages_found as $found) { if (preg_match('/^.*\\/[0-9A-Za-z\\-\\_]+(' . $extension . ')$/', $found)) { $page_found = $found; $page_extension = $extension; break 2; } } } } if ($parent && !empty($page_found)) { $file = new \SplFileInfo($page_found); $page->init($file, $page_extension); $content_exists = true; if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onPageProcessed', new Event(['page' => $page])); } } // set current modified of page $last_modified = $page->modified(); /** @var \DirectoryIterator $file */ foreach (new \FilesystemIterator($directory) as $file) { $name = $file->getFilename(); // Ignore all hidden files if set. if ($this->ignore_hidden) { if ($name && $name[0] == '.') { continue; } } if ($file->isFile()) { // Update the last modified if it's newer than already found if (!in_array($file->getBasename(), $this->ignore_files) && ($modified = $file->getMTime()) > $last_modified) { $last_modified = $modified; } } elseif ($file->isDir() && !in_array($file->getFilename(), $this->ignore_folders)) { if (!$page->path()) { $page->path($file->getPath()); } $path = $directory . DS . $name; $child = $this->recurse($path, $page); if (Utils::startsWith($name, '_')) { $child->routable(false); } $this->children[$page->path()][$child->path()] = array('slug' => $child->slug()); if ($config->get('system.pages.events.page')) { $this->grav->fireEvent('onFolderProcessed', new Event(['page' => $page])); } } } // Set routability to false if no page found if (!$content_exists) { $page->routable(false); } // Override the modified and ID so that it takes the latest change into account $page->modified($last_modified); $page->id($last_modified . md5($page->filePath())); // Sort based on Defaults or Page Overridden sort order $this->children[$page->path()] = $this->sort($page); return $page; }
/** * 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 startsWithFilter($haystack, $needle) { return Utils::startsWith($haystack, $needle); }
private function cleanFilesData($key, $file) { $config = $this->grav['config']; $blueprint = isset($this->items['fields'][$key]['files']) ? $this->items['fields'][$key]['files'] : []; /** @var Page $page */ $page = null; $cleanFiles[$key] = []; if (!isset($blueprint)) { return false; } $type = trim("{$this->view}/{$this->admin->route}", '/'); $data = $this->admin->data($type, $this->post); $fields = $data->blueprints()->fields(); $blueprint = isset($fields[$key]) ? $fields[$key] : []; $cleanFiles = [$key => []]; foreach ((array) $file['error'] as $index => $error) { if ($error == UPLOAD_ERR_OK) { $tmp_name = $file['tmp_name'][$index]; $name = $file['name'][$index]; $type = $file['type'][$index]; $destination = Folder::getRelativePath(rtrim($blueprint['destination'], '/')); if (!$this->match_in_array($type, $blueprint['accept'])) { throw new \RuntimeException('File "' . $name . '" is not an accepted MIME type.'); } if (Utils::startsWith($destination, '@page:')) { $parts = explode(':', $destination); $route = $parts[1]; $page = $this->grav['page']->find($route); if (!$page) { throw new \RuntimeException('Unable to upload file to destination. Page route not found.'); } $destination = $page->relativePagePath(); } else { if ($destination == '@self') { $page = $this->admin->page(true); $destination = $page->relativePagePath(); } else { Folder::mkdir($destination); } } if (move_uploaded_file($tmp_name, "{$destination}/{$name}")) { $path = $page ? $this->grav['uri']->convertUrl($page, $page->route() . '/' . $name) : $destination . '/' . $name; $cleanFiles[$key][] = $path; } else { throw new \RuntimeException("Unable to upload file(s) to {$destination}/{$name}"); } } } return $cleanFiles[$key]; }