/** * method: load * * returns: * Boolean true or false depending on whether it succeeded, there are some codepaths which call setError() * this is because of serious errors which can't be handled at the moment * * NOTE: * - if language is false, you need to call setLanguage before you * call load otherwise the source can't load the correct file */ public function load() { if (!$this->language) { return false; } $dir = $this->getConfig("directory"); $source = Amslib_File::reduceSlashes("{$dir}/{$this->language}.xml"); $filename = false; try { // NOTE: This is ugly and I believe it's a failure of Amslib_File::find() to not do this automatically if (file_exists($source)) { $filename = $source; } else { if (file_exists($f = Amslib_File::find(Amslib_Website::relative($source), true))) { $filename = $f; } else { if (file_exists($f = Amslib_File::find(Amslib_Website::absolute($source), true))) { $filename = $f; } } } if (!$filename) { Amslib_Debug::log("stack_trace", "directory", $dir, "filename", $filename, "language", $this->language); } else { $this->qp = Amslib_QueryPath::qp($filename); return true; } } catch (Exception $e) { Amslib_Debug::log("Exception: ", $e->getMessage(), "file=", $filename, "source=", $source); Amslib_Debug::log("stack_trace"); } return false; }
function TestOfReduceSlashes() { $this->caseTitle('reduceSlashes'); $document = 'http://www.crm-test.local/'; $this->log($document); $this->assertEqual(strpos($document, 'http://'), 0); $result = Amslib_File::reduceSlashes($document); $this->log($result); $this->assertFalse(strpos($document, 'http://')); }
/** * method: findPlugin * * todo: write documentation */ protected static function findPlugin($name, $location = NULL) { $search = array_merge(array($location), self::$location); foreach ($search as $location) { // TODO: this obviously hardcodes the xml configuration filename, perhaps this is not ideal if (file_exists("{$location}/{$name}/package.xml")) { // double check that the location starts and ends with a slash // something this isn't the case and the programmer forgets // then the plugin doesnt load, all because of a simple missing slash return Amslib_File::reduceSlashes("/{$location}/"); } } return false; }
/** * method: getURL * * todo: write documentation */ public static function getURL($name = NULL, $group = NULL, $lang = "default", $domain = NULL) { if ($domain == NULL) { $domain = self::$domain; } // if the $name parameter is an array, this code will split the $name parameter to // use the first as the route name and all the rest as optional parameters if (is_array($name)) { $params = array_slice($name, 1); $name = array_shift($name); } else { $params = array(); } $route = self::getRoute($name, $group, $domain); // NOTE: If you request a webservice and cannot find it, make this a serious error // You cannot return a "closest" url in this case, cause it causes a LOT of problems // NOTE: If you call a webservice which results in the home page opening, which is what called // the webservice in the first place, it'll cause an infinite loop of repeatedly trying to // open the home page, which generates a new webservice request and this cycle never ends // NOTE: This solves the problem, for now, but ultimately, shows a critical problem that needs addressing if (strpos($name, "service:") === 0 && $route["name"] === false) { return false; } // NOTE: I think it's safe to assume sending NULL means you want the default language // NOTE: otherwise it would never ever match a language and the system would fail worse // NOTE: although this is silly, cause it means that passing "default" and NULL are the same, why not just use one? if ($lang == NULL) { $lang = "default"; } $url = isset($route["src"][$lang]) ? $route["src"][$lang] : ""; // If the url contains a http, don't attempt to make it relative, it's an absolute url // NOTE: perhaps a better way to solve this is to mark routes as absolute, then I don't have to "best guess" $url = strpos($url, "http") !== false ? $url : Amslib_Website::relative($url); // NOTE: perhaps I should move this highly specific code into it's own method so I can keep things small and tidy // Now we can replace all the wildcard targets in the url with parameters passed into the function // NOTE: I like codeigniters version of this better, they use like (:any) or (:num) and replace specifically $target = array('(\\w+)', '(.*?)', '(.*)'); $append = array(); foreach (Amslib_Array::valid($params) as $k => $p) { // I copied this replacement code from: http://stackoverflow.com/revisions/1252710/3 $pos = false; foreach ($target as $t) { $pos = strpos($url, $t); if ($pos !== false) { $pos = array($pos, strlen($t)); break; } } if (is_array($pos)) { $url = substr_replace($url, $p, $pos[0], $pos[1]); } else { if (!is_array($p)) { $p = array($p); } $append = array_merge($append, $p); } } // NOTE: this is pretty dumb, I should try to work out a generic way to deal with all of these // http-like prefixes so I don't have to keep writing this shitty code everywhere..... // NOTE: I think I have solved this in the new Amslib_Website::reduceSlashes method $prefix = ""; if (strpos($url, "http://") !== false) { $prefix = "http://"; } if (strpos($url, "https://") !== false) { $prefix = "https://"; } return $prefix . Amslib_File::reduceSlashes(str_replace($prefix, "", $url) . implode("/", array_filter($append)) . "/"); }
/** * method: setCacheDirectory * * todo: write documentation */ public function setCacheDirectory($directory) { $directory = Amslib_File::reduceSlashes($directory); if (!is_dir($directory) && !file_exists($directory)) { if (!Amslib_File::mkdir($directory)) { return false; } } $this->cache_dir = $directory; }
/** * method: findResource * * todo: write documentation */ protected function findResource($resource, $absolute = false) { // If the resource has an attribute "absolute" don't process it, return it directly // An absolute resource will also have a protocol token inside the string if ($absolute || strpos($resource, "://") !== false) { return $resource; } $location = $this->getLocation(); // PREPARE THE STRING: expand any parameters inside the resource name $resource = self::expandPath($resource); // NOTE: we have to do this to get around a bug in lchop/rchop $query = ($str = Amslib_String::lchop($resource, "?")) == $resource ? false : $str; $resource = Amslib_String::rchop($resource, "?"); $output = false; // TEST 1: look in the package directory for the file $test1 = Amslib_File::reduceSlashes("{$location}/{$resource}"); if (!$output && file_exists($test1)) { $output = Amslib_File::relative($test1); } // TEST 2: Test whether the file "exists" without any assistance if (!$output && file_exists($resource)) { $output = Amslib_File::relative($resource); } // TEST 3: Does the file exists relative to the document root? $test3 = Amslib_File::absolute($resource); if (!$output && file_exists($test3)) { // Why do we see whether $test3 exists, then discard it and use $resource? $output = Amslib_File::relative($resource); } // TEST 4: search the include path for the file $test4 = Amslib_File::find($resource, true); if ($output && file_exists($test4)) { $output = Amslib_File::relative($test4); } // Return either $output value on it's own, or appended with the query if required // If output is false or valid string, it'll return $output at minimum, // only appending the query if it's valid too return $output && $query ? "{$output}?{$query}" : $output; }
/** * method: sanitiseURL * * todo: write documentation */ protected function sanitiseURL($url) { // Capture the http:// part so you can replace it afterwards // NOTE: what happens if you are running from https:// ? $http = strpos($url, "http://") !== false ? "http://" : ""; // strip away the http:// part first, because it won't survive the reduceSlashes otherwise $url = $http . Amslib_File::reduceSlashes(str_replace("http://", "", $url)); return $url == "/" ? "" : $url; }
/** * method: reduceSlashes * * A method to reduceSlashes but take care of urls like http:// so they don't break * * params: * $string - The string to reduce the slashes in * $token - The token to split the string on, this should * only exist once in the string and the right * side will be reduced and the left side will not * defaults: "://" * * returns: * A string with any // or ///[n+] reduced to / */ public static function reduceSlashes($string, $token = "://") { list($prefix, $postfix) = explode($token, $string) + array(NULL, NULL); if ($postfix) { $string = $postfix; } return ($postfix ? $prefix . $token : "") . Amslib_File::reduceSlashes($string); }
/** * method: getLanguage * * Obtain the language set in the session for the specific type of language "domain" (normally website or content) * * parameters: * $name - The name of the language to retrieve * * returns: * Boolean false if obtaining a language has failed, or the 4 character language code, e.g: en_GB, en_ES * * notes: * - See the notes from the method Amslib_Plugin_Application::setLanguage for what the * language code, domains terms mean. * - Remember also, if a language is not found, the first language in the approved list will be * selected, stored and returned as a sensible default */ public static function getLanguage($name) { $lang = false; if (is_string($name) && strlen($name)) { $lang = Amslib_SESSION::get(Amslib_File::reduceSlashes(self::$langKey . "/{$name}")); } if (!$lang) { $lang = self::setLanguage($name, current(self::getLanguageList($name))); } return $lang; }
/** * method: extract * * todo: write documentation */ public static function extract($path) { // If the path is just /, then obviously it has nothing, just return it if ($path == "/") { return $path; } $parts = explode("/", trim($path, "/ ")); if (count($parts)) { $first = array_shift($parts); $lang = self::sanitise($first); if ($lang == $first) { self::set($lang); // Make sure there are only single slashes and make sure the path starts and ends with a slash return Amslib_File::reduceSlashes("/" . implode("/", $parts) . "/"); } } return $path; }