PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.6.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.6.0
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
betterdocs / includes / Plugin.php

Plugin.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.6.0, at includes/Plugin.php

510 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly
7 }
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 use WPDeveloper\BetterDocs\Core\Admin;
14 use WPDeveloper\BetterDocs\Core\BaseAPI;
15 use WPDeveloper\BetterDocs\Core\Install;
16 use WPDeveloper\BetterDocs\Core\KBMigration;
17 use WPDeveloper\BetterDocs\Core\Query;
18 use WPDeveloper\BetterDocs\Core\Request;
19 use WPDeveloper\BetterDocs\Core\Rewrite;
20 use WPDeveloper\BetterDocs\Core\Roles;
21 use WPDeveloper\BetterDocs\Core\Scripts;
22 use WPDeveloper\BetterDocs\Core\Settings;
23 use WPDeveloper\BetterDocs\Core\ShortcodeFactory;
24 use WPDeveloper\BetterDocs\Core\WriteWithAI;
25 use WPDeveloper\BetterDocs\Core\ArticleSummary;
26 use WPDeveloper\BetterDocs\Core\ArticleQualityScore;
27 use WPDeveloper\BetterDocs\Core\UnifiedMetabox;
28 use WPDeveloper\BetterDocs\Dependencies\DI\Container;
29 use WPDeveloper\BetterDocs\Dependencies\DI\ContainerBuilder;
30 use WPDeveloper\BetterDocs\Editors\Editor;
31 use WPDeveloper\BetterDocs\FrontEnd\FrontEnd;
32 use WPDeveloper\BetterDocs\FrontEnd\SearchExtender;
33 use WPDeveloper\BetterDocs\FrontEnd\TemplateTags;
34 use WPDeveloper\BetterDocs\FrontEnd\WooProductFAQ;
35 use WPDeveloper\BetterDocs\Modules\StyleHandler as ModulesStyleHandler;
36 use WPDeveloper\BetterDocs\Utils\Database;
37 use WPDeveloper\BetterDocs\Utils\Enqueue;
38 use WPDeveloper\BetterDocs\Utils\Helper;
39 use WPDeveloper\BetterDocs\Utils\Views;
40
41 final class Plugin {
42 private static $_instance = null;
43 /**
44 * Assets manager
45 *
46 * @var Enqueue
47 */
48 public $assets;
49 /**
50 * View manager
51 *
52 * @var Views
53 */
54 public $views;
55 /**
56 * Container Manager
57 *
58 * @var Container
59 */
60 public $container;
61 /**
62 * Editor Manager
63 * @var Editor
64 */
65 public $editor;
66 /**
67 * Helper class
68 * @var Helper
69 */
70 public $helper;
71 /**
72 * KBMigration class
73 * @var KBMigration
74 */
75 public $kbmigration;
76 /**
77 * KBMigration class
78 * @var Admin
79 */
80 public $admin;
81 /**
82 * Helper class
83 * @var Database
84 */
85 public $database;
86 /**
87 * Helper class
88 * @var Settings
89 */
90 public $settings;
91 /**
92 * Helper class
93 * @var TemplateTags
94 */
95 public $template_helper;
96 /**
97 * Article Summary class
98 * @var ArticleSummary
99 */
100 public $article_summary;
101 /**
102 * Customizer class
103 * @var Customizer
104 */
105 public $customizer;
106 /**
107 * Query class
108 * @var Query
109 */
110 public $query;
111 /**
112 * Rewrite Class
113 * @var Rewrite
114 */
115 public $rewrite;
116 /**
117 * Request Class
118 * @var Request
119 */
120 public $request;
121 /**
122 * Analytics Class
123 * @var Analytics
124 */
125 public $analytics;
126 /**
127 * Plugin Version
128 * @var string
129 */
130 public $version = '4.6.0';
131
132 /**
133 * WriteWithAI Class
134 * @var string
135 */
136 public $ai_autowrtie;
137 public $backgroundProccessor;
138
139 /**
140 * ArticleQualityScore Class
141 * @var ArticleQualityScore
142 */
143 public $article_quality_score;
144
145 /**
146 * Plugin DB Version
147 * @var string
148 */
149 public $db_version = '1.0.1';
150
151 public function __construct() {
152 $this->define_constants();
153
154 do_action( 'betterdocs_init_before' );
155
156 $this->setup_container();
157 /**
158 * Register activation and deactivation hooks
159 * and version updates check
160 */
161 $this->container->get( Install::class );
162
163 add_action( 'init', array( $this, 'initialize' ), 0 );
164
165 /**
166 * Initialize API
167 */
168 add_action( 'rest_api_init', array( $this, 'api_initialization' ) );
169
170 /**
171 * For admin only
172 */
173 add_action( 'admin_init', array( $this, 'admin_init' ), 0 );
174
175 /**
176 * For AJAX only
177 */
178 $this->ajax();
179
180 /**
181 * Style Handler For Parsing and Saving Styles as file.
182 */
183 ModulesStyleHandler::init();
184 }
185
186 private function define_constants() {
187 $this->define( 'BETTERDOCS_VERSION', $this->version );
188 $this->define( 'BETTERDOCS_DB_VERSION', $this->db_version );
189 $this->define( 'BETTERDOCS_ABSPATH', dirname( BETTERDOCS_PLUGIN_FILE ) . '/' );
190 $this->define( 'BETTERDOCS_ABSURL', plugin_dir_url( BETTERDOCS_PLUGIN_FILE ) );
191 $this->define( 'BETTERDOCS_PLUGIN_BASENAME', plugin_basename( BETTERDOCS_PLUGIN_FILE ) );
192 $this->define( 'BETTERDOCS_BLOCKS_DIRECTORY', BETTERDOCS_ABSPATH . 'assets/blocks/' );
193 $this->define( 'BETTERDOCS_ROOT_DIR_PATH', plugin_dir_path( BETTERDOCS_PLUGIN_FILE ) );
194 $this->define( 'BETTERDOCS_FSE_TEMPLATES_PATH', BETTERDOCS_ROOT_DIR_PATH . 'views/templates/fse' );
195
196 /**
197 * Third Party Constants
198 * @since 2.5.0
199 *
200 * WPML compatibility with Polylang
201 */
202 if ( Helper::is_plugin_active( 'polylang/polylang.php' ) ) {
203 // Polylang's documented integration constant — must use the upstream-defined name.
204 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
205 define( 'PLL_WPML_COMPAT', false );
206 }
207 }
208
209 /**
210 * Define constant if not already set.
211 *
212 * @param string $name Constant name.
213 * @param string|bool $value Constant value.
214 */
215 private function define( $name, $value ) {
216 if ( ! defined( $name ) ) {
217 // Caller passes plugin-prefixed names (BETTERDOCS_*); $name comes from a controlled internal allowlist.
218 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.VariableConstantNameFound
219 define( $name, $value );
220 }
221 }
222
223 public function setup_container() {
224 $config_array = require_once BETTERDOCS_ABSPATH . 'includes/config.php';
225 $config = apply_filters( 'betterdocs_container_config', $config_array );
226 $builder = new ContainerBuilder();
227
228 $builder->addDefinitions( $config );
229 $this->container = $builder->build();
230 }
231
232 public function initialize() {
233
234 /**
235 * Setup localization.
236 */
237 $this->load_plugin_textdomain();
238
239 $this->container->get( Scripts::class );
240 $this->rewrite = $this->container->get( Rewrite::class );
241 $this->request = $this->container->get( Request::class );
242 $this->query = $this->container->get( Query::class );
243
244 // Initialize background process
245 $this->backgroundProccessor = $this->container->get( HelpScoutMigration::class );
246
247 $this->rewrite->init();
248 $this->request->init();
249
250 $this->assets = $this->container->get( Enqueue::class );
251 $this->views = $this->container->get( Views::class );
252 $this->helper = $this->container->get( Helper::class );
253 $this->kbmigration = $this->container->get( KBMigration::class );
254 $this->admin = $this->container->get( Admin::class );
255 $this->database = $this->container->get( Database::class );
256 $this->settings = $this->container->get( Settings::class );
257 $this->analytics = $this->container->get( Analytics::class );
258
259 $this->template_helper = $this->container->get( TemplateTags::class );
260 $this->customizer = $this->container->get( Customizer::class );
261 $this->editor = $this->container->get( Editor::class );
262 $this->ai_autowrtie = $this->container->get( WriteWithAI::class );
263 $this->article_summary = $this->container->get( ArticleSummary::class );
264
265 // Initialize unified metabox before individual features
266 $this->container->get( UnifiedMetabox::class );
267 $this->article_quality_score = $this->container->get( ArticleQualityScore::class );
268
269 $this->container->get( Admin::class );
270 $this->container->get( Roles::class );
271 $this->container->get( ReportEmail::class );
272 // Usage-analytics collector. Registered here (runs on every request, incl.
273 // WP-Cron) rather than in Admin so its `betterdocs_insights_data` filter
274 // callback is present whenever the tracking payload is built.
275 $this->container->get( \WPDeveloper\BetterDocs\Insights\Collector::class );
276 /**
277 * Initialize Shortcode
278 * Make sure you have listed out all shortcode in shortcode factory.
279 */
280 $this->container->get( ShortcodeFactory::class )->init();
281
282 $this->container->get( FrontEnd::class );
283 $this->container->get( SearchExtender::class );
284
285 /**
286 * Single-product FAQ rendering (WooCommerce). The class itself bails when
287 * WooCommerce is inactive or the feature is disabled.
288 */
289 $this->container->get( WooProductFAQ::class );
290
291 do_action( 'betterdocs_init' );
292
293 $this->editor->init();
294 }
295
296 /**
297 * Load plugins textdomain `betterdocs` into actions.
298 * @return void
299 */
300 public function load_plugin_textdomain( $textdomain = 'betterdocs', $plugin_file = BETTERDOCS_PLUGIN_FILE ) {
301 $locale = determine_locale();
302
303 /**
304 * Filter to adjust the BetterDocs locale to use for translations.
305 */
306 // 'plugin_locale' is a WP-core filter; using its documented name is required.
307 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
308 $locale = apply_filters( 'plugin_locale', $locale, $textdomain );
309
310 if ( file_exists( WP_LANG_DIR . "/$textdomain-" . $locale . '.mo' ) ) {
311 unload_textdomain( $textdomain );
312 load_textdomain( $textdomain, WP_LANG_DIR . "/$textdomain-" . $locale . '.mo' );
313 }
314 }
315
316 /**
317 * For AJAX Only
318 * @return void
319 */
320 public function ajax() {
321 }
322
323 /**
324 * Create a plugin instance.
325 *
326 * @param mixed ...$args
327 *
328 * @return static
329 *
330 * @suppress PHP0441
331 * @since 2.5.0
332 */
333 public static function get_instance() {
334 if ( null == self::$_instance ) {
335 self::$_instance = new self();
336
337 do_action( 'betterdocs_loaded' );
338 }
339
340 return self::$_instance;
341 }
342
343 /**
344 * Hooked with `admin_init` action.
345 * @return void
346 */
347 public function admin_init() {
348 /**
349 * Maybe Redirect
350 * for setup related settings.
351 */
352 $this->maybe_redirect();
353 }
354
355 /**
356 * Summary of maybe_redirect
357 * @return void
358 */
359 public function maybe_redirect() {
360 // Bail if no activation transient is set.
361 if ( ! $this->database->get_transient( 'betterdocs_maybe_redirect' ) ) {
362 return;
363 }
364
365 // Delete the activation transient.
366 $this->database->delete_transient( 'betterdocs_maybe_redirect' );
367
368 if ( ! is_multisite() ) {
369 $betterdocs_settings = get_option( 'betterdocs_settings' );
370 if ( $betterdocs_settings ) {
371 wp_safe_redirect( add_query_arg( array( 'page' => 'betterdocs-settings' ), admin_url( 'admin.php' ) ) );
372 } else {
373 wp_safe_redirect( add_query_arg( array( 'page' => 'betterdocs-setup' ), admin_url( 'admin.php' ) ) );
374 }
375 }
376 }
377
378 /**
379 * Is Pro Plugin Is Installed?
380 * @return bool
381 */
382 public function is_pro_installed() {
383 return $this->helper->get_plugins( 'betterdocs-pro/betterdocs-pro.php' );
384 }
385
386 /**
387 * Is Pro Plugin Is Active?
388 * @return bool
389 */
390 public function pro_file() {
391 return WP_PLUGIN_DIR . '/betterdocs-pro/betterdocs-pro.php';
392 }
393
394 public function is_pro_active() {
395 if ( file_exists( $this->pro_file() ) ) {
396 return $this->helper->is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' );
397 }
398
399 return false;
400 }
401
402 public function chatbot_file() {
403 return WP_PLUGIN_DIR . '/betterdocs-ai-chatbot/betterdocs-ai-chatbot.php';
404 }
405
406 public function is_chatbot_active() {
407 if ( file_exists( $this->chatbot_file() ) ) {
408 return $this->helper->is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' );
409 }
410
411 return false;
412 }
413
414 public function pro_version() {
415 if ( ! $this->is_pro_active() ) {
416 return false;
417 }
418
419 if ( ! function_exists( 'get_plugin_data' ) ) {
420 require_once ABSPATH . 'wp-admin/includes/plugin.php';
421 }
422
423 $plugin_data = get_plugin_data( $this->pro_file() );
424
425 return $plugin_data[ 'Version' ];
426 }
427
428 /**
429 * Get all the API initialized.
430 * @return void
431 */
432 public function api_initialization() {
433 $_api_classes = scandir( __DIR__ . DIRECTORY_SEPARATOR . 'REST' );
434
435 if ( ! empty( $_api_classes ) && is_array( $_api_classes ) ) {
436 foreach ( $_api_classes as $class ) {
437 if ( '.' == $class || '..' == $class || strpos( $class, '.' ) === 0 ) {
438 continue;
439 }
440
441 $classname = basename( $class, '.php' );
442 $classname = '\\' . __NAMESPACE__ . "\\REST\\$classname";
443 $_api_class = $this->container->get( $classname );
444
445 if ( $_api_class instanceof BaseAPI ) {
446 $_api_class->register();
447 }
448 }
449 }
450 }
451
452 public function is_betterdocs_screen( $hook, $admin_check = true ): bool {
453 /**
454 * Filter the list of admin screen hook suffixes treated as BetterDocs
455 * screens (controls whether the React admin bundle + styles load).
456 * Pro/add-ons can register their own React pages here, e.g. the
457 * Knowledge Base admin page.
458 *
459 * @param string[] $screens Full hook suffixes (e.g. betterdocs_page_betterdocs-foo).
460 */
461 $screens = apply_filters( 'betterdocs_admin_screens', array(
462 'toplevel_page_betterdocs-dashboard',
463 'toplevel_page_betterdocs-admin',
464 'admin_page_betterdocs-admin',
465 'betterdocs_page_betterdocs-admin',
466 'betterdocs_page_betterdocs-analytics',
467 'betterdocs_page_betterdocs-settings',
468 'betterdocs_page_betterdocs-faq',
469 'betterdocs_page_betterdocs-glossaries',
470 'betterdocs_page_betterdocs-ai-chatbot',
471 'betterdocs_page_betterdocs-doc-categories',
472 'betterdocs_page_betterdocs-doc-tags',
473 ) );
474
475 if ( $admin_check ) {
476 if ( in_array( $hook, $screens ) ) {
477 return true;
478 }
479
480 return false;
481 }
482
483 return false;
484 }
485
486 public function get_betterdocs_screen() {
487 $registered_screens = array(
488 'toplevel_page_betterdocs-dashboard',
489 'admin_page_betterdocs-admin',
490 'betterdocs_page_betterdocs-admin',
491 'betterdocs_page_betterdocs-settings',
492 'betterdocs_page_betterdocs-analytics',
493 'betterdocs_page_betterdocs-faq',
494 'betterdocs_page_betterdocs-glossaries',
495 'betterdocs_page_betterdocs-ai-chatbot',
496 'betterdocs_page_betterdocs-doc-categories',
497 'betterdocs_page_betterdocs-doc-tags',
498 'edit-docs'
499 );
500
501 $current_screen_id = get_current_screen() != null ? get_current_screen()->id : '';
502
503 if ( in_array( $current_screen_id, $registered_screens ) ) {
504 return $current_screen_id;
505 }
506
507 return false;
508 }
509 }
510