/** * 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); }
/** * Parse a SEF URL path into URL parameters * * @param string $path The path to parse, e.g. /foo/bar/1/2/3 * * @return array|null The URL parameters or null if we can't parse the route with this rule */ public function parse($path) { $extraParams = array(); if (strpos($path, '?') !== false) { $uri = new Uri($path); $path = $uri->getPath(); $extraParams = $uri->getQuery(true); } if ($this->useCallableForParse) { $ret = call_user_func($this->parseCallable, $path); } else { // Explode the path parts $segments = explode('/', $path); // Try to extract the URL parameters by parsing the segments $params = $this->parseRoute($segments); // If we got null back we can't parse this route if (is_null($params)) { return null; } // Mix in the push variables $params = array_merge($this->pushVars, $params); // Return the URL parameters $ret = $params; } return array_merge($ret, $extraParams); }
/** * Returns a JUri instance with a prototype URI used as the base for the * other URIs created by the JSON renderer * * @return Uri The prototype JUri instance */ protected function _getPrototypeURIForPagination() { $protoUri = new Uri(Uri::rebase('index.php', $this->container)); $protoUri->setQuery($this->input->getData()); $protoUri->delVar('savestate'); $protoUri->delVar('base_path'); return $protoUri; }
/** * 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) . ' /') . '>'; }
/** * A utility function to rebase a (partial) URL based on the live_site and base_url of the application configuration * in the provided container. You can override the base_url of the application through the $baseUrl parameter. * * It's simpler to explain with a short example. Let's consider an application with * live_site = 'http://www.example.com' and base_url='/administrator/index.php?option=com_foobar&baz=1'. * Using Uri::rebase('?view=report&item=export', $container) will result to the following absolute URL: * http://www.example.com/administrator/index.php?baz=1&item=export&option=com_foobar&view=report * Using Uri::rebase('?option=com_whatever', $container) will result to the following absolute URL: * http://www.example.com/administrator/index.php?baz=1&option=com_whatever * Therefore by manipulating the base_url in the application's configuration you can have an application which runs * inside another application (no matter if the other application is based on Awf or not). The "only" thing you will * have to do is specialise your Application object to act as a bridge to the parent application. * * @param $url * @param Application $container * @param null $baseUrl * * @return string */ public static function rebase($url, Container $container, $baseUrl = null) { if (empty($baseUrl)) { $baseUrl = $container->appConfig->get('base_url', 'index.php'); if (empty($baseUrl)) { $baseUrl = 'index.php'; } $baseUrl = rtrim($baseUrl, '/'); } $base = self::base(false, $container); $base = rtrim($base, '/') . '/' . ltrim($baseUrl, '/'); $rebaseURI = new Uri($base); $oldURI = new Uri($url); $vars = $oldURI->getQuery(true); if (!empty($vars)) { foreach ($vars as $k => $v) { $rebaseURI->setVar($k, $v); } } if ($oldURI->getFragment()) { $rebaseURI->setFragment($oldURI->getFragment()); } return (string) $rebaseURI; }
/** * Sets the additional URL parameters from the input. If no input is specified we will use the application's * input. The URL parameters of the base URL will be automatically removed. * * @param Input $input The input object to use * * @return void */ public function setAdditionalUrlParamsFromInput(Input $input = null) { // Make sure we have an input if (!is_object($input)) { $input = $this->application->getContainer()->input; } // Get the input's data array $data = $input->getData(); // Get the rebase URL parameters to eliminate $rebase = Uri::rebase('index.php', $this->application->getContainer()); $rebase = new Uri($rebase); $eliminateParams = $rebase->getQuery(true); $eliminateParams = array_keys($eliminateParams); // Set the additional URL parameters foreach ($data as $key => $value) { // We can't process object data automatically if (is_object($value)) { continue; } // We can't process array data automatically if (is_array($value)) { continue; } // Ignore the URL parameters from the URL rebasing if (in_array($key, $eliminateParams)) { continue; } $this->setAdditionalUrlParam($key, $value); } }
/** * Is this menu item the active one? * * @return boolean */ public function isActive() { // Get the current URI $uri = Uri::getInstance(); // If we have an exact match to the custom URL, return true if ($uri->toString() == $this->url) { return true; } // If there are no parameters to check and the URLs don't match, it's not an active menu item if (empty($this->params)) { return false; } // Otherwise check if the parameters match foreach ($this->params as $k => $v) { $uv = $uri->getVar($k, null); if ($uv != $v) { return false; } } return true; }
/** * 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); } }