Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
* Fixed featured Community Cloud snippets failing to load with some cloud API responses. (PRO)
* Fixed bulk actions in Community Cloud running against an empty selection, so selected snippets were never downloaded.
(PRO)
* Fixed file-based execution keeping a snippet active after it was deactivated, when a stale object-cache copy was
written into the on-disk index.

## [3.10.2] (2026-09-01)

Expand Down
34 changes: 34 additions & 0 deletions src/php/Flat_Files/Snippet_Files.php
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ public function deactivate_snippet( int $snippet_id, bool $network ): void {
return;
}

// The object-cache copy can still say active; the database row does not.
$snippet->active = false;

$table = self::get_hashed_table_name( code_snippets()->db->get_table_name( $network ) );
$base_dir = self::get_base_dir( $table, $handler->get_dir_name() );

Expand Down Expand Up @@ -645,12 +648,14 @@ private function create_snippet_flat_files(): void {
$db = code_snippets()->db;

$scopes = Snippet::get_all_scopes();
$indexes = [];

$data = $db->fetch_active_snippets( $scopes );

foreach ( $data as $snippet ) {
$snippet_obj = get_snippet( $snippet['id'], $db->ms_table === $snippet['table'] );
$this->handle_snippet( $snippet_obj, $snippet['table'] );
$this->remember_index_entry( $indexes, $snippet_obj, $snippet['table'] );
}

if ( is_multisite() ) {
Expand All @@ -664,13 +669,42 @@ private function create_snippet_flat_files(): void {
$table_name = $snippet['table'];
$snippet_obj = get_snippet( $snippet['id'], false );
$this->handle_snippet( $snippet_obj, $table_name );
$this->remember_index_entry( $indexes, $snippet_obj, $table_name );
}

restore_current_blog();
}

$db->set_table_vars();
}

foreach ( $indexes as $base_dir => $snippets ) {
$this->config_repo->save( $base_dir, $snippets );
}
}

/**
* Record a snippet for a full index rewrite.
*
* handle_snippet() merges into the existing index, which can leave a
* deactivated snippet marked active. Replacing the index with only the
* currently active set drops those stale entries.
*
* @param array<string, array<int, array<string, mixed>>> $indexes Index lists keyed by directory.
* @param Snippet $snippet Snippet just written.
* @param string $table Database table name.
*
* @return void
*/
private function remember_index_entry( array &$indexes, Snippet $snippet, string $table ): void {
$handler = $this->handler_registry->get_handler( $snippet->type );

if ( ! $handler ) {
return;
}

$base_dir = self::get_base_dir( self::get_hashed_table_name( $table ), $handler->get_dir_name() );
$indexes[ $base_dir ][ $snippet->id ] = $snippet->get_fields();
}

/**
Expand Down
9 changes: 7 additions & 2 deletions src/php/snippet-ops.php
Original file line number Diff line number Diff line change
Expand Up @@ -562,15 +562,20 @@ function deactivate_snippet( int $id, ?bool $network = null ): ?Snippet {
return null;
}

// Flush before get_snippet() so file-based execution does not write a stale
// cached "active" object into wp-content/code-snippets/*/index.php.
clean_snippets_cache( $table );

$snippet = get_snippet( $id, $network );
$snippet->active = false;

// Update the recently active list.
$snippet = get_snippet( $id );
$recently_active = get_self_option( $network, 'recently_active_snippets', [] );
$recently_active[ $id ] = time();
update_self_option( $network, 'recently_active_snippets', $recently_active );

update_shared_network_snippets( [ $snippet ] );
do_action( 'code_snippets/deactivate_snippet', $id, $network );
clean_snippets_cache( $table );

return $snippet;
}
Expand Down
Loading