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/Plugin.php +327 -64 3.3.44.9.2 View file →
@@ -5,32 +5,45 @@
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;
9 13 use WPDeveloper\BetterDocs\Core\Admin;
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;
14 +use WPDeveloper\BetterDocs\Core\AnalyticsTracker;
15 +use WPDeveloper\BetterDocs\Core\AnalyticsRetention;
15 16 use WPDeveloper\BetterDocs\Core\BaseAPI;
16 17 use WPDeveloper\BetterDocs\Core\Install;
18 +use WPDeveloper\BetterDocs\Core\KBMigration;
19 +use WPDeveloper\BetterDocs\Core\Query;
17 20 use WPDeveloper\BetterDocs\Core\Request;
18 21 use WPDeveloper\BetterDocs\Core\Rewrite;
22 +use WPDeveloper\BetterDocs\Core\Roles;
19 23 use WPDeveloper\BetterDocs\Core\Scripts;
20 -use WPDeveloper\BetterDocs\Utils\Helper;
21 24 use WPDeveloper\BetterDocs\Core\Settings;
22 -use WPDeveloper\BetterDocs\Core\KBMigration;
23 -use WPDeveloper\BetterDocs\Utils\Enqueue;
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;
24 33 use WPDeveloper\BetterDocs\Editors\Editor;
25 -use WPDeveloper\BetterDocs\Utils\Database;
26 -use WPDeveloper\BetterDocs\Admin\Analytics;
27 -use WPDeveloper\BetterDocs\Admin\ReportEmail;
28 34 use WPDeveloper\BetterDocs\FrontEnd\FrontEnd;
29 -use WPDeveloper\BetterDocs\Core\ShortcodeFactory;
35 +use WPDeveloper\BetterDocs\FrontEnd\PrintTemplate;
36 +use WPDeveloper\BetterDocs\FrontEnd\SearchExtender;
30 37 use WPDeveloper\BetterDocs\FrontEnd\TemplateTags;
31 -use WPDeveloper\BetterDocs\Admin\Customizer\Customizer;
32 -use WPDeveloper\BetterDocs\Dependencies\DI\ContainerBuilder;
38 +use WPDeveloper\BetterDocs\FrontEnd\WooProductFAQ;
39 +use WPDeveloper\BetterDocs\Abilities\AbilitiesRegistrar;
40 +use WPDeveloper\BetterDocs\Mcp\MCPManager;
41 +use WPDeveloper\BetterDocs\Modules\StyleHandler as ModulesStyleHandler;
42 +use WPDeveloper\BetterDocs\Utils\Database;
43 +use WPDeveloper\BetterDocs\Utils\Enqueue;
44 +use WPDeveloper\BetterDocs\Utils\Helper;
45 +use WPDeveloper\BetterDocs\Utils\Views;
33 46
34 47 final class Plugin {
35 48 private static $_instance = null;
36 49 /**
@@ -86,8 +99,13 @@
86 99 * @var TemplateTags
87 100 */
88 101 public $template_helper;
89 102 /**
103 + * Article Summary class
104 + * @var ArticleSummary
105 + */
106 + public $article_summary;
107 + /**
90 108 * Customizer class
91 109 * @var Customizer
92 110 */
93 111 public $customizer;
@@ -114,9 +132,9 @@
114 132 /**
115 133 * Plugin Version
116 134 * @var string
117 135 */
118 - public $version = '3.3.4';
136 + public $version = '4.9.2';
119 137
120 138 /**
121 139 * WriteWithAI Class
122 140 * @var string
@@ -121,19 +139,27 @@
121 139 * WriteWithAI Class
122 140 * @var string
123 141 */
124 142 public $ai_autowrtie;
143 + public $backgroundProccessor;
125 144
126 145 /**
146 + * ArticleQualityScore Class
147 + * @var ArticleQualityScore
148 + */
149 + public $article_quality_score;
150 +
151 + /**
127 152 * Plugin DB Version
128 153 * @var string
129 154 */
130 - public $db_version = '1.0.1';
155 + public $db_version = '1.0.3';
131 156
132 157 public function __construct() {
133 158 $this->define_constants();
134 159
135 160 do_action( 'betterdocs_init_before' );
161 +
136 162 $this->setup_container();
137 163 /**
138 164 * Register activation and deactivation hooks
139 165 * and version updates check
@@ -139,21 +165,42 @@
139 165 * and version updates check
140 166 */
141 167 $this->container->get( Install::class );
142 168
143 - $this->initialize();
169 + /**
170 + * Abilities API registrar.
171 + *
172 + * Resolved here, at plugin load, and not from initialize(): both the
173 + * bundled Abilities API and WordPress core's build their registry as a
174 + * lazy singleton and fire `wp_abilities_api_init` from it, at or after
175 + * `init`, the first time anything reads the registry. Our listeners
176 + * therefore have to be attached before that first read, whenever it
177 + * happens — and a container resolve on `init` would already be too late
178 + * for a plugin that reads the registry earlier in the same hook.
179 + */
180 + $this->container->get( AbilitiesRegistrar::class );
144 181
145 - add_action( 'init', [ $this, 'init' ], 0 );
182 + add_action( 'init', array( $this, 'initialize' ), 0 );
146 183
147 184 /**
185 + * Initialize API
186 + */
187 + add_action( 'rest_api_init', array( $this, 'api_initialization' ) );
188 +
189 + /**
148 190 * For admin only
149 191 */
150 - add_action( 'admin_init', [ $this, 'admin_init' ], 0 );
192 + add_action( 'admin_init', array( $this, 'admin_init' ), 0 );
151 193
152 194 /**
153 195 * For AJAX only
154 196 */
155 197 $this->ajax();
198 +
199 + /**
200 + * Style Handler For Parsing and Saving Styles as file.
201 + */
202 + ModulesStyleHandler::init();
156 203 }
157 204
158 205 private function define_constants() {
159 206 $this->define( 'BETTERDOCS_VERSION', $this->version );
@@ -160,9 +207,11 @@
160 207 $this->define( 'BETTERDOCS_DB_VERSION', $this->db_version );
161 208 $this->define( 'BETTERDOCS_ABSPATH', dirname( BETTERDOCS_PLUGIN_FILE ) . '/' );
162 209 $this->define( 'BETTERDOCS_ABSURL', plugin_dir_url( BETTERDOCS_PLUGIN_FILE ) );
163 210 $this->define( 'BETTERDOCS_PLUGIN_BASENAME', plugin_basename( BETTERDOCS_PLUGIN_FILE ) );
164 - $this->define( 'BETTERDOCS_BLOCKS_DIRECTORY', BETTERDOCS_ABSPATH . 'assets/blocks/' );
211 + // Compiled block metadata lives under assets/build/ since the Node 24 asset
212 + // restructure; register_block_type() fails silently if this path is wrong.
213 + $this->define( 'BETTERDOCS_BLOCKS_DIRECTORY', BETTERDOCS_ABSPATH . 'assets/build/blocks/' );
165 214 $this->define( 'BETTERDOCS_ROOT_DIR_PATH', plugin_dir_path( BETTERDOCS_PLUGIN_FILE ) );
166 215 $this->define( 'BETTERDOCS_FSE_TEMPLATES_PATH', BETTERDOCS_ROOT_DIR_PATH . 'views/templates/fse' );
167 216
168 217 /**
@@ -171,8 +220,10 @@
171 220 *
172 221 * WPML compatibility with Polylang
173 222 */
174 223 if ( Helper::is_plugin_active( 'polylang/polylang.php' ) ) {
224 + // Polylang's documented integration constant — must use the upstream-defined name.
225 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
175 226 define( 'PLL_WPML_COMPAT', false );
176 227 }
177 228 }
178 229
@@ -178,13 +229,15 @@
178 229
179 230 /**
180 231 * Define constant if not already set.
181 232 *
182 - * @param string $name Constant name.
233 + * @param string $name Constant name.
183 234 * @param string|bool $value Constant value.
184 235 */
185 236 private function define( $name, $value ) {
186 237 if ( ! defined( $name ) ) {
238 + // Caller passes plugin-prefixed names (BETTERDOCS_*); $name comes from a controlled internal allowlist.
239 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.VariableConstantNameFound
187 240 define( $name, $value );
188 241 }
189 242 }
190 243
@@ -197,58 +250,68 @@
197 250 $this->container = $builder->build();
198 251 }
199 252
200 253 public function initialize() {
254 +
255 + /**
256 + * Setup localization.
257 + */
258 + $this->load_plugin_textdomain();
259 +
201 260 $this->container->get( Scripts::class );
202 261 $this->rewrite = $this->container->get( Rewrite::class );
203 262 $this->request = $this->container->get( Request::class );
204 263 $this->query = $this->container->get( Query::class );
205 264
265 + // Initialize background process
266 + $this->backgroundProccessor = $this->container->get( HelpScoutMigration::class );
267 +
206 268 $this->rewrite->init();
207 269 $this->request->init();
208 270
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 );
271 + $this->assets = $this->container->get( Enqueue::class );
272 + $this->views = $this->container->get( Views::class );
273 + $this->helper = $this->container->get( Helper::class );
274 + $this->kbmigration = $this->container->get( KBMigration::class );
275 + $this->admin = $this->container->get( Admin::class );
276 + $this->database = $this->container->get( Database::class );
277 + $this->settings = $this->container->get( Settings::class );
278 + $this->analytics = $this->container->get( Analytics::class );
279 + // Free analytics collectors: the frontend view/scroll tracker and the
280 + // daily retention purge. Each self-registers its hooks on construct.
281 + $this->container->get( AnalyticsTracker::class );
282 + $this->container->get( AnalyticsRetention::class );
217 283
218 284 $this->template_helper = $this->container->get( TemplateTags::class );
219 285 $this->customizer = $this->container->get( Customizer::class );
220 286 $this->editor = $this->container->get( Editor::class );
221 - $this->ai_autowrtie = $this->container->get( WriteWithAI::class );
287 + $this->ai_autowrtie = $this->container->get( WriteWithAI::class );
288 + $this->article_summary = $this->container->get( ArticleSummary::class );
222 289
223 - /**
224 - * Initialize all editors.
225 - * Elementor, Gutenberg/BlockEditor
226 - */
227 - add_action( 'init', [ $this->editor, 'init' ] );
290 + // Initialize unified metabox before individual features
291 + $this->container->get( UnifiedMetabox::class );
292 + $this->article_quality_score = $this->container->get( ArticleQualityScore::class );
228 293
229 - /**
230 - * Initialize API
231 - */
232 - add_action( 'rest_api_init', [ $this, 'api_initialization' ] );
233 - }
294 + // Editor "Suggest Categories / Tags / Glossaries" AI actions on the docs
295 + // post type (gated by enable_docs_ai_suite + an OpenAI key inside the class).
296 + $this->container->get( DocsAISuite::class );
234 297
235 - /**
236 - * Initialize the BetterDocs Plugin
237 - *
238 - * @return void
239 - * @since 2.5.0
240 - */
241 - public function init() {
298 + $this->container->get( Admin::class );
299 + $this->container->get( Roles::class );
300 +
242 301 /**
243 - * Setup localization.
302 + * MCP transport: rewrite rules, the pretty endpoint, OAuth discovery
303 + * and every REST route. Resolved here rather than at plugin load
304 + * (where the abilities registrar has to be) because its earliest hook
305 + * is `init`, which is what this method already runs on.
244 306 */
245 - $this->load_plugin_textdomain();
307 + $this->container->get( MCPManager::class );
246 308
247 - $this->container->get( Admin::class );
248 - $this->container->get( Roles::class );
249 309 $this->container->get( ReportEmail::class );
250 -
310 + // Usage-analytics collector. Registered here (runs on every request, incl.
311 + // WP-Cron) rather than in Admin so its `betterdocs_insights_data` filter
312 + // callback is present whenever the tracking payload is built.
313 + $this->container->get( \WPDeveloper\BetterDocs\Insights\Collector::class );
251 314 /**
252 315 * Initialize Shortcode
253 316 * Make sure you have listed out all shortcode in shortcode factory.
254 317 */
@@ -254,10 +317,24 @@
254 317 */
255 318 $this->container->get( ShortcodeFactory::class )->init();
256 319
257 320 $this->container->get( FrontEnd::class );
321 + $this->container->get( SearchExtender::class );
258 322
323 + // Running logo header / page footer for the browser's own Print command.
324 + // Registered unconditionally: it covers every front-end page, including
325 + // the ones that carry no BetterDocs print button.
326 + $this->container->get( PrintTemplate::class );
327 +
328 + /**
329 + * Single-product FAQ rendering (WooCommerce). The class itself bails when
330 + * WooCommerce is inactive or the feature is disabled.
331 + */
332 + $this->container->get( WooProductFAQ::class );
333 +
259 334 do_action( 'betterdocs_init' );
335 +
336 + $this->editor->init();
260 337 }
261 338
262 339 /**
263 340 * Load plugins textdomain `betterdocs` into actions.
@@ -268,13 +345,16 @@
268 345
269 346 /**
270 347 * Filter to adjust the BetterDocs locale to use for translations.
271 348 */
349 + // 'plugin_locale' is a WP-core filter; using its documented name is required.
350 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
272 351 $locale = apply_filters( 'plugin_locale', $locale, $textdomain );
273 352
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' );
353 + if ( file_exists( WP_LANG_DIR . "/$textdomain-" . $locale . '.mo' ) ) {
354 + unload_textdomain( $textdomain );
355 + load_textdomain( $textdomain, WP_LANG_DIR . "/$textdomain-" . $locale . '.mo' );
356 + }
277 357 }
278 358
279 359 /**
280 360 * For AJAX Only
@@ -293,15 +373,15 @@
293 373 * @suppress PHP0441
294 374 * @since 2.5.0
295 375 */
296 376 public static function get_instance() {
297 - if ( static::$_instance == null ) {
298 - static::$_instance = new self();
377 + if ( null == self::$_instance ) {
378 + self::$_instance = new self();
299 379
300 380 do_action( 'betterdocs_loaded' );
301 381 }
302 382
303 - return static::$_instance;
383 + return self::$_instance;
304 384 }
305 385
306 386 /**
307 387 * Hooked with `admin_init` action.
@@ -328,14 +408,18 @@
328 408 // Delete the activation transient.
329 409 $this->database->delete_transient( 'betterdocs_maybe_redirect' );
330 410
331 411 if ( ! is_multisite() ) {
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' ) ) );
412 + $betterdocs_settings = get_option( 'betterdocs_settings' );
413 + if ( $betterdocs_settings ) {
414 + wp_safe_redirect( add_query_arg( array( 'page' => 'betterdocs-settings' ), admin_url( 'admin.php' ) ) );
335 415 } else {
336 - wp_safe_redirect( add_query_arg( [ 'page' => 'betterdocs-setup' ], admin_url( 'admin.php' ) ) );
416 + wp_safe_redirect( add_query_arg( array( 'page' => 'betterdocs-setup' ), admin_url( 'admin.php' ) ) );
337 417 }
418 + // This runs at `admin_init` priority 0. Without exiting, the rest of
419 + // admin_init still executes and can mutate the very state the redirect
420 + // target depends on before the browser ever follows the Location header.
421 + exit;
338 422 }
339 423 }
340 424
341 425 /**
@@ -349,13 +433,129 @@
349 433 /**
350 434 * Is Pro Plugin Is Active?
351 435 * @return bool
352 436 */
437 + public function pro_file() {
438 + return WP_PLUGIN_DIR . '/betterdocs-pro/betterdocs-pro.php';
439 + }
440 +
353 441 public function is_pro_active() {
354 - return $this->helper->is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' );
442 + if ( file_exists( $this->pro_file() ) ) {
443 + return $this->helper->is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' );
444 + }
445 +
446 + return false;
355 447 }
356 448
449 + public function chatbot_file() {
450 + return WP_PLUGIN_DIR . '/betterdocs-ai-chatbot/betterdocs-ai-chatbot.php';
451 + }
452 +
453 + public function is_chatbot_active() {
454 + if ( file_exists( $this->chatbot_file() ) ) {
455 + return $this->helper->is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' );
456 + }
457 +
458 + return false;
459 + }
460 +
357 461 /**
462 + * Whether Pro provides the real API Documentation screen.
463 + *
464 + * Pro flips this via `betterdocs_pro_has_api_docs`; the class_exists() default
465 + * keeps the gate correct against a Pro build that predates that filter.
466 + *
467 + * @return bool
468 + */
469 + public function has_api_docs() {
470 + return (bool) apply_filters(
471 + 'betterdocs_pro_has_api_docs',
472 + class_exists( '\\WPDeveloper\\BetterDocsPro\\Core\\ApiReferences' )
473 + );
474 + }
475 +
476 + /**
477 + * Whether Free should show its locked API Docs teaser.
478 + *
479 + * Only without Pro. An older Pro has already paid, so they get nothing here —
480 + * they need a plugin update, not an upsell.
481 + *
482 + * @return bool
483 + */
484 + public function show_api_docs_teaser() {
485 + return ! $this->is_pro_active() && ! $this->has_api_docs();
486 + }
487 +
488 + /**
489 + * Whether the real Glossaries screen is available (i.e. Pro is licensing it).
490 + *
491 + * Glossaries ships in Free's code but is Pro-licensed, so unlike API Docs there
492 + * is no separate Pro class to detect — the gate is simply Pro being active. Kept
493 + * behind a filter so Pro/add-ons can flip it explicitly, mirroring
494 + * `betterdocs_pro_has_api_docs`.
495 + *
496 + * @return bool
497 + */
498 + public function has_glossaries() {
499 + return (bool) apply_filters( 'betterdocs_pro_has_glossaries', $this->is_pro_active() );
500 + }
501 +
502 + /**
503 + * Whether Free should show its locked Glossaries teaser.
504 + *
505 + * Only without Pro — an active Pro either has the feature or has simply left it
506 + * disabled in settings; neither case wants an upsell. Mirrors
507 + * show_api_docs_teaser().
508 + *
509 + * @return bool
510 + */
511 + public function show_glossary_teaser() {
512 + return ! $this->is_pro_active() && ! $this->has_glossaries();
513 + }
514 +
515 + /**
516 + * Whether Pro provides the real Content Intelligence screen.
517 + *
518 + * Pro flips this via `betterdocs_pro_has_content_intelligence`; the
519 + * class_exists() default keeps the gate correct against a Pro build that
520 + * predates that filter.
521 + *
522 + * @return bool
523 + */
524 + public function has_content_intelligence() {
525 + return (bool) apply_filters(
526 + 'betterdocs_pro_has_content_intelligence',
527 + class_exists( '\\WPDeveloper\\BetterDocsPro\\Core\\ContentIntelligenceService' )
528 + );
529 + }
530 +
531 + /**
532 + * Whether Free should show its locked Content Intelligence teaser.
533 + *
534 + * Only without Pro. An older Pro has already paid, so they get nothing here —
535 + * they need a plugin update, not an upsell.
536 + *
537 + * @return bool
538 + */
539 + public function show_content_intelligence_teaser() {
540 + return ! $this->is_pro_active() && ! $this->has_content_intelligence();
541 + }
542 +
543 + public function pro_version() {
544 + if ( ! $this->is_pro_active() ) {
545 + return false;
546 + }
547 +
548 + if ( ! function_exists( 'get_plugin_data' ) ) {
549 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
550 + }
551 +
552 + $plugin_data = get_plugin_data( $this->pro_file() );
553 +
554 + return $plugin_data[ 'Version' ];
555 + }
556 +
557 + /**
358 558 * Get all the API initialized.
359 559 * @return void
360 560 */
361 561 public function api_initialization() {
@@ -362,9 +562,9 @@
362 562 $_api_classes = scandir( __DIR__ . DIRECTORY_SEPARATOR . 'REST' );
363 563
364 564 if ( ! empty( $_api_classes ) && is_array( $_api_classes ) ) {
365 565 foreach ( $_api_classes as $class ) {
366 - if ( $class == '.' || $class == '..' || strpos( $class, '.' ) === 0) {
566 + if ( '.' == $class || '..' == $class || strpos( $class, '.' ) === 0 ) {
367 567 continue;
368 568 }
369 569
370 570 $classname = basename( $class, '.php' );
@@ -375,6 +575,69 @@
375 575 $_api_class->register();
376 576 }
377 577 }
378 578 }
579 + }
580 +
581 + public function is_betterdocs_screen( $hook, $admin_check = true ): bool {
582 + /**
583 + * Filter the list of admin screen hook suffixes treated as BetterDocs
584 + * screens (controls whether the React admin bundle + styles load).
585 + * Pro/add-ons can register their own React pages here, e.g. the
586 + * Knowledge Base admin page.
587 + *
588 + * @param string[] $screens Full hook suffixes (e.g. betterdocs_page_betterdocs-foo).
589 + */
590 + $screens = apply_filters( 'betterdocs_admin_screens', array(
591 + 'toplevel_page_betterdocs-dashboard',
592 + 'toplevel_page_betterdocs-admin',
593 + 'admin_page_betterdocs-admin',
594 + 'betterdocs_page_betterdocs-admin',
595 + 'betterdocs_page_betterdocs-analytics',
596 + 'betterdocs_page_betterdocs-content-iq',
597 + 'betterdocs_page_betterdocs-settings',
598 + 'betterdocs_page_betterdocs-mcp',
599 + 'betterdocs_page_betterdocs-faq',
600 + 'betterdocs_page_betterdocs-glossaries',
601 + 'betterdocs_page_betterdocs-ai-chatbot',
602 + 'betterdocs_page_betterdocs-api-docs',
603 + 'betterdocs_page_betterdocs-doc-categories',
604 + 'betterdocs_page_betterdocs-doc-tags',
605 + ) );
606 +
607 + if ( $admin_check ) {
608 + if ( in_array( $hook, $screens ) ) {
609 + return true;
610 + }
611 +
612 + return false;
613 + }
614 +
615 + return false;
616 + }
617 +
618 + public function get_betterdocs_screen() {
619 + $registered_screens = array(
620 + 'toplevel_page_betterdocs-dashboard',
621 + 'admin_page_betterdocs-admin',
622 + 'betterdocs_page_betterdocs-admin',
623 + 'betterdocs_page_betterdocs-settings',
624 + 'betterdocs_page_betterdocs-mcp',
625 + 'betterdocs_page_betterdocs-analytics',
626 + 'betterdocs_page_betterdocs-faq',
627 + 'betterdocs_page_betterdocs-glossaries',
628 + 'betterdocs_page_betterdocs-ai-chatbot',
629 + 'betterdocs_page_betterdocs-api-docs',
630 + 'betterdocs_page_betterdocs-doc-categories',
631 + 'betterdocs_page_betterdocs-doc-tags',
632 + 'edit-docs'
633 + );
634 +
635 + $current_screen_id = get_current_screen() != null ? get_current_screen()->id : '';
636 +
637 + if ( in_array( $current_screen_id, $registered_screens ) ) {
638 + return $current_screen_id;
639 + }
640 +
641 + return false;
379 642 }
380 643 }