/** * Will try to include a GET parameter for an existing URL, preserving existing parameters and * fragments. If no URL is given, falls back to $_SERVER['REQUEST_URI']. Uses parse_url() to * dissect the URL, and http_build_query() to reconstruct it with the additional parameter. * Converts any '&' (ampersand) URL parameter separators to the more XHTML compliant '&'. * * CAUTION: If the URL is determined to be relative, it is prepended with Director::absoluteBaseURL(). * This method will always return an absolute URL because Director::makeRelative() can lead to * inconsistent results. * * @param string $varname * @param string $varvalue * @param string $currentURL Relative or absolute URL. * @param string $separator Separator for http_build_query(). * * @return string */ public static function setGetVar($varname, $varvalue, $currentURL = null, $separator = '&') { $uri = $currentURL ? $currentURL : Director::makeRelative($_SERVER['REQUEST_URI']); $isRelative = false; // We need absolute URLs for parse_url() if (Director::is_relative_url($uri)) { $uri = Director::absoluteBaseURL() . $uri; $isRelative = true; } // try to parse uri $parts = parse_url($uri); if (!$parts) { throw new InvalidArgumentException("Can't parse URL: " . $uri); } // Parse params and add new variable $params = array(); if (isset($parts['query'])) { parse_str($parts['query'], $params); } $params[$varname] = $varvalue; // Generate URI segments and formatting $scheme = isset($parts['scheme']) ? $parts['scheme'] : 'http'; $user = isset($parts['user']) && $parts['user'] != '' ? $parts['user'] : ''; if ($user != '') { // format in either user:pass@host.com or user@host.com $user .= isset($parts['pass']) && $parts['pass'] != '' ? ':' . $parts['pass'] . '@' : '@'; } $host = isset($parts['host']) ? $parts['host'] : ''; $port = isset($parts['port']) && $parts['port'] != '' ? ':' . $parts['port'] : ''; $path = isset($parts['path']) && $parts['path'] != '' ? $parts['path'] : ''; // handle URL params which are existing / new $params = $params ? '?' . http_build_query($params, null, $separator) : ''; // keep fragments (anchors) intact. $fragment = isset($parts['fragment']) && $parts['fragment'] != '' ? '#' . $parts['fragment'] : ''; // Recompile URI segments $newUri = $scheme . '://' . $user . $host . $port . $path . $params . $fragment; if ($isRelative) { return Director::makeRelative($newUri); } return $newUri; }
/** * The process() method handles the "meat" of the template processing. * * It takes care of caching the output (via {@link Cache}), as well as * replacing the special "$Content" and "$Layout" placeholders with their * respective subtemplates. * * The method injects extra HTML in the header via {@link Requirements::includeInHTML()}. * * Note: You can call this method indirectly by {@link ViewableData->renderWith()}. * * @param ViewableData $item * @param array|null $arguments Arguments to an included template * @param ViewableData $inheritedScope The current scope of a parent template including a sub-template * @return DBHTMLText Parsed template output. */ public function process($item, $arguments = null, $inheritedScope = null) { SSViewer::$topLevel[] = $item; $template = $this->chosen; $cacheFile = TEMP_FOLDER . "/.cache" . str_replace(array('\\', '/', ':'), '.', Director::makeRelative(realpath($template))); $lastEdited = filemtime($template); if (!file_exists($cacheFile) || filemtime($cacheFile) < $lastEdited) { $content = file_get_contents($template); $content = $this->parseTemplateContent($content, $template); $fh = fopen($cacheFile, 'w'); fwrite($fh, $content); fclose($fh); } $underlay = array('I18NNamespace' => basename($template)); // Makes the rendered sub-templates available on the parent item, // through $Content and $Layout placeholders. foreach (array('Content', 'Layout') as $subtemplate) { $sub = null; if (isset($this->subTemplates[$subtemplate])) { $sub = $this->subTemplates[$subtemplate]; } elseif (!is_array($this->templates)) { $sub = ['type' => $subtemplate, $this->templates]; } elseif (!array_key_exists('type', $this->templates) || !$this->templates['type']) { $sub = array_merge($this->templates, ['type' => $subtemplate]); } if ($sub) { $subtemplateViewer = clone $this; // Disable requirements - this will be handled by the parent template $subtemplateViewer->includeRequirements(false); // Select the right template $subtemplateViewer->setTemplate($sub); if ($subtemplateViewer->exists()) { $underlay[$subtemplate] = $subtemplateViewer->process($item, $arguments); } } } $output = $this->includeGeneratedTemplate($cacheFile, $item, $arguments, $underlay, $inheritedScope); if ($this->includeRequirements) { $output = Requirements::includeInHTML($output); } array_pop(SSViewer::$topLevel); // If we have our crazy base tag, then fix # links referencing the current page. $rewrite = SSViewer::config()->get('rewrite_hash_links'); if ($this->rewriteHashlinks && $rewrite) { if (strpos($output, '<base') !== false) { if ($rewrite === 'php') { $thisURLRelativeToBase = "<?php echo \\SilverStripe\\Core\\Convert::raw2att(preg_replace(\"/^(\\\\/)+/\", \"/\", \$_SERVER['REQUEST_URI'])); ?>"; } else { $thisURLRelativeToBase = Convert::raw2att(preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'])); } $output = preg_replace('/(<a[^>]+href *= *)"#/i', '\\1"' . $thisURLRelativeToBase . '#', $output); } } return DBField::create_field('HTMLFragment', $output); }
/** * Given a PHP class name, finds the module where it's located. * * @param string $name * @return string */ public static function get_owner_module($name) { $manifest = ClassLoader::instance()->getManifest(); $path = $manifest->getItemPath($name); if (!$path) { return false; } $path = Director::makeRelative($path); $path = str_replace('\\', '/', $path); $parts = explode('/', trim($path, '/')); return array_shift($parts); }
/** * If the last request was a 3xx response, then follow the redirection * * @return HTTPResponse The response given, or null if no redirect occurred */ public function followRedirection() { if ($this->lastResponse->getHeader('Location')) { $url = Director::makeRelative($this->lastResponse->getHeader('Location')); $url = strtok($url, '#'); return $this->get($url); } }
public function testMakeRelative() { $siteUrl = Director::absoluteBaseURL(); $siteUrlNoProtocol = preg_replace('/https?:\\/\\//', '', $siteUrl); $this->assertEquals(Director::makeRelative("{$siteUrl}"), ''); $this->assertEquals(Director::makeRelative("https://{$siteUrlNoProtocol}"), ''); $this->assertEquals(Director::makeRelative("http://{$siteUrlNoProtocol}"), ''); $this->assertEquals(Director::makeRelative(" {$siteUrl}/testpage "), 'testpage'); $this->assertEquals(Director::makeRelative("{$siteUrlNoProtocol}/testpage"), 'testpage'); $this->assertEquals(Director::makeRelative('ftp://test.com'), 'ftp://test.com'); $this->assertEquals(Director::makeRelative('http://test.com'), 'http://test.com'); $this->assertEquals(Director::makeRelative('relative'), 'relative'); $this->assertEquals(Director::makeRelative("{$siteUrl}/?url=http://test.com"), '?url=http://test.com'); $this->assertEquals("test", Director::makeRelative("https://" . $siteUrlNoProtocol . "/test")); $this->assertEquals("test", Director::makeRelative("http://" . $siteUrlNoProtocol . "/test")); }