/** * Parse a fancy path definition into a path relative to the site's root, * respecting template overrides, suitable for inclusion of media files. * For example, media://com_foobar/css/test.css is parsed into * media/com_foobar/css/test.css if no override is found, or * templates/mytemplate/media/com_foobar/css/test.css if the current * template is called mytemplate and there's a media override for it. * * The valid protocols are: * media:// The media directory or a media override * site:// Path relative to site's root (no overrides) * * @param string $path Fancy path * @param boolean $localFile When true, it returns the local path, not the URL * @param Application $app The application we're operating under * * @return string Parsed path */ public static function parsePath($path, $localFile = false, $app = null) { $rootPath = $app->getContainer()->filesystemBase; if (!is_object($app)) { $app = Application::getInstance(); } if ($localFile) { $url = rtrim($rootPath, DIRECTORY_SEPARATOR) . '/'; } else { $url = Uri::base(false, $app->getContainer()); } $altPaths = self::getAltPaths($path, $app); $ext = pathinfo($altPaths['normal'], PATHINFO_EXTENSION); // We have an uncompressed CSS / JS file. We must look for a minimised file. if (in_array($ext, array('css', 'js')) && strstr($altPaths['normal'], '.min.') === false) { $minFile = dirname($altPaths['normal']) . '/' . basename($altPaths['normal'], $ext) . 'min.' . $ext; $normalFileExists = @file_exists($altPaths['normal']); $minFileExists = @file_exists($rootPath . '/' . $minFile); // If debug is not enabled prefer the minimised file if it exists if ((!defined('AKEEBADEBUG') || !AKEEBADEBUG) && $minFileExists) { $altPaths['normal'] = $minFile; } elseif ($minFileExists && !$normalFileExists) { $altPaths['normal'] = $minFile; } } $filePath = $altPaths['normal']; // If AKEEBADEBUG is enabled prefer the debug path, if one exists if (defined('AKEEBADEBUG') && AKEEBADEBUG && isset($altPaths['debug'])) { if (file_exists($rootPath . '/' . $altPaths['debug'])) { $filePath = $altPaths['debug']; } } elseif (isset($altPaths['alternate'])) { // Look for a minimised file, if available if (in_array($ext, array('css', 'js')) && strstr($altPaths['alternate'], '.min.') === false) { $minFile = dirname($altPaths['alternate']) . '/' . basename($altPaths['alternate'], $ext) . 'min.' . $ext; if (@file_exists($rootPath . '/' . $minFile)) { $altPaths['alternate'] = $minFile; } } if (file_exists($rootPath . '/' . $altPaths['alternate'])) { $filePath = $altPaths['alternate']; } } $url .= $filePath; return $url; }
/** * Constructor * * @param Container $container A named configuration array for object construction.<br/> * Inside it you can have an 'mvc_option' array with the following options:<br/> * name: the name (optional) of the view (defaults to the view class name suffix).<br/> * escape: the name (optional) of the function to use for escaping strings<br/> * template_path: the path (optional) of the layout directory (defaults to base_path + /views/ + view name<br/> * layout: the layout (optional) to use to display the view<br/> * * @return View */ public function __construct($container = null) { // Make sure we have a container if (!is_object($container)) { $container = Application::getInstance()->getContainer(); } // Cache some useful references in the class $this->input = $container->input; $this->container = $container; $this->config = isset($container['mvc_config']) ? $container['mvc_config'] : array(); // Get the view name $this->name = $this->getName(); // Set the default template search path if (array_key_exists('template_path', $this->config)) { // User-defined dirs $this->setTemplatePath($this->config['template_path']); } else { $this->setTemplatePath($this->container->basePath . '/View/' . ucfirst($this->name) . '/tmpl'); } // Set the layout if (array_key_exists('layout', $this->config)) { $this->setLayout($this->config['layout']); } $templatePath = $this->container->templatePath; $fallback = $templatePath . '/' . $this->container->application->getTemplate() . '/html/' . ucfirst($this->container->application->getName()) . '/' . $this->name; $this->addTemplatePath($fallback); // Get extra directories through event dispatchers $extraPathsResults = $this->container->eventDispatcher->trigger('onGetViewTemplatePaths', array($this->getName())); if (is_array($extraPathsResults) && !empty($extraPathsResults)) { foreach ($extraPathsResults as $somePaths) { if (!empty($somePaths)) { foreach ($somePaths as $aPath) { $this->addTemplatePath($aPath); } } } } $this->baseurl = Uri::base(true, $this->container); }
/** * Write a <img></img> element * * @param string $file The relative or absolute URL to use for the src attribute. * @param string $alt The alt text. * @param mixed $attribs String or associative array of attribute(s) to use. * @param boolean $relative Path to file is relative to /media folder * @param Application $app The application to get configuration from * * @return string */ public static function image($file, $alt, $attribs = null, $relative = false, Application $app = null) { if ($relative) { if (!is_object($app)) { $app = Application::getInstance(); } $file = Uri::base(false, $app->getContainer()) . 'media/' . ltrim($file, '/'); } return '<img src="' . $file . '" alt="' . $alt . '" ' . trim((is_array($attribs) ? ArrayHelper::toString($attribs) : $attribs) . ' /') . '>'; }
/** * Convert an absolute URI to a relative one * * @param string $uri The URI to convert * * @return string The relative URL */ protected function _removeURIBase($uri) { static $root = null, $rootlen = 0; if (is_null($root)) { $root = rtrim(Uri::base(false, $this->container), '/'); $rootlen = strlen($root); } if (substr($uri, 0, $rootlen) == $root) { $uri = substr($uri, $rootlen); } return ltrim($uri, '/'); }
/** * Redirect to another URL. * * Optionally enqueues a message in the system message queue (which will be displayed * the next time a page is loaded) using the enqueueMessage method. If the headers have * not been sent the redirect will be accomplished using a "301 Moved Permanently" * code in the header pointing to the new location. If the headers have already been * sent this will be accomplished using a JavaScript statement. * * @param string $url The URL to redirect to. Can only be http/https URL * @param string $msg An optional message to display on redirect. * @param string $msgType An optional message type. Defaults to message. * @param boolean $moved True if the page is 301 Permanently Moved, otherwise 303 See Other is assumed. * * @return void Calls exit(). * * @see Application::enqueueMessage() */ public function redirect($url, $msg = '', $msgType = 'info', $moved = false) { // Check for relative internal links. if (preg_match('#^index\\.php#', $url)) { $url = Uri::base(false, $this->container) . $url; } // Strip out any line breaks. $url = preg_split("/[\r\n]/", $url); $url = $url[0]; /* * If we don't start with a http we need to fix this before we proceed. * We could validly start with something else (e.g. ftp), though this would * be unlikely and isn't supported by this API. */ if (!preg_match('#^http#i', $url)) { $uri = Uri::getInstance(); $prefix = $uri->toString(array('scheme', 'user', 'pass', 'host', 'port')); if ($url[0] == '/') { // We just need the prefix since we have a path relative to the root. $url = $prefix . $url; } else { // It's relative to where we are now, so lets add that. $parts = explode('/', $uri->toString(array('path'))); array_pop($parts); $path = implode('/', $parts) . '/'; $url = $prefix . $path . $url; } } // If the message exists, enqueue it. if (is_string($msg) && trim($msg)) { $this->enqueueMessage($msg, $msgType); } // Persist messages if they exist. if (count($this->messageQueue)) { $this->container->segment->setFlash('application_queue', $this->messageQueue); } $this->container->session->commit(); // If the headers have been sent, then we cannot send an additional location header // so we will output a javascript redirect statement. if (headers_sent()) { $url = htmlspecialchars($url); $url = str_replace('&', '&', $url); echo "<script>document.location.href='" . $url . "';</script>\n"; } else { header($moved ? 'HTTP/1.1 301 Moved Permanently' : 'HTTP/1.1 303 See other'); header('Location: ' . $url); } exit(0); }
/** * Parse a routed URL based on the routing rules, setting the input variables of the attached application. * * @param string $url The URL to parse. If omitted the current URL will be used. * @param boolean $rebase Is this a rebased URL? If false we assume we're given a relative URL. */ public function parse($url = null, $rebase = true) { // If we are not given a URL, use the current URL of the site if (empty($url)) { $url = Uri::current(); } // Initialise $removePath = null; $removeVars = null; if ($rebase) { // Get the base URL $baseUrl = $this->container->appConfig->get('base_url', ''); if (empty($baseUrl)) { $baseUrl = ''; } $baseUrl = rtrim($baseUrl, '/'); $base = Uri::base(false, $this->container); $base = rtrim($base, '/') . '/' . $baseUrl; $rebaseURI = new Uri($base); // Get the path and vars to remove from the parsed route $removePath = $rebaseURI->getPath(); $removePath = trim($removePath, '/'); $removeVars = $rebaseURI->getQuery(true); } $uri = new Uri($url); $path = $uri->getPath(); $path = trim($path, '/'); // Remove the $removePath if (!empty($removePath)) { if (strpos($path, $removePath) === 0) { $path = substr($path, strlen($removePath)); } } // Use the routing rules to parse the URL $routeVars = null; if (!empty($this->rules)) { /** @var Rule $rule */ foreach ($this->rules as $rule) { $routeVars = $rule->parse($path); if (is_array($routeVars)) { break; } } } if (is_null($routeVars)) { $routeVars = array(); } // Mix route and URI vars $uriVars = $uri->getQuery(true); $routeVars = array_merge($routeVars, $uriVars); // Eliminate $removeVars if (is_array($removeVars) && !empty($removeVars)) { foreach ($removeVars as $k => $v) { if (isset($routeVars[$k]) && $routeVars[$k] == $v) { unset($routeVars[$k]); } } } // Set the query vars to the application if (is_array($routeVars) && !empty($routeVars)) { $this->container->input->setData($routeVars); } }