OwlCyberSecurity - MANAGER
Edit File: class-redux-filesystem.php
<?php /** * Redux Filesystem Class * * @class Redux_Filesystem * @version 4.0.0 * @package Redux Framework/Classes * @noinspection PhpUnused * @noinspection PhpConditionCheckedByNextConditionInspection */ defined( 'ABSPATH' ) || exit; if ( ! class_exists( 'Redux_Filesystem', false ) ) { /** * Class Redux_Filesystem */ class Redux_Filesystem { /** * Instance of this class. * * @since 1.0.0 * @var object */ protected static $instance = null; /** * WP Filesystem object. * * @var object */ protected static $direct = null; /** * File system credentials. * * @var array */ private $creds = array(); /** * ReduxFramework object pointer. * * @var object */ public $parent = null; /** * Instance of WP_Filesystem * * @var WP_Filesystem_Base|null */ private $wp_filesystem; /** * If DBI_Filesystem should attempt to use the WP_Filesystem class. * * @var bool */ private $use_filesystem = false; /** * Default chmod octal value for directories. * * @var int */ private $chmod_dir; /** * Default chmod octal value for files. * * @var int */ private $chmod_file; /** * Default cache folder. * * @var string */ public $cache_folder; /** * Kill switch. * * @var bool */ public $killswitch = false; /** * Pass `true` when instantiating to skip using WP_Filesystem. * * @param bool $force_no_fs Force no use of the filesystem. */ public function __construct( bool $force_no_fs = false ) { // This little number fixes some issues with certain filesystem setups. if ( ! function_exists( 'request_filesystem_credentials' ) ) { require_once ABSPATH . '/wp-admin/includes/template.php'; require_once ABSPATH . '/wp-includes/pluggable.php'; require_once ABSPATH . '/wp-admin/includes/file.php'; } if ( ! $force_no_fs && function_exists( 'request_filesystem_credentials' ) ) { if ( ( defined( 'WPMDB_WP_FILESYSTEM' ) && WPMDB_WP_FILESYSTEM ) || ! defined( 'WPMDB_WP_FILESYSTEM' ) ) { $this->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 '<div class="wrap">'; echo '<div class="error">'; echo '<p>'; // translators: %1$s: Upload URL. %2$s: Codex URL. echo '<strong>' . esc_html__( 'File Permission Issues', 'redux-framework' ) . '</strong><br/>' . 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' ), '<code>' . esc_url( Redux_Functions_Ex::wp_normalize_path( trailingslashit( WP_CONTENT_DIR ) ) . '/uploads/' ) . '</code>', ' <a href="https://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants" target="_blank">' . esc_html__( 'outlined here', 'redux-framework' ) . '</a>' ); echo '</p>'; echo '</div>'; echo '<h2></h2>'; echo '</div>'; } } /** * Attempt to initiate WP_Filesystem * If this fails, $use_filesystem is set to false and all methods in this class should use native php fallbacks * Thwarts `request_filesystem_credentials()` attempt to display a form for obtaining creds from users * TODO: provide notice and input in wp-admin for users when this fails */ public function maybe_init_wp_filesystem() { // Set up the filesystem with creds. require_once ABSPATH . '/wp-admin/includes/template.php'; require_once ABSPATH . '/wp-includes/pluggable.php'; require_once ABSPATH . '/wp-admin/includes/file.php'; ob_start(); $credentials = request_filesystem_credentials( '', '', false, false ); $ob_contents = ob_get_contents(); ob_end_clean(); if ( @wp_filesystem( $credentials ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors global $wp_filesystem; $this->wp_filesystem = $wp_filesystem; $this->use_filesystem = true; $this->generate_default_files(); } } /** * Init WO Filesystem. * * @param string $form_url Form URL. * @param string $method Connect method. * @param bool $context Context. * * @return bool */ public function advanced_filesystem_init( string $form_url, string $method = '', bool $context = false ): bool { if ( ! empty( $this->wp_filesystem ) && $this->use_filesystem ) { return true; } if ( ! empty( $this->creds ) ) { return true; } ob_start(); $this->creds = request_filesystem_credentials( $form_url, $method, false, $context ); /* first attempt to get credentials */ if ( false === $this->creds ) { $this->creds = array(); $this->parent->ftp_form = ob_get_contents(); ob_end_clean(); /** * If we come here, we don't have credentials * so the request for them is displaying * no need for further processing * */ return false; } /* now we got some credentials - try to use them */ if ( ! @wp_filesystem( $this->creds ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors $this->creds = array(); /* incorrect connection data - ask for credentials again, now with an error message */ request_filesystem_credentials( $form_url, '', true, $context ); $this->parent->ftp_form = ob_get_contents(); ob_end_clean(); return false; } global $wp_filesystem; $this->wp_filesystem = $wp_filesystem; $this->use_filesystem = true; $this->generate_default_files(); return true; } /** * Load WP filesystem directly. */ public static function load_direct() { if ( null === self::$direct ) { require_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-base.php'; require_once ABSPATH . '/wp-admin/includes/class-wp-filesystem-direct.php'; self::$direct = new WP_Filesystem_Direct( array() ); } } /** * Execute filesystem request. * * @param string $action Action to perform. * @param string $file File to perform upon. * @param array $params Argument for action. * * @return bool|void */ public function execute( string $action, string $file = '', array $params = array() ) { if ( empty( $this->parent->args ) ) { return; } if ( ! empty( $params ) ) { // phpcs:ignore WordPress.PHP.DontExtract extract( $params ); } if ( empty( $this->wp_filesystem ) ) { if ( 'submenu' === $this->parent->args['menu_type'] ) { $page_parent = $this->parent->args['page_parent']; $base = $page_parent . '?page=' . $this->parent->args['page_slug']; } else { $base = 'admin.php?page=' . $this->parent->args['page_slug']; } $url = wp_nonce_url( $base, 'redux-options' ); $this->advanced_filesystem_init( $url, 'direct', dirname( $file ) ); } return $this->do_action( $action, $file, $params ); } /** * Generates the default Redux cache folder. * * @return void */ private function generate_default_files() { // Set default permissions. if ( defined( 'FS_CHMOD_DIR' ) ) { $this->chmod_dir = FS_CHMOD_DIR; } else { $this->chmod_dir = ( fileperms( ABSPATH ) & 0777 | 0755 ); } if ( defined( 'FS_CHMOD_FILE' ) ) { $this->chmod_file = FS_CHMOD_FILE; } else { $this->chmod_file = ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ); } if ( ! $this->is_dir( Redux_Core::$upload_dir ) ) { $this->mkdir( Redux_Core::$upload_dir ); } } /** * Do request filesystem action. * * @param string $action Requested action. * @param string $file File to perform action upon. * @param array $params Action arguments. * * @return bool|void */ public function do_action( string $action, string $file = '', array $params = array() ) { $destination = ''; $overwrite = ''; $content = ''; if ( ! empty( $params ) ) { // phpcs:ignore WordPress.PHP.DontExtract extract( $params ); } global $wp_filesystem; if ( defined( 'FS_CHMOD_FILE' ) ) { $chmod = FS_CHMOD_FILE; } else { $chmod = 0644; } if ( isset( $params['chmod'] ) && ! empty( $params['chmod'] ) ) { $chmod = $params['chmod']; } $res = false; if ( ! isset( $recursive ) ) { $recursive = false; } // Do unique stuff. if ( 'mkdir' === $action ) { $chmod = null; if ( isset( $params['chmod'] ) && ! empty( $params['chmod'] ) ) { $chmod = $params['chmod']; } $res = $this->mkdir( $file, $chmod ); } elseif ( 'rmdir' === $action ) { $res = $this->rmdir( $file, $recursive ); } elseif ( 'copy' === $action && false === $this->killswitch ) { $res = $this->copy( $file, $destination, $overwrite, $chmod ); } elseif ( 'move' === $action && false === $this->killswitch ) { $res = $this->move( $file, $destination, $overwrite ); } elseif ( 'delete' === $action ) { if ( $this->is_dir( $file ) ) { $res = $this->rmdir( $file, $recursive ); } else { $res = $this->unlink( $file ); } } elseif ( 'dirlist' === $action ) { if ( ! isset( $include_hidden ) ) { $include_hidden = true; } $res = $this->scandir( $file, $include_hidden, $recursive ); } elseif ( 'put_contents' === $action && false === $this->killswitch ) { // Write a string to a file. if ( isset( $this->parent->ftp_form ) && ! empty( $this->parent->ftp_form ) ) { self::load_direct(); $res = self::$direct->put_contents( $file, $content, $chmod ); } else { $res = $this->put_contents( $file, $content, $chmod ); } } elseif ( 'chown' === $action ) { // Changes the file owner. if ( isset( $owner ) && ! empty( $owner ) ) { $res = $wp_filesystem->chmod( $file, $chmod, $recursive ); } } elseif ( 'owner' === $action ) { // Gets the file owner. $res = $this->wp_filesystem->owner( $file ); } elseif ( 'chmod' === $action ) { if ( ! isset( $params['chmod'] ) || ( empty( $params['chmod'] ) ) ) { $chmod = false; } $res = $this->chmod( $file, $chmod ); } elseif ( 'get_contents' === $action ) { // Reads entire file into a string. if ( isset( $this->parent->ftp_form ) && ! empty( $this->parent->ftp_form ) ) { self::load_direct(); $res = self::$direct->get_contents( $file ); } else { $res = $this->get_contents( $file ); } } elseif ( 'get_contents_array' === $action ) { // Reads entire file into an array. $res = $this->wp_filesystem->get_contents_array( $file ); } elseif ( 'object' === $action ) { $res = $this->wp_filesystem; } elseif ( 'unzip' === $action ) { $unzipfile = unzip_file( $file, $destination ); if ( $unzipfile ) { $res = true; } } if ( ! $res ) { if ( 'dirlist' === $action ) { if ( empty( $res ) ) { return; } if ( ! is_array( $res ) ) { if ( count( glob( "$file*" ) ) === 0 ) { return; } } } $this->killswitch = true; // translators: %1$s: Upload URL. %2$s: Codex URL. $msg = '<strong>' . esc_html__( 'File Permission Issues', 'redux-framework' ) . '</strong><br/>' . 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' ), '<code>' . esc_url( Redux_Functions_Ex::wp_normalize_path( trailingslashit( WP_CONTENT_DIR ) ) ) . '/uploads/</code>', '<a href="https://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants" target="_blank">' . esc_html__( 'outlined here', 'redux-framework' ) . '</a>' ); $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, "<?php\n//Silence is golden" ); } } /** * Recursive mkdir. * * @param string $abs_path Absolute path. * @param int|null $perms Permissions, if default not required. * * @return bool */ public function mkdir( string $abs_path, int $perms = null ): bool { if ( is_null( $perms ) ) { $perms = $this->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(); }