PageRenderTime 285ms CodeModel.GetById 30ms RepoModel.GetById 2ms app.codeStats 0ms

/atk4/lib/PathFinder.php

https://github.com/git86/todo
PHP | 341 lines | 205 code | 55 blank | 81 comment | 33 complexity | 427f6546fa20c6984c13e3f03da5becb MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php
  2. /***********************************************************
  3. ..
  4. Reference:
  5. http://agiletoolkit.org/doc/ref
  6. **ATK4*****************************************************
  7. This file is part of Agile Toolkit 4
  8. http://agiletoolkit.org
  9. (c) 2008-2011 Agile Technologies Ireland Limited
  10. Distributed under Affero General Public License v3
  11. If you are using this file in YOUR web software, you
  12. must make your make source code for YOUR web software
  13. public.
  14. See LICENSE.txt for more information
  15. You can obtain non-public copy of Agile Toolkit 4 at
  16. http://agiletoolkit.org/commercial
  17. *****************************************************ATK4**/
  18. class PathFinder extends AbstractController {
  19. /*
  20. PathFinder will help you to maintain consistent structure of files. This
  21. controller is used by many other parts of Agile Toolkit
  22. PathFinder concerns itself only with relative paths. It relies on PageManager
  23. ($api->pm) to convert relative paths into absolute.
  24. */
  25. public $base_location=null;
  26. // Object referencing base location. You might want to add more content here
  27. public $atk_location=null;
  28. // Referencing to location of a shared library
  29. function init(){
  30. parent::init();
  31. $this->api->pathfinder=$this;
  32. $GLOBALS['atk_pathfinder']=$this; // used by autoload
  33. // getting ready for atk
  34. //$this->api->proxyFunctions($this,array('addLocation','locate'));
  35. $this->addDefaultLocations();
  36. }
  37. function addDefaultLocations(){
  38. // Typically base directory is good for includes,
  39. // but atk4/ can also contain some data
  40. // Primary search point is the webroot directory. We are defining
  41. // those so you don't have to
  42. $base_directory=dirname(@$_SERVER['SCRIPT_FILENAME']);
  43. // Compatibility with command-line
  44. if(!$base_directory)$base_directory=realpath($GLOBALS['argv'][0]);
  45. if(method_exists($this->api,'addDefaultLocations'))$this->api->addDefaultLocations($this,$base_directory);
  46. $this->base_location=$this->addLocation('/',array(
  47. 'php'=>'lib',
  48. 'page'=>'page',
  49. 'template'=>'templates/'.$this->api->skin,
  50. 'xslt'=>'templates/xslt',
  51. 'mail'=>'templates/mail',
  52. 'js'=>'templates/js',
  53. 'banners'=>'banners',
  54. 'logs'=>'logs',
  55. 'dbupdates'=>'docs/dbupdates',
  56. ))->setBasePath($base_directory)
  57. ;
  58. // Files not found in webroot - will be looked for in library dir
  59. // We are assuming that we are located as atk4/lib/PathFinder.php
  60. $atk_directory=dirname(dirname(__FILE__));
  61. $atk_url=basename($atk_directory);
  62. $this->atk_location=$this->addLocation('atk4',array(
  63. 'php'=>'lib',
  64. // page: for security reasons no pages are allowed
  65. 'docs'=>'', // files like README, COPYING etc
  66. 'template'=>array('templates/'.$this->api->skin,'templates'=>'templates/shared'),
  67. 'xslt'=>'templates/xslt',
  68. 'mail'=>'templates/mail',
  69. 'js'=>'templates/js',
  70. // TODO: check that the folowing two are actually being used
  71. 'images'=>'img',
  72. 'css'=>array('templates/js','templates/'.$this->api->skin.'/css','templates/shared/css'),
  73. ))
  74. ->setBasePath(dirname(dirname(__FILE__)))
  75. ->setBaseURL($this->api->getConfig('atk/base_path','/atk4/'))
  76. ;
  77. }
  78. function addLocation($path,$contents=array()){
  79. $location=$this
  80. ->add('PathFinder_Location',$path)
  81. ->defineContents($contents)
  82. ;
  83. return $location;
  84. }
  85. function locate($type,$filename='',$return='relative'){
  86. /*
  87. Search for filename inside multiple locations, which contain
  88. resources of $type
  89. if filename is not defined, the location of the first available resource is defined
  90. */
  91. $attempted_locations=array();
  92. foreach($this->elements as $location){
  93. if(!($location instanceof PathFinder_Location))continue;
  94. $path=$location->locate($type,$filename,$return);
  95. if(is_string($path)){
  96. // file found!
  97. return $path;
  98. }elseif(is_array($path)){
  99. $attempted_locations=array_merge($attempted_locations,$path);
  100. }
  101. }
  102. throw new PathFinder_Exception($type,$filename,$attempted_locations);
  103. }
  104. function search($type,$filename='',$return='relative'){
  105. /*
  106. Similar to locate but returns array with all matches for the specified file
  107. in array
  108. */
  109. $matches=array();
  110. foreach($this->elements as $location){
  111. if(!($location instanceof PathFinder_Location))continue;
  112. $path=$location->locate($type,$filename,$return);
  113. if(is_string($path)){
  114. // file found!
  115. $matches[]=$path;
  116. }
  117. }
  118. return $matches;
  119. }
  120. function _searchDirFiles($dir,&$files,$prefix=''){
  121. $d=dir($dir);
  122. while(false !== ($file=$d->read())){
  123. if($file[0]=='.')continue;
  124. if(is_dir($dir.'/'.$file)){
  125. $this->_searchDirFiles($dir.'/'.$file,$files,$prefix.$file.'/');
  126. }else{
  127. $files[]=$prefix.$file;
  128. }
  129. }
  130. $d->close();
  131. }
  132. function searchDir($type,$directory){
  133. /*
  134. List all files inside particular directory
  135. */
  136. $dirs=$this->search($type,$directory,'path');
  137. $files=array();
  138. foreach($dirs as $dir){
  139. $this->_searchDirFiles($dir,$files);
  140. }
  141. return $files;
  142. }
  143. }
  144. class PathFinder_Exception extends BaseException {
  145. function __construct($type,$filename,$attempted_locations,$message=null){
  146. parent::__construct("Unable to include $filename".($message?':'.$message:''));
  147. $this->addMoreInfo('type',$type);
  148. $this->addMoreInfo('attempted_locations',$attempted_locations);
  149. }
  150. function collectBasicData(){
  151. }
  152. }
  153. class PathFinder_Location extends AbstractModel {
  154. /*
  155. Represents a location, which contains number of sub-locations. Each
  156. of which may contain certain type of data
  157. */
  158. public $parent_location=null;
  159. public $contents=array();
  160. // contains list of 'type'=>'subdir' which lists all the
  161. // resources which can be found in this directory
  162. public $relative_path=null;
  163. // Path to relative file within this resource
  164. public $base_url=null;
  165. public $base_path=null;
  166. function init(){
  167. parent::init();
  168. $this->relative_path=$this->short_name;
  169. if($this->short_name[0]=='/' || (strlen($this->short_name)>1 && $this->short_name[1]==':')){
  170. // Absolute path. Independent from base_location
  171. }else{
  172. $this->setParent($this->owner->base_location);
  173. }
  174. }
  175. function setParent($parent){
  176. $this->parent_location=$parent;
  177. return $this;
  178. }
  179. function __toString(){
  180. // this is our path
  181. $s=(isset($this->parent_location)?
  182. ((string)$this->parent_location):'');
  183. if($s && substr($s,-1)!='/' && $this->relative_path)$s.='/';
  184. $s.=$this->relative_path;
  185. return $s;
  186. }
  187. function getURL($file_path=null){
  188. // Returns how this location or file can be accessed through web
  189. // base url + relative path + file_path
  190. $url='';
  191. if($this->base_url)$url=$this->base_url;else
  192. if($this->parent_location){
  193. $url=$this->parent_location->getURL();
  194. if(substr($url,-1)!='/')$url.='/';
  195. $url.=$this->relative_path;
  196. }else
  197. throw new BaseException('Unable to determine URL');
  198. if($file_path){
  199. if(substr($url,-1)!='/')$url.='/';
  200. $url.=$file_path;
  201. }
  202. return $url;
  203. }
  204. function getPath($file_path=null){
  205. // Returns how this location or file can be accessed through filesystem
  206. $path='';
  207. if($this->base_path)$path=$this->base_path;else
  208. if($this->parent_location){
  209. $path=$this->parent_location->getPath();
  210. if(substr($path,-1)!='/')$path.='/';
  211. $path.=$this->relative_path;
  212. }else
  213. throw new BaseException('Unable to determine Path for '.$this.', parent='.$this->parent_location);
  214. if($file_path){
  215. if(substr($path,-1)!='/')$path.='/';
  216. $path.=$file_path;
  217. }
  218. return $path;
  219. }
  220. function setBaseURL($url){
  221. /*
  222. something like /my/app
  223. */
  224. $this->base_url=$url;
  225. return $this;
  226. }
  227. function setBasePath($path){
  228. /*
  229. something like /home/web/public_html
  230. */
  231. $this->base_path=$path;
  232. return $this;
  233. }
  234. function defineContents($contents){
  235. if($contents==='all'){
  236. $contents=array('all'=>'all');
  237. }
  238. if(is_string($contents)){
  239. $contents=array($contents=>'.');
  240. }
  241. $this->contents=array_merge_recursive($this->contents,$contents);
  242. return $this;
  243. }
  244. function locate($type,$filename,$return='relative'){
  245. // Locates the file and if found - returns location,
  246. // otherwise returns array of attempted locations
  247. // specify empty filename to find location
  248. $attempted_locations=array();
  249. $locations=array();
  250. $location=null;
  251. // first - look if type is explicitly defined in
  252. if(isset($this->contents[$type])){
  253. if(is_array($this->contents[$type])){
  254. $locations=$this->contents[$type];
  255. }else{
  256. $locations=array($this->contents[$type]);
  257. }
  258. // next - look if locations claims to have all resource types
  259. }elseif(isset($this->contents['all'])){
  260. $locations=array($type);
  261. echo (string)$this;
  262. }
  263. foreach($locations as $path){
  264. $f=$this->getPath($pathfile=$path.'/'.$filename);
  265. if(file_exists($f)){
  266. if(!is_readable($f)){
  267. throw new PathFinder_Exception($type,$filename,$f,'File found but it is not readable');
  268. }
  269. if($return=='relative')return $pathfile;
  270. if($return=='url')return $this->getURL($pathfile);
  271. if($return=='path')return $f;
  272. throw new BaseException('Wrong return type for locate()');
  273. }else $attempted_locations[]=$f;
  274. }
  275. return $attempted_locations;
  276. }
  277. }