PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.2
4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 All 200 releases
← All changes | includes/Core/Install.php +49 -40 4.8.14.9.2 View file →
@@ -152,13 +152,20 @@
152 152 global $wpdb;
153 153
154 154 $charset_collate = $wpdb->get_charset_collate();
155 155
156 + // keyword_hash exists purely to make the lookup indexable: `keyword` is
157 + // TEXT and is matched with BINARY (for collation safety), which no index
158 + // can serve — so every front-end search used to full-scan this table.
159 + // The hash narrows to a single row via the index; the BINARY comparison
160 + // still decides the match, so behaviour is unchanged.
156 161 $search_keyword_table = $wpdb->prefix . 'betterdocs_search_keyword';
157 162 $search_keyword = "CREATE TABLE $search_keyword_table (
158 163 id bigint NOT NULL AUTO_INCREMENT,
159 164 keyword text NOT NULL,
160 - PRIMARY KEY (id)
165 + keyword_hash char(32) NOT NULL DEFAULT '',
166 + PRIMARY KEY (id),
167 + KEY keyword_hash (keyword_hash)
161 168 ) {$charset_collate};";
162 169
163 170 $search_log_table = $wpdb->prefix . 'betterdocs_search_log';
164 171 $search_log = "CREATE TABLE $search_log_table (
@@ -193,8 +200,11 @@
193 200 KEY created_at (created_at),
194 201 UNIQUE KEY post_created (post_id, created_at)
195 202 ) {$charset_collate};";
196 203
204 + // The betterdocs_api_specs table moved to Pro (API Documentation is a
205 + // Pro-only feature; Pro's Install creates it).
206 +
197 207 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
198 208 dbDelta( $search_keyword . $search_log . $analytics_table );
199 209
200 210 // Update DB Version
@@ -201,11 +211,46 @@
201 211 update_option( 'betterdocs_db_version', $_db_code_version );
202 212 }
203 213
204 214 public function migrate_customizer() {
205 - $search_layout = get_theme_mod( 'betterdocs_search_layout_select' );
206 - if ( empty( $search_layout ) ) {
207 - set_theme_mod( 'betterdocs_search_layout_select', 'layout-1' );
215 + /**
216 + * Seed the layout Customizer settings for installs that never explicitly
217 + * picked a layout. Some consumers read the raw theme_mod without a fallback
218 + * (e.g. FrontEnd::article_reactions()), so an unseeded mod can render
219 + * differently from the layout the front-end otherwise defaults to.
220 + *
221 + * Two rules keep this safe and correct:
222 + * 1. Only seed a mod that has never been set ( get_theme_mod() === false ).
223 + * An explicit choice — including an explicit 'layout-1' — is never
224 + * overwritten, so existing sites cannot change layout on update.
225 + * 2. Pull the value from Customizer\Defaults (the single source of truth
226 + * the front-end already renders from) instead of a hardcoded string, so
227 + * it can never drift from the real default again. Pro defaults are merged
228 + * in automatically when BetterDocs Pro is active.
229 + */
230 + $defaults = betterdocs()->customizer->defaults->defaults();
231 + $layout_mods = [
232 + 'betterdocs_search_layout_select',
233 + 'betterdocs_docs_layout_select',
234 + 'betterdocs_single_layout_select',
235 + 'betterdocs_archive_layout_select',
236 + 'betterdocs_select_faq_template',
237 + 'betterdocs_multikb_layout_select', // BetterDocs Pro.
238 + 'betterdocs_select_faq_template_mkb', // BetterDocs Pro.
239 + ];
240 +
241 + foreach ( $layout_mods as $mod ) {
242 + // Respect an explicit user choice (including an explicit 'layout-1').
243 + if ( get_theme_mod( $mod, false ) !== false ) {
244 + continue;
245 + }
246 +
247 + // Only seed when a real default is registered (skips inactive add-ons).
248 + if ( empty( $defaults[ $mod ] ) ) {
249 + continue;
250 + }
251 +
252 + set_theme_mod( $mod, $defaults[ $mod ] );
208 253 }
209 254
210 255 $search_heading = get_theme_mod( 'betterdocs_live_search_heading_switch' );
211 256 if ( empty( $search_heading ) ) {
@@ -211,45 +256,9 @@
211 256 if ( empty( $search_heading ) ) {
212 257 set_theme_mod( 'betterdocs_live_search_heading_switch', false );
213 258 }
214 259
215 - $docs_layout = get_theme_mod( 'betterdocs_docs_layout_select' );
216 - if ( empty( $docs_layout ) ) {
217 - set_theme_mod( 'betterdocs_docs_layout_select', 'layout-1' );
218 - }
219 -
220 - $single_layout = get_theme_mod( 'betterdocs_single_layout_select' );
221 - if ( empty( $single_layout ) ) {
222 - set_theme_mod( 'betterdocs_single_layout_select', 'layout-1' );
223 - }
224 -
225 - $category_archive_layout = get_theme_mod( 'betterdocs_archive_layout_select' );
226 - if ( empty( $category_archive_layout ) ) {
227 - set_theme_mod( 'betterdocs_archive_layout_select', 'layout-1' );
228 - }
229 -
230 - $search_layout_select = get_theme_mod( 'betterdocs_search_layout_select' );
231 - if ( empty( $search_layout_select ) ) {
232 - set_theme_mod( 'betterdocs_search_layout_select', 'layout-1' );
233 - }
234 -
235 - $docs_faq = get_theme_mod( 'betterdocs_select_faq_template' );
236 - if ( empty( $docs_faq ) ) {
237 - set_theme_mod( 'betterdocs_select_faq_template', 'layout-1' );
238 - }
239 -
240 260 if ( get_option( 'betterdocs_settings' ) && betterdocs()->settings->get( 'enable_estimated_reading_time' ) == false ) {
241 261 betterdocs()->settings->save( 'enable_estimated_reading_time', false );
242 - }
243 -
244 - if ( function_exists( 'betterdocs_pro' ) ) {
245 - $mkb_layout = get_theme_mod( 'betterdocs_multikb_layout_select' );
246 - if ( empty( $mkb_layout ) ) {
247 - set_theme_mod( 'betterdocs_multikb_layout_select', 'layout-1' );
248 - }
249 - $mkb_faq = get_theme_mod( 'betterdocs_select_faq_template_mkb' );
250 - if ( empty( $mkb_faq ) ) {
251 - set_theme_mod( 'betterdocs_select_faq_template_mkb', 'layout-1' );
252 - }
253 262 }
254 263 }
255 264 }