suppress_errors = apply_filters( 'wpo_wcpdf_file_system_suppress_errors', true ); $debug_settings = get_option( 'wpo_wcpdf_settings_debug', array() ); if ( ! is_array( $debug_settings ) ) { $debug_settings = array(); } $debug_settings['file_system_method'] = apply_filters( // Allow overriding the filesystem method via filter 'wpo_wcpdf_filesystem_method', $debug_settings['file_system_method'] ?? self::FILESYSTEM_DEFAULT ); $this->system_enabled = in_array( $debug_settings['file_system_method'], self::FILESYSTEM_METHODS, true ) ? $debug_settings['file_system_method'] : self::FILESYSTEM_DEFAULT; if ( $this->is_wp_filesystem() ) { $this->initialize_wp_filesystem(); } elseif ( ! defined( 'FS_CHMOD_FILE' ) ) { define( 'FS_CHMOD_FILE', ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ) ); } } /** * Check if WP_Filesystem is enabled. * @return bool */ public function is_wp_filesystem(): bool { return ( 'wp' === $this->system_enabled ); } /** * Check if PHP file functions are being used. * @return bool */ public function is_php_filesystem(): bool { return ( 'php' === $this->system_enabled ); } /** * Initialize WP_Filesystem * @return void */ public function initialize_wp_filesystem(): void { // Force the use of the direct filesystem method if not already defined if ( ! defined( 'FS_METHOD' ) ) { define( 'FS_METHOD', 'direct' ); } require_once ABSPATH . 'wp-admin/includes/file.php'; global $wp_filesystem; if ( ! WP_Filesystem() || ! $wp_filesystem || ! is_a( $wp_filesystem, '\WP_Filesystem_Direct' ) ) { wcpdf_log_error( 'WP_Filesystem initialization failed or not using direct method. Falling back to PHP methods.', 'warning' ); $this->system_enabled = $this->change_setting_value( 'php' ); return; } $this->wp_filesystem = $wp_filesystem; } /** * Change the filesystem setting value * @param string $method * @return string */ protected function change_setting_value( string $method ): string { $debug_settings = get_option( 'wpo_wcpdf_settings_debug', array() ); $debug_settings['file_system_method'] = in_array( $method, self::FILESYSTEM_METHODS, true ) ? $method : self::FILESYSTEM_DEFAULT; update_option( 'wpo_wcpdf_settings_debug', $debug_settings ); return $debug_settings['file_system_method']; } /** * Get file contents * @param string $filename * @return string|bool */ public function get_contents( string $filename ) { if ( empty( $filename ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->get_contents( $filename ) : ( $this->suppress_errors ? @file_get_contents( $filename ) : file_get_contents( $filename ) ); } /** * Check if file is readable * @param string $filename * @return bool */ public function is_readable( string $filename ): bool { if ( empty( $filename ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->is_readable( $filename ) : ( $this->suppress_errors ? @is_readable( $filename ) : is_readable( $filename ) ); } /** * Write file contents * @param string $filename * @param string $contents * @param int|false $mode * @return int|bool */ public function put_contents( string $filename, string $contents, $mode = false ) { if ( empty( $filename ) || empty( $contents ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->put_contents( $filename, $contents, $mode ) : ( $this->suppress_errors ? @file_put_contents( $filename, $contents ) : file_put_contents( $filename, $contents ) ); } /** * Output a file directly to the response. * * @param string $filename * @return bool */ public function output_file( string $filename ): bool { if ( empty( $filename ) ) { return false; } // WP_Filesystem_Direct doesn't provide a streaming API, so fall back to get_contents(). if ( $this->is_wp_filesystem() ) { $contents = $this->wp_filesystem->get_contents( $filename ); if ( false === $contents ) { return false; } echo $contents; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped return true; } $handle = $this->suppress_errors ? @fopen( $filename, 'rb' ) : fopen( $filename, 'rb' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen if ( false === $handle ) { return false; } while ( ! feof( $handle ) ) { $buffer = fread( $handle, 8192 ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread if ( false === $buffer ) { fclose( $handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose return false; } echo $buffer; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } fclose( $handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose return true; } /** * Check if file exists * @param string $filename * @return bool */ public function exists( string $filename ): bool { if ( empty( $filename ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->exists( $filename ) : ( $this->suppress_errors ? @file_exists( $filename ) : file_exists( $filename ) ); } /** * Check if directory exists * @param string $filename * @return bool */ public function is_dir( string $filename ): bool { if ( empty( $filename ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->is_dir( $filename ) : ( $this->suppress_errors ? @is_dir( $filename ) : is_dir( $filename ) ); } /** * Create a directory * @param string $path * @return bool */ public function mkdir( string $path ): bool { if ( empty( $path ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->mkdir( $path ) : ( $this->suppress_errors ? @mkdir( $path ) : mkdir( $path ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir } /** * Check if file is writable * @param string $filename * @return bool */ public function is_writable( string $filename ): bool { if ( empty( $filename ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->is_writable( $filename ) : ( 'Windows' === PHP_OS_FAMILY ? wp_is_writable( $filename ) : ( $this->suppress_errors ? @is_writable( $filename ) : is_writable( $filename ) ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable ); } /** * Delete a file * @param string $filename * @param bool $recursive * @return bool */ public function delete( string $filename, bool $recursive = false ): bool { if ( empty( $filename ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->delete( $filename, $recursive ) : ( $this->suppress_errors ? @unlink( $filename ) : unlink( $filename ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink } /** * Get directory listing * @param string $path * @return array|bool */ public function dirlist( string $path ) { if ( empty( $path ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->dirlist( $path ) : ( $this->suppress_errors ? @scandir( $path ) : scandir( $path ) ); } /** * Get file modification time * @param string $filename * @return int|bool */ public function mtime( string $filename ) { if ( empty( $filename ) ) { return false; } return $this->is_wp_filesystem() ? $this->wp_filesystem->mtime( $filename ) : ( $this->suppress_errors ? @filemtime( $filename ) : filemtime( $filename ) ); } } endif; // Class exists check