/src/class/base/File.class.php

https://bitbucket.org/stk2k/charcoalphp2.1 · PHP · 446 lines · 199 code · 54 blank · 193 comment · 25 complexity · bf80f0aa21228a57cd42533691ca1874 MD5 · raw file

  1. <?php
  2. /**
  3. * File Class
  4. *
  5. * PHP version 5
  6. *
  7. * @package class.base
  8. * @author CharcoalPHP Development Team
  9. * @copyright 2008 stk2k, sazysoft
  10. */
  11. class Charcoal_File extends Charcoal_Object
  12. {
  13. private $path;
  14. /**
  15. * Construct object
  16. *
  17. * @param Charcoal_String|string $file_name Name of the file or directory.
  18. * @param Charcoal_File $parent Parent object
  19. */
  20. public function __construct( $file_name, $parent = NULL )
  21. {
  22. // Charcoal_ParamTrait::validateString( 1, $file_name );
  23. // Charcoal_ParamTrait::validateFile( 2, $parent, TRUE );
  24. // assert( $file_name instanceof Charcoal_String || is_string($file_name), 'Paremeter 1 must be string or Charcoal_String' );
  25. // assert( $parent instanceof Charcoal_File || $parent === NULL, 'Paremeter 2 must be NULL or Charcoal_File' );
  26. parent::__construct();
  27. $path = $parent ? $parent->getPath() . '/' . us($file_name) : us($file_name);
  28. $this->path = str_replace('//','/',$path);
  29. }
  30. /**
  31. * Create file object
  32. *
  33. * @param Charcoal_String|string $file_name Name of the file or directory.
  34. *
  35. * @return Charcoal_File
  36. */
  37. public static function create( $file_name )
  38. {
  39. // Charcoal_ParamTrait::validateString( 1, $file_name );
  40. return new Charcoal_File( $file_name );
  41. }
  42. /**
  43. * Returns if the file or directory can be read.
  44. *
  45. * @return bool TRUE if the file or directory can be read.
  46. */
  47. public function canRead()
  48. {
  49. return is_readable( $this->path );
  50. }
  51. /**
  52. * Returns if the file or directory can be written.
  53. *
  54. * @return bool TRUE if the file or directory can be written.
  55. */
  56. public function canWrite()
  57. {
  58. return is_writeable( $this->path );
  59. }
  60. /**
  61. * Returns file size of the file or directory in bytes.
  62. *
  63. * @return int size of the file or directory in bytes.
  64. */
  65. public function getFileSize()
  66. {
  67. return filesize( $this->path );
  68. }
  69. /**
  70. * Delete the file or directory
  71. *
  72. * @param bool $drilldown If TRUE, all of child directory may be removed automatically.
  73. *
  74. * @return bool TRUE if the file or directory is successfully deleted, otherwise FALSE.
  75. */
  76. public function delete( $drilldown = FALSE )
  77. {
  78. if ( is_file( $this->path ) ){
  79. return @unlink( $this->path );
  80. }
  81. if ( $drilldown ){
  82. return self::removeDirectoryRecursive( $this->path );
  83. }
  84. return @rmdir( $this->path );
  85. }
  86. /**
  87. * Delete the file or directory
  88. *
  89. * @param string $path directory path to remove
  90. *
  91. * @return bool TRUE if the file or directory is successfully deleted, otherwise FALSE.
  92. */
  93. private static function removeDirectoryRecursive( $path )
  94. {
  95. if ( !file_exists($path) ){
  96. //if ( CHARCOAL_RUNMODE != 'http' ) echo "file_exists failed: $path" . PHP_EOL;
  97. return FALSE;
  98. }
  99. $handle = opendir("$path");
  100. if ( $handle === FALSE ) {
  101. //if ( CHARCOAL_RUNMODE != 'http' ) echo "opendir failed: $path" . PHP_EOL;
  102. return FALSE;
  103. }
  104. while ( false !== ($item = readdir($handle)) ) {
  105. if ($item != "." && $item != "..") {
  106. if (is_dir("$path/$item")) {
  107. self::removeDirectoryRecursive( "$path/$item" );
  108. } else {
  109. unlink( "$path/$item" );
  110. //if ( CHARCOAL_RUNMODE != 'http' ) echo "unlink: $path/$item ret=$ret" . PHP_EOL;
  111. }
  112. }
  113. }
  114. closedir( $handle );
  115. $ret = @rmdir( $path );
  116. //if ( CHARCOAL_RUNMODE != 'http' ) echo "rmdir: $path ret=$ret" . PHP_EOL;
  117. return $ret;
  118. }
  119. /**
  120. * Virtual path
  121. *
  122. * @return Charcoal_String
  123. */
  124. public function getPath()
  125. {
  126. return $this->path;
  127. }
  128. /**
  129. * Return if the path means file.
  130. *
  131. * @return bool TRUE if path means file, otherwise FALSE.
  132. */
  133. public function isFile()
  134. {
  135. return is_file( $this->path );
  136. }
  137. /**
  138. * Return if the path means directory.
  139. *
  140. * @return bool TRUE if path means directory, otherwise FALSE.
  141. */
  142. public function isDir()
  143. {
  144. return is_dir( $this->path );
  145. }
  146. /**
  147. * Return if the path means directory.
  148. *
  149. * @return bool TRUE if path means directory, otherwise FALSE.
  150. */
  151. public function isDirectory()
  152. {
  153. return is_dir( $this->path );
  154. }
  155. /**
  156. * Return if the file or directory can be read.
  157. *
  158. * @return bool TRUE if the file or directory can be read, otherwise FALSE.
  159. */
  160. public function isReadable()
  161. {
  162. return is_readable( $this->path );
  163. }
  164. /**
  165. * Return if the file or directory can be written.
  166. *
  167. * @return bool TRUE if the file or directory can be written, otherwise FALSE.
  168. */
  169. public function isWriteable()
  170. {
  171. return is_writable( $this->path );
  172. }
  173. /**
  174. * Extension of the file
  175. *
  176. * @return Charcoal_String Extension of the file
  177. */
  178. public function getExtension()
  179. {
  180. return pathinfo( $this->path, PATHINFO_EXTENSION );
  181. }
  182. /**
  183. * returns last modified time(UNIX time)
  184. *
  185. * @return int UNIX time
  186. */
  187. public function getLastModified()
  188. {
  189. return filemtime( $this->path );
  190. }
  191. /**
  192. * Return if the file or directory exists.
  193. *
  194. * @return bool TRUE if the file or directory exists, otherwise FALSE.
  195. */
  196. public function exists()
  197. {
  198. return file_exists( $this->path );
  199. }
  200. /**
  201. * Absolute path of the file or directory
  202. *
  203. * @return Charcoal_String
  204. */
  205. public function getAbsolutePath()
  206. {
  207. return realpath( $this->path );
  208. }
  209. /**
  210. * Name of the file or directory
  211. *
  212. * @param Charcoal_String|string|NULL $suffix file suffix which is ignored.
  213. *
  214. * @return Charcoal_String
  215. */
  216. public function getName( $suffix = NULL )
  217. {
  218. $name = $suffix ? basename( $this->path, $suffix ) : basename( $this->path );
  219. return $name;
  220. }
  221. /**
  222. * Name of parent directory
  223. *
  224. * @return Charcoal_String
  225. */
  226. public function getDirName()
  227. {
  228. return s(dirname( $this->path ));
  229. }
  230. /**
  231. * Child of the file or directory
  232. *
  233. * @param Charcoal_String|string $file_or_dir_name
  234. *
  235. * @return Charcoal_File
  236. */
  237. public function getChild( $file_or_dir_name )
  238. {
  239. return new Charcoal_File( $this->path . DIRECTORY_SEPARATOR . $file_or_dir_name );
  240. }
  241. /**
  242. * Parent of the file or directory
  243. *
  244. * @return Charcoal_File
  245. */
  246. public function getParent()
  247. {
  248. return new Charcoal_File( dirname($this->path) );
  249. }
  250. /**
  251. * Contents of the file or directory
  252. *
  253. * @return Charcoal_File
  254. */
  255. public function getContents()
  256. {
  257. return file_get_contents( $this->path );
  258. }
  259. /**
  260. * get contents of the file as array
  261. *
  262. * @return array file contents
  263. */
  264. public function getContentsAsArray()
  265. {
  266. return file( $this->path );
  267. }
  268. /**
  269. * Save string data as a file
  270. *
  271. * @param Charcoal_String|string $contents
  272. *
  273. * @return Charcoal_File
  274. */
  275. public function putContents( $contents )
  276. {
  277. return file_put_contents( $this->path, $contents, LOCK_EX );
  278. }
  279. /**
  280. * Rename the file or directory
  281. *
  282. * @param Charcoal_File $new_file
  283. */
  284. public function rename( $new_file )
  285. {
  286. $res = rename( $this->path, $new_file->getPath() );
  287. if ( $res === FALSE ){
  288. _throw( new Charcoal_FileRenameException( $this->getPath() ,$new_file->getPath() ) );
  289. }
  290. }
  291. /**
  292. * Create file
  293. *
  294. * @param string $mode File mode
  295. * @param string $contents File contents
  296. *
  297. * @return void
  298. */
  299. public function makeFile( $mode, $contents )
  300. {
  301. // Charcoal_ParamTrait::validateString( 1, $mode );
  302. // Charcoal_ParamTrait::validateString( 2, $contents );
  303. $parent_dir = $this->getParent();
  304. $parent_dir->makeDirectory( $mode );
  305. $path = $this->path;
  306. $ret = file_put_contents( $path, $contents );
  307. if ( $ret === FALSE ){
  308. _throw( new Charcoal_MakeFileException( $path ) );
  309. }
  310. }
  311. /**
  312. * Create empty directory
  313. *
  314. * @param string $mode File mode.If this parameter is set NULL, 0777 will be applied.
  315. *
  316. * @return void
  317. */
  318. public function makeDirectory( $mode = NULL )
  319. {
  320. // Charcoal_ParamTrait::validateInteger( 2, $mode, TRUE );
  321. $path = $this->path;
  322. $mode = $mode ? ui( $mode ) : 0777;
  323. if ( file_exists($path) ){
  324. if ( is_file($path) ){
  325. _throw( new Charcoal_MakeDirectoryException( $path ) );
  326. }
  327. return;
  328. }
  329. $parent_dir = $this->getParent();
  330. if ( !$parent_dir->exists() ){
  331. $parent_dir->makeDirectory( $mode );
  332. }
  333. $res = mkdir( $path, $mode );
  334. if ( $res === FALSE ){
  335. _throw( new Charcoal_MakeDirectoryException( $path ) );
  336. }
  337. }
  338. /**
  339. * Listing up files in directory which this object means
  340. *
  341. * @param Charcoal_IFileFilter $filter Fileter object which implements selection logic. If this parameter is omitted, all files will be selected.
  342. *
  343. * @return array of Charcoal_File File objects which are found by the filter. If it fails, NULL is returned.
  344. */
  345. public function listFiles( $filter = NULL )
  346. {
  347. $path = $this->path;
  348. if ( !file_exists($path) ) return NULL;
  349. if ( !is_readable($path) ) return NULL;
  350. if ( is_file($path) ) return NULL;
  351. $files = array();
  352. $dh = opendir($path);
  353. while( ($file_name = readdir($dh)) !== FALSE ){
  354. if ( $file_name === '.' || $file_name === '..' ){
  355. continue;
  356. }
  357. $file = new Charcoal_File( $file_name, $this );
  358. if ( $filter ){
  359. if ( $filter->accept($file) ){
  360. $files[] = $file;
  361. }
  362. }
  363. else{
  364. $files[] = $file;
  365. }
  366. }
  367. return $files;
  368. }
  369. /**
  370. * Update last modified date of the file
  371. *
  372. * @param integer|Charcoal_Integer $time time value to set
  373. *
  374. * @return boolean TRUE if success, FALSE if failed
  375. */
  376. public function touch( $time = NULL )
  377. {
  378. if ( $time === NULL ){
  379. return touch( $this->path );
  380. }
  381. return touch( $this->path, ui($time) );
  382. }
  383. /**
  384. * String expression of this object
  385. *
  386. * @return string
  387. */
  388. public function toString()
  389. {
  390. return $this->path;
  391. }
  392. }