PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.5.3
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.5.3
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 3.5.2 All 199 releases
← All changes | includes/Plugin.php +65 -211 4.8.13.5.3 View file →
@@ -5,42 +5,32 @@
5 5 if ( ! defined( 'ABSPATH' ) ) {
6 6 exit; // Exit if accessed directly
7 7 }
8 8
9 -use WPDeveloper\BetterDocs\Admin\Analytics;
10 -use WPDeveloper\BetterDocs\Admin\Customizer\Customizer;
11 -use WPDeveloper\BetterDocs\Admin\HelpScoutMigration;
12 -use WPDeveloper\BetterDocs\Admin\ReportEmail;
13 9 use WPDeveloper\BetterDocs\Core\Admin;
14 -use WPDeveloper\BetterDocs\Core\AnalyticsTracker;
15 -use WPDeveloper\BetterDocs\Core\AnalyticsRetention;
10 +use WPDeveloper\BetterDocs\Core\Query;
11 +use WPDeveloper\BetterDocs\Core\Roles;
12 +use WPDeveloper\BetterDocs\Core\WriteWithAI;
13 +use WPDeveloper\BetterDocs\Dependencies\DI\Container;
14 +use WPDeveloper\BetterDocs\Utils\Views;
16 15 use WPDeveloper\BetterDocs\Core\BaseAPI;
17 16 use WPDeveloper\BetterDocs\Core\Install;
18 -use WPDeveloper\BetterDocs\Core\KBMigration;
19 -use WPDeveloper\BetterDocs\Core\Query;
20 17 use WPDeveloper\BetterDocs\Core\Request;
21 18 use WPDeveloper\BetterDocs\Core\Rewrite;
22 -use WPDeveloper\BetterDocs\Core\Roles;
23 19 use WPDeveloper\BetterDocs\Core\Scripts;
20 +use WPDeveloper\BetterDocs\Utils\Helper;
24 21 use WPDeveloper\BetterDocs\Core\Settings;
25 -use WPDeveloper\BetterDocs\Core\ShortcodeFactory;
26 -use WPDeveloper\BetterDocs\Core\WriteWithAI;
27 -use WPDeveloper\BetterDocs\Core\ArticleSummary;
28 -use WPDeveloper\BetterDocs\Core\ArticleQualityScore;
29 -use WPDeveloper\BetterDocs\Core\UnifiedMetabox;
30 -use WPDeveloper\BetterDocs\Core\DocsAISuite;
31 -use WPDeveloper\BetterDocs\Dependencies\DI\Container;
32 -use WPDeveloper\BetterDocs\Dependencies\DI\ContainerBuilder;
22 +use WPDeveloper\BetterDocs\Core\KBMigration;
23 +use WPDeveloper\BetterDocs\Utils\Enqueue;
33 24 use WPDeveloper\BetterDocs\Editors\Editor;
25 +use WPDeveloper\BetterDocs\Utils\Database;
26 +use WPDeveloper\BetterDocs\Admin\Analytics;
27 +use WPDeveloper\BetterDocs\Admin\ReportEmail;
34 28 use WPDeveloper\BetterDocs\FrontEnd\FrontEnd;
35 -use WPDeveloper\BetterDocs\FrontEnd\SearchExtender;
29 +use WPDeveloper\BetterDocs\Core\ShortcodeFactory;
36 30 use WPDeveloper\BetterDocs\FrontEnd\TemplateTags;
37 -use WPDeveloper\BetterDocs\FrontEnd\WooProductFAQ;
38 -use WPDeveloper\BetterDocs\Modules\StyleHandler as ModulesStyleHandler;
39 -use WPDeveloper\BetterDocs\Utils\Database;
40 -use WPDeveloper\BetterDocs\Utils\Enqueue;
41 -use WPDeveloper\BetterDocs\Utils\Helper;
42 -use WPDeveloper\BetterDocs\Utils\Views;
31 +use WPDeveloper\BetterDocs\Admin\Customizer\Customizer;
32 +use WPDeveloper\BetterDocs\Dependencies\DI\ContainerBuilder;
43 33
44 34 final class Plugin {
45 35 private static $_instance = null;
46 36 /**
@@ -96,13 +86,8 @@
96 86 * @var TemplateTags
97 87 */
98 88 public $template_helper;
99 89 /**
100 - * Article Summary class
101 - * @var ArticleSummary
102 - */
103 - public $article_summary;
104 - /**
105 90 * Customizer class
106 91 * @var Customizer
107 92 */
108 93 public $customizer;
@@ -129,9 +114,9 @@
129 114 /**
130 115 * Plugin Version
131 116 * @var string
132 117 */
133 - public $version = '4.8.1';
118 + public $version = '3.5.3';
134 119
135 120 /**
136 121 * WriteWithAI Class
137 122 * @var string
@@ -136,27 +121,19 @@
136 121 * WriteWithAI Class
137 122 * @var string
138 123 */
139 124 public $ai_autowrtie;
140 - public $backgroundProccessor;
141 125
142 126 /**
143 - * ArticleQualityScore Class
144 - * @var ArticleQualityScore
145 - */
146 - public $article_quality_score;
147 -
148 - /**
149 127 * Plugin DB Version
150 128 * @var string
151 129 */
152 - public $db_version = '1.0.2';
130 + public $db_version = '1.0.1';
153 131
154 132 public function __construct() {
155 133 $this->define_constants();
156 134
157 135 do_action( 'betterdocs_init_before' );
158 -
159 136 $this->setup_container();
160 137 /**
161 138 * Register activation and deactivation hooks
162 139 * and version updates check
@@ -162,29 +139,21 @@
162 139 * and version updates check
163 140 */
164 141 $this->container->get( Install::class );
165 142
166 - add_action( 'init', array( $this, 'initialize' ), 0 );
143 + $this->initialize();
167 144
168 - /**
169 - * Initialize API
170 - */
171 - add_action( 'rest_api_init', array( $this, 'api_initialization' ) );
145 + add_action( 'init', [ $this, 'init' ], 0 );
172 146
173 147 /**
174 148 * For admin only
175 149 */
176 - add_action( 'admin_init', array( $this, 'admin_init' ), 0 );
150 + add_action( 'admin_init', [ $this, 'admin_init' ], 0 );
177 151
178 152 /**
179 153 * For AJAX only
180 154 */
181 155 $this->ajax();
182 -
183 - /**
184 - * Style Handler For Parsing and Saving Styles as file.
185 - */
186 - ModulesStyleHandler::init();
187 156 }
188 157
189 158 private function define_constants() {
190 159 $this->define( 'BETTERDOCS_VERSION', $this->version );
@@ -191,11 +160,9 @@
191 160 $this->define( 'BETTERDOCS_DB_VERSION', $this->db_version );
192 161 $this->define( 'BETTERDOCS_ABSPATH', dirname( BETTERDOCS_PLUGIN_FILE ) . '/' );
193 162 $this->define( 'BETTERDOCS_ABSURL', plugin_dir_url( BETTERDOCS_PLUGIN_FILE ) );
194 163 $this->define( 'BETTERDOCS_PLUGIN_BASENAME', plugin_basename( BETTERDOCS_PLUGIN_FILE ) );
195 - // Compiled block metadata lives under assets/build/ since the Node 24 asset
196 - // restructure; register_block_type() fails silently if this path is wrong.
197 - $this->define( 'BETTERDOCS_BLOCKS_DIRECTORY', BETTERDOCS_ABSPATH . 'assets/build/blocks/' );
164 + $this->define( 'BETTERDOCS_BLOCKS_DIRECTORY', BETTERDOCS_ABSPATH . 'assets/blocks/' );
198 165 $this->define( 'BETTERDOCS_ROOT_DIR_PATH', plugin_dir_path( BETTERDOCS_PLUGIN_FILE ) );
199 166 $this->define( 'BETTERDOCS_FSE_TEMPLATES_PATH', BETTERDOCS_ROOT_DIR_PATH . 'views/templates/fse' );
200 167
201 168 /**
@@ -204,10 +171,8 @@
204 171 *
205 172 * WPML compatibility with Polylang
206 173 */
207 174 if ( Helper::is_plugin_active( 'polylang/polylang.php' ) ) {
208 - // Polylang's documented integration constant — must use the upstream-defined name.
209 - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
210 175 define( 'PLL_WPML_COMPAT', false );
211 176 }
212 177 }
213 178
@@ -213,15 +178,13 @@
213 178
214 179 /**
215 180 * Define constant if not already set.
216 181 *
217 - * @param string $name Constant name.
182 + * @param string $name Constant name.
218 183 * @param string|bool $value Constant value.
219 184 */
220 185 private function define( $name, $value ) {
221 186 if ( ! defined( $name ) ) {
222 - // Caller passes plugin-prefixed names (BETTERDOCS_*); $name comes from a controlled internal allowlist.
223 - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.VariableConstantNameFound
224 187 define( $name, $value );
225 188 }
226 189 }
227 190
@@ -234,59 +197,58 @@
234 197 $this->container = $builder->build();
235 198 }
236 199
237 200 public function initialize() {
238 -
239 - /**
240 - * Setup localization.
241 - */
242 - $this->load_plugin_textdomain();
243 -
244 201 $this->container->get( Scripts::class );
245 202 $this->rewrite = $this->container->get( Rewrite::class );
246 203 $this->request = $this->container->get( Request::class );
247 204 $this->query = $this->container->get( Query::class );
248 205
249 - // Initialize background process
250 - $this->backgroundProccessor = $this->container->get( HelpScoutMigration::class );
251 -
252 206 $this->rewrite->init();
253 207 $this->request->init();
254 208
255 - $this->assets = $this->container->get( Enqueue::class );
256 - $this->views = $this->container->get( Views::class );
257 - $this->helper = $this->container->get( Helper::class );
258 - $this->kbmigration = $this->container->get( KBMigration::class );
259 - $this->admin = $this->container->get( Admin::class );
260 - $this->database = $this->container->get( Database::class );
261 - $this->settings = $this->container->get( Settings::class );
262 - $this->analytics = $this->container->get( Analytics::class );
263 - // Free analytics collectors: the frontend view/scroll tracker and the
264 - // daily retention purge. Each self-registers its hooks on construct.
265 - $this->container->get( AnalyticsTracker::class );
266 - $this->container->get( AnalyticsRetention::class );
209 + $this->assets = $this->container->get( Enqueue::class );
210 + $this->views = $this->container->get( Views::class );
211 + $this->helper = $this->container->get( Helper::class );
212 + $this->kbmigration = $this->container->get( KBMigration::class );
213 + $this->admin = $this->container->get( Admin::class );
214 + $this->database = $this->container->get( Database::class );
215 + $this->settings = $this->container->get( Settings::class );
216 + $this->analytics = $this->container->get( Analytics::class );
267 217
268 218 $this->template_helper = $this->container->get( TemplateTags::class );
269 219 $this->customizer = $this->container->get( Customizer::class );
270 220 $this->editor = $this->container->get( Editor::class );
271 - $this->ai_autowrtie = $this->container->get( WriteWithAI::class );
272 - $this->article_summary = $this->container->get( ArticleSummary::class );
221 + $this->ai_autowrtie = $this->container->get( WriteWithAI::class );
273 222
274 - // Initialize unified metabox before individual features
275 - $this->container->get( UnifiedMetabox::class );
276 - $this->article_quality_score = $this->container->get( ArticleQualityScore::class );
223 + /**
224 + * Initialize all editors.
225 + * Elementor, Gutenberg/BlockEditor
226 + */
227 + add_action( 'init', [ $this->editor, 'init' ] );
277 228
278 - // Editor "Suggest Categories / Tags / Glossaries" AI actions on the docs
279 - // post type (gated by enable_docs_ai_suite + an OpenAI key inside the class).
280 - $this->container->get( DocsAISuite::class );
229 + /**
230 + * Initialize API
231 + */
232 + add_action( 'rest_api_init', [ $this, 'api_initialization' ] );
233 + }
281 234
235 + /**
236 + * Initialize the BetterDocs Plugin
237 + *
238 + * @return void
239 + * @since 2.5.0
240 + */
241 + public function init() {
242 + /**
243 + * Setup localization.
244 + */
245 + $this->load_plugin_textdomain();
246 +
282 247 $this->container->get( Admin::class );
283 248 $this->container->get( Roles::class );
284 249 $this->container->get( ReportEmail::class );
285 - // Usage-analytics collector. Registered here (runs on every request, incl.
286 - // WP-Cron) rather than in Admin so its `betterdocs_insights_data` filter
287 - // callback is present whenever the tracking payload is built.
288 - $this->container->get( \WPDeveloper\BetterDocs\Insights\Collector::class );
250 +
289 251 /**
290 252 * Initialize Shortcode
291 253 * Make sure you have listed out all shortcode in shortcode factory.
292 254 */
@@ -292,19 +254,10 @@
292 254 */
293 255 $this->container->get( ShortcodeFactory::class )->init();
294 256
295 257 $this->container->get( FrontEnd::class );
296 - $this->container->get( SearchExtender::class );
297 258
298 - /**
299 - * Single-product FAQ rendering (WooCommerce). The class itself bails when
300 - * WooCommerce is inactive or the feature is disabled.
301 - */
302 - $this->container->get( WooProductFAQ::class );
303 -
304 259 do_action( 'betterdocs_init' );
305 -
306 - $this->editor->init();
307 260 }
308 261
309 262 /**
310 263 * Load plugins textdomain `betterdocs` into actions.
@@ -315,16 +268,13 @@
315 268
316 269 /**
317 270 * Filter to adjust the BetterDocs locale to use for translations.
318 271 */
319 - // 'plugin_locale' is a WP-core filter; using its documented name is required.
320 - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
321 272 $locale = apply_filters( 'plugin_locale', $locale, $textdomain );
322 273
323 - if ( file_exists( WP_LANG_DIR . "/$textdomain-" . $locale . '.mo' ) ) {
324 - unload_textdomain( $textdomain );
325 - load_textdomain( $textdomain, WP_LANG_DIR . "/$textdomain-" . $locale . '.mo' );
326 - }
274 + unload_textdomain( $textdomain );
275 + load_textdomain( $textdomain, WP_LANG_DIR . "/$textdomain-" . $locale . '.mo' );
276 + load_plugin_textdomain( $textdomain, false, plugin_basename( dirname( $plugin_file ) ) . '/languages' );
327 277 }
328 278
329 279 /**
330 280 * For AJAX Only
@@ -343,15 +293,15 @@
343 293 * @suppress PHP0441
344 294 * @since 2.5.0
345 295 */
346 296 public static function get_instance() {
347 - if ( null == self::$_instance ) {
348 - self::$_instance = new self();
297 + if ( static::$_instance == null ) {
298 + static::$_instance = new self();
349 299
350 300 do_action( 'betterdocs_loaded' );
351 301 }
352 302
353 - return self::$_instance;
303 + return static::$_instance;
354 304 }
355 305
356 306 /**
357 307 * Hooked with `admin_init` action.
@@ -378,18 +328,14 @@
378 328 // Delete the activation transient.
379 329 $this->database->delete_transient( 'betterdocs_maybe_redirect' );
380 330
381 331 if ( ! is_multisite() ) {
382 - $betterdocs_settings = get_option( 'betterdocs_settings' );
383 - if ( $betterdocs_settings ) {
384 - wp_safe_redirect( add_query_arg( array( 'page' => 'betterdocs-settings' ), admin_url( 'admin.php' ) ) );
332 + $betterdocs_settings = get_option('betterdocs_settings');
333 + if ( $betterdocs_settings) {
334 + wp_safe_redirect( add_query_arg( [ 'page' => 'betterdocs-settings' ], admin_url( 'admin.php' ) ) );
385 335 } else {
386 - wp_safe_redirect( add_query_arg( array( 'page' => 'betterdocs-setup' ), admin_url( 'admin.php' ) ) );
336 + wp_safe_redirect( add_query_arg( [ 'page' => 'betterdocs-setup' ], admin_url( 'admin.php' ) ) );
387 337 }
388 - // This runs at `admin_init` priority 0. Without exiting, the rest of
389 - // admin_init still executes and can mutate the very state the redirect
390 - // target depends on before the browser ever follows the Location header.
391 - exit;
392 338 }
393 339 }
394 340
395 341 /**
@@ -403,46 +349,12 @@
403 349 /**
404 350 * Is Pro Plugin Is Active?
405 351 * @return bool
406 352 */
407 - public function pro_file() {
408 - return WP_PLUGIN_DIR . '/betterdocs-pro/betterdocs-pro.php';
409 - }
410 -
411 353 public function is_pro_active() {
412 - if ( file_exists( $this->pro_file() ) ) {
413 - return $this->helper->is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' );
414 - }
415 -
416 - return false;
354 + return $this->helper->is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' );
417 355 }
418 356
419 - public function chatbot_file() {
420 - return WP_PLUGIN_DIR . '/betterdocs-ai-chatbot/betterdocs-ai-chatbot.php';
421 - }
422 -
423 - public function is_chatbot_active() {
424 - if ( file_exists( $this->chatbot_file() ) ) {
425 - return $this->helper->is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' );
426 - }
427 -
428 - return false;
429 - }
430 -
431 - public function pro_version() {
432 - if ( ! $this->is_pro_active() ) {
433 - return false;
434 - }
435 -
436 - if ( ! function_exists( 'get_plugin_data' ) ) {
437 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
438 - }
439 -
440 - $plugin_data = get_plugin_data( $this->pro_file() );
441 -
442 - return $plugin_data[ 'Version' ];
443 - }
444 -
445 357 /**
446 358 * Get all the API initialized.
447 359 * @return void
448 360 */
@@ -450,9 +362,9 @@
450 362 $_api_classes = scandir( __DIR__ . DIRECTORY_SEPARATOR . 'REST' );
451 363
452 364 if ( ! empty( $_api_classes ) && is_array( $_api_classes ) ) {
453 365 foreach ( $_api_classes as $class ) {
454 - if ( '.' == $class || '..' == $class || strpos( $class, '.' ) === 0 ) {
366 + if ( $class == '.' || $class == '..' || strpos( $class, '.' ) === 0) {
455 367 continue;
456 368 }
457 369
458 370 $classname = basename( $class, '.php' );
@@ -463,64 +375,6 @@
463 375 $_api_class->register();
464 376 }
465 377 }
466 378 }
467 - }
468 -
469 - public function is_betterdocs_screen( $hook, $admin_check = true ): bool {
470 - /**
471 - * Filter the list of admin screen hook suffixes treated as BetterDocs
472 - * screens (controls whether the React admin bundle + styles load).
473 - * Pro/add-ons can register their own React pages here, e.g. the
474 - * Knowledge Base admin page.
475 - *
476 - * @param string[] $screens Full hook suffixes (e.g. betterdocs_page_betterdocs-foo).
477 - */
478 - $screens = apply_filters( 'betterdocs_admin_screens', array(
479 - 'toplevel_page_betterdocs-dashboard',
480 - 'toplevel_page_betterdocs-admin',
481 - 'admin_page_betterdocs-admin',
482 - 'betterdocs_page_betterdocs-admin',
483 - 'betterdocs_page_betterdocs-analytics',
484 - 'betterdocs_page_betterdocs-settings',
485 - 'betterdocs_page_betterdocs-faq',
486 - 'betterdocs_page_betterdocs-glossaries',
487 - 'betterdocs_page_betterdocs-ai-chatbot',
488 - 'betterdocs_page_betterdocs-doc-categories',
489 - 'betterdocs_page_betterdocs-doc-tags',
490 - ) );
491 -
492 - if ( $admin_check ) {
493 - if ( in_array( $hook, $screens ) ) {
494 - return true;
495 - }
496 -
497 - return false;
498 - }
499 -
500 - return false;
501 - }
502 -
503 - public function get_betterdocs_screen() {
504 - $registered_screens = array(
505 - 'toplevel_page_betterdocs-dashboard',
506 - 'admin_page_betterdocs-admin',
507 - 'betterdocs_page_betterdocs-admin',
508 - 'betterdocs_page_betterdocs-settings',
509 - 'betterdocs_page_betterdocs-analytics',
510 - 'betterdocs_page_betterdocs-faq',
511 - 'betterdocs_page_betterdocs-glossaries',
512 - 'betterdocs_page_betterdocs-ai-chatbot',
513 - 'betterdocs_page_betterdocs-doc-categories',
514 - 'betterdocs_page_betterdocs-doc-tags',
515 - 'edit-docs'
516 - );
517 -
518 - $current_screen_id = get_current_screen() != null ? get_current_screen()->id : '';
519 -
520 - if ( in_array( $current_screen_id, $registered_screens ) ) {
521 - return $current_screen_id;
522 - }
523 -
524 - return false;
525 379 }
526 380 }