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