From 3698275322edc908f570be859676598d78a28765 Mon Sep 17 00:00:00 2001 From: Shea Bunge Date: Mon, 21 Sep 2026 18:25:40 +1000 Subject: [PATCH 1/3] fix: read setting defaults without building the translated settings fields --- src/php/Settings/Settings_Fields.php | 102 +++++++-------------------- 1 file changed, 26 insertions(+), 76 deletions(-) diff --git a/src/php/Settings/Settings_Fields.php b/src/php/Settings/Settings_Fields.php index 8333c343c..04718cbe8 100644 --- a/src/php/Settings/Settings_Fields.php +++ b/src/php/Settings/Settings_Fields.php @@ -14,75 +14,19 @@ */ class Settings_Fields { - /** - * Instance of this class. - * - * @var Settings_Fields - */ - private static Settings_Fields $instance; - - /** - * The settings fields definitions. - * - * @var array> - */ - private array $fields; - - /** - * The default settings values. - * - * @var array> - */ - private array $defaults; - - /** - * Constructor. - * - * Initializes the settings fields and default values. - */ - public function __construct() { - $this->init_fields(); - $this->init_defaults(); - } - - /** - * Retrieve the instance of this class. - * - * @return Settings_Fields - */ - private static function get_instance(): Settings_Fields { - if ( ! isset( self::$instance ) ) { - self::$instance = new self(); - } - - return self::$instance; - } - /** * Retrieve the default setting values * * @return array> */ public static function get_default_values(): array { - return self::get_instance()->defaults; - } + static $defaults = []; - /** - * Retrieve the settings fields. - * - * @return array> - */ - public static function get_field_definitions(): array { - return self::get_instance()->fields; - } + if ( ! empty( $defaults ) ) { + return $defaults; + } - /** - * Initialize default settings values. - * - * @return void - */ - private function init_defaults() { - $this->defaults = [ + $defaults = [ 'general' => [ 'activate_by_default' => true, 'enable_tags' => true, @@ -116,18 +60,23 @@ private function init_defaults() { ], ]; - $this->defaults = apply_filters( 'code_snippets_settings_defaults', $this->defaults ); + $defaults = apply_filters( 'code_snippets_settings_defaults', $defaults ); + return $defaults; } /** - * Initialize the settings fields values. + * Retrieve the settings fields. * - * @return void + * @return array> */ - private function init_fields() { - $this->fields = []; + public static function get_field_definitions(): array { + static $fields = []; + + if ( ! empty( $fields ) ) { + return $fields; + } - $this->fields['debug'] = [ + $fields['debug'] = [ 'database_update' => [ 'name' => __( 'Database Table Upgrade', 'code-snippets' ), 'type' => 'action', @@ -141,7 +90,7 @@ private function init_fields() { ], ]; - $this->fields['version-switch'] = [ + $fields['version-switch'] = [ 'version_switcher' => [ 'name' => __( 'Switch Version', 'code-snippets' ), 'type' => 'callback', @@ -159,7 +108,7 @@ private function init_fields() { ], ]; - $this->fields['general'] = [ + $fields['general'] = [ 'activate_by_default' => [ 'name' => __( 'Activate by Default', 'code-snippets' ), 'type' => 'checkbox', @@ -201,7 +150,7 @@ private function init_fields() { ]; if ( ! code_snippets()->licensing->is_licensed() ) { - $this->fields['general']['hide_upgrade_menu'] = [ + $fields['general']['hide_upgrade_menu'] = [ 'name' => __( 'Hide Upgrade Notices', 'code-snippets' ), 'type' => 'checkbox', 'label' => __( 'Hide notices inviting you to upgrade to Code Snippets Pro.', 'code-snippets' ), @@ -209,20 +158,20 @@ private function init_fields() { } if ( ! is_multisite() || is_main_site() ) { - $this->fields['general']['complete_uninstall'] = [ + $fields['general']['complete_uninstall'] = [ 'name' => __( 'Complete Uninstall', 'code-snippets' ), 'type' => 'checkbox', 'label' => __( 'When the plugin is deleted from the Plugins menu, also delete all snippets and plugin settings.', 'code-snippets' ), ]; } - $this->fields['general']['enable_admin_bar'] = [ + $fields['general']['enable_admin_bar'] = [ 'name' => __( 'Enable Admin Bar Menu', 'code-snippets' ), 'type' => 'checkbox', 'label' => __( 'Show a Snippets menu in the admin bar for quick access to snippets.', 'code-snippets' ), ]; - $this->fields['general']['admin_bar_snippet_limit'] = [ + $fields['general']['admin_bar_snippet_limit'] = [ 'name' => __( 'Admin Bar Snippets Per Page', 'code-snippets' ), 'type' => 'number', 'desc' => __( 'Number of snippets to show in the admin bar Active/Inactive menus before paginating.', 'code-snippets' ), @@ -236,14 +185,14 @@ private function init_fields() { ], ]; - $this->fields['general']['enable_feedback_reporter'] = [ + $fields['general']['enable_feedback_reporter'] = [ 'name' => __( 'Enable Feedback Reporter', 'code-snippets' ), 'type' => 'checkbox', 'label' => __( 'Show a button on Code Snippets pages for reporting bugs, requesting features and sending feedback.', 'code-snippets' ), 'desc' => __( 'Reports include your site address, contact details and a list of active plugins, so that the team can reproduce the problem.', 'code-snippets' ), ]; - $this->fields['editor'] = [ + $fields['editor'] = [ 'indent_with_tabs' => [ 'name' => __( 'Indent With Tabs', 'code-snippets' ), 'type' => 'checkbox', @@ -330,6 +279,7 @@ private function init_fields() { ], ]; - $this->fields = apply_filters( 'code_snippets_settings_fields', $this->fields ); + $fields = apply_filters( 'code_snippets_settings_fields', $fields ); + return $fields; } } From 42fc46c1ad887d0893976276714044fb2d2905a9 Mon Sep 17 00:00:00 2001 From: TallblokeUK Date: Sun, 11 Oct 2026 11:50:56 +0100 Subject: [PATCH 2/3] docs: note the early translation loading fix in the changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa136b51e..8aff7200c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,8 @@ snippet running under file-based execution. * Fixed the snippet editor reporting a save as failed and undelivered when no response was received, which it cannot determine. +* Fixed translations being loaded too early, with a notice from WordPress, when posts were queried while plugins were + still loading. ## [3.10.2] (2026-09-01) From 89621d222cfeefbfe98ce7c6b1cfaddada717e62 Mon Sep 17 00:00:00 2001 From: TallblokeUK Date: Sun, 11 Oct 2026 11:51:04 +0100 Subject: [PATCH 3/3] test: cover reading settings before translations may load --- .../Settings_Early_Translation_Test.php | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/unit/Settings/Settings_Early_Translation_Test.php diff --git a/tests/unit/Settings/Settings_Early_Translation_Test.php b/tests/unit/Settings/Settings_Early_Translation_Test.php new file mode 100644 index 000000000..efbf6b8f4 --- /dev/null +++ b/tests/unit/Settings/Settings_Early_Translation_Test.php @@ -0,0 +1,103 @@ +translated[] = $text; + } + + return $translation; + } + + /** + * Start recording, with the cached settings cleared so the read is a cold one. + * + * @return void + */ + private function start_recording(): void { + wp_cache_delete( CACHE_KEY, CACHE_GROUP ); + $this->translated = []; + + add_filter( 'gettext', [ $this, 'record_translation' ], 10, 3 ); + } + + /** + * A setting's value can be read without translating anything. + * + * @runInSeparateProcess + * @preserveGlobalState disabled + * + * @return void + */ + public function test_reading_a_setting_translates_nothing(): void { + $this->start_recording(); + + get_setting( 'general', 'disable_prism' ); + + $this->assertSame( + [], + $this->translated, + 'reading a setting should not translate anything, as settings are read before translations may load' + ); + } + + /** + * A post query handled by the shortcode filter translates nothing. + * + * @runInSeparateProcess + * @preserveGlobalState disabled + * + * @return void + */ + public function test_a_post_query_translates_nothing(): void { + $post_id = $this->factory()->post->create( [ 'post_content' => 'No shortcodes in here.' ] ); + + $this->start_recording(); + + $query = new WP_Query( [ 'p' => $post_id ] ); + + $this->assertCount( 1, $query->posts, 'the query should return a post, or the filter has nothing to handle' ); + $this->assertSame( + [], + $this->translated, + 'a post query should not translate anything, as one can run while plugins are still loading' + ); + } +}