PageRenderTime 51ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/main/php/lang/FileSystemClassLoader.class.php

http://github.com/xp-framework/xp-framework
PHP | 171 lines | 105 code | 10 blank | 56 comment | 4 complexity | 2dbdeeb3b6b39fc2b5900a1589f5b5c0 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. uses('lang.AbstractClassLoader');
  7. /**
  8. * Loads a class from the filesystem
  9. *
  10. * @test xp://net.xp_framework.unittest.reflection.ClassLoaderTest
  11. * @test xp://net.xp_framework.unittest.reflection.ClassFromFileSystemTest
  12. * @see xp://lang.XPClass#forName
  13. */
  14. class FileSystemClassLoader extends AbstractClassLoader {
  15. /**
  16. * Constructor.
  17. *
  18. * The path argument is optional and lets you define where to search for
  19. * classes (it will be prefixed to the class name)
  20. *
  21. * @param string path default '' file system path
  22. */
  23. public function __construct($path= '') {
  24. $this->path= rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
  25. }
  26. /**
  27. * Load class bytes
  28. *
  29. * @param string name fully qualified class name
  30. * @return string
  31. */
  32. public function loadClassBytes($name) {
  33. return file_get_contents($this->path.strtr($name, '.', DIRECTORY_SEPARATOR).xp::CLASS_FILE_EXT);
  34. }
  35. /**
  36. * Checks whether this loader can provide the requested class
  37. *
  38. * @param string class
  39. * @return bool
  40. */
  41. public function providesClass($class) {
  42. $f= $this->path.strtr($class, '.', DIRECTORY_SEPARATOR).xp::CLASS_FILE_EXT;
  43. return $f === realpath($f);
  44. }
  45. /**
  46. * Checks whether this loader can provide the requested resource
  47. *
  48. * @param string filename
  49. * @return bool
  50. */
  51. public function providesResource($filename) {
  52. return is_file($this->path.$filename);
  53. }
  54. /**
  55. * Checks whether this loader can provide the requested package
  56. *
  57. * @param string package
  58. * @return bool
  59. */
  60. public function providesPackage($package) {
  61. return is_dir($this->path.strtr($package, '.', DIRECTORY_SEPARATOR));
  62. }
  63. /**
  64. * Returns URI suitable for include() given a class name
  65. *
  66. * @param string class
  67. * @return string
  68. */
  69. protected function classUri($class) {
  70. return $this->path.strtr($class, '.', DIRECTORY_SEPARATOR).xp::CLASS_FILE_EXT;
  71. }
  72. /**
  73. * Return a class at the given URI
  74. *
  75. * @param string uri
  76. * @return string fully qualified class name, or NULL
  77. */
  78. protected function classAtUri($uri) {
  79. if (0 !== substr_compare($uri, xp::CLASS_FILE_EXT, -strlen(xp::CLASS_FILE_EXT))) return NULL;
  80. // Resolve path if not absolute
  81. if ((DIRECTORY_SEPARATOR === $uri{0} || (':' === $uri{1} && '\\' === $uri{2}))) {
  82. $absolute= realpath($uri);
  83. } else {
  84. $absolute= realpath($this->path.DIRECTORY_SEPARATOR.$uri);
  85. }
  86. // Verify path is inside this path, exists and is a file
  87. $l= strlen($this->path);
  88. if (FALSE === $absolute || 0 !== strncmp($absolute, $this->path, $l) || !is_file($absolute)) return NULL;
  89. return strtr(
  90. substr($absolute, $l, -strlen(xp::CLASS_FILE_EXT)),
  91. '/'.DIRECTORY_SEPARATOR,
  92. '..'
  93. );
  94. }
  95. /**
  96. * Loads a resource.
  97. *
  98. * @param string filename name of resource
  99. * @return string
  100. * @throws lang.ElementNotFoundException in case the resource cannot be found
  101. */
  102. public function getResource($filename) {
  103. if (!is_file($fn= $this->path.strtr($filename, '/', DIRECTORY_SEPARATOR))) {
  104. return raise('lang.ElementNotFoundException', 'Could not load resource '.$filename);
  105. }
  106. return file_get_contents($fn);
  107. }
  108. /**
  109. * Retrieve a stream to the resource
  110. *
  111. * @param string filename name of resource
  112. * @return io.File
  113. * @throws lang.ElementNotFoundException in case the resource cannot be found
  114. */
  115. public function getResourceAsStream($filename) {
  116. if (!is_file($fn= $this->path.strtr($filename, '/', DIRECTORY_SEPARATOR))) {
  117. return raise('lang.ElementNotFoundException', 'Could not load resource '.$filename);
  118. }
  119. return new \io\File($fn); // Trigger autoloading!
  120. }
  121. /**
  122. * Fetch instance of classloader by the path to the archive
  123. *
  124. * @param string path
  125. * @param bool expand default TRUE whether to expand the path using realpath
  126. * @return lang.FileSystemClassLoader
  127. */
  128. public static function instanceFor($path, $expand= TRUE) {
  129. static $pool= array();
  130. $path= $expand ? realpath($path) : $path;
  131. if (!isset($pool[$path])) {
  132. $pool[$path]= new self($path);
  133. }
  134. return $pool[$path];
  135. }
  136. /**
  137. * Get package contents
  138. *
  139. * @param string package
  140. * @return string[] filenames
  141. */
  142. public function packageContents($package) {
  143. $contents= array();
  144. if ($d= @dir($this->path.strtr($package, '.', DIRECTORY_SEPARATOR))) {
  145. while ($e= $d->read()) {
  146. if ('.' != $e{0}) $contents[]= $e.(is_dir($d->path.DIRECTORY_SEPARATOR.$e) ? '/' : '');
  147. }
  148. $d->close();
  149. }
  150. return $contents;
  151. }
  152. }
  153. ?>