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 +58 -43 4.5.24.9.2 View file →
@@ -1,8 +1,12 @@
1 1 <?php
2 +namespace WPDeveloper\BetterDocs\Core;
2 3
3 -namespace WPDeveloper\BetterDocs\Core;
4 +if ( ! defined( 'ABSPATH' ) ) {
5 + exit;
6 +}
4 7
8 +
5 9 use WPDeveloper\BetterDocs\Utils\Base;
6 10 use WPDeveloper\BetterDocs\Utils\Database;
7 11 use WPDeveloper\BetterDocs\Dependencies\DI\Container;
8 12
@@ -148,13 +152,20 @@
148 152 global $wpdb;
149 153
150 154 $charset_collate = $wpdb->get_charset_collate();
151 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.
152 161 $search_keyword_table = $wpdb->prefix . 'betterdocs_search_keyword';
153 162 $search_keyword = "CREATE TABLE $search_keyword_table (
154 163 id bigint NOT NULL AUTO_INCREMENT,
155 164 keyword text NOT NULL,
156 - PRIMARY KEY (id)
165 + keyword_hash char(32) NOT NULL DEFAULT '',
166 + PRIMARY KEY (id),
167 + KEY keyword_hash (keyword_hash)
157 168 ) {$charset_collate};";
158 169
159 170 $search_log_table = $wpdb->prefix . 'betterdocs_search_log';
160 171 $search_log = "CREATE TABLE $search_log_table (
@@ -164,9 +175,10 @@
164 175 not_found_count mediumint(9) NULL,
165 176 created_at date DEFAULT '0000-00-00' NOT NULL,
166 177 PRIMARY KEY (id),
167 178 KEY keyword_id (keyword_id),
168 - KEY created_at (created_at)
179 + KEY created_at (created_at),
180 + KEY keyword_created (keyword_id, created_at)
169 181 ) {$charset_collate};";
170 182
171 183 $_analytics_table = $wpdb->prefix . 'betterdocs_analytics';
172 184 $analytics_table = "CREATE TABLE $_analytics_table (
@@ -184,11 +196,15 @@
184 196 KEY unique_visit (unique_visit),
185 197 KEY happy (happy),
186 198 KEY sad (sad),
187 199 KEY normal (normal),
188 - KEY created_at (created_at)
200 + KEY created_at (created_at),
201 + UNIQUE KEY post_created (post_id, created_at)
189 202 ) {$charset_collate};";
190 203
204 + // The betterdocs_api_specs table moved to Pro (API Documentation is a
205 + // Pro-only feature; Pro's Install creates it).
206 +
191 207 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
192 208 dbDelta( $search_keyword . $search_log . $analytics_table );
193 209
194 210 // Update DB Version
@@ -195,11 +211,46 @@
195 211 update_option( 'betterdocs_db_version', $_db_code_version );
196 212 }
197 213
198 214 public function migrate_customizer() {
199 - $search_layout = get_theme_mod( 'betterdocs_search_layout_select' );
200 - if ( empty( $search_layout ) ) {
201 - 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 ] );
202 253 }
203 254
204 255 $search_heading = get_theme_mod( 'betterdocs_live_search_heading_switch' );
205 256 if ( empty( $search_heading ) ) {
@@ -205,45 +256,9 @@
205 256 if ( empty( $search_heading ) ) {
206 257 set_theme_mod( 'betterdocs_live_search_heading_switch', false );
207 258 }
208 259
209 - $docs_layout = get_theme_mod( 'betterdocs_docs_layout_select' );
210 - if ( empty( $docs_layout ) ) {
211 - set_theme_mod( 'betterdocs_docs_layout_select', 'layout-1' );
212 - }
213 -
214 - $single_layout = get_theme_mod( 'betterdocs_single_layout_select' );
215 - if ( empty( $single_layout ) ) {
216 - set_theme_mod( 'betterdocs_single_layout_select', 'layout-1' );
217 - }
218 -
219 - $category_archive_layout = get_theme_mod( 'betterdocs_archive_layout_select' );
220 - if ( empty( $category_archive_layout ) ) {
221 - set_theme_mod( 'betterdocs_archive_layout_select', 'layout-1' );
222 - }
223 -
224 - $search_layout_select = get_theme_mod( 'betterdocs_search_layout_select' );
225 - if ( empty( $search_layout_select ) ) {
226 - set_theme_mod( 'betterdocs_search_layout_select', 'layout-1' );
227 - }
228 -
229 - $docs_faq = get_theme_mod( 'betterdocs_select_faq_template' );
230 - if ( empty( $docs_faq ) ) {
231 - set_theme_mod( 'betterdocs_select_faq_template', 'layout-1' );
232 - }
233 -
234 260 if ( get_option( 'betterdocs_settings' ) && betterdocs()->settings->get( 'enable_estimated_reading_time' ) == false ) {
235 261 betterdocs()->settings->save( 'enable_estimated_reading_time', false );
236 - }
237 -
238 - if ( function_exists( 'betterdocs_pro' ) ) {
239 - $mkb_layout = get_theme_mod( 'betterdocs_multikb_layout_select' );
240 - if ( empty( $mkb_layout ) ) {
241 - set_theme_mod( 'betterdocs_multikb_layout_select', 'layout-1' );
242 - }
243 - $mkb_faq = get_theme_mod( 'betterdocs_select_faq_template_mkb' );
244 - if ( empty( $mkb_faq ) ) {
245 - set_theme_mod( 'betterdocs_select_faq_template_mkb', 'layout-1' );
246 - }
247 262 }
248 263 }
249 264 }