[ 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              return chmod( $file, $mode );
 174          }
 175  
 176          // Is a directory, and we want recursive.
 177          $file     = trailingslashit( $file );
 178          $filelist = $this->dirlist( $file );
 179  
 180          foreach ( (array) $filelist as $filename => $filemeta ) {
 181              $this->chmod( $file . $filename, $mode, $recursive );
 182          }
 183  
 184          return true;
 185      }
 186  
 187      /**
 188       * Changes the owner of a file or directory.
 189       *
 190       * @since 2.5.0
 191       *
 192       * @param string     $file      Path to the file or directory.
 193       * @param string|int $owner     A user name or number.
 194       * @param bool       $recursive Optional. If set to true, changes file owner recursively.
 195       *                              Default false.
 196       * @return bool True on success, false on failure.
 197       */
 198  	public function chown( $file, $owner, $recursive = false ) {
 199          if ( ! $this->exists( $file ) ) {
 200              return false;
 201          }
 202  
 203          if ( ! $recursive ) {
 204              return chown( $file, $owner );
 205          }
 206  
 207          if ( ! $this->is_dir( $file ) ) {
 208              return chown( $file, $owner );
 209          }
 210  
 211          // Is a directory, and we want recursive.
 212          $filelist = $this->dirlist( $file );
 213  
 214          foreach ( $filelist as $filename ) {
 215              $this->chown( $file . '/' . $filename, $owner, $recursive );
 216          }
 217  
 218          return true;
 219      }
 220  
 221      /**
 222       * Gets the file owner.
 223       *
 224       * @since 2.5.0
 225       *
 226       * @param string $file Path to the file.
 227       * @return string|false Username of the owner on success, false on failure.
 228       */
 229  	public function owner( $file ) {
 230          $owneruid = @fileowner( $file );
 231  
 232          if ( ! $owneruid ) {
 233              return false;
 234          }
 235  
 236          if ( ! function_exists( 'posix_getpwuid' ) ) {
 237              return $owneruid;
 238          }
 239  
 240          $ownerarray = posix_getpwuid( $owneruid );
 241  
 242          if ( ! $ownerarray ) {
 243              return false;
 244          }
 245  
 246          return $ownerarray['name'];
 247      }
 248  
 249      /**
 250       * Gets the permissions of the specified file or filepath in their octal format.
 251       *
 252       * @since 2.5.0
 253       *
 254       * @param string $file Path to the file.
 255       * @return string Mode of the file (the last 3 digits), or the string "0" on failure.
 256       */
 257  	public function getchmod( $file ) {
 258          $perms = @fileperms( $file );
 259          if ( false === $perms ) {
 260              return '0';
 261          }
 262  
 263          return substr( decoct( $perms ), -3 );
 264      }
 265  
 266      /**
 267       * Gets the file's group.
 268       *
 269       * @since 2.5.0
 270       *
 271       * @param string $file Path to the file.
 272       * @return string|false The group on success, false on failure.
 273       */
 274  	public function group( $file ) {
 275          $gid = @filegroup( $file );
 276  
 277          if ( ! $gid ) {
 278              return false;
 279          }
 280  
 281          if ( ! function_exists( 'posix_getgrgid' ) ) {
 282              return $gid;
 283          }
 284  
 285          $grouparray = posix_getgrgid( $gid );
 286  
 287          if ( ! $grouparray ) {
 288              return false;
 289          }
 290  
 291          return $grouparray['name'];
 292      }
 293  
 294      /**
 295       * Copies a file.
 296       *
 297       * @since 2.5.0
 298       *
 299       * @param string    $source      Path to the source file.
 300       * @param string    $destination Path to the destination file.
 301       * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
 302       *                               Default false.
 303       * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
 304       *                               0755 for dirs. Default false.
 305       * @return bool True on success, false on failure.
 306       */
 307  	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
 308          if ( ! $overwrite && $this->exists( $destination ) ) {
 309              return false;
 310          }
 311  
 312          $rtval = copy( $source, $destination );
 313  
 314          if ( $mode ) {
 315              $this->chmod( $destination, $mode );
 316          }
 317  
 318          return $rtval;
 319      }
 320  
 321      /**
 322       * Moves a file or directory.
 323       *
 324       * After moving files or directories, OPcache will need to be invalidated.
 325       *
 326       * If moving a directory fails, `copy_dir()` can be used for a recursive copy.
 327       *
 328       * Use `move_dir()` for moving directories with OPcache invalidation and a
 329       * fallback to `copy_dir()`.
 330       *
 331       * @since 2.5.0
 332       *
 333       * @param string $source      Path to the source file.
 334       * @param string $destination Path to the destination file.
 335       * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
 336       *                            Default false.
 337       * @return bool True on success, false on failure.
 338       */
 339  	public function move( $source, $destination, $overwrite = false ) {
 340          if ( ! $overwrite && $this->exists( $destination ) ) {
 341              return false;
 342          }
 343  
 344          if ( $overwrite && $this->exists( $destination ) && ! $this->delete( $destination, true ) ) {
 345              // Can't overwrite if the destination couldn't be deleted.
 346              return false;
 347          }
 348  
 349          // Try using rename first. if that fails (for example, source is read only) try copy.
 350          if ( @rename( $source, $destination ) ) {
 351              return true;
 352          }
 353  
 354          // Backward compatibility: Only fall back to `::copy()` for single files.
 355          if ( $this->is_file( $source ) && $this->copy( $source, $destination, $overwrite ) && $this->exists( $destination ) ) {
 356              $this->delete( $source );
 357  
 358              return true;
 359          } else {
 360              return false;
 361          }
 362      }
 363  
 364      /**
 365       * Deletes a file or directory.
 366       *
 367       * @since 2.5.0
 368       *
 369       * @param string       $file      Path to the file or directory.
 370       * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
 371       *                                Default false.
 372       * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
 373       *                                Default false.
 374       * @return bool True on success, false on failure.
 375       */
 376  	public function delete( $file, $recursive = false, $type = false ) {
 377          if ( empty( $file ) ) {
 378              // Some filesystems report this as /, which can cause non-expected recursive deletion of all files in the filesystem.
 379              return false;
 380          }
 381  
 382          $file = str_replace( '\\', '/', $file ); // For Win32, occasional problems deleting files otherwise.
 383  
 384          if ( 'f' === $type || $this->is_file( $file ) ) {
 385              return @unlink( $file );
 386          }
 387  
 388          if ( ! $recursive && $this->is_dir( $file ) ) {
 389              return @rmdir( $file );
 390          }
 391  
 392          // At this point it's a folder, and we're in recursive mode.
 393          $file     = trailingslashit( $file );
 394          $filelist = $this->dirlist( $file, true );
 395  
 396          $retval = true;
 397  
 398          if ( is_array( $filelist ) ) {
 399              foreach ( $filelist as $filename => $fileinfo ) {
 400                  if ( ! $this->delete( $file . $filename, $recursive, $fileinfo['type'] ) ) {
 401                      $retval = false;
 402                  }
 403              }
 404          }
 405  
 406          if ( file_exists( $file ) && ! @rmdir( $file ) ) {
 407              $retval = false;
 408          }
 409  
 410          return $retval;
 411      }
 412  
 413      /**
 414       * Checks if a file or directory exists.
 415       *
 416       * @since 2.5.0
 417       *
 418       * @param string $path Path to file or directory.
 419       * @return bool Whether $path exists or not.
 420       */
 421  	public function exists( $path ) {
 422          return @file_exists( $path );
 423      }
 424  
 425      /**
 426       * Checks if resource is a file.
 427       *
 428       * @since 2.5.0
 429       *
 430       * @param string $file File path.
 431       * @return bool Whether $file is a file.
 432       */
 433  	public function is_file( $file ) {
 434          return @is_file( $file );
 435      }
 436  
 437      /**
 438       * Checks if resource is a directory.
 439       *
 440       * @since 2.5.0
 441       *
 442       * @param string $path Directory path.
 443       * @return bool Whether $path is a directory.
 444       */
 445  	public function is_dir( $path ) {
 446          return @is_dir( $path );
 447      }
 448  
 449      /**
 450       * Checks if a file is readable.
 451       *
 452       * @since 2.5.0
 453       *
 454       * @param string $file Path to file.
 455       * @return bool Whether $file is readable.
 456       */
 457  	public function is_readable( $file ) {
 458          return @is_readable( $file );
 459      }
 460  
 461      /**
 462       * Checks if a file or directory is writable.
 463       *
 464       * @since 2.5.0
 465       *
 466       * @param string $path Path to file or directory.
 467       * @return bool Whether $path is writable.
 468       */
 469  	public function is_writable( $path ) {
 470          return @is_writable( $path );
 471      }
 472  
 473      /**
 474       * Gets the file's last access time.
 475       *
 476       * @since 2.5.0
 477       *
 478       * @param string $file Path to file.
 479       * @return int|false Unix timestamp representing last access time, false on failure.
 480       */
 481  	public function atime( $file ) {
 482          return @fileatime( $file );
 483      }
 484  
 485      /**
 486       * Gets the file modification time.
 487       *
 488       * @since 2.5.0
 489       *
 490       * @param string $file Path to file.
 491       * @return int|false Unix timestamp representing modification time, false on failure.
 492       */
 493  	public function mtime( $file ) {
 494          return @filemtime( $file );
 495      }
 496  
 497      /**
 498       * Gets the file size (in bytes).
 499       *
 500       * @since 2.5.0
 501       *
 502       * @param string $file Path to file.
 503       * @return int|false Size of the file in bytes on success, false on failure.
 504       */
 505  	public function size( $file ) {
 506          return @filesize( $file );
 507      }
 508  
 509      /**
 510       * Sets the access and modification times of a file.
 511       *
 512       * Note: If $file doesn't exist, it will be created.
 513       *
 514       * @since 2.5.0
 515       *
 516       * @param string $file  Path to file.
 517       * @param int    $time  Optional. Modified time to set for file.
 518       *                      Default 0.
 519       * @param int    $atime Optional. Access time to set for file.
 520       *                      Default 0.
 521       * @return bool True on success, false on failure.
 522       */
 523  	public function touch( $file, $time = 0, $atime = 0 ) {
 524          if ( 0 === $time ) {
 525              $time = time();
 526          }
 527  
 528          if ( 0 === $atime ) {
 529              $atime = time();
 530          }
 531  
 532          return touch( $file, $time, $atime );
 533      }
 534  
 535      /**
 536       * Creates a directory.
 537       *
 538       * @since 2.5.0
 539       *
 540       * @param string           $path  Path for new directory.
 541       * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
 542       *                                Default false.
 543       * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
 544       *                                Default false.
 545       * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
 546       *                                Default false.
 547       * @return bool True on success, false on failure.
 548       */
 549  	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
 550          // Safe mode fails with a trailing slash under certain PHP versions.
 551          $path = untrailingslashit( $path );
 552  
 553          if ( empty( $path ) ) {
 554              return false;
 555          }
 556  
 557          if ( ! $chmod ) {
 558              $chmod = FS_CHMOD_DIR;
 559          }
 560  
 561          if ( ! @mkdir( $path ) ) {
 562              return false;
 563          }
 564  
 565          $this->chmod( $path, $chmod );
 566  
 567          if ( $chown ) {
 568              $this->chown( $path, $chown );
 569          }
 570  
 571          if ( $chgrp ) {
 572              $this->chgrp( $path, $chgrp );
 573          }
 574  
 575          return true;
 576      }
 577  
 578      /**
 579       * Deletes a directory.
 580       *
 581       * @since 2.5.0
 582       *
 583       * @param string $path      Path to directory.
 584       * @param bool   $recursive Optional. Whether to recursively remove files/directories.
 585       *                          Default false.
 586       * @return bool True on success, false on failure.
 587       */
 588  	public function rmdir( $path, $recursive = false ) {
 589          return $this->delete( $path, $recursive );
 590      }
 591  
 592      /**
 593       * Gets details for files in a directory or a specific file.
 594       *
 595       * @since 2.5.0
 596       *
 597       * @param string $path           Path to directory or file.
 598       * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
 599       *                               Default true.
 600       * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
 601       *                               Default false.
 602       * @return array|false {
 603       *     Array of arrays containing file information. False if unable to list directory contents.
 604       *
 605       *     @type array ...$0 {
 606       *         Array of file information. Note that some elements may not be available on all filesystems.
 607       *
 608       *         @type string           $name        Name of the file or directory.
 609       *         @type string           $perms       *nix representation of permissions.
 610       *         @type string           $permsn      Octal representation of permissions.
 611       *         @type false            $number      File number. Always false in this context.
 612       *         @type string|false     $owner       Owner name or ID, or false if not available.
 613       *         @type string|false     $group       File permissions group, or false if not available.
 614       *         @type int|string|false $size        Size of file in bytes. May be a numeric string.
 615       *                                             False if not available.
 616       *         @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
 617       *                                             False if not available.
 618       *         @type string|false     $lastmod     Last modified month (3 letters) and day (without leading 0), or
 619       *                                             false if not available.
 620       *         @type string|false     $time        Last modified time, or false if not available.
 621       *         @type string           $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
 622       *         @type array|false      $files       If a directory and `$recursive` is true, contains another array of
 623       *                                             files. False if unable to list directory contents.
 624       *     }
 625       * }
 626       */
 627  	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
 628          if ( $this->is_file( $path ) ) {
 629              $limit_file = basename( $path );
 630              $path       = dirname( $path );
 631          } else {
 632              $limit_file = false;
 633          }
 634  
 635          if ( ! $this->is_dir( $path ) || ! $this->is_readable( $path ) ) {
 636              return false;
 637          }
 638  
 639          $dir = dir( $path );
 640  
 641          if ( ! $dir ) {
 642              return false;
 643          }
 644  
 645          $path = trailingslashit( $path );
 646          $ret  = array();
 647  
 648          while ( false !== ( $entry = $dir->read() ) ) {
 649              $struc         = array();
 650              $struc['name'] = $entry;
 651  
 652              if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
 653                  continue;
 654              }
 655  
 656              if ( ! $include_hidden && '.' === $struc['name'][0] ) {
 657                  continue;
 658              }
 659  
 660              if ( $limit_file && $struc['name'] !== $limit_file ) {
 661                  continue;
 662              }
 663  
 664              $struc['perms']       = $this->gethchmod( $path . $entry );
 665              $struc['permsn']      = $this->getnumchmodfromh( $struc['perms'] );
 666              $struc['number']      = false;
 667              $struc['owner']       = $this->owner( $path . $entry );
 668              $struc['group']       = $this->group( $path . $entry );
 669              $struc['size']        = $this->size( $path . $entry );
 670              $struc['lastmodunix'] = $this->mtime( $path . $entry );
 671              $struc['lastmod']     = gmdate( 'M j', $struc['lastmodunix'] );
 672              $struc['time']        = gmdate( 'h:i:s', $struc['lastmodunix'] );
 673              $struc['type']        = $this->is_dir( $path . $entry ) ? 'd' : 'f';
 674  
 675              if ( 'd' === $struc['type'] ) {
 676                  if ( $recursive ) {
 677                      $struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive );
 678                  } else {
 679                      $struc['files'] = array();
 680                  }
 681              }
 682  
 683              $ret[ $struc['name'] ] = $struc;
 684          }
 685  
 686          $dir->close();
 687          unset( $dir );
 688  
 689          return $ret;
 690      }
 691  }


Generated : Sun Jan 18 08:20:04 2026 Cross-referenced by PHPXref