/** * Constructor for the evergreen class that sets up all the necessary parts of the framework so it can run. * * @access public */ public function __construct() { $starttime = microtime(true); try { // register the autoloaders Autoloader::register(); // setup error handling set_error_handler(array("Config", "logError"), ini_get("error_reporting")); // load the main config.php file if (file_exists(Reg::get("Path.physical") . '/config/config.php')) { include_once Reg::get("Path.physical") . '/config/config.php'; } else { echo "You are missing the configuration file and without it Evergreen cannot run."; exit; } // load the main errors.php file if (file_exists(Reg::get("Path.physical") . '/config/errors.php')) { include Reg::get("Path.physical") . '/config/errors.php'; } // check if the welcome content is present and if it is show it if (file_exists(Reg::get("Path.physical") . '/public/welcome.php')) { // Load the welcome content include Reg::get("Path.physical") . '/public/welcome.php'; exit; } // code that is run at the exit of the script register_shutdown_function(array($this, 'shutdown'), $starttime); // process the uri and setup the Reg variables Config::processURI(); // wait till after all the config files are loaded before loading in the autoload files Autoloader::loadFiles(); // build the controller class name $load['name'] = Config::uriToClass(Reg::get("URI.working.controller")); if (Reg::hasVal("Branch.name")) { $load['branch'] = Config::uriToClass(Reg::get("Branch.name")); } $load['type'] = 'Controller'; $load = implode('_', $load); // create an instance of the controller $controller = new $load(); // run the _showView method in the loaded controller $controller->_showView(); } catch (EvergreenException $e) { // handler for the EvergreenException class $e->processError(); } catch (Exception $e) { // handler for general exceptions if (Config::read("System.mode") != "development") { echo Config::read("Error.generalErrorMessage"); exit; } else { echo $e; } } }
/** * Callback function for the designer fix preg_replace_callback * Automatically adjusts paths if they have .. in them * * @access private * @final * @param array $match An array of the found items from the regular expression * @return string */ private final function _designerFixCallback($match) { // if this isn't empty then it is a link $link = !empty($match[2]); // get the tag $tag = $match[1]; // set the default to return the full string that was matched $return = $match[0]; $custom = false; // do the replacement switch ($tag) { case "[current]": $return = Reg::get("Path.current"); break; case "[site]": $return = Reg::get("Path.site"); break; case "[skin]": $return = Reg::get("Path.skin"); break; case "[root]": $return = Reg::get("Path.root"); break; case "[branch.site]": $return = Reg::get("Path.branch"); break; case "[branch.skin]": $return = Reg::get("Path.branchSkin"); break; case "[branch.root]": $return = Reg::get("Path.branchRoot"); break; default: // see if it is a php variable. Quick way to echo variables from $this if (strpos($tag, '$') === 1) { $custom = true; $var = str_replace(array('[', ']', '$', 'this->'), '', $tag); // if it is in an object then we need to go down the objects pulling out the variables // not pretty if (strpos($var, '->') !== false) { $parts = explode('->', $var); $failed = false; $var = $this->{array_shift($parts)}; foreach ($parts as $part) { if (!isset($var->{$part})) { // variable isn't set so it failed $failed = true; break; } $var = $var->{$part}; } if ($failed === false) { $return = $var; } } else { // it is a variable that isn't an object if (isset($this->{$var})) { $return = $this->{$var}; } } // the variable didn't exist so send nothing back to the page // don't want variable names to sneak in if ($return == $tag) { $return = ''; } } else { if (Reg::has(str_replace(array('[', ']'), '', $tag))) { $custom = true; // get the variable from the registry $return = Reg::get(str_replace(array('[', ']'), '', $tag)); } else { // look for the tag within the working URI $working_uri = Reg::get("URI.working"); if (Reg::hasVal("Branch.name")) { $working_uri = array_merge(array("branch" => Reg::get("Branch.name")), $working_uri); } foreach ($working_uri as $key => $item) { $tmp_key = "[" . $key . "]"; if ($tag == $tmp_key && Reg::has('Path.' . $key)) { $return = Reg::get('Path.' . $key); break 1; } } } } break; } // if it is a link then we need to do some more processing if ($link === true && $custom === false) { // remove any ../ from the url so that they are clean $link_arr = explode("/", $match[2]); $up_link_count = count(array_keys(array_slice($link_arr, 1), "..")); $return = explode('/', $return); $return = implode("/", $up_link_count ? array_slice($return, 0, -1 * $up_link_count) : $return) . implode("/", array_pad(array_slice($link_arr, $up_link_count + 1), -(count(array_slice($link_arr, $up_link_count + 1)) + 1), "")); // if mod_rewrite isn't being used then need to make sure the URL is valid by turning any extra ? into & if (Reg::get("URI.useModRewrite") != true && !empty($return)) { if (substr_count($return, "?", 0) > 1) { $return = strrev(preg_replace("/\\?/i", "&", strrev($return), substr_count($return, "?", 0) - 1)); } } } else { if (!empty($match[2])) { $return .= $match[2]; } } // call hook Hook::call('Controller.designerFixCallback', array(&$match, &$return)); return $return; }
/** * Loads the url for the error. If the url points to a page inside the framework the function attempts to load it and handles any errors * or issues associated such as loading in a default error. If the url points to a page outside the framework then header location is set * and execution is stopped. * * @access public * @static * @final * @param string|array $url The url that should be loaded can be the url or an array in the URI.map format */ public function loadURL($url) { // call hook Hook::call('Exception.loadURL.before', array(&$url)); if (!empty($url)) { if (!is_array($url) && preg_match("/^(http:|https:|ftp:|ftps:)/im", $url)) { // call hook Hook::call('Exception.loadURL.redirect', array(&$url)); header('Location: ' . $url); header('Connection: close'); exit; } if (is_array($url)) { $url = '/' . implode('/', array_merge(Reg::get("URI.map"), $url)); } $url = str_replace(Reg::get('Path.root'), "", $url); $_SERVER['REQUEST_URI'] = $url; Reg::set("URI.working", $url); Reg::del("Branch.name"); Config::processURI(); $load['name'] = Config::uriToClass(Reg::get("URI.working.controller")); if (Reg::hasVal("Branch.name")) { $load['branch'] = Config::uriToClass(Reg::get("Branch.name")); } $load['type'] = 'Controller'; $load = implode('_', $load); $controller = new $load(); if (!is_object($controller)) { if (!file_exists(Reg::get("System.defaultError404"))) { include Reg::get("System.defaultError404"); } else { echo Reg::get("System.defaultError404"); } } else { try { // call hook Hook::call('Exception.loadURL.controller', array(&$controller)); $controller->_showView(); } catch (EvergreenException $e) { var_dump($e); exit; if (Reg::get("System.mode") == "development") { if (isset(self::$params['code'])) { $code = self::$params['code']; } // call hook Hook::call('Exception.loadURL.default', array(&$url, &$code)); switch ($code) { case 'GEN': if (file_exists(Reg::get("System.defaultErrorGEN"))) { include Reg::get("System.defaultErrorGEN"); } else { echo Reg::get("System.defaultErrorGEN"); } break; case 'DB': if (file_exists(Reg::get("System.defaultErrorDB"))) { include Reg::get("System.defaultErrorDB"); } else { echo Reg::get("System.defaultErrorDB"); } break; default: if (file_exists(Reg::get("System.defaultErrorGEN"))) { include Reg::get("System.defaultErrorGEN"); } else { echo Reg::get("System.defaultErrorGEN"); } break; } } } } } else { if (file_exists(Reg::get("System.defaultErrorGEN"))) { include Reg::get("System.defaultErrorGEN"); } else { echo Reg::get("System.defaultErrorGEN"); } } }
/** * Processes the uri by figuring out what mode we are running in, mod_rewrite or querystring, and by setting up and checking if we are in a branch or a route * it also merges the uri values with the uri map and sets up all the Param and Path variables for use in the framework. * * @access public * @static * @return boolean true if successful and boolean false if a route was matched */ public static function processURI() { // call hook Hook::call('Config.processURI.before'); // make sure that the uri map exists and is an array with at least 2 keys if (!is_array(Reg::get("URI.map")) || count(Reg::get("URI.map")) < 2) { throw new EvergreenException("NO_URI_MAP"); } // make sure that the view and controller keys exist in the uri map if (!array_key_exists('controller', Reg::get("URI.map")) || !array_key_exists('view', Reg::get("URI.map"))) { throw new EvergreenException("URI_MAP_INVALID_KEYS"); } // check that there is not already a value in URI.working if (!Reg::hasVal("URI.working")) { // check if we are using mod_rewrite or a querystring if (Reg::get("URI.useModRewrite")) { // set up URI.working with the url based off of mod_rewrite if (strpos($_SERVER['REQUEST_URI'], "?")) { $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], "?")); } $_SERVER['REQUEST_URI'] = preg_replace("/^(" . str_replace("/", "\\/", Reg::get("URI.base")) . "?)/i", "", $_SERVER['REQUEST_URI']); // set URI.prepend to nothing as we dont need it in mod_rewrite mode Reg::set("URI.prepend", ""); Reg::set("URI.working", $_SERVER['REQUEST_URI']); } else { // set up URI.working with the url based off of querystring if (!is_string(Reg::get("URI.prependIdentifier")) || !strlen(Reg::get("URI.prependIdentifier"))) { throw new EvergreenException("NO_PREPEND_IDENTIFIER"); } $queryParts = explode("&", $_SERVER['QUERY_STRING']); foreach ($queryParts as $key => $value) { if (preg_match("/" . Reg::get("URI.prependIdentifier") . "=(.*)/i", $value)) { unset($queryParts[$key]); break; } } $_SERVER['QUERY_STRING'] = implode("&", $queryParts); // set URI.prepend to route to index.php and create a query string using the prepend identifier Reg::set("URI.prepend", "/index.php?" . Reg::get("URI.prependIdentifier") . "="); Reg::set("URI.working", isset($_GET[Reg::get("URI.prependIdentifier")]) ? $_GET[Reg::get("URI.prependIdentifier")] : ''); } } // make sure that the uri in URI.working is cleaned up and ready to be used if (substr(Reg::get("URI.working"), 0, 1) == "/") { $path_info = substr(Reg::get("URI.working"), 1, strlen(Reg::get("URI.working"))); } else { $path_info = is_array(Reg::get("URI.working")) ? implode("/", Reg::get("URI.working")) : Reg::get("URI.working"); } // explode the cleaned URI.working so that those elements can become the new values for the URI.map if (!empty($path_info)) { $uri_vals = explode('/', $path_info); } else { $uri_vals = array(); } // check for a leading slash in the uri and do a redirect to get rid of it so the url stays clean if (count($uri_vals) > 0 && empty($uri_vals[count($uri_vals) - 1])) { unset($uri_vals[count($uri_vals) - 1]); if (!is_array(Reg::get("Route.current")) && !Error::triggered()) { if (empty($_POST) && empty($_FILES) && !headers_sent()) { // only do the redirect if this isnt a route, an error hasn�t been triggered, headers havent been sent, and nothing is being posted or uploaded header("HTTP/1.1 301 Moved Permanently"); header("Location: " . Reg::get("URI.base") . Reg::get("URI.prepend") . "/" . implode("/", $uri_vals) . (!empty($_SERVER['QUERY_STRING']) ? !Reg::get("URI.useModRewrite") ? "&" . $_SERVER['QUERY_STRING'] : "?" . $_SERVER['QUERY_STRING'] : "")); header("Connection: close"); exit; } } } // check if there is a branch in the uri and if there is then load in it's configuration and reprocess the uri $uri_vals = self::checkForBranch($uri_vals); // check if the current uri matches a defined route, if so reprocess the uri if (self::checkRoutes("/" . implode("/", $uri_vals))) { return false; } // assign the uri map to another variable for ease of use $uriMap = Reg::get("URI.map"); $count = 0; foreach ($uriMap as $key => $item) { if (!empty($item) && empty($uri_vals[$count])) { // if map key doesn't have a uri value but has a default set then set to default if (is_array($item)) { $uri_params[$key] = reset($item); } else { $uri_params[$key] = $item; } } else { if (!empty($uri_vals[$count])) { if (strtolower($key) == 'controller' || is_array($item) && count($item) > 1 && (is_array($item[1]) || function_exists($item[1]))) { if (strtolower($key) != 'controller') { // if there is validation defined for a uri map key then test the value if (!is_array($item[1]) && function_exists($item[1]) && $item[1]($uri_vals[$count]) == true || is_array($item[1]) && count($item[1]) > 1 && is_callable($item[1]) && call_user_func($item[1], $uri_vals[$count]) == true) { // uri value passed map key validation so set value to key $uri_params[$key] = $uri_vals[$count]; $count++; continue; } else { if (strtolower($key) != 'controller') { // uri value didn't pass the validation so set this map's key to the default value $uri_params[$key] = (string) $item[0]; } } } else { // check if the controller exists if (file_exists(Reg::get("Path.physical") . (strlen(Reg::get("Branch.name")) ? "/branches/" . self::uriToFile(Reg::get("Branch.name")) : "") . "/controllers/" . self::uriToFile($uri_vals[$count]) . ".php")) { $uri_params[$key] = $uri_vals[$count]; $count++; continue; } else { // if the controller if (is_array($item)) { $uri_params[$key] = reset($item); } else { $uri_params[$key] = $item; } } } } else { // a uri value matched a map key so set the key with the uri value $uri_params[$key] = $uri_vals[$count]; $count++; continue; } } else { // no matching uri was found for this map key so set it's value to null $uri_params[$key] = null; } } } unset($uriMap, $key, $item); // set the URI.working to the $uri_params variable which was generated above using the URI.map and the current uri Reg::set("URI.working", $uri_params); // set the Params to the $uri_params variable which was generated above using the URI.map and the current uri Reg::set("Param", $uri_params); // clean up the generated working uri variable unset($uri_params); // check if we are using mod_rewrite or querystring and grab the uri from the one we are using to generate paths for the Path variables if (Reg::get("URI.useModRewrite") == true) { $uri_paths = explode("/", ltrim($_SERVER['REQUEST_URI'], '/')); } else { if (isset($_GET[Reg::get("URI.prependIdentifier")])) { $uri_paths = explode("/", trim($_GET[Reg::get("URI.prependIdentifier")], '/')); } else { $uri_paths = array(); } } // setup the main Path variables Reg::set("Path.site", Reg::get("URI.base") . Reg::get("URI.prepend")); if (Reg::hasVal("Branch.name")) { // if we are in a branch then setup additional branch path variables Reg::set("Path.branch", str_replace("//", "/", Reg::get("Path.site") . "/" . Reg::get("Branch.name"))); Reg::set("Path.branchRoot", str_replace("//", "/", Reg::get("URI.base") . "/branches/" . Reg::get("Branch.name"))); Reg::set("Path.branchSkin", str_replace("//", "/", Reg::get("Path.branchRoot") . "/public")); } Reg::set("Path.root", str_replace("//", "/", Reg::get("URI.base"))); Reg::set("Path.skin", str_replace("//", "/", Reg::get("Path.root") . "/public")); // setup all the other path variables based on the URI.map definition $count = 0; $position = 0; $skip = 0; $uriMap = Reg::get("URI.map"); $uriWorking = Reg::get("URI.working"); foreach ($uriWorking as $key => $value) { // if the current item is a prepend with a default and the default is the current item in the uri then dont show that item in the paths if (is_array($uriMap[$key]) && $uriMap[$key][0] == $value) { $skip++; $count--; $position--; } // fix the paths so that they dont show the URI.map defined defaults if (isset($uriMap[$key]) && $uriMap[$key] == $value) { unset($uriWorking[$key]); $position = $count; $count--; } else { // if this is not a default then advance the position and have it show in the variable $position = $count + 1; } // set the actual variables Reg::set("Path." . $key, Reg::get("Path.site") . '/' . trim(implode('/', array_merge((array) Reg::get('Branch.name'), array_slice($uriWorking, $skip, $position))), '/')); $count++; } // clean up after setting other path variables unset($uriMap); // setup the array to build the Path.current variable and make sure that the url is clean $current_uri_map = array(); foreach ($uri_paths as $item) { if (!empty($item)) { $current_uri_map[] = $item; } } Reg::set("Path.current", str_replace("//", "/", implode("/", array_merge(array(Reg::get("Path.site")), $current_uri_map)))); // call hook Hook::call('Config.processURI.after'); return true; }