| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * WordPress Direct Filesystem. 4 * 5 * @package WordPress 6 * @subpackage Filesystem 7 */ 8 9 /** 10 * WordPress Filesystem Class for direct PHP file and folder manipulation. 11 * 12 * @since 2.5.0 13 * 14 * @see WP_Filesystem_Base 15 */ 16 class WP_Filesystem_Direct extends WP_Filesystem_Base { 17 18 /** 19 * Constructor. 20 * 21 * @since 2.5.0 22 * 23 * @param mixed $arg Not used. 24 */ 25 public function __construct( $arg ) { 26 $this->method = 'direct'; 27 $this->errors = new WP_Error(); 28 } 29 30 /** 31 * Reads entire file into a string. 32 * 33 * @since 2.5.0 34 * 35 * @param string $file Name of the file to read. 36 * @return string|false Read data on success, false on failure. 37 */ 38 public function get_contents( $file ) { 39 return @file_get_contents( $file ); 40 } 41 42 /** 43 * Reads entire file into an array. 44 * 45 * @since 2.5.0 46 * 47 * @param string $file Path to the file. 48 * @return array|false File contents in an array on success, false on failure. 49 */ 50 public function get_contents_array( $file ) { 51 return @file( $file ); 52 } 53 54 /** 55 * Writes a string to a file. 56 * 57 * @since 2.5.0 58 * 59 * @param string $file Remote path to the file where to write the data. 60 * @param string $contents The data to write. 61 * @param int|false $mode Optional. The file permissions as octal number, usually 0644. 62 * Default false. 63 * @return bool True on success, false on failure. 64 */ 65 public function put_contents( $file, $contents, $mode = false ) { 66 $fp = @fopen( $file, 'wb' ); 67 68 if ( ! $fp ) { 69 return false; 70 } 71 72 mbstring_binary_safe_encoding(); 73 74 $data_length = strlen( $contents ); 75 76 $bytes_written = fwrite( $fp, $contents ); 77 78 reset_mbstring_encoding(); 79 80 fclose( $fp ); 81 82 if ( $data_length !== $bytes_written ) { 83 return false; 84 } 85 86 $this->chmod( $file, $mode ); 87 88 return true; 89 } 90 91 /** 92 * Gets the current working directory. 93 * 94 * @since 2.5.0 95 * 96 * @return string|false The current working directory on success, false on failure. 97 */ 98 public function cwd() { 99 return getcwd(); 100 } 101 102 /** 103 * Changes current directory. 104 * 105 * @since 2.5.0 106 * 107 * @param string $dir The new current directory. 108 * @return bool True on success, false on failure. 109 */ 110 public function chdir( $dir ) { 111 return @chdir( $dir ); 112 } 113 114 /** 115 * Changes the file group. 116 * 117 * @since 2.5.0 118 * 119 * @param string $file Path to the file. 120 * @param string|int $group A group name or number. 121 * @param bool $recursive Optional. If set to true, changes file group recursively. 122 * Default false. 123 * @return bool True on success, false on failure. 124 */ 125 public function chgrp( $file, $group, $recursive = false ) { 126 if ( ! $this->exists( $file ) ) { 127 return false; 128 } 129 130 if ( ! $recursive ) { 131 return chgrp( $file, $group ); 132 } 133 134 if ( ! $this->is_dir( $file ) ) { 135 return chgrp( $file, $group ); 136 } 137 138 // Is a directory, and we want recursive. 139 $file = trailingslashit( $file ); 140 $filelist = $this->dirlist( $file ); 141 142 foreach ( $filelist as $filename ) { 143 $this->chgrp( $file . $filename, $group, $recursive ); 144 } 145 146 return true; 147 } 148 149 /** 150 * Changes filesystem permissions. 151 * 152 * @since 2.5.0 153 * 154 * @param string $file Path to the file. 155 * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, 156 * 0755 for directories. Default false. 157 * @param bool $recursive Optional. If set to true, changes file permissions recursively. 158 * Default false. 159 * @return bool True on success, false on failure. 160 */ 161 public function chmod( $file, $mode = false, $recursive = false ) { 162 if ( ! $mode ) { 163 if ( $this->is_file( $file ) ) { 164 $mode = FS_CHMOD_FILE; 165 } elseif ( $this->is_dir( $file ) ) { 166 $mode = FS_CHMOD_DIR; 167 } else { 168 return false; 169 } 170 } 171 172 if ( ! $recursive || ! $this->is_dir( $file ) ) { 173 $current_mode = fileperms( $file ) & 0777 | 0644; 174 175 /* 176 * fileperms() populates the stat cache, so have to clear it 177 * to maintain parity with the previous behavior. 178 */ 179 clearstatcache( true, $file ); 180 181 /* 182 * Avoid calling chmod() if the requested mode is already set, 183 * to prevent throwing a warning when we aren't the owner. 184 */ 185 if ( $current_mode === $mode ) { 186 return true; 187 } 188 189 return chmod( $file, $mode ); 190 } 191 192 // Is a directory, and we want recursive. 193 $file = trailingslashit( $file ); 194 $filelist = $this->dirlist( $file ); 195 196 foreach ( (array) $filelist as $filename => $filemeta ) { 197 $this->chmod( $file . $filename, $mode, $recursive ); 198 } 199 200 return true; 201 } 202 203 /** 204 * Changes the owner of a file or directory. 205 * 206 * @since 2.5.0 207 * 208 * @param string $file Path to the file or directory. 209 * @param string|int $owner A user name or number. 210 * @param bool $recursive Optional. If set to true, changes file owner recursively. 211 * Default false. 212 * @return bool True on success, false on failure. 213 */ 214 public function chown( $file, $owner, $recursive = false ) { 215 if ( ! $this->exists( $file ) ) { 216 return false; 217 } 218 219 if ( ! $recursive ) { 220 return chown( $file, $owner ); 221 } 222 223 if ( ! $this->is_dir( $file ) ) { 224 return chown( $file, $owner ); 225 } 226 227 // Is a directory, and we want recursive. 228 $filelist = $this->dirlist( $file ); 229 230 foreach ( $filelist as $filename ) { 231 $this->chown( $file . '/' . $filename, $owner, $recursive ); 232 } 233 234 return true; 235 } 236 237 /** 238 * Gets the file owner. 239 * 240 * @since 2.5.0 241 * 242 * @param string $file Path to the file. 243 * @return string|false Username of the owner on success, false on failure. 244 */ 245 public function owner( $file ) { 246 $owneruid = @fileowner( $file ); 247 248 if ( ! $owneruid ) { 249 return false; 250 } 251 252 if ( ! function_exists( 'posix_getpwuid' ) ) { 253 return $owneruid; 254 } 255 256 $ownerarray = posix_getpwuid( $owneruid ); 257 258 if ( ! $ownerarray ) { 259 return false; 260 } 261 262 return $ownerarray['name']; 263 } 264 265 /** 266 * Gets the permissions of the specified file or filepath in their octal format. 267 * 268 * @since 2.5.0 269 * 270 * @param string $file Path to the file. 271 * @return string Mode of the file (the last 3 digits), or the string "0" on failure. 272 */ 273 public function getchmod( $file ) { 274 $perms = @fileperms( $file ); 275 if ( false === $perms ) { 276 return '0'; 277 } 278 279 return substr( decoct( $perms ), -3 ); 280 } 281 282 /** 283 * Gets the file's group. 284 * 285 * @since 2.5.0 286 * 287 * @param string $file Path to the file. 288 * @return string|false The group on success, false on failure. 289 */ 290 public function group( $file ) { 291 $gid = @filegroup( $file ); 292 293 if ( ! $gid ) { 294 return false; 295 } 296 297 if ( ! function_exists( 'posix_getgrgid' ) ) { 298 return $gid; 299 } 300 301 $grouparray = posix_getgrgid( $gid ); 302 303 if ( ! $grouparray ) { 304 return false; 305 } 306 307 return $grouparray['name']; 308 } 309 310 /** 311 * Copies a file. 312 * 313 * @since 2.5.0 314 * 315 * @param string $source Path to the source file. 316 * @param string $destination Path to the destination file. 317 * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. 318 * Default false. 319 * @param int|false $mode Optional. The permissions as octal number, usually 0644 for files, 320 * 0755 for dirs. Default false. 321 * @return bool True on success, false on failure. 322 */ 323 public function copy( $source, $destination, $overwrite = false, $mode = false ) { 324 if ( ! $overwrite && $this->exists( $destination ) ) { 325 return false; 326 } 327 328 $rtval = copy( $source, $destination ); 329 330 if ( $mode ) { 331 $this->chmod( $destination, $mode ); 332 } 333 334 return $rtval; 335 } 336 337 /** 338 * Moves a file or directory. 339 * 340 * After moving files or directories, OPcache will need to be invalidated. 341 * 342 * If moving a directory fails, `copy_dir()` can be used for a recursive copy. 343 * 344 * Use `move_dir()` for moving directories with OPcache invalidation and a 345 * fallback to `copy_dir()`. 346 * 347 * @since 2.5.0 348 * 349 * @param string $source Path to the source file. 350 * @param string $destination Path to the destination file. 351 * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. 352 * Default false. 353 * @return bool True on success, false on failure. 354 */ 355 public function move( $source, $destination, $overwrite = false ) { 356 if ( ! $overwrite && $this->exists( $destination ) ) { 357 return false; 358 } 359 360 if ( $overwrite && $this->exists( $destination ) && ! $this->delete( $destination, true ) ) { 361 // Can't overwrite if the destination couldn't be deleted. 362 return false; 363 } 364 365 // Try using rename first. if that fails (for example, source is read only) try copy. 366 if ( @rename( $source, $destination ) ) { 367 return true; 368 } 369 370 // Backward compatibility: Only fall back to `::copy()` for single files. 371 if ( $this->is_file( $source ) && $this->copy( $source, $destination, $overwrite ) && $this->exists( $destination ) ) { 372 $this->delete( $source ); 373 374 return true; 375 } else { 376 return false; 377 } 378 } 379 380 /** 381 * Deletes a file or directory. 382 * 383 * @since 2.5.0 384 * 385 * @param string $file Path to the file or directory. 386 * @param bool $recursive Optional. If set to true, deletes files and folders recursively. 387 * Default false. 388 * @param string|false $type Type of resource. 'f' for file, 'd' for directory. 389 * Default false. 390 * @return bool True on success, false on failure. 391 */ 392 public function delete( $file, $recursive = false, $type = false ) { 393 if ( empty( $file ) ) { 394 // Some filesystems report this as /, which can cause non-expected recursive deletion of all files in the filesystem. 395 return false; 396 } 397 398 $file = str_replace( '\\', '/', $file ); // For Win32, occasional problems deleting files otherwise. 399 400 if ( 'f' === $type || $this->is_file( $file ) ) { 401 return @unlink( $file ); 402 } 403 404 if ( ! $recursive && $this->is_dir( $file ) ) { 405 return @rmdir( $file ); 406 } 407 408 // At this point it's a folder, and we're in recursive mode. 409 $file = trailingslashit( $file ); 410 $filelist = $this->dirlist( $file, true ); 411 412 $retval = true; 413 414 if ( is_array( $filelist ) ) { 415 foreach ( $filelist as $filename => $fileinfo ) { 416 if ( ! $this->delete( $file . $filename, $recursive, $fileinfo['type'] ) ) { 417 $retval = false; 418 } 419 } 420 } 421 422 if ( file_exists( $file ) && ! @rmdir( $file ) ) { 423 $retval = false; 424 } 425 426 return $retval; 427 } 428 429 /** 430 * Checks if a file or directory exists. 431 * 432 * @since 2.5.0 433 * 434 * @param string $path Path to file or directory. 435 * @return bool Whether $path exists or not. 436 */ 437 public function exists( $path ) { 438 return @file_exists( $path ); 439 } 440 441 /** 442 * Checks if resource is a file. 443 * 444 * @since 2.5.0 445 * 446 * @param string $file File path. 447 * @return bool Whether $file is a file. 448 */ 449 public function is_file( $file ) { 450 return @is_file( $file ); 451 } 452 453 /** 454 * Checks if resource is a directory. 455 * 456 * @since 2.5.0 457 * 458 * @param string $path Directory path. 459 * @return bool Whether $path is a directory. 460 */ 461 public function is_dir( $path ) { 462 return @is_dir( $path ); 463 } 464 465 /** 466 * Checks if a file is readable. 467 * 468 * @since 2.5.0 469 * 470 * @param string $file Path to file. 471 * @return bool Whether $file is readable. 472 */ 473 public function is_readable( $file ) { 474 return @is_readable( $file ); 475 } 476 477 /** 478 * Checks if a file or directory is writable. 479 * 480 * @since 2.5.0 481 * 482 * @param string $path Path to file or directory. 483 * @return bool Whether $path is writable. 484 */ 485 public function is_writable( $path ) { 486 return @is_writable( $path ); 487 } 488 489 /** 490 * Gets the file's last access time. 491 * 492 * @since 2.5.0 493 * 494 * @param string $file Path to file. 495 * @return int|false Unix timestamp representing last access time, false on failure. 496 */ 497 public function atime( $file ) { 498 return @fileatime( $file ); 499 } 500 501 /** 502 * Gets the file modification time. 503 * 504 * @since 2.5.0 505 * 506 * @param string $file Path to file. 507 * @return int|false Unix timestamp representing modification time, false on failure. 508 */ 509 public function mtime( $file ) { 510 return @filemtime( $file ); 511 } 512 513 /** 514 * Gets the file size (in bytes). 515 * 516 * @since 2.5.0 517 * 518 * @param string $file Path to file. 519 * @return int|false Size of the file in bytes on success, false on failure. 520 */ 521 public function size( $file ) { 522 return @filesize( $file ); 523 } 524 525 /** 526 * Sets the access and modification times of a file. 527 * 528 * Note: If $file doesn't exist, it will be created. 529 * 530 * @since 2.5.0 531 * 532 * @param string $file Path to file. 533 * @param int $time Optional. Modified time to set for file. 534 * Default 0. 535 * @param int $atime Optional. Access time to set for file. 536 * Default 0. 537 * @return bool True on success, false on failure. 538 */ 539 public function touch( $file, $time = 0, $atime = 0 ) { 540 if ( 0 === $time ) { 541 $time = time(); 542 } 543 544 if ( 0 === $atime ) { 545 $atime = time(); 546 } 547 548 return touch( $file, $time, $atime ); 549 } 550 551 /** 552 * Creates a directory. 553 * 554 * @since 2.5.0 555 * 556 * @param string $path Path for new directory. 557 * @param int|false $chmod Optional. The permissions as octal number (or false to skip chmod). 558 * Default false. 559 * @param string|int|false $chown Optional. A user name or number (or false to skip chown). 560 * Default false. 561 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp). 562 * Default false. 563 * @return bool True on success, false on failure. 564 */ 565 public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) { 566 // Safe mode fails with a trailing slash under certain PHP versions. 567 $path = untrailingslashit( $path ); 568 569 if ( empty( $path ) ) { 570 return false; 571 } 572 573 if ( ! $chmod ) { 574 $chmod = FS_CHMOD_DIR; 575 } 576 577 if ( ! @mkdir( $path ) ) { 578 return false; 579 } 580 581 $this->chmod( $path, $chmod ); 582 583 if ( $chown ) { 584 $this->chown( $path, $chown ); 585 } 586 587 if ( $chgrp ) { 588 $this->chgrp( $path, $chgrp ); 589 } 590 591 return true; 592 } 593 594 /** 595 * Deletes a directory. 596 * 597 * @since 2.5.0 598 * 599 * @param string $path Path to directory. 600 * @param bool $recursive Optional. Whether to recursively remove files/directories. 601 * Default false. 602 * @return bool True on success, false on failure. 603 */ 604 public function rmdir( $path, $recursive = false ) { 605 return $this->delete( $path, $recursive ); 606 } 607 608 /** 609 * Gets details for files in a directory or a specific file. 610 * 611 * @since 2.5.0 612 * 613 * @param string $path Path to directory or file. 614 * @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files. 615 * Default true. 616 * @param bool $recursive Optional. Whether to recursively include file details in nested directories. 617 * Default false. 618 * @return array|false { 619 * Array of arrays containing file information. False if unable to list directory contents. 620 * 621 * @type array ...$0 { 622 * Array of file information. Note that some elements may not be available on all filesystems. 623 * 624 * @type string $name Name of the file or directory. 625 * @type string $perms *nix representation of permissions. 626 * @type string $permsn Octal representation of permissions. 627 * @type false $number File number. Always false in this context. 628 * @type string|false $owner Owner name or ID, or false if not available. 629 * @type string|false $group File permissions group, or false if not available. 630 * @type int|string|false $size Size of file in bytes. May be a numeric string. 631 * False if not available. 632 * @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string. 633 * False if not available. 634 * @type string|false $lastmod Last modified month (3 letters) and day (without leading 0), or 635 * false if not available. 636 * @type string|false $time Last modified time, or false if not available. 637 * @type string $type Type of resource. 'f' for file, 'd' for directory, 'l' for link. 638 * @type array|false $files If a directory and `$recursive` is true, contains another array of 639 * files. False if unable to list directory contents. 640 * } 641 * } 642 */ 643 public function dirlist( $path, $include_hidden = true, $recursive = false ) { 644 if ( $this->is_file( $path ) ) { 645 $limit_file = basename( $path ); 646 $path = dirname( $path ); 647 } else { 648 $limit_file = false; 649 } 650 651 if ( ! $this->is_dir( $path ) || ! $this->is_readable( $path ) ) { 652 return false; 653 } 654 655 $dir = dir( $path ); 656 657 if ( ! $dir ) { 658 return false; 659 } 660 661 $path = trailingslashit( $path ); 662 $ret = array(); 663 664 while ( false !== ( $entry = $dir->read() ) ) { 665 $struc = array(); 666 $struc['name'] = $entry; 667 668 if ( '.' === $struc['name'] || '..' === $struc['name'] ) { 669 continue; 670 } 671 672 if ( ! $include_hidden && '.' === $struc['name'][0] ) { 673 continue; 674 } 675 676 if ( $limit_file && $struc['name'] !== $limit_file ) { 677 continue; 678 } 679 680 $struc['perms'] = $this->gethchmod( $path . $entry ); 681 $struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] ); 682 $struc['number'] = false; 683 $struc['owner'] = $this->owner( $path . $entry ); 684 $struc['group'] = $this->group( $path . $entry ); 685 $struc['size'] = $this->size( $path . $entry ); 686 $struc['lastmodunix'] = $this->mtime( $path . $entry ); 687 $struc['lastmod'] = gmdate( 'M j', $struc['lastmodunix'] ); 688 $struc['time'] = gmdate( 'h:i:s', $struc['lastmodunix'] ); 689 $struc['type'] = $this->is_dir( $path . $entry ) ? 'd' : 'f'; 690 691 if ( 'd' === $struc['type'] ) { 692 if ( $recursive ) { 693 $struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive ); 694 } else { 695 $struc['files'] = array(); 696 } 697 } 698 699 $ret[ $struc['name'] ] = $struc; 700 } 701 702 $dir->close(); 703 unset( $dir ); 704 705 return $ret; 706 } 707 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Wed Apr 15 08:20:10 2026 | Cross-referenced by PHPXref |