Skip to content

File-based execution keeps running snippets after they are deactivated #561

Description

@robertstaddon

Current behavior

With Enable File-Based Execution turned on, deactivating a snippet updates the database (active = 0) and the Snippets admin list, but the snippet keeps executing on the front end.

File-based execution reads wp-content/code-snippets/{hash}/php/index.php, not the database. After deactivate, that index still contains the snippet with 'active' => 1 (and {id}.php is still loaded). Purging page cache does not help, because this is the on-disk execution index, not a page cache.

A second, related symptom: turning file-based execution off makes the snippet actually stop (database is respected). Turning it back on can bring the deactivated snippet back, because a full index rebuild merges into the existing index.php instead of replacing it with only currently active snippets.

Without file-based execution, deactivate works as expected.

Expected behavior

Deactivating a snippet should immediately stop file-based execution of that snippet: the on-disk index should mark it inactive or drop it, and a later rebuild of the files should not resurrect it.

Steps to reproduce

  1. Enable Snippets → Settings → Enable File-Based Execution.
  2. Create a PHP snippet with Run everywhere (or Global), for example:
add_action( 'wp_footer', static function () {
	echo '<!-- CS-DEACTIVATE-TEST -->';
} );
  1. Save and activate. Confirm the comment appears in the page source.
  2. Deactivate the snippet from All Snippets. Confirm the list shows it inactive.
  3. View the front end (bypass page cache if needed). The comment is still in the source.
  4. Open wp-content/code-snippets/*/php/index.php. The snippet is still listed with 'active' => 1.
  5. Disable Enable File-Based Execution. The comment disappears.
  6. Re-enable file-based execution. The comment often comes back even though the snippet is still inactive in the database.

WordPress version

7.1

Code Snippets version

3.10.2 (Pro). The same deactivate_snippet() order is still in current GitHub develop.

Code Snippets license

Pro

Anything else?

This is easy to miss: the admin UI is correct, only the file-based runner is wrong.

Root cause

deactivate_snippet() in src/php/snippet-ops.php (Pro: php/snippet-ops.php):

  1. Sets active = 0 in the database.
  2. Calls get_snippet( $id ) before clean_snippets_cache().
  3. Fires code_snippets/deactivate_snippet.
  4. Flushes the object cache after that action.

get_snippet() returns the cached object from all_snippets_{table}, which still has active === true. The snippets list has usually already populated that cache in the same request.

Snippet_Files::deactivate_snippet() is hooked to that action. It calls get_snippet() again and Flat_File_Config_Repository::update(), which merges $snippet->get_fields() into index.php. That writes 'active' => 1 back onto disk.

quick_deactivate_snippet() in Evaluate_Functions already does this in the right order (DB → flush cache → action). The normal deactivate path does not.

On rebuild, create_snippet_flat_files() / handle_snippet() also merge into the existing index, so a stale 'active' => 1 entry for a snippet that is no longer in fetch_active_snippets() can survive when file-based execution is turned back on.

Suggested fix (small)

  • Flush the snippet object cache before get_snippet() / the deactivate action.
  • Force $snippet->active = false before writing the index (or pass $remove = true into config_repo->update()).
  • On a full file rebuild, replace each type’s index.php with the currently active set instead of merging.

I have a local patch along those lines and can open a PR.

Workaround

Leave Enable File-Based Execution off, or delete the stale entry from php/index.php (and the matching {id}.php) until this is fixed.

How we hit it

A deactivated PHP snippet still ran under file-based execution and changed front-end query behavior. Disabling every other plugin did not help; disabling file-based execution did. Re-enabling file-based execution brought the inactive snippet back without changing the database row.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions