PageRenderTime 43ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/htrouter/Module/Dir.php

http://github.com/jaytaph/HTRouter
PHP | 202 lines | 137 code | 45 blank | 20 comment | 28 complexity | f4724a4c5a2b92c3894618b6bffc6f9d MD5 | raw file
  1. <?php
  2. /**
  3. * Mod_dir.
  4. */
  5. namespace HTRouter\Module;
  6. use HTRouter\Module;
  7. class Dir extends Module {
  8. const DEFAULT_DIRECTORY_INDEX_FILE = "index.php";
  9. public function init(\HTRouter $router, \HTRouter\HTDIContainer $container)
  10. {
  11. parent::init($router, $container);
  12. // Register directives
  13. $router->registerDirective($this, "DirectoryIndex");
  14. $router->registerDirective($this, "DirectorySlash");
  15. $router->registerDirective($this, "FallbackResource");
  16. // Register hooks
  17. $router->registerHook(\HTRouter::HOOK_FIXUPS, array($this, "dirFixups"), 99);
  18. // Set default values
  19. $this->getConfig()->set("DirectorySlash", true);
  20. }
  21. public function DirectoryIndexDirective(\HTRouter\Request $request, $line) {
  22. $localUrls = explode(" ", $line);
  23. foreach ($localUrls as $url) {
  24. $this->getConfig()->append("DirectoryIndex", $url);
  25. }
  26. }
  27. public function DirectorySlashDirective(\HTRouter\Request $request, $line) {
  28. $utils = new \HTRouter\Utils;
  29. $value = $utils->fetchDirectiveFlags($line, array("on" => true, "off" => false));
  30. $this->getConfig()->set("DirectorySlash", $value);
  31. }
  32. public function FallbackResourceDirective(\HTRouter\Request $request, $line) {
  33. $this->getConfig()->set("FallbackResource", $line);
  34. }
  35. public function mergeConfigs(\HTRouter\VarContainer $base, \HTRouter\VarContainer $add) {
  36. $base->set("DirectoryIndex", $add->get("DirectoryIndex") ? $add->get("DirectoryIndex") : $base->get("DirectoryIndex"));
  37. $base->set("DirectorySlash", $add->get("DirectorySlash") == false ? $base->get("DirectorySlash") : $add->get("DirectorySlash"));
  38. $base->set("FallbackResource", $add->get("FallbackResource") ? $add->get("FallbackResource") : $base->get("FallbackResource"));
  39. }
  40. protected function _fixup_dflt(\HTRouter\Request $request) {
  41. // Do fallback
  42. $path = $this->getConfig()->get("FallbackResource");
  43. if ($path == false) {
  44. return \HTRouter::STATUS_DECLINED;
  45. }
  46. $url = $this->_updateUrl($request->getUri(), $path);
  47. // In case a subrequest throws an error
  48. $error_notfound = false;
  49. $subContainer = $this->_prepareContainerForSubRequest($url);
  50. $processor = new \HTRouter\Processor($subContainer);
  51. $status = $processor->processRequest();
  52. $subrequest = $subContainer->getRequest();
  53. $subrequest->setStatus($status);
  54. if (is_file($subrequest->getDocumentRoot() . $subrequest->getFilename())) {
  55. $this->_container->setRequest($subrequest);
  56. return \HTRouter::STATUS_OK;
  57. }
  58. if ($subrequest->getStatus() >= 300 && $subrequest->getStatus() < 400) {
  59. $this->_container->setRequest($subrequest);
  60. return $subrequest->getStatus();
  61. }
  62. if ($subrequest->getStatus() != \HTRouter::STATUS_HTTP_NOT_FOUND &&
  63. $subrequest->getStatus() != \HTRouter::STATUS_HTTP_OK) {
  64. $error_notfound = $subrequest->getStatus();
  65. }
  66. // "error_notfound" is set? return error_notfound
  67. if ($error_notfound) {
  68. return $error_notfound;
  69. }
  70. // Nothing to be done. Proceed to next module
  71. return \HTRouter::STATUS_DECLINED;
  72. }
  73. protected function _fixup_dir(\HTRouter\Request $request) {
  74. $utils = new \HTRouter\Utils;
  75. // Check if it doesn't end on a slash?
  76. $url = $request->getUri();
  77. if (!empty($url) and ($url[strlen($url)-1] != '/')) {
  78. // We are fixing a directory and we aren't allowed to add a slash. No good.
  79. if ($this->getConfig()->get("DirectorySlash") == false) {
  80. return \HTRouter::STATUS_DECLINED;
  81. }
  82. // Add the extra slash to the URL
  83. $url = parse_url($url);
  84. $url['path'] .= "/";
  85. $url = $utils->unparse_url($url);
  86. // Redirect permanently new slashed url ( http://example.org/dir => http://example.org/dir/ )
  87. $request->appendOutHeaders("Location", $url);
  88. return \HTRouter::STATUS_HTTP_MOVED_PERMANENTLY;
  89. }
  90. // In case a subrequest throws an error
  91. $error_notfound = false;
  92. // We can safely check and match against our directory index now
  93. $names = $this->getConfig()->get("DirectoryIndex");
  94. $names[] = self::DEFAULT_DIRECTORY_INDEX_FILE; // @TODO: Seriously wrong. This needs to be placed in config?
  95. foreach ($names as $name) {
  96. $url = $this->_updateUrl($request->getUri(), $name);
  97. $subContainer = $this->_prepareContainerForSubRequest($url);
  98. $processor = new \HTRouter\Processor($subContainer);
  99. $status = $processor->processRequest();
  100. $subrequest = $subContainer->getRequest();
  101. $subrequest->setStatus($status);
  102. if (is_file($subrequest->getDocumentRoot() . $subrequest->getFilename())) {
  103. $this->_container->setRequest($subrequest);
  104. return \HTRouter::STATUS_OK;
  105. }
  106. if ($subrequest->getStatus() >= 300 && $subrequest->getStatus() < 400) {
  107. $this->_container->setRequest($subrequest);
  108. return $subrequest->getStatus();
  109. }
  110. if ($subrequest->getStatus() != \HTRouter::STATUS_HTTP_NOT_FOUND &&
  111. $subrequest->getStatus() != \HTRouter::STATUS_HTTP_OK) {
  112. $error_notfound = $subrequest->getStatus();
  113. }
  114. }
  115. // "error_notfound" is set? return error_notfound
  116. if ($error_notfound) {
  117. return $error_notfound;
  118. }
  119. // Nothing to be done. Proceed to next module
  120. return \HTRouter::STATUS_DECLINED;
  121. }
  122. public function dirFixups(\HTRouter\Request $request) {
  123. $filename = $request->getFilename();
  124. if (empty($filename) || is_dir($request->getDocumentRoot() . $filename)) {
  125. return $this->_fixup_dir($request);
  126. } elseif (! empty($filename) && ! file_exists($request->getDocumentRoot() . $filename) &&
  127. @filetype($request->getDocumentRoot() . $filename) == "unknown") {
  128. // @TODO: This must be different FILE_NOT_EXIST
  129. return $this->_fixup_dflt($request);
  130. }
  131. return \HTRouter::STATUS_DECLINED;
  132. }
  133. protected function _updateUrl($url, $path) {
  134. $utils = new \HTRouter\Utils;
  135. $url = parse_url($url);
  136. // Is it an absolute url?
  137. if ($path[0] == "/") {
  138. $url['path'] = $path; // Replace
  139. } else {
  140. $url['path'] .= $path; // Append
  141. }
  142. $url = $utils->unparse_url($url);
  143. return $url;
  144. }
  145. protected function _prepareContainerForSubRequest($url) {
  146. $subrequest = clone ($this->_container->getRequest());
  147. $subrequest->setMainRequest(false);
  148. $subrequest->setUri($url);
  149. $subrequest->setFilename(null);
  150. $subContainer = clone ($this->_container);
  151. $subContainer->setRequest($subrequest);
  152. return $subContainer;
  153. }
  154. public function getAliases() {
  155. return array("mod_dir.c", "mod_dir", "dir");
  156. }
  157. }