[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/includes/ -> class-wp-filesystem-direct.php (source)

   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  }


Generated : Wed Apr 15 08:20:10 2026 Cross-referenced by PHPXref