logger = $logger; } /** * Prepare folders and access guards. * * @return void */ public function prepare() { foreach ( $this->directories() as $directory ) { if ( ! is_dir( $directory ) ) { wp_mkdir_p( $directory ); } $this->write_guard_files( $directory ); } } /** * Get plugin-managed directories. * * @return array */ public function directories() { return array( $this->storage_dir(), $this->storage_dir() . 'cache', $this->storage_dir() . 'cache/pages', $this->storage_dir() . 'cache/assets', ); } /** * Page cache directory. * * @return string */ public function page_cache_dir() { return trailingslashit( $this->storage_dir() . 'cache/pages' ); } /** * Optimized asset directory. * * @return string */ public function asset_cache_dir() { return trailingslashit( $this->storage_dir() . 'cache/assets' ); } /** * Optimized asset URL. * * @return string */ public function asset_cache_url() { return trailingslashit( $this->storage_url() . 'cache/assets' ); } /** * Logs directory. * * @return string */ public function logs_dir() { return trailingslashit( $this->storage_dir() . 'logs' ); } /** * Remove cached files under a controlled root. * * @param string $directory Directory to clear. * @return int Deleted file count. */ public function clear_directory( $directory ) { $real_directory = realpath( $directory ); $allowed = realpath( $this->storage_dir() . 'cache' ); if ( false === $real_directory || false === $allowed || 0 !== strpos( $real_directory, $allowed ) ) { return 0; } $deleted = 0; $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $real_directory, \FilesystemIterator::SKIP_DOTS ), \RecursiveIteratorIterator::CHILD_FIRST ); foreach ( $iterator as $item ) { if ( $item->isDir() ) { $this->remove_directory( $item->getPathname() ); continue; } if ( $this->delete_file( $item->getPathname() ) ) { ++$deleted; } } $this->prepare(); return $deleted; } /** * Read a file through the WordPress filesystem API. * * @param string $file File path. * @return string|false */ public function get_contents( $file ) { $wp_filesystem = $this->wp_filesystem(); return $wp_filesystem ? $wp_filesystem->get_contents( $file ) : false; } /** * Write a file through the WordPress filesystem API. * * @param string $file File path. * @param string $contents File contents. * @return bool */ public function put_contents( $file, $contents ) { $directory = dirname( $file ); if ( ! is_dir( $directory ) ) { wp_mkdir_p( $directory ); } $wp_filesystem = $this->wp_filesystem(); if ( ! $wp_filesystem ) { return false; } return (bool) $wp_filesystem->put_contents( $file, $contents, defined( 'FS_CHMOD_FILE' ) ? FS_CHMOD_FILE : 0644 ); } /** * Delete a file using WordPress' deletion helper. * * @param string $file File path. * @return bool */ public function delete_file( $file ) { if ( ! file_exists( $file ) || is_dir( $file ) ) { return false; } wp_delete_file( $file ); return ! file_exists( $file ); } /** * Remove a directory through the WordPress filesystem API. * * @param string $directory Directory path. * @return bool */ public function remove_directory( $directory ) { $wp_filesystem = $this->wp_filesystem(); if ( ! $wp_filesystem || ! is_dir( $directory ) ) { return false; } return (bool) $wp_filesystem->rmdir( $directory, true ); } /** * Count files and bytes. * * @param string $directory Directory. * @return array */ public function directory_stats( $directory ) { $stats = array( 'files' => 0, 'bytes' => 0, ); if ( ! is_dir( $directory ) ) { return $stats; } $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $directory, \FilesystemIterator::SKIP_DOTS ) ); foreach ( $iterator as $item ) { if ( ! $item->isFile() ) { continue; } $stats['files']++; $stats['bytes'] += (int) $item->getSize(); } return $stats; } /** * Write guard files. * * @param string $directory Directory. * @return void */ private function write_guard_files( $directory ) { if ( ! is_dir( $directory ) || ! wp_is_writable( $directory ) ) { return; } $index = trailingslashit( $directory ) . 'index.html'; if ( ! file_exists( $index ) ) { $this->put_contents( $index, '' ); } } /** * Base storage directory in uploads. * * @return string */ private function storage_dir() { $storage = $this->storage(); return $storage['dir']; } /** * Base storage URL in uploads. * * @return string */ private function storage_url() { $storage = $this->storage(); return $storage['url']; } /** * Resolve uploads storage paths. * * @return array */ private function storage() { if ( null !== $this->storage ) { return $this->storage; } $uploads = wp_upload_dir( null, false ); $base_dir = empty( $uploads['basedir'] ) ? WP_CONTENT_DIR . '/uploads' : $uploads['basedir']; $base_url = empty( $uploads['baseurl'] ) ? content_url( 'uploads' ) : $uploads['baseurl']; $this->storage = array( 'dir' => trailingslashit( $base_dir ) . 'acelora-site-accelerator/', 'url' => trailingslashit( $base_url ) . 'acelora-site-accelerator/', ); return $this->storage; } /** * Get the WordPress filesystem instance. * * @return \WP_Filesystem_Base|null */ private function wp_filesystem() { global $wp_filesystem; if ( $this->wp_filesystem ) { return $this->wp_filesystem; } if ( ! function_exists( 'WP_Filesystem' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } if ( ! $wp_filesystem ) { WP_Filesystem(); } $this->wp_filesystem = $wp_filesystem; return $this->wp_filesystem; } }