private function getLoadedConfig($url) { $aetherUrl = new AetherUrlParser(); $aetherUrl->parse($url); $conf = $this->getConfig(); $conf->matchUrl($aetherUrl); return $conf; }
public function testParseServerArray() { $server = array('HTTP_HOST' => 'aether.raymond.raw.no', 'SERVER_NAME' => 'aether.raymond.raw.no', 'SERVER_PORT' => 80, 'AUTH_TYPE' => 'Basic', 'GATEWAY_INTERFACE' => 'CGI/1.1', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/foobar/hello?foo', 'SCRIPT_NAME' => '/deployer.php', 'PHP_SELF' => '/deployer.php', 'REQUEST_TIME' => 1170332549); $parser = new AetherUrlParser(); $parser->parseServerArray($server); $this->assertEquals($parser->get('scheme'), 'http'); $this->assertEquals($parser->get('path'), '/foobar/hello'); $server['PHP_AUTH_USER'] = '******'; $server['PHP_AUTH_PW'] = 'bar'; $parser->parseServerArray($server); $this->assertEquals($parser->get('user'), 'foo'); $this->assertEquals($parser->get('pass'), 'bar'); // Get as string again $this->assertEquals($parser->__toString(), 'http://*****:*****@aether.raymond.raw.no/foobar/hello'); }
/** * Start Aether. * On start it will parse the projects configuration file, * it will try to match the presented http request to a rule * in the project configuration and create some overview * over which modules it will need to render once * a request to render them comes * * @access public * @return Aether * @param string $configPath Optional path to the configuration file for the project */ public function __construct($configPath = false) { self::$aetherPath = pathinfo(__FILE__, PATHINFO_DIRNAME) . "/"; spl_autoload_register(array('Aether', 'autoLoad')); $this->sl = new AetherServiceLocator(); $this->sl->set('aetherPath', self::$aetherPath); // Initiate all required helper objects $parsedUrl = new AetherUrlParser(); $parsedUrl->parseServerArray($_SERVER); $this->sl->set('parsedUrl', $parsedUrl); // Set autoloader // TODO Make this more uesable /** * Find config folder for project * By convention the config folder is always placed at * $project/config, while using getcwd() MUST return the * $project/www/ folder */ $projectPath = preg_replace("/www\\/?\$/", "", getcwd()); $this->sl->set("projectRoot", $projectPath); if (!defined("PROJECT_PATH")) { define("PROJECT_PATH", $projectPath); } $paths = array($configPath, $projectPath . 'config/autogenerated.config.xml', $projectPath . 'config/aether.config.xml'); foreach ($paths as $configPath) { if (file_exists($configPath)) { break; } } try { $config = new AetherConfig($configPath); $config->matchUrl($parsedUrl); $this->sl->set('aetherConfig', $config); } catch (AetherMissingFileException $e) { /** * This means that someone forgot to ensure the config * file actually exists */ $msg = "No configuration file for project found: " . $e->getMessage(); throw new Exception($msg); } catch (AetherNoUrlRuleMatchException $e) { /** * This means parsing of configuration file failed * by the simple fact that no rules matches * the url. This is due to a bad developer */ $msg = "No rule matched url in config file: " . $e->getMessage(); throw new Exception($msg); } $options = $config->getOptions(array('AetherRunningMode' => 'prod', 'cache' => 'off')); if ($options['cache'] == 'on') { $cacheClass = isset($options['cacheClass']) ? $options['cacheClass'] : 'AetherCache'; $cacheOptions = isset($options['cacheOptions']) ? $options['cacheOptions'] : []; $cache = $this->getCacheObject($cacheClass, $cacheOptions); $this->sl->set("cache", $cache); } /** * Make sure base and root for this request is stored * in the service locator so it can be made available * to the magical $aether array in templates */ $magic = $this->sl->getVector('templateGlobals'); $magic['base'] = $config->getBase(); $magic['root'] = $config->getRoot(); $magic['urlVars'] = $config->getUrlVars(); $magic['runningMode'] = $options['AetherRunningMode']; $magic['requestUri'] = $_SERVER['REQUEST_URI']; $magic['domain'] = $_SERVER['HTTP_HOST']; if (isset($_SERVER['HTTP_REFERER'])) { $magic['referer'] = $_SERVER['HTTP_REFERER']; } $magic['options'] = $options; /** * If we are in TEST mode we should prepare a timer object * and time everything that happens */ if ($options['AetherRunningMode'] == 'test') { // Prepare timer $timer = new AetherTimer(); $timer->start('aether_main'); $this->sl->set('timer', $timer); } // Initiate section try { $searchPath = isset($options['searchpath']) ? $options['searchpath'] : $projectPath; AetherSectionFactory::$path = $searchPath; $this->section = AetherSectionFactory::create($config->getSection(), $this->sl); $this->sl->set('section', $this->section); if (isset($timer)) { $timer->tick('aether_main', 'section_initiate'); } } catch (Exception $e) { // Failed to load section, what to do? throw new Exception('Failed horribly: ' . $e->getMessage()); } }
/** * Match an url against this config * * @access public * @return bool * @param AetherUrlParser $url */ public function matchUrl(AetherUrlParser $url) { $configFilePath = $this->configFilePath; if (!file_exists($configFilePath)) { throw new AetherMissingFileException("Config file [{$configFilePath}] is missing."); } $doc = new DOMDocument(); $doc->preserveWhiteSpace = false; $doc->load($configFilePath); $this->doc = $doc; $xpath = new DOMXPath($doc); /* * Find starting point of url rules, from this point on we * use recursion to decide on the correct rule to use */ $sitename = $url->get('host'); $xquery = "/config/site[@name='{$sitename}']"; $xquery .= '/urlRules'; $nodelist = $xpath->query($xquery); // Fallback to the "any" site qualifier if ($nodelist->length == 0) { $sitename = '*'; $xquery = "/config/site[@name='{$sitename}']/urlRules"; $nodelist = $xpath->query($xquery); } if ($nodelist->length == 0) { throw new AetherNoUrlRuleMatchException("No config entry matched site: {$sitename}"); } $urlRules = $nodelist->item(0); // Subtract global options $ruleBase = " | /config/site[@name='{$sitename}']/urlRules/"; $xquery = "/config/site[@name='{$sitename}']/option"; $xquery .= $ruleBase . 'section'; $xquery .= $ruleBase . 'template'; $xquery .= $ruleBase . 'module'; $xquery .= $ruleBase . 'option'; $optionList = $xpath->query($xquery); if ($optionList->length > 0) { $this->readNodeConfiguration($optionList); } $path = $url->get('path'); $explodedPath = explode('/', substr($path, 1)); // Treat /foo/bar the same as /foo/bar/ if (end($explodedPath) !== "") { $explodedPath[] = ""; } /** * If AetherSlashMode is "keep", make sure $current is prefixed * with a slash as the slash is not maintained from earlier */ if ($this->slashMode() == 'keep') { foreach ($explodedPath as $key => $part) { $explodedPath[$key] = '/' . $part; } } try { $node = $this->findMatchingConfigNode($urlRules, $explodedPath); } catch (AetherNoUrlRuleMatchException $e) { // No match found :( Send 404 and throw exception to logs header("Status: 404 Not Found"); echo "<html><body><h1>404 Not found</h1></body></html>"; throw new Exception("Technical error. No resource found on this url: " . (string) $url . ", " . $e); } catch (Exception $e) { // This is expected // Comment above was exceptionally not expected -- simeng 2011-10-10 } }
public function testMatchWithMinusInItWorks() { $aetherUrl = new AetherUrlParser(); $cat = "hifi-produkter"; $url = 'http://raw.no/unittest/' . $cat; $aetherUrl->parse($url); $conf = $this->getConfig(); $conf->matchUrl($aetherUrl); $this->assertEquals($conf->getUrlVariable('catName'), $cat); }