Skip to content

fix(filesystem): replace raw filesystem operations with WP_Filesystem APIs#3197

Open
faisalahammad wants to merge 2 commits into
gocodebox:devfrom
faisalahammad:fix/filesystem-api-replacement
Open

fix(filesystem): replace raw filesystem operations with WP_Filesystem APIs#3197
faisalahammad wants to merge 2 commits into
gocodebox:devfrom
faisalahammad:fix/filesystem-api-replacement

Conversation

@faisalahammad

Copy link
Copy Markdown
Contributor

Summary

Replace raw PHP filesystem operations flagged by Plugin Check with WP_Filesystem APIs and wp_delete_file()/wp_tempnam() helpers across 5 files. All 18 file_system_operations_* errors resolved.

Changes

includes/class.llms.data.php — get_file_version()

Before:

$fp = fopen( $file, 'r' );
$file_data = fread( $fp, 8192 );
fclose( $fp );

After:

global $wp_filesystem;
require_once ABSPATH . 'wp-admin/includes/file.php';
if ( ! WP_Filesystem() ) {
    return '';
}
$file_data = $wp_filesystem->get_contents( $file );
$file_data = substr( $file_data, 0, 8192 );

Why: Plugin Check flags fopen/fread/fclose as raw filesystem calls. WP_Filesystem get_contents() reads in one call and we slice the first 8KB via substr.

includes/class.llms.install.php — create_files()

Before:

$file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' );
if ( $file_handle ) {
    fwrite( $file_handle, $file['content'] );
    fclose( $file_handle );
}

After:

global $wp_filesystem;
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem();
// ...
if ( wp_mkdir_p( $file['base'] ) && ! $wp_filesystem->exists( $file_path ) ) {
    $wp_filesystem->put_contents( $file_path, $file['content'], 0644 );
}

Why: Drop phpcs:ignore comments and use WP_Filesystem put_contents(). Removes 3 phpcs:ignore annotations on the previous lines.

includes/admin/class-llms-admin-export-download.php

Before: unlink( $path );
After: wp_delete_file( $path );

Why: wp_delete_file() is the WordPress wrapper for unlink() and is the recommended API per WordPress coding standards.

includes/admin/class.llms.admin.page.status.php — remove_log_file()

Before:

if ( $log && is_file( $log ) && is_writable( $log ) ) {
    unlink( $log );

After:

global $wp_filesystem;
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem();

if ( $log && $wp_filesystem->exists( $log ) && $wp_filesystem->is_writable( $log ) ) {
    wp_delete_file( $log );

Why: Plugin Check flags is_writable and unlink. Use the WP_Filesystem equivalents plus wp_delete_file.

includes/admin/post-types/meta-boxes/class.llms.meta.box.voucher.export.php

array_to_csv()

Before: Used fopen('php://temp') + fputcsv + fread + fclose to build an in-memory CSV string.

After: Builds CSV directly via a new csv_row() helper that produces RFC 4180 compliant output without touching a stream.

Why: fopen/fread/fclose were flagged. CSV format identical to fputcsv for flat fields (always-enclosed, doubled enclosure for embedded quotes). Signature and return type unchanged, existing callers unaffected.

send_email()

Before: tempnam + fopen + fwrite + rename + fclose + unlink.

After: wp_tempnam() + WP_Filesystem::put_contents() + wp_delete_file().

Why: Use the WordPress temp file helper and WP_Filesystem write instead of low-level stream and filesystem ops.

Skipped

  • includes/class-llms-media-protector.php:606 readfile(): already has phpcs:ignore. Intentional. Streams large protected media files to the browser. WP_Filesystem::get_contents() would load the entire file into memory which is worse for large media.

Testing

  1. php -l on all 5 modified files: no syntax errors
  2. vendor/bin/phpcs --sniffs=WordPress.WP.AlternativeFunctions on modified files: zero errors
  3. composer check-cs full project run: zero errors
  4. Manual review of each change confirms behavior preserved (file read returns same 8KB slice, file write produces identical content, log deletion logic equivalent, CSV output identical for flat voucher data, email attachment still sent with .csv extension)

Build

Two commits on fix/filesystem-api-replacement:

  • 468d6f9fb fix: replace raw filesystem operations with WP_Filesystem APIs
  • bc2c4c9a9 chore: add changelog entry for filesystem API fix

Replace fopen/fread/fwrite/fclose/unlink/rename/is_writable calls flagged
by Plugin Check with WP_Filesystem methods and wp_delete_file/wp_tempnam
helpers across 5 files.

- class.llms.data.php: get_file_version() reads via WP_Filesystem::get_contents().
- class.llms.install.php: create_files() writes via WP_Filesystem::put_contents().
- class-llms-admin-export-download.php: unlink() -> wp_delete_file().
- class.llms.admin.page.status.php: is_file/is_writable/unlink replaced with WP_Filesystem equivalents.
- class.llms.meta.box.voucher.export.php: array_to_csv() builds CSV string without streams; send_email() writes via WP_Filesystem::put_contents() and removes with wp_delete_file().
@faisalahammad faisalahammad requested a review from brianhogg as a code owner June 19, 2026 05:16
@brianhogg brianhogg moved this to Awaiting Review in Development Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Awaiting Review

Development

Successfully merging this pull request may close these issues.

2 participants