dmBridge PHP API
DMInternalURI.php
00001 <?php
00002 #
00003 # dmBridge: a data access framework for CONTENTdm(R)
00004 #
00005 # Copyright © 2009, 2010, 2011 Board of Regents of the Nevada System of Higher
00006 # Education, on behalf of the University of Nevada, Las Vegas
00007 #
00008 
00024 class DMInternalURI extends DMURI {
00025    
00030    private static $routes_xml;
00031 
00035    private $extension;
00036 
00040    private static function getAllowedExtensions() {
00041       return array_merge(DMMediaType::getKnownExtensions(),
00042             array("xml", "json", "jsonp", "atom", "html", "sitemap"));
00043    }
00044 
00049    private static function getPathMinusExtension($path) {
00050       $tmp = explode(".", $path);
00051       if (count($tmp) > 1) {
00052          $ext = $tmp[count($tmp) - 1];
00053          if (in_array($ext, DMMediaType::getKnownExtensions())) {
00054             array_pop($tmp);
00055             return implode(".", $tmp);
00056          }
00057       }
00058       return $path;
00059    }
00060 
00071    public static function getResourceURI($component,
00072          $params, $representation = null) {
00073       $prefix = "";
00074       switch ($component) {
00075       case DMBridgeComponent::HTTPAPI:
00076          $prefix = "api/1/";
00077          break;
00078       default:
00079          break;
00080       }
00081 
00082       return self::getURIWithParams($prefix . $params, array(),
00083             $representation == "html" ? null : $representation);
00084    }
00085 
00092    private static function getRouteMatchingParamsFromRoutesFile(
00093          $params, $path = null) {
00094       // parse routes XML
00095       if ($path == null) {
00096          $routes_xml = self::getRoutesXML();
00097       } else {
00098          if (file_exists($path)) {
00099             $routes_xml = new DOMDocument("1.0", "utf-8");
00100             $routes_xml->load($path);
00101          } else {
00102             return null;
00103          }
00104       }
00105 
00106       // parse the URI
00107       $uri_parts = explode("/", $params);
00108       $uri_count = count($uri_parts);
00109 
00110       $version = 1; // default resource version; may be overridden below
00111       $xml_route_parts = array();
00112       $props = array(
00113          'ctrlr' => null,
00114          'method' => null,
00115          'parameters' => null
00116       );
00117       $representations = array();
00118       foreach ($routes_xml->getElementsByTagName("route") as $xml_route) {
00119          $xml_route_parts = explode("/", $xml_route->getAttribute("path"));
00120          $xml_route_count = count($xml_route_parts);
00121          if ($uri_count != $xml_route_count) { // not a match
00122             continue;
00123          }
00124          $parameters = array();
00125          for ($i = 0; $i < $uri_count; $i++) {
00126             if ($xml_route_parts[$i] != $uri_parts[$i]
00127                   && strpos($xml_route_parts[$i], ":") !== 0) {
00128                break; // not a match
00129             }
00130             if (strpos($xml_route_parts[$i], ":") === 0) {
00131                $parameters[] = $uri_parts[$i];
00132                if ($xml_route_parts[$i] == ":int") {
00133                   if ((string) $uri_parts[$i] != (string) round($uri_parts[$i])) {
00134                      break; // not a match
00135                   }
00136                }
00137             }
00138 
00139             if ($i == $uri_count - 1) { // successful match
00140                $invocation = $xml_route
00141                   ->getElementsByTagName("invocation")->item(0);
00142                $props['ctrlr'] = $invocation
00143                   ->getElementsByTagName("class")->item(0)->nodeValue;
00144                $props['method'] = $invocation
00145                   ->getElementsByTagName("method")->item(0)->nodeValue;
00146                $props['parameters'] = implode(",", $parameters);
00147                $xml_representations = $xml_route
00148                   ->getElementsByTagName("representations")->item(0);
00149                foreach ($xml_representations->getElementsByTagName(
00150                      "representation") as $rep) {
00151                   $representations[$rep->getAttribute("ext")]
00152                         = DMMediaType::getTypeForString($rep->nodeValue);
00153                }
00154                $version = (int) $xml_route
00155                   ->getElementsByTagName("resourceVersion")->item(0)
00156                      ->nodeValue;
00157                break(2);
00158             }
00159          }
00160       }
00161 
00162       if ($props['ctrlr'] && $props['method']) {
00163          $route = new DMRoute($props['ctrlr'], $props['method']);
00164          if ($props['parameters']) {
00165             $route->setParameters($props['parameters']);
00166          }
00167          $route->setAvailableRepresentations($representations);
00168 
00169          return $route;
00170       }
00171       return null;
00172    }
00173 
00177    private static function getRoutesXML() {
00178       if (!self::$routes_xml) {
00179          $path = dirname(__FILE__) . "/../../includes/routes.xml";
00180          self::$routes_xml = new DOMDocument("1.0", "utf-8");
00181          self::$routes_xml->load($path);
00182       }
00183       return self::$routes_xml;
00184    }
00185 
00196    public static function getURIWithParams($params, array $query = array(),
00197          $representation = null) {
00198       $path = DMConfigIni::getInstance()->getString("dmbridge.base_uri_path");
00199       $uri = clone DMHTTPRequest::getCurrent()->getURI();
00200       $uri->unsetQuery();
00201       $uri->setPath($path);
00202       $uri->setParams($params);
00203       $uri->setExtension($representation);
00204       
00205       if (array_key_exists("r", $query) && !$params) {
00206          $uri->setParams($query['r']);
00207       }
00208 
00209       foreach ($query as $k => $v) {
00210          $uri->addQueryValue($k, $v);
00211       }
00212       return $uri;
00213    }
00214 
00220    public function getAbsoluteURIAsString() {
00221       if (!$this->getScheme() || !$this->getHost()) {
00222          return null;
00223       }
00224 
00225       $clone = clone $this;
00226       $uri = $clone->getScheme() . "://";
00227       if ($clone->getUser()) {
00228          $uri .= $clone->getUser();
00229       }
00230       if ($clone->getPassword()) {
00231          $uri .= ":" . $clone->getPassword();
00232       }
00233       if ($clone->getUser() || $clone->getPassword()) {
00234          $uri .= "@";
00235       }
00236       $uri .= $clone->getHost();
00237       if ($clone->getPort() != 80) {
00238          $uri .= ":" . $clone->getPort();
00239       }
00240       $uri .= $clone->getPath();
00241       if ($clone->getExtension() && !($clone->isTemplateEngine()
00242             && $clone->getExtension() == "html")) {
00243          $uri .= "." . $clone->getExtension();
00244       }
00245       $clone->unsetQueryKey("r");
00246       if (count($clone->getQuery())) {
00247          $uri .= "?" . $clone->getQueryString();
00248       }
00249       if ($clone->getFragment()) {
00250          $uri .= "#" . $clone->getFragment();
00251       }
00252       return $uri;
00253    }
00254 
00258    public function isControlPanel() {
00259       $components = $this->getParamComponents();
00260       return (bool) count($components) && $components[0] == "admin";
00261    }
00262 
00266    public function getExtension() {
00267       return $this->extension;
00268    }
00269 
00273    public function setExtension($ext) {
00274       $this->extension = $ext;
00275    }
00276 
00280    public function isHTTPAPI() {
00281       $components = $this->getParamComponents();
00282       return (bool) count($components) && $components[0] == "api";
00283    }
00284 
00288    private function getModuleRoute() {
00289       $mm = DMModuleManager::getInstance();
00290       foreach ($mm->getEnabledModules() as $module) {
00291          $route = self::getRouteMatchingParamsFromRoutesFile(
00292                $this->getParams(),
00293                $module->getAbsolutePathname() . "/routes.xml");
00294          if ($route) {
00295             $route->setModuleRoute(true);
00296             return $route;
00297          }
00298       }
00299       return null;
00300    }
00301 
00306    public function getParams() {
00307       $path = DMConfigIni::getInstance()->getString("dmbridge.base_uri_path");
00308       return trim(str_replace($path, "",
00309             self::getPathMinusExtension($this->getPath())), "/");
00310    }
00311 
00315    public function setParams($params) {
00316       $path = DMConfigIni::getInstance()->getString("dmbridge.base_uri_path");
00317       $this->setPath($path . "/" . $params);
00318    }
00319 
00324    public function getParamComponents() {
00325       return explode("/", $this->getParams());
00326    }
00327 
00332    public function getRoute() {
00333       $r = $this->getModuleRoute();
00334       if ($r) {
00335          return $r;
00336       }
00337 
00338       $tmp1 = $this->getParamComponents();
00339 
00340       $dxp = new DOMXPath(self::getRoutesXML());
00341       $result = $dxp->query("//route/@path");
00342 
00343       // look for built-in routes
00344       foreach ($result as $route) {
00345          $tmp2 = explode("/", $route->value);
00346 
00347          $count1 = count($tmp1);
00348          $count2 = count($tmp2);
00349          if ($count1 == $count2) {
00350             for ($i = 0; $i < $count1; $i++) {
00351                if ($i + 1 == $count1) { // match
00352                   $r = self::getRouteMatchingParamsFromRoutesFile(
00353                         $this->getParams());
00354                   if ($r) {
00355                      return $r;
00356                   }
00357                }
00358             }
00359          }
00360       }
00361    }
00362 
00368    public function setString($str) {
00369       $tmp = parse_url($str);
00370 
00371       if (!is_array($tmp)) {
00372          throw new DMIllegalArgumentException(
00373                DMLocalizedString::getString("INVALID_URL"));
00374       }
00375 
00376       if (array_key_exists("scheme", $tmp)) {
00377          $this->setScheme($tmp['scheme']);
00378       }
00379       if (array_key_exists("host", $tmp)) {
00380          $this->setHost($tmp['host']);
00381       }
00382       if (array_key_exists("port", $tmp)) {
00383          $this->setPort($tmp['port']);
00384       }
00385       if (array_key_exists("user", $tmp)) {
00386          $this->setUser($tmp['user']);
00387       }
00388       if (array_key_exists("pass", $tmp)) {
00389          $this->setPassword($tmp['pass']);
00390       }
00391       if (array_key_exists("path", $tmp)) {
00392          $tmp2 = explode(".", $tmp['path']);
00393          $last_part = $tmp2[count($tmp2)-1];
00394          if (in_array($last_part, self::getAllowedExtensions())) {
00395             $this->setExtension(array_pop($tmp2));
00396             $path = implode(".", $tmp2);
00397             $this->setPath($path);
00398          } else {
00399             $this->setPath($tmp['path']);
00400          }
00401       }
00402       $this->unsetQuery();
00403       if (array_key_exists("query", $tmp)) {
00404          $q = explode("&", $tmp['query']);
00405          foreach ($q as $kv) {
00406             $parts = explode("=", $kv);
00407             if (count($parts) == 2) {
00408                $this->addQueryValue(
00409                      urldecode($parts[0]), urldecode($parts[1]));
00410             }
00411          }
00412       }
00413       if (array_key_exists("fragment", $tmp)) {
00414          $this->setFragment($tmp['fragment']);
00415       }
00416    }
00417 
00421    public function isTemplateEngine() {
00422       $components = $this->getParamComponents();
00423       return (bool) count($components) && $components[0] == "objects";
00424    }
00425 
00432    public function getVersion() {
00433       $parts = $this->getParamComponents();
00434       if (count($parts) > 1 && is_numeric($parts[1])) {
00435          return $parts[1];
00436       }
00437       return null;
00438    }
00439 
00440 }
 All Data Structures Functions Variables