File Manager
<?php
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
/**
* Class that enhance the WP filesystem class.
*
* @since 1.7.1
* @author Grégory Viguier
*/
class Imagify_Filesystem extends WP_Filesystem_Direct {
/**
* Class version.
*
* @var string
*/
const VERSION = '1.2';
/**
* Delimiter used for regex patterns.
*
* @var string
* @since 1.8
* @author Grégory Viguier
*/
const PATTERN_DELIMITER = '@';
/**
* The single instance of the class.
*
* @var object
* @access protected
*/
protected static $_instance;
/** ----------------------------------------------------------------------------------------- */
/** INSTANCIATION =========================================================================== */
/** ----------------------------------------------------------------------------------------- */
/**
* Constructor.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*/
public function __construct() {
// Define the permission constants if not already done.
if ( ! defined( 'FS_CHMOD_DIR' ) ) {
define( 'FS_CHMOD_DIR', ( fileperms( ABSPATH ) & 0777 | 0755 ) );
}
if ( ! defined( 'FS_CHMOD_FILE' ) ) {
define( 'FS_CHMOD_FILE', ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ) );
}
parent::__construct( '' );
}
/**
* Get the main Instance.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @return object Main instance.
*/
public static function get_instance() {
if ( ! isset( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/** ----------------------------------------------------------------------------------------- */
/** CUSTOM TOOLS ============================================================================ */
/** ----------------------------------------------------------------------------------------- */
/**
* Get the file name.
* Replacement for basename().
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return string|bool The base name of the given path. False on failure.
*/
public function file_name( $file_path ) {
if ( ! $file_path ) {
return false;
}
return wp_basename( $file_path );
}
/**
* Get the parent directory's path.
* Replacement for dirname().
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return string|bool The directory path with a trailing slash. False on failure.
*/
public function dir_path( $file_path ) {
if ( ! $file_path ) {
return false;
}
$file_path = dirname( $file_path );
return $this->is_root( $file_path ) ? $this->get_root() : trailingslashit( $file_path );
}
/**
* Get information about a file path.
* Replacement for pathinfo().
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @param string $option If present, specifies a specific element to be returned; one of 'dir_path', 'file_name', 'extension' or 'file_base'.
* If option is not specified, returns all available elements.
* @return array|string|null If the option parameter is not passed, an associative array containing the following elements is returned: 'dir_path' (with trailing slash), 'file_name' (with extension), 'extension' (if any), and 'file_base' (without extension).
*/
public function path_info( $file_path, $option = null ) {
if ( ! $file_path ) {
if ( isset( $option ) ) {
return '';
}
return array(
'dir_path' => '',
'file_name' => '',
'extension' => null,
'file_base' => '',
);
}
if ( isset( $option ) ) {
$options = array(
'dir_path' => PATHINFO_DIRNAME,
'file_name' => PATHINFO_BASENAME,
'extension' => PATHINFO_EXTENSION,
'file_base' => PATHINFO_FILENAME,
);
if ( ! isset( $options[ $option ] ) ) {
return '';
}
$output = pathinfo( $file_path, $options[ $option ] );
if ( 'dir_path' !== $option ) {
return $output;
}
return $this->is_root( $output ) ? $this->get_root() : trailingslashit( $output );
}
$output = pathinfo( $file_path );
$output['dirname'] = $this->is_root( $output['dirname'] ) ? $this->get_root() : trailingslashit( $output['dirname'] );
$output['extension'] = isset( $output['extension'] ) ? $output['extension'] : null;
// '/www/htdocs/inc/lib.inc.php'
return array(
'dir_path' => $output['dirname'], // '/www/htdocs/inc/'
'file_name' => $output['basename'], // 'lib.inc.php'
'extension' => $output['extension'], // 'php'
'file_base' => $output['filename'], // 'lib.inc'
);
}
/**
* Recursive directory creation based on full path. Will attempt to set permissions on folders.
* Replacement for recursive mkdir().
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $path Full path to attempt to create.
* @return bool Whether the path was created. True if path already exists.
*/
public function make_dir( $path ) {
/*
* Safe mode fails with a trailing slash under certain PHP versions.
*/
$path = untrailingslashit( wp_normalize_path( $path ) );
if ( $this->is_root( $path ) ) {
return $this->is_dir( $this->get_root() ) && $this->is_writable( $this->get_root() );
}
if ( $this->exists( $path ) ) {
return $this->is_dir( $path ) && $this->is_writable( $path );
}
$site_root = $this->get_site_root();
if ( strpos( $path, $site_root ) !== 0 ) {
return false;
}
$bits = preg_replace( '@^' . preg_quote( $site_root, '@' ) . '@i', '', $path );
$bits = explode( '/', trim( $bits, '/' ) );
$path = untrailingslashit( $site_root );
foreach ( $bits as $bit ) {
$parent_path = $path;
$path .= '/' . $bit;
if ( $this->exists( $path ) ) {
if ( ! $this->is_dir( $path ) ) {
return false;
}
continue;
}
if ( ! $this->is_writable( $parent_path ) ) {
$this->chmod_dir( $parent_path );
if ( ! $this->is_writable( $parent_path ) ) {
return false;
}
}
$this->mkdir( $path );
if ( ! $this->exists( $path ) ) {
return false;
}
$this->touch( trailingslashit( $path ) . 'index.php' );
}
return true;
}
/**
* Set a file permissions using FS_CHMOD_FILE.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return bool True on success, false on failure.
*/
public function chmod_file( $file_path ) {
if ( ! $file_path ) {
return false;
}
return $this->chmod( $file_path, FS_CHMOD_FILE );
}
/**
* Set a directory permissions using FS_CHMOD_DIR.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the directory.
* @return bool True on success, false on failure.
*/
public function chmod_dir( $file_path ) {
if ( ! $file_path ) {
return false;
}
return $this->chmod( $file_path, FS_CHMOD_DIR );
}
/**
* Get a file mime type.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path A file path (prefered) or a filename.
* @return string|bool A mime type. False on failure: the test is limited to mime types supported by Imagify.
*/
public function get_mime_type( $file_path ) {
if ( ! $file_path ) {
return false;
}
$file_type = wp_check_filetype( $file_path, imagify_get_mime_types() );
return $file_type['type'];
}
/**
* Get a file modification date, formated as "mysql". Fallback to current date.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return string The date.
*/
public function get_date( $file_path ) {
static $offset;
if ( ! $file_path ) {
return current_time( 'mysql' );
}
$date = $this->mtime( $file_path );
if ( ! $date ) {
return current_time( 'mysql' );
}
if ( ! isset( $offset ) ) {
$offset = get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
}
return gmdate( 'Y-m-d H:i:s', $date + $offset );
}
/**
* Tell if a file is symlinked.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path An absolute path.
* @return bool
*/
public function is_symlinked( $file_path ) {
static $site_root;
static $plugin_paths = array();
global $wp_plugin_paths;
if ( ! $file_path ) {
return false;
}
$real_path = realpath( $file_path );
if ( ! $real_path ) {
return false;
}
if ( ! isset( $site_root ) ) {
$site_root = $this->normalize_path_for_comparison( $this->get_site_root() );
}
$lower_file_path = $this->normalize_path_for_comparison( $real_path );
if ( strpos( $lower_file_path, $site_root ) !== 0 ) {
return true;
}
if ( $wp_plugin_paths && is_array( $wp_plugin_paths ) ) {
if ( ! $plugin_paths ) {
foreach ( $wp_plugin_paths as $dir => $real_dir ) {
$dir = $this->normalize_path_for_comparison( $dir );
$plugin_paths[ $dir ] = $this->normalize_path_for_comparison( $real_dir );
}
}
$lower_file_path = $this->normalize_path_for_comparison( $file_path );
foreach ( $plugin_paths as $dir => $real_dir ) {
if ( strpos( $lower_file_path, $dir ) === 0 ) {
return true;
}
}
}
return false;
}
/**
* Tell if a file is a pdf.
*
* @since 1.8
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return bool
*/
public function is_pdf( $file_path ) {
if ( function_exists( 'finfo_fopen' ) ) {
$finfo = finfo_open( FILEINFO_MIME );
if ( $finfo ) {
$mimetype = finfo_file( $finfo, $file_path );
if ( false !== $mimetype ) {
return 'application/pdf' === $mimetype;
}
}
}
if ( function_exists( 'mime_content_type' ) ) {
$mimetype = mime_content_type( $file_path );
return 'application/pdf' === $mimetype;
}
return false;
}
/** ----------------------------------------------------------------------------------------- */
/** CLASS OVERWRITES ======================================================================== */
/** ----------------------------------------------------------------------------------------- */
/**
* Move a file and apply chmod.
* If the file failed to be moved once, a 2nd attempt is made after applying chmod.
*
* @since 1.8
* @access public
* @author Grégory Viguier
*
* @param string $source Path to the file to move.
* @param string $destination Path to the destination.
* @param bool $overwrite Allow to overwrite existing file at destination.
* @return bool True on success, false on failure.
*/
public function move( $source, $destination, $overwrite = false ) {
if ( parent::move( $source, $destination, $overwrite ) ) {
return $this->chmod_file( $destination );
}
if ( ! $this->chmod_file( $destination ) ) {
return false;
}
if ( parent::move( $source, $destination, $overwrite ) ) {
return $this->chmod_file( $destination );
}
return false;
}
/**
* Determine if a file or directory is writable.
* This function is used to work around certain ACL issues in PHP primarily affecting Windows Servers.
* Replacement for is_writable().
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return bool
*/
public function is_writable( $file_path ) {
if ( ! $file_path ) {
return false;
}
return wp_is_writable( $file_path );
}
/** ----------------------------------------------------------------------------------------- */
/** WORK WITH IMAGES ======================================================================== */
/** ----------------------------------------------------------------------------------------- */
/**
* Tell if a file is an image.
*
* @since 1.8
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return bool
*/
public function is_image( $file_path ) {
if ( function_exists( 'finfo_fopen' ) ) {
$finfo = finfo_open( FILEINFO_MIME );
if ( $finfo ) {
$mimetype = finfo_file( $finfo, $file_path );
if ( false !== $mimetype ) {
return strpos( $mimetype, 'image/' ) === 0;
}
}
}
if ( function_exists( 'exif_imagetype' ) ) {
$mimetype = exif_imagetype( $file_path );
return (bool) $mimetype;
}
if ( function_exists( 'mime_content_type' ) ) {
$mimetype = mime_content_type( $file_path );
return strpos( $mimetype, 'image/' ) === 0;
}
return false;
}
/**
* Get an image data.
* Replacement for getimagesize().
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return array The image data. An empty array on failure.
*/
public function get_image_size( $file_path ) {
if ( ! $file_path ) {
return array();
}
$size = @getimagesize( $file_path );
if ( ! $size || ! isset( $size[0], $size[1] ) ) {
return array();
}
return array(
0 => (int) $size[0],
1 => (int) $size[1],
'width' => (int) $size[0],
'height' => (int) $size[1],
'type' => (int) $size[2],
'attr' => $size[3],
'channels' => isset( $size['channels'] ) ? (int) $size['channels'] : null,
'bits' => isset( $size['bits'] ) ? (int) $size['bits'] : null,
'mime' => $size['mime'],
);
}
/**
* Tell if exif_read_data() is available.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @return bool
*/
public function can_get_exif() {
static $callable;
if ( ! isset( $callable ) ) {
$callable = is_callable( 'exif_read_data' );
}
return $callable;
}
/**
* Get the EXIF headers from an image file.
* Replacement for exif_read_data().
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
* @see https://secure.php.net/manual/en/function.exif-read-data.php
*
* @param string $file_path Path to the file.
* @param string $sections A comma separated list of sections that need to be present in file to produce a result array. See exif_read_data() documentation for values: FILE, COMPUTED, ANY_TAG, IFD0, THUMBNAIL, COMMENT, EXIF.
* @param bool $arrays Specifies whether or not each section becomes an array. The sections COMPUTED, THUMBNAIL, and COMMENT always become arrays as they may contain values whose names conflict with other sections.
* @param bool $thumbnail When set to TRUE the thumbnail itself is read. Otherwise, only the tagged data is read.
* @return array The EXIF headers. An empty array on failure.
*/
public function get_image_exif( $file_path, $sections = null, $arrays = false, $thumbnail = false ) {
if ( ! $file_path || ! $this->can_get_exif() ) {
return array();
}
$exif = @exif_read_data( $file_path, $sections, $arrays, $thumbnail );
return is_array( $exif ) ? $exif : array();
}
/**
* Tell if a file is an animated gif.
*
* @since 1.9.5
* @access public
* @source https://www.php.net/manual/en/function.imagecreatefromgif.php#104473
* @author Grégory Viguier
*
* @param string $file_path Path to the file.
* @return bool|null Null if the file cannot be read.
*/
public function is_animated_gif( $file_path ) {
if ( $this->path_info( $file_path, 'extension' ) !== 'gif' ) {
// Not a gif file.
return false;
}
$fh = @fopen( $file_path, 'rb' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen
if ( ! $fh ) {
// Could not open the file.
return null;
}
/**
* An animated gif contains multiple "frames", with each frame having a header made up of:
* - a static 4-byte sequence (\x00\x21\xF9\x04),
* - 4 variable bytes,
* - a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?).
*/
$count = 0;
// We read through the file til we reach the end of the file, or we've found at least 2 frame headers.
while ( ! feof( $fh ) && $count < 2 ) {
// Read 100kb at a time.
$chunk = fread( $fh, 1024 * 100 ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fread
$count += preg_match_all( '#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches );
}
fclose( $fh ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
return $count > 1;
}
/** ----------------------------------------------------------------------------------------- */
/** WORK WITH PATHS ========================================================================= */
/** ----------------------------------------------------------------------------------------- */
/**
* Make an absolute path relative to WordPress' root folder.
* Also works for files from registered symlinked plugins.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path An absolute path.
* @param string $base A base path to use instead of ABSPATH.
* @return string|bool A relative path. Can return the absolute path or false in case of a failure.
*/
public function make_path_relative( $file_path, $base = '' ) {
global $wp_plugin_paths;
if ( ! $file_path ) {
return false;
}
$file_path = wp_normalize_path( $file_path );
$base = $base ? $this->normalize_dir_path( $base ) : $this->get_site_root();
$pos = strpos( $file_path, $base );
if ( false === $pos && $wp_plugin_paths && is_array( $wp_plugin_paths ) ) {
// The file is probably part of a symlinked plugin.
arsort( $wp_plugin_paths );
foreach ( $wp_plugin_paths as $dir => $real_dir ) {
if ( strpos( $file_path, $real_dir ) === 0 ) {
$file_path = wp_normalize_path( $dir . substr( $file_path, strlen( $real_dir ) ) );
}
}
$pos = strpos( $file_path, $base );
}
if ( false === $pos ) {
// We're in trouble.
return $file_path;
}
return substr_replace( $file_path, '', 0, $pos + strlen( $base ) );
}
/**
* Normalize a directory path.
* The path is normalized and a trailing slash is added.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path The file path.
* @return string The normalized dir path.
*/
public function normalize_dir_path( $file_path ) {
return wp_normalize_path( trailingslashit( $file_path ) );
}
/**
* Normalize a file path, aiming for path comparison.
* The path is normalized, case-lowered, and a trailing slash is added.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $file_path The file path.
* @return string The normalized file path.
*/
public function normalize_path_for_comparison( $file_path ) {
return strtolower( $this->normalize_dir_path( $file_path ) );
}
/** ----------------------------------------------------------------------------------------- */
/** SOME WELL KNOWN PATHS AND URLS ========================================================== */
/** ----------------------------------------------------------------------------------------- */
/**
* Tell if WordPress is installed in its own directory: aka WP's path !== site's path.
*
* @since 1.8.1
* @access public
* @see https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory
* @author Grégory Viguier
*
* @return string
*/
public function has_wp_its_own_directory() {
return $this->get_abspath() !== $this->get_site_root();
}
/**
* The path to the server's root is not always '/', it can also be '//' or 'C://'.
* I am get_root.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @return string The path to the server's root.
*/
public function get_root() {
static $groot;
if ( isset( $groot ) ) {
return $groot;
}
$groot = preg_replace( '@^((?:.:)?/+).*@', '$1', $this->get_site_root() );
return $groot;
}
/**
* Tell if a path is the server's root.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $path The path.
* @return bool
*/
public function is_root( $path ) {
$path = rtrim( $path, '/\\' );
return '.' === $path || '' === $path || preg_match( '@^.:$@', $path );
}
/**
* Get the path to the site's root.
* This is an improved version of get_home_path() that *should* work in almost every cases.
* Because creating a constant like ABSPATH was too simple.
*
* @since 1.8.1
* @access public
* @see get_home_path()
* @author Grégory Viguier
*
* @return string
*/
public function get_site_root() {
static $root_path;
if ( isset( $root_path ) ) {
return $root_path;
}
/**
* Filter the path to the site's root.
*
* @since 1.8.1
* @author Grégory Viguier
*
* @param string $root_path Path to the site's root. Default is null.
*/
$root_path = apply_filters( 'imagify_site_root', null );
if ( is_string( $root_path ) ) {
$root_path = trailingslashit( wp_normalize_path( $root_path ) );
return $root_path;
}
$home = set_url_scheme( untrailingslashit( get_option( 'home' ) ), 'http' );
$siteurl = set_url_scheme( untrailingslashit( get_option( 'siteurl' ) ), 'http' );
if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
$wp_path_rel_to_home = str_ireplace( $home, '', $siteurl ); /* $siteurl - $home */
$pos = strripos( str_replace( '\\', '/', ABSPATH ), trailingslashit( $wp_path_rel_to_home ) );
$root_path = substr( ABSPATH, 0, $pos );
$root_path = trailingslashit( wp_normalize_path( $root_path ) );
return $root_path;
}
if ( ! defined( 'PATH_CURRENT_SITE' ) || ! is_multisite() || is_main_site() ) {
$root_path = $this->get_abspath();
return $root_path;
}
/**
* For a multisite in its own directory, get_home_path() returns the expected path only for the main site.
*
* Friend, each time an attempt is made to improve this method, and especially this part, please increment the following counter.
* Improvement attempts: 3.
*/
$document_root = realpath( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) ); // `realpath()` is needed for those cases where $_SERVER['DOCUMENT_ROOT'] is totally different from ABSPATH.
$document_root = trailingslashit( str_replace( '\\', '/', $document_root ) );
$path_current_site = trim( str_replace( '\\', '/', PATH_CURRENT_SITE ), '/' );
$root_path = trailingslashit( wp_normalize_path( $document_root . $path_current_site ) );
return $root_path;
}
/**
* Get the URL of the site's root. It corresponds to the main site's home page URL.
*
* @since 1.8.1
* @access public
* @author Grégory Viguier
*
* @return string
*/
public function get_site_root_url() {
static $root_url;
if ( isset( $root_url ) ) {
return $root_url;
}
if ( ! is_multisite() || is_main_site() ) {
$root_url = home_url( '/' );
return $root_url;
}
$current_network = false;
if ( function_exists( 'get_network' ) ) {
$current_network = get_network();
} elseif ( function_exists( 'get_current_site' ) ) {
$current_network = get_current_site();
}
if ( ! $current_network ) {
$root_url = home_url( '/' );
return $root_url;
}
$root_url = is_ssl() ? 'https' : 'http';
$root_url = set_url_scheme( 'http://' . $current_network->domain . $current_network->path, $root_url );
$root_url = trailingslashit( $root_url );
return $root_url;
}
/**
* Tell if a path is the site's root.
*
* @since 1.8.1
* @access public
* @author Grégory Viguier
*
* @param string $path The path.
* @return bool
*/
public function is_site_root( $path ) {
return $this->normalize_dir_path( $path ) === $this->get_site_root();
}
/**
* Get a clean value of ABSPATH.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @return string The path to WordPress' root folder.
*/
public function get_abspath() {
static $abspath;
if ( isset( $abspath ) ) {
return $abspath;
}
$abspath = wp_normalize_path( ABSPATH );
// Make sure ABSPATH is not messed up: it could be defined as a relative path for example (yeah, I know, but we've seen it).
$test_file = wp_normalize_path( IMAGIFY_FILE );
$pos = strpos( $test_file, $abspath );
if ( $pos > 0 ) {
// ABSPATH has a wrong value.
$abspath = substr( $test_file, 0, $pos ) . $abspath;
} elseif ( false === $pos && class_exists( 'ReflectionClass' ) ) {
// Imagify is symlinked (dude, you look for trouble).
$reflector = new ReflectionClass( 'WP' );
$test_file = $reflector->getFileName();
$pos = strpos( $test_file, $abspath );
if ( 0 < $pos ) {
// ABSPATH has a wrong value.
$abspath = substr( $test_file, 0, $pos ) . $abspath;
}
}
$abspath = trailingslashit( $abspath );
if ( '/' !== substr( $abspath, 0, 1 ) && ':' !== substr( $abspath, 1, 1 ) ) {
$abspath = '/' . $abspath;
}
return $abspath;
}
/**
* Tell if a path is WP's root (ABSPATH).
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param string $path The path.
* @return bool
*/
public function is_abspath( $path ) {
return $this->normalize_dir_path( $path ) === $this->get_abspath();
}
/**
* Get the upload basedir.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @param bool $bypass_error True to return the path even if there is an error. This is used when we want to display this path in a message for example.
* @return string|bool The path. False on failure.
*/
public function get_upload_basedir( $bypass_error = false ) {
static $upload_basedir;
static $upload_basedir_or_error;
if ( isset( $upload_basedir ) ) {
return $bypass_error ? $upload_basedir : $upload_basedir_or_error;
}
$uploads = wp_upload_dir();
$upload_basedir = $this->normalize_dir_path( $uploads['basedir'] );
if ( false !== $uploads['error'] ) {
$upload_basedir_or_error = false;
} else {
$upload_basedir_or_error = $upload_basedir;
}
return $bypass_error ? $upload_basedir : $upload_basedir_or_error;
}
/**
* Get the upload baseurl.
*
* @since 1.7.1
* @access public
* @author Grégory Viguier
*
* @return string|bool The URL. False on failure.
*/
public function get_upload_baseurl() {
static $upload_baseurl;
if ( isset( $upload_baseurl ) ) {
return $upload_baseurl;
}
$uploads = wp_upload_dir();
if ( false !== $uploads['error'] ) {
$upload_baseurl = false;
return $upload_baseurl;
}
$upload_baseurl = trailingslashit( $uploads['baseurl'] );
return $upload_baseurl;
}
/**
* Get the path to the uploads base directory of the main site.
*
* @since 1.8
* @access public
* @author Grégory Viguier
*
* @return string
*/
public function get_main_upload_basedir() {
static $basedir;
if ( isset( $basedir ) ) {
return $basedir;
}
$basedir = get_imagify_upload_basedir( true );
if ( is_multisite() ) {
$pattern = '/' . $this->get_multisite_uploads_subdir_pattern() . '$';
$basedir = preg_replace( self::PATTERN_DELIMITER . $pattern . self::PATTERN_DELIMITER, '/', $basedir );
}
return $basedir;
}
/**
* Get the URL of the uploads base directory of the main site.
*
* @since 1.8
* @access public
* @author Grégory Viguier
*
* @return string
*/
public function get_main_upload_baseurl() {
static $baseurl;
if ( isset( $baseurl ) ) {
return $baseurl;
}
$baseurl = get_imagify_upload_baseurl( true );
if ( is_multisite() ) {
$pattern = '/' . $this->get_multisite_uploads_subdir_pattern() . '$';
$baseurl = preg_replace( self::PATTERN_DELIMITER . $pattern . self::PATTERN_DELIMITER, '/', $baseurl );
}
return $baseurl;
}
/**
* Get the regex pattern used to match the uploads subdir on multisite in a file path.
* Pattern delimiter is `Imagify_Filesystem::PATTERN_DELIMITER`.
* Paths tested against these patterns are lower-cased.
*
* @since 1.8
* @access public
* @see _wp_upload_dir()
* @author Grégory Viguier
*
* @return string
*/
public function get_multisite_uploads_subdir_pattern() {
static $pattern;
if ( isset( $pattern ) ) {
return $pattern;
}
$pattern = '';
if ( ! is_multisite() ) {
return $pattern;
}
if ( ! get_site_option( 'ms_files_rewriting' ) ) {
if ( defined( 'MULTISITE' ) ) {
$pattern = 'sites/\d+/';
} else {
$pattern = '\d+/';
}
} elseif ( defined( 'UPLOADS' ) ) {
$site_id = (string) get_current_blog_id();
$path = $this->get_upload_basedir( true ); // Something like `/absolute/path/to/wp-content/blogs.dir/3/files/`, also for site 1.
$path = strrev( $path );
if ( preg_match( self::PATTERN_DELIMITER . '^.*' . strrev( $site_id ) . '[^/]*/' . self::PATTERN_DELIMITER . 'U', $path, $matches ) ) {
$pattern = end( $matches );
$pattern = ltrim( strtolower( strrev( $pattern ) ), '/' );
$pattern = str_replace( $site_id, '\d+', $pattern );
}
}
/**
* Filter the regex pattern used to match the uploads subdir on multisite in a file path.
* Pattern delimiter is `Imagify_Filesystem::PATTERN_DELIMITER`.
* Important: lowercase, no heading slash, mandatory trailing slash.
*
* @since 1.8
* @author Grégory Viguier
*
* @param string $pattern The regex pattern.
*/
$pattern = apply_filters( 'imagify_multisite_uploads_subdir_pattern', $pattern );
return $pattern;
}
}
File Manager Version 1.0, Coded By Lucas
Email: hehe@yahoo.com