maybe_init_wp_filesystem(); } } $uploads_dir = wp_upload_dir(); $this->cache_folder = trailingslashit( $uploads_dir['basedir'] ) . 'redux/'; if ( ! $this->file_exists( $this->cache_folder ) ) { $this->mkdir( $this->cache_folder ); } } /** * Return an instance of this class. * * @param object $me ReduxFramework pointer. * * @since 1.0.0 * @return object A single instance of this class. */ public static function get_instance( $me = null ) { // If the single instance hasn't been set, set it now. if ( null === self::$instance ) { self::$instance = new self(); } if ( null !== $me ) { self::$instance->parent = $me; } return self::$instance; } /** * Build an FTP form. */ public function ftp_form() { if ( isset( $this->parent->ftp_form ) && ! empty( $this->parent->ftp_form ) ) { echo '
';
// translators: %1$s: Upload URL. %2$s: Codex URL.
echo '' . esc_html__( 'File Permission Issues', 'redux-framework' ) . '
' . sprintf( esc_html__( 'We were unable to modify required files. Please ensure that %1$s has the proper read-write permissions, or modify your wp-config.php file to contain your FTP login credentials as %2$s.', 'redux-framework' ), '' . esc_url( Redux_Functions_Ex::wp_normalize_path( trailingslashit( WP_CONTENT_DIR ) ) . '/uploads/' ) . '', ' ' . esc_html__( 'outlined here', 'redux-framework' ) . '' );
echo '
' . esc_url( Redux_Functions_Ex::wp_normalize_path( trailingslashit( WP_CONTENT_DIR ) ) ) . '/uploads/', '' . esc_html__( 'outlined here', 'redux-framework' ) . '' );
$data = array(
'parent' => self::$instance->parent,
'type' => 'error',
'msg' => $msg,
'id' => 'redux-wp-login',
'dismiss' => false,
);
Redux_Admin_Notices::set_notice( $data );
}
return $res;
}
/**
* Getter for the instantiated WP_Filesystem. This should be used carefully since $wp_filesystem won't always have a value.
*
* @return WP_Filesystem_Base|false
*/
public function get_wp_filesystem() {
if ( $this->use_filesystem ) {
return $this->wp_filesystem;
} else {
return false;
}
}
/**
* Check if WP_Filesystem being used.
*
* @return bool
*/
public function using_wp_filesystem(): bool {
return $this->use_filesystem;
}
/**
* Attempts to use the correct path for the FS method being used.
*
* @param string $abs_path Absolute path.
*
* @return string
*/
public function get_sanitized_path( string $abs_path ): string {
if ( $this->using_wp_filesystem() ) {
return str_replace( ABSPATH, $this->wp_filesystem->abspath(), $abs_path );
}
return $abs_path;
}
/**
* Create file if not exists then set mtime and atime on file
*
* @param string $abs_path Absolute path.
* @param int $time Time.
* @param int $atime Altered time.
*
* @return bool
*/
public function touch( string $abs_path, int $time = 0, int $atime = 0 ): bool {
if ( 0 === $time ) {
$time = time();
}
if ( 0 === $atime ) {
$atime = time();
}
// phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP
$return = @touch( $abs_path, $time, $atime );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->touch( $abs_path, $time, $atime );
}
return $return;
}
/**
* Calls file_put_contents with chmod.
*
* @param string $abs_path Absolute path.
* @param string $contents Content to write to the file.
* @param string|null $perms Default permissions value.
*
* @return bool
*/
public function put_contents( string $abs_path, string $contents, string $perms = null ): bool {
$return = false;
if ( ! $this->is_dir( dirname( $abs_path ) ) ) {
$this->mkdir( dirname( $abs_path ) );
}
if ( $this->is_writable( dirname( $abs_path ) ) ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents, WordPress.PHP.NoSilencedErrors.Discouraged
$return = @file_put_contents( $abs_path, $contents );
$this->chmod( $abs_path );
if ( null === $perms ) {
$perms = $this->chmod_file;
}
}
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writable, WordPress.WP.AlternativeFunctions.file_system_operations_is_writable
if ( $this->is_writable( dirname( $abs_path ) ) ) {
$return = $this->wp_filesystem->put_contents( $abs_path, $contents, $perms );
}
}
return (bool) $return;
}
/**
* Does the specified file or dir exist?
*
* @param string $abs_path Absolute path.
* @return bool
*/
public function file_exists( string $abs_path ): bool {
$return = file_exists( $abs_path );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->exists( $abs_path );
}
return $return;
}
/**
* Get a file's size.
*
* @param string $abs_path Absolute path.
*
* @return int
*/
public function filesize( string $abs_path ): int {
$return = filesize( $abs_path );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->size( $abs_path );
}
return $return;
}
/**
* Get the contents of a file as a string.
*
* @param string $abs_path Absolute path.
*
* @return string
*/
public function get_local_file_contents( string $abs_path ): string {
try {
$contents = '';
if ( $this->file_exists( $abs_path ) && is_file( $abs_path ) ) {
if ( $this->is_writable( $abs_path ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions
ob_start();
include_once $abs_path;
$contents = ob_get_clean();
}
}
} catch ( Exception $e ) {
// This means that ob_start has been disabled on the system. Lets fallback to good old file_get_contents.
$contents = file_get_contents( $abs_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
}
return $contents;
}
/**
* Get the contents of a file as a string.
*
* @param string $abs_path Absolute path.
*
* @return string
*/
public function get_contents( string $abs_path ): string {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = '';
if ( $this->use_filesystem ) {
$return = $this->wp_filesystem->get_contents( $abs_path );
}
if ( empty( $return ) ) {
$return = $this->get_local_file_contents( $abs_path );
}
return $return;
}
/**
* Delete a file.
*
* @param string $abs_path Absolute path.
*
* @return bool
*/
public function unlink( string $abs_path ): bool {
// phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP.AlternativeFunctions
$return = @unlink( $abs_path );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->delete( $abs_path );
}
return $return;
}
/**
* Chmod a file.
*
* @param string $abs_path Absolute path.
* @param int|null $perms Permission value, if not provided, defaults to WP standards.
*
* @return bool
*/
public function chmod( string $abs_path, int $perms = null ): bool {
if ( ! $this->file_exists( $abs_path ) ) {
return false;
}
if ( is_null( $perms ) ) {
$perms = $this->is_file( $abs_path ) ? $this->chmod_file : $this->chmod_dir;
}
// phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP.AlternativeFunctions
$return = @chmod( $abs_path, $perms );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->chmod( $abs_path, $perms );
}
return $return;
}
/**
* Check if this path is a directory.
*
* @param string $abs_path Absolute path.
*
* @return bool
*/
public function is_dir( string $abs_path ): bool {
$return = is_dir( $abs_path );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->is_dir( $abs_path );
}
return $return;
}
/**
* Check if the specified path is a file.
*
* @param string $abs_path Absolute path.
*
* @return bool
*/
public function is_file( string $abs_path ): bool {
$return = is_file( $abs_path );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->is_file( $abs_path );
}
return $return;
}
/**
* Is the specified path readable?
*
* @param string $abs_path Absolute path.
*
* @return bool
*/
public function is_readable( string $abs_path ): bool {
$return = is_readable( $abs_path );
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->is_readable( $abs_path );
}
return $return;
}
/**
* Is the specified path writable?
*
* @param string $abs_path Absolute path.
*
* @return bool
*/
public function is_writable( string $abs_path ): bool {
$return = is_writable( $abs_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
$return = $this->wp_filesystem->is_writable( $abs_path );
}
return $return;
}
/**
* Create an index file at the given path.
*
* @param string $path Directory to add the index to.
*/
private function create_index( string $path ) {
$index_path = trailingslashit( $path ) . 'index.php';
if ( ! $this->file_exists( $index_path ) ) {
$this->put_contents( $index_path, "chmod_dir;
}
if ( $this->is_dir( $abs_path ) ) {
$this->chmod( $abs_path, $perms );
$this->create_index( $abs_path );
return true;
}
try {
$mkdirp = wp_mkdir_p( $abs_path );
} catch ( Exception $e ) {
$mkdirp = false;
}
if ( $mkdirp ) {
$this->chmod( $abs_path, $perms );
$this->create_index( $abs_path );
return true;
}
$return = false;
if ( $this->is_writable( dirname( $abs_path ) ) ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP.AlternativeFunctions, WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writable
$return = @mkdir( $abs_path, $perms, true );
}
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
if ( $this->is_dir( $abs_path ) ) {
$this->create_index( $abs_path );
return true;
}
// WP_Filesystem doesn't offer a recursive mkdir().
$abs_path = str_replace( '//', '/', $abs_path );
$abs_path = rtrim( $abs_path, '/' );
if ( empty( $abs_path ) ) {
$abs_path = '/';
}
$dirs = explode( '/', ltrim( $abs_path, '/' ) );
$current_dir = '';
foreach ( $dirs as $dir ) {
$current_dir .= '/' . $dir;
// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writable, WordPress.WP.AlternativeFunctions.file_system_operations_is_writable
if ( ! $this->is_dir( $current_dir ) && $this->is_writable( dirname( $current_dir ) ) ) {
$this->wp_filesystem->mkdir( $current_dir, $perms );
}
}
$return = $this->is_dir( $abs_path );
}
return $return;
}
/**
* Delete a directory.
*
* @param string $abs_path Absolute path.
* @param bool $recursive Set to recursively create.
*
* @return bool
*/
public function rmdir( string $abs_path, bool $recursive = false ): bool {
if ( ! $this->is_dir( $abs_path ) ) {
return false;
}
// Taken from WP_Filesystem_Direct.
if ( ! $recursive ) {
// phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP.AlternativeFunctions
$return = @rmdir( $abs_path );
} else {
// At this point, it's a folder, and we're in recursive mode.
$abs_path = trailingslashit( $abs_path );
$filelist = $this->scandir( $abs_path );
$return = true;
if ( is_array( $filelist ) ) {
foreach ( $filelist as $filename => $fileinfo ) {
if ( 'd' === $fileinfo['type'] ) {
$return = $this->rmdir( $abs_path . $filename, $recursive );
} else {
$return = $this->unlink( $abs_path . $filename );
}
}
}
// phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP.AlternativeFunctions
if ( file_exists( $abs_path ) && ! @rmdir( $abs_path ) ) {
$return = false;
}
}
if ( ! $return && $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
return $this->wp_filesystem->rmdir( $abs_path, $recursive );
}
return $return;
}
/**
* Get a list of files/folders under the specified directory.
*
* @param string $abs_path Absolute path.
* @param bool $include_hidden Include hidden files, defaults to true.
* @param bool $recursive Recursive search, defaults to false.
*
* @return array|bool
*/
public function scandir( string $abs_path, bool $include_hidden = true, bool $recursive = false ) {
if ( $this->is_file( $abs_path ) ) {
$limit_file = basename( $abs_path );
$abs_path = dirname( $abs_path );
} else {
$limit_file = false;
}
if ( ! $this->is_dir( $abs_path ) || ! $this->is_readable( $abs_path ) ) {
return false;
}
$dir = dir( $abs_path );
if ( false === $dir ) {
if ( $this->use_filesystem ) {
$abs_path = $this->get_sanitized_path( $abs_path );
return $this->wp_filesystem->dirlist( $abs_path, $include_hidden, $recursive );
}
return false;
}
$ret = array();
while ( false !== ( $entry = $dir->read() ) ) {
$struc = array();
$struc['name'] = $entry;
if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
continue;
}
if ( ! $include_hidden && '.' === $struc['name'][0] ) {
continue;
}
if ( $limit_file && $struc['name'] !== $limit_file ) {
continue;
}
$struc['type'] = $this->is_dir( $abs_path . '/' . $entry ) ? 'd' : 'f';
if ( 'd' === $struc['type'] ) {
if ( $recursive ) {
$struc['files'] = $this->scandir( $abs_path . '/' . $struc['name'], $include_hidden, $recursive );
} else {
$struc['files'] = array();
}
}
$ret[ $struc['name'] ] = $struc;
}
$dir->close();
unset( $dir );
return $ret;
}
/**
* Light wrapper for move_uploaded_file with chmod.
*
* @param string $file Source file.
* @param string $destination File destination.
* @param int|null $perms Permission value.
*
* @return bool
*/
public function move_uploaded_file( string $file, string $destination, int $perms = null ): bool {
// TODO: look into replicating more functionality from wp_handle_upload().
// phpcs:ignore WordPress.PHP.NoSilencedErrors
$return = @move_uploaded_file( $file, $destination );
if ( $return ) {
$this->chmod( $destination, $perms );
}
return $return;
}
/**
* Copy a file.
*
* @param string $source_abs_path Source path.
* @param string $destination_abs_path Destination path.
* @param bool $overwrite Overwrite file.
* @param mixed $perms Permission value.
* @return bool
* Taken from WP_Filesystem_Direct
*/
public function copy( string $source_abs_path, string $destination_abs_path, bool $overwrite = true, $perms = false ): bool {
// Error if source file doesn't exist.
if ( ! $this->file_exists( $source_abs_path ) ) {
return false;
}
if ( ! $overwrite && $this->file_exists( $destination_abs_path ) ) {
return false;
}
if ( ! $this->is_dir( dirname( $destination_abs_path ) ) ) {
$this->mkdir( dirname( $destination_abs_path ) );
}
// phpcs:ignore WordPress.PHP.NoSilencedErrors
$return = @copy( $source_abs_path, $destination_abs_path );
if ( $perms && $return ) {
$this->chmod( $destination_abs_path, $perms );
}
if ( ! $return && $this->use_filesystem ) {
$source_abs_path = $this->get_sanitized_path( $source_abs_path );
$destination_abs_path = $this->get_sanitized_path( $destination_abs_path );
$return = $this->wp_filesystem->copy(
$source_abs_path,
$destination_abs_path,
$overwrite,
$perms
);
}
return $return;
}
/**
* Move a file.
*
* @param string $source_abs_path Source absolute path.
* @param string $destination_abs_path Destination absolute path.
* @param bool $overwrite Overwrite if file exists.
* @return bool
*/
public function move( string $source_abs_path, string $destination_abs_path, bool $overwrite = true ): bool {
// Error if source file doesn't exist.
if ( ! $this->file_exists( $source_abs_path ) ) {
return false;
}
// Try using rename first.
// If that fails (for example, the source is read only) try copy.
// Taken in part from WP_Filesystem_Direct.
if ( ! $overwrite && $this->file_exists( $destination_abs_path ) ) {
return false;
} elseif ( @rename( $source_abs_path, $destination_abs_path ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP.AlternativeFunctions
return true;
} elseif ( $this->copy( $source_abs_path, $destination_abs_path, $overwrite ) && $this->file_exists(
$destination_abs_path
) ) {
$this->unlink( $source_abs_path );
return true;
} else {
$return = false;
}
if ( $this->use_filesystem ) {
$source_abs_path = $this->get_sanitized_path( $source_abs_path );
$destination_abs_path = $this->get_sanitized_path( $destination_abs_path );
$return = $this->wp_filesystem->move( $source_abs_path, $destination_abs_path, $overwrite );
}
return $return;
}
/**
* Shim: get_template.
*
* @param string $file Template name.
*
* @return void Path to template file.
*/
public function get_template( string $file ) {
$panel = new Redux_Panel( $this );
$panel->get_template( $file );
}
}
Redux_Filesystem::get_instance();
}