PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/file.php

https://github.com/Henmania/cakephp
PHP | 542 lines | 370 code | 23 blank | 149 comment | 35 complexity | 83ad21b1710ea5de709be2b1b5586de5 MD5 | raw file
  1. <?php
  2. /**
  3. * Convenience class for reading, writing and appending to files.
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice.
  12. *
  13. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP(tm) Project
  15. * @package cake
  16. * @subpackage cake.cake.libs
  17. * @since CakePHP(tm) v 0.2.9
  18. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  19. */
  20. /**
  21. * Included libraries.
  22. *
  23. */
  24. if (!class_exists('Object')) {
  25. require LIBS . 'object.php';
  26. }
  27. if (!class_exists('Folder')) {
  28. require LIBS . 'folder.php';
  29. }
  30. /**
  31. * Convenience class for reading, writing and appending to files.
  32. *
  33. * @package cake
  34. * @subpackage cake.cake.libs
  35. */
  36. class File extends Object {
  37. /**
  38. * Folder object of the File
  39. *
  40. * @var Folder
  41. * @access public
  42. */
  43. var $Folder = null;
  44. /**
  45. * Filename
  46. *
  47. * @var string
  48. * @access public
  49. */
  50. var $name = null;
  51. /**
  52. * file info
  53. *
  54. * @var string
  55. * @access public
  56. */
  57. var $info = array();
  58. /**
  59. * Holds the file handler resource if the file is opened
  60. *
  61. * @var resource
  62. * @access public
  63. */
  64. var $handle = null;
  65. /**
  66. * enable locking for file reading and writing
  67. *
  68. * @var boolean
  69. * @access public
  70. */
  71. var $lock = null;
  72. /**
  73. * path property
  74. *
  75. * Current file's absolute path
  76. *
  77. * @var mixed null
  78. * @access public
  79. */
  80. var $path = null;
  81. /**
  82. * Constructor
  83. *
  84. * @param string $path Path to file
  85. * @param boolean $create Create file if it does not exist (if true)
  86. * @param integer $mode Mode to apply to the folder holding the file
  87. */
  88. function __construct($path, $create = false, $mode = 0755) {
  89. parent::__construct();
  90. $this->Folder =& new Folder(dirname($path), $create, $mode);
  91. if (!is_dir($path)) {
  92. $this->name = basename($path);
  93. }
  94. $this->pwd();
  95. $create && !$this->exists() && $this->safe($path) && $this->create();
  96. }
  97. /**
  98. * Closes the current file if it is opened
  99. *
  100. */
  101. function __destruct() {
  102. $this->close();
  103. }
  104. /**
  105. * Creates the File.
  106. *
  107. * @return boolean Success
  108. * @access public
  109. */
  110. function create() {
  111. $dir = $this->Folder->pwd();
  112. if (is_dir($dir) && is_writable($dir) && !$this->exists()) {
  113. $old = umask(0);
  114. if (touch($this->path)) {
  115. umask($old);
  116. return true;
  117. }
  118. }
  119. return false;
  120. }
  121. /**
  122. * Opens the current file with a given $mode
  123. *
  124. * @param string $mode A valid 'fopen' mode string (r|w|a ...)
  125. * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
  126. * @return boolean True on success, false on failure
  127. * @access public
  128. */
  129. function open($mode = 'r', $force = false) {
  130. if (!$force && is_resource($this->handle)) {
  131. return true;
  132. }
  133. clearstatcache();
  134. if ($this->exists() === false) {
  135. if ($this->create() === false) {
  136. return false;
  137. }
  138. }
  139. $this->handle = fopen($this->path, $mode);
  140. if (is_resource($this->handle)) {
  141. return true;
  142. }
  143. return false;
  144. }
  145. /**
  146. * Return the contents of this File as a string.
  147. *
  148. * @param string $bytes where to start
  149. * @param string $mode A `fread` compatible mode.
  150. * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
  151. * @return mixed string on success, false on failure
  152. * @access public
  153. */
  154. function read($bytes = false, $mode = 'rb', $force = false) {
  155. if ($bytes === false && $this->lock === null) {
  156. return file_get_contents($this->path);
  157. }
  158. if ($this->open($mode, $force) === false) {
  159. return false;
  160. }
  161. if ($this->lock !== null && flock($this->handle, LOCK_SH) === false) {
  162. return false;
  163. }
  164. if (is_int($bytes)) {
  165. return fread($this->handle, $bytes);
  166. }
  167. $data = '';
  168. while (!feof($this->handle)) {
  169. $data .= fgets($this->handle, 4096);
  170. }
  171. if ($this->lock !== null) {
  172. flock($this->handle, LOCK_UN);
  173. }
  174. if ($bytes === false) {
  175. $this->close();
  176. }
  177. return trim($data);
  178. }
  179. /**
  180. * Sets or gets the offset for the currently opened file.
  181. *
  182. * @param mixed $offset The $offset in bytes to seek. If set to false then the current offset is returned.
  183. * @param integer $seek PHP Constant SEEK_SET | SEEK_CUR | SEEK_END determining what the $offset is relative to
  184. * @return mixed True on success, false on failure (set mode), false on failure or integer offset on success (get mode)
  185. * @access public
  186. */
  187. function offset($offset = false, $seek = SEEK_SET) {
  188. if ($offset === false) {
  189. if (is_resource($this->handle)) {
  190. return ftell($this->handle);
  191. }
  192. } elseif ($this->open() === true) {
  193. return fseek($this->handle, $offset, $seek) === 0;
  194. }
  195. return false;
  196. }
  197. /**
  198. * Prepares a ascii string for writing. Converts line endings to the
  199. * correct terminator for the current platform. If windows "\r\n" will be used
  200. * all other platforms will use "\n"
  201. *
  202. * @param string $data Data to prepare for writing.
  203. * @return string The with converted line endings.
  204. * @access public
  205. */
  206. function prepare($data, $forceWindows = false) {
  207. $lineBreak = "\n";
  208. if (DIRECTORY_SEPARATOR == '\\' || $forceWindows === true) {
  209. $lineBreak = "\r\n";
  210. }
  211. return strtr($data, array("\r\n" => $lineBreak, "\n" => $lineBreak, "\r" => $lineBreak));
  212. }
  213. /**
  214. * Write given data to this File.
  215. *
  216. * @param string $data Data to write to this File.
  217. * @param string $mode Mode of writing. {@link http://php.net/fwrite See fwrite()}.
  218. * @param string $force force the file to open
  219. * @return boolean Success
  220. * @access public
  221. */
  222. function write($data, $mode = 'w', $force = false) {
  223. $success = false;
  224. if ($this->open($mode, $force) === true) {
  225. if ($this->lock !== null) {
  226. if (flock($this->handle, LOCK_EX) === false) {
  227. return false;
  228. }
  229. }
  230. if (fwrite($this->handle, $data) !== false) {
  231. $success = true;
  232. }
  233. if ($this->lock !== null) {
  234. flock($this->handle, LOCK_UN);
  235. }
  236. }
  237. return $success;
  238. }
  239. /**
  240. * Append given data string to this File.
  241. *
  242. * @param string $data Data to write
  243. * @param string $force force the file to open
  244. * @return boolean Success
  245. * @access public
  246. */
  247. function append($data, $force = false) {
  248. return $this->write($data, 'a', $force);
  249. }
  250. /**
  251. * Closes the current file if it is opened.
  252. *
  253. * @return boolean True if closing was successful or file was already closed, otherwise false
  254. * @access public
  255. */
  256. function close() {
  257. if (!is_resource($this->handle)) {
  258. return true;
  259. }
  260. return fclose($this->handle);
  261. }
  262. /**
  263. * Deletes the File.
  264. *
  265. * @return boolean Success
  266. * @access public
  267. */
  268. function delete() {
  269. clearstatcache();
  270. if ($this->exists()) {
  271. return unlink($this->path);
  272. }
  273. return false;
  274. }
  275. /**
  276. * Returns the File info.
  277. *
  278. * @return string The File extension
  279. * @access public
  280. */
  281. function info() {
  282. if ($this->info == null) {
  283. $this->info = pathinfo($this->path);
  284. }
  285. if (!isset($this->info['filename'])) {
  286. $this->info['filename'] = $this->name();
  287. }
  288. return $this->info;
  289. }
  290. /**
  291. * Returns the File extension.
  292. *
  293. * @return string The File extension
  294. * @access public
  295. */
  296. function ext() {
  297. if ($this->info == null) {
  298. $this->info();
  299. }
  300. if (isset($this->info['extension'])) {
  301. return $this->info['extension'];
  302. }
  303. return false;
  304. }
  305. /**
  306. * Returns the File name without extension.
  307. *
  308. * @return string The File name without extension.
  309. * @access public
  310. */
  311. function name() {
  312. if ($this->info == null) {
  313. $this->info();
  314. }
  315. if (isset($this->info['extension'])) {
  316. return basename($this->name, '.'.$this->info['extension']);
  317. } elseif ($this->name) {
  318. return $this->name;
  319. }
  320. return false;
  321. }
  322. /**
  323. * makes filename safe for saving
  324. *
  325. * @param string $name The name of the file to make safe if different from $this->name
  326. * @param strin $ext The name of the extension to make safe if different from $this->ext
  327. * @return string $ext the extension of the file
  328. * @access public
  329. */
  330. function safe($name = null, $ext = null) {
  331. if (!$name) {
  332. $name = $this->name;
  333. }
  334. if (!$ext) {
  335. $ext = $this->ext();
  336. }
  337. return preg_replace( "/(?:[^\w\.-]+)/", "_", basename($name, $ext));
  338. }
  339. /**
  340. * Get md5 Checksum of file with previous check of Filesize
  341. *
  342. * @param mixed $maxsize in MB or true to force
  343. * @return string md5 Checksum {@link http://php.net/md5_file See md5_file()}
  344. * @access public
  345. */
  346. function md5($maxsize = 5) {
  347. if ($maxsize === true) {
  348. return md5_file($this->path);
  349. }
  350. $size = $this->size();
  351. if ($size && $size < ($maxsize * 1024) * 1024) {
  352. return md5_file($this->path);
  353. }
  354. return false;
  355. }
  356. /**
  357. * Returns the full path of the File.
  358. *
  359. * @return string Full path to file
  360. * @access public
  361. */
  362. function pwd() {
  363. if (is_null($this->path)) {
  364. $this->path = $this->Folder->slashTerm($this->Folder->pwd()) . $this->name;
  365. }
  366. return $this->path;
  367. }
  368. /**
  369. * Returns true if the File exists.
  370. *
  371. * @return boolean true if it exists, false otherwise
  372. * @access public
  373. */
  374. function exists() {
  375. return (file_exists($this->path) && is_file($this->path));
  376. }
  377. /**
  378. * Returns the "chmod" (permissions) of the File.
  379. *
  380. * @return string Permissions for the file
  381. * @access public
  382. */
  383. function perms() {
  384. if ($this->exists()) {
  385. return substr(sprintf('%o', fileperms($this->path)), -4);
  386. }
  387. return false;
  388. }
  389. /**
  390. * Returns the Filesize
  391. *
  392. * @return integer size of the file in bytes, or false in case of an error
  393. * @access public
  394. */
  395. function size() {
  396. if ($this->exists()) {
  397. return filesize($this->path);
  398. }
  399. return false;
  400. }
  401. /**
  402. * Returns true if the File is writable.
  403. *
  404. * @return boolean true if its writable, false otherwise
  405. * @access public
  406. */
  407. function writable() {
  408. return is_writable($this->path);
  409. }
  410. /**
  411. * Returns true if the File is executable.
  412. *
  413. * @return boolean true if its executable, false otherwise
  414. * @access public
  415. */
  416. function executable() {
  417. return is_executable($this->path);
  418. }
  419. /**
  420. * Returns true if the File is readable.
  421. *
  422. * @return boolean true if file is readable, false otherwise
  423. * @access public
  424. */
  425. function readable() {
  426. return is_readable($this->path);
  427. }
  428. /**
  429. * Returns the File's owner.
  430. *
  431. * @return integer the Fileowner
  432. * @access public
  433. */
  434. function owner() {
  435. if ($this->exists()) {
  436. return fileowner($this->path);
  437. }
  438. return false;
  439. }
  440. /**
  441. * Returns the File's group.
  442. *
  443. * @return integer the Filegroup
  444. * @access public
  445. */
  446. function group() {
  447. if ($this->exists()) {
  448. return filegroup($this->path);
  449. }
  450. return false;
  451. }
  452. /**
  453. * Returns last access time.
  454. *
  455. * @return integer timestamp Timestamp of last access time
  456. * @access public
  457. */
  458. function lastAccess() {
  459. if ($this->exists()) {
  460. return fileatime($this->path);
  461. }
  462. return false;
  463. }
  464. /**
  465. * Returns last modified time.
  466. *
  467. * @return integer timestamp Timestamp of last modification
  468. * @access public
  469. */
  470. function lastChange() {
  471. if ($this->exists()) {
  472. return filemtime($this->path);
  473. }
  474. return false;
  475. }
  476. /**
  477. * Returns the current folder.
  478. *
  479. * @return Folder Current folder
  480. * @access public
  481. */
  482. function &Folder() {
  483. return $this->Folder;
  484. }
  485. /**
  486. * Copy the File to $dest
  487. *
  488. * @param string $dest destination for the copy
  489. * @param boolean $overwrite Overwrite $dest if exists
  490. * @return boolean Succes
  491. * @access public
  492. */
  493. function copy($dest, $overwrite = true) {
  494. if (!$this->exists() || is_file($dest) && !$overwrite) {
  495. return false;
  496. }
  497. return copy($this->path, $dest);
  498. }
  499. }