PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.2.6
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.2.6
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/Core/Admin.php +340 -361 4.5.24.2.6 View file →
@@ -20,9 +20,8 @@
20 20 */
21 21 private static $cache_bank;
22 22 /**
23 23 * Admin Root Menu Slug
24 - *
25 24 * @var string
26 25 */
27 26 private $slug = 'betterdocs-dashboard';
28 27 /**
@@ -54,19 +53,17 @@
54 53 private $kbmigration;
55 54
56 55 /**
57 56 * Enqueue
58 - *
59 57 * @var Enqueue
60 58 */
61 59 private $assets;
62 60
63 61 // modules
64 - protected $installer;
62 + protected $installer;
65 63
66 64 /**
67 65 * FAQBuilder
68 - *
69 66 * @var FAQBuilder
70 67 */
71 68 private $faq_builder;
72 69 private $glossaries;
@@ -77,10 +74,10 @@
77 74 $this->settings = $settings;
78 75 $this->kbmigration = $kbmigration;
79 76 $this->slug = 'betterdocs-dashboard';
80 77
81 - add_action( 'init', array( $type, 'register' ), 9 );
82 - add_action( 'rest_api_init', array( $this, 'order_terms_in_wp_terms_admin_table' ) );
78 + add_action( 'init', [ $type, 'register' ], 9 );
79 + add_action('rest_api_init', [$this, 'order_terms_in_wp_terms_admin_table']);
83 80
84 81 $type->init();
85 82 $type->admin_init();
86 83
@@ -93,47 +90,46 @@
93 90
94 91 $this->installer = new PluginInstaller();
95 92
96 93 $this->plugin_insights();
97 - add_action( 'admin_notices', array( $this, 'compatibility_notices' ) );
94 + add_action( 'admin_notices', [ $this, 'compatibility_notices' ] );
98 95 // add_action( 'admin_init', [$this, 'notices'], 9 );
99 - add_filter( 'admin_init', array( $this, 'save_admin_page' ), 99 );
96 + add_filter( 'admin_init', [ $this, 'save_admin_page' ], 99 );
100 97
101 - add_action( 'admin_menu', array( $this, 'menus' ) );
102 - add_action( 'admin_menu', array( $this, 'reset_submenu' ) );
103 - add_action( 'admin_head', array( $this, 'add_custom_classes_to_menu_items' ) );
104 - add_filter( 'plugin_action_links_' . BETTERDOCS_PLUGIN_BASENAME, array( $this, 'insert_plugin_links' ) );
98 + add_action( 'admin_menu', [ $this, 'menus' ] );
99 + add_action( 'admin_menu', [ $this, 'reset_submenu' ] );
100 + add_action( 'admin_head', [ $this, 'add_custom_classes_to_menu_items' ] );
101 + add_filter( 'plugin_action_links_' . BETTERDOCS_PLUGIN_BASENAME, [ $this, 'insert_plugin_links' ] );
105 102
106 103 // $this->container->get( SetupWizard::class )->init();
107 104
108 - add_action( 'admin_enqueue_scripts', array( $this, 'styles' ) );
109 - add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
110 - // add_action( 'betterdocs_listing_header', [ $this, 'header' ], 10, 1 );
111 - add_action( 'admin_bar_menu', array( $this, 'toolbar_menu' ), 32 );
105 + add_action( 'admin_enqueue_scripts', [ $this, 'styles' ] );
106 + add_action( 'admin_enqueue_scripts', [ $this, 'scripts' ] );
107 + //add_action( 'betterdocs_listing_header', [ $this, 'header' ], 10, 1 );
108 + add_action( 'admin_bar_menu', [ $this, 'toolbar_menu' ], 32 );
112 109
113 - add_filter( 'admin_body_class', array( $this, 'body_classes' ) );
114 - add_filter( 'parent_file', array( $type, 'highlight_admin_menu' ) );
115 - add_filter( 'submenu_file', array( $type, 'highlight_admin_submenu' ), 10, 2 );
116 - add_filter( 'betterdocs_admin_menu', array( $this, 'quick_setup_menu' ), 10, 1 );
110 + add_filter( 'admin_body_class', [ $this, 'body_classes' ] );
111 + add_filter( 'parent_file', [ $type, 'highlight_admin_menu' ] );
112 + add_filter( 'submenu_file', [ $type, 'highlight_admin_submenu' ], 10, 2 );
113 + add_filter( 'betterdocs_admin_menu', [ $this, 'quick_setup_menu' ], 10, 1 );
117 114
118 115 /**
119 116 * Remove Comments Column from List Table.
120 117 */
121 - add_filter( 'manage_docs_posts_columns', array( $this, 'set_custom_edit_action_columns' ) );
122 - add_filter( 'manage_docs_posts_custom_column', array( $this, 'manage_custom_columns' ), 10, 2 );
118 + add_filter( 'manage_docs_posts_columns', [ $this, 'set_custom_edit_action_columns' ] );
119 + add_filter( 'manage_docs_posts_custom_column', [ $this, 'manage_custom_columns' ], 10, 2 );
123 120
124 121 /**
125 122 * Add New Column
126 123 */
127 - add_filter( 'manage_users_columns', array( $this, 'add_users_total_docs_column' ), 10, 1 );
128 - add_filter( 'manage_users_custom_column', array( $this, 'popular_users_docs_data' ), 10, 3 );
124 + add_filter( 'manage_users_columns', [ $this, 'add_users_total_docs_column' ], 10, 1 );
125 + add_filter( 'manage_users_custom_column', [ $this, 'popular_users_docs_data' ], 10, 3 );
129 126 if ( is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ) ) {
130 127 add_action( 'admin_footer-plugins.php', array( $this, 'disable_deactivation' ) );
131 128 }
132 129
133 130 if ( $this->settings->get( 'enable_estimated_reading_time' ) ) {
134 - // Hook into unified metabox instead of creating separate metabox
135 - add_action( 'betterdocs_reading_time_tab_content', array( $this, 'render_estimated_time_markup' ) );
131 + add_action( 'add_meta_boxes', [ $this, 'reading_meta_box_' ], 10 );
136 132 }
137 133
138 134 self::$cache_bank = CacheBank::get_instance();
139 135
@@ -149,23 +145,18 @@
149 145 // Initialize Black Friday Pointer
150 146 $this->init_black_friday_pointer();
151 147
152 148 // Register AJAX handler for pointer dismissal
153 - add_action( 'wp_ajax_betterdocs_dismiss_black_friday_pointer', array( $this, 'ajax_dismiss_black_friday_pointer' ) );
149 + add_action( 'wp_ajax_betterdocs_dismiss_black_friday_pointer', [ $this, 'ajax_dismiss_black_friday_pointer' ] );
154 150 }
155 151
156 152 public function order_terms_in_wp_terms_admin_table() {
157 - // order the terms correctly to be shown on the admin panel categories menu with betterdocs order
158 - add_action(
159 - 'rest_insert_doc_category',
160 - function ( $term, $request, $bool ) {
161 - $max_order = Helper::get_max_doc_category_order_from_term_meta() ?? 0;
162 - $next_order = $max_order + 1;
163 - update_term_meta( $term->term_id, 'doc_category_order', $next_order );
164 - },
165 - 10,
166 - 3
167 - );
153 + //order the terms correctly to be shown on the admin panel categories menu with betterdocs order
154 + add_action('rest_insert_doc_category', function( $term, $request, $bool ) {
155 + $max_order = Helper::get_max_doc_category_order_from_term_meta() ?? 0;
156 + $next_order = $max_order + 1;
157 + update_term_meta( $term->term_id, 'doc_category_order', $next_order );
158 + }, 10, 3);
168 159 }
169 160
170 161 public function disable_deactivation() {
171 162 $tooltip_text = esc_html__( 'Deactivate BetterDocs Pro First', 'betterdocs' );
@@ -212,17 +203,17 @@
212 203 <?php
213 204 }
214 205
215 206 public function add_users_total_docs_column( $columns ) {
216 - $new_column = array(
217 - 'docs' => __( 'Docs', 'betterdocs' ),
218 - );
207 + $new_column = [
208 + 'docs' => __( 'Docs', 'betterdocs' )
209 + ];
219 210 $columns = array_merge( $columns, $new_column );
220 211 return $columns;
221 212 }
222 213
223 214 public function popular_users_docs_data( $output, $column_name, $user_id ) {
224 - if ( 'docs' == $column_name ) {
215 + if ( $column_name == 'docs' ) {
225 216 $total_count = count_user_posts( $user_id, 'docs', true );
226 217 return '<a href="edit.php?post_type=docs&author=' . $user_id . '" class="edit"><span aria-hidden="true">' . $total_count . '</span></a>';
227 218 }
228 219 return $output;
@@ -227,8 +218,20 @@
227 218 }
228 219 return $output;
229 220 }
230 221
222 + public function reading_meta_box_() {
223 + add_meta_box(
224 + 'betterdocs_estimated_time_metabox',
225 + __( 'Estimated Reading Time', 'betterdocs' ),
226 + [
227 + $this,
228 + 'render_estimated_time_markup'
229 + ],
230 + 'docs'
231 + );
232 + }
233 +
231 234 public function render_estimated_time_markup() {
232 235 betterdocs()->views->get( 'admin/metabox/estimated-reading-box' );
233 236 }
234 237
@@ -240,9 +243,9 @@
240 243 if ( isset( $plugin_data['Version'] ) && version_compare( $plugin_data['Version'], '2.5.0', '>=' ) ) {
241 244 return;
242 245 }
243 246
244 - betterdocs()->views->get( 'admin/notices/compatibility', array( 'version' => $plugin_data['Version'] ) );
247 + betterdocs()->views->get( 'admin/notices/compatibility', [ 'version' => $plugin_data['Version'] ] );
245 248 }
246 249 }
247 250
248 251 public function plugin_insights( $prevent_init = false ) {
@@ -247,20 +250,20 @@
247 250
248 251 public function plugin_insights( $prevent_init = false ) {
249 252 $this->insights = Insights::get_instance(
250 253 BETTERDOCS_PLUGIN_FILE,
251 - array(
254 + [
252 255 'opt_in' => true,
253 256 'goodbye_form' => true,
254 - 'item_id' => 'c7b16777b4f1b83f6083',
255 - )
257 + 'item_id' => 'c7b16777b4f1b83f6083'
258 + ]
256 259 );
257 260
258 261 $this->insights->set_notice_options(
259 - array(
262 + [
260 263 'notice' => __( 'Want to help make <strong>BetterDocs</strong> even more awesome? You can get a <strong>10% discount coupon</strong> for Premium extensions if you allow us to track the usage.', 'betterdocs' ),
261 - 'extra_notice' => __( 'We collect non-sensitive diagnostic data and plugin usage information. Your site URL, WordPress & PHP version, plugins & themes and email address to send you the discount coupon. This data lets us make sure this plugin always stays compatible with the most popular plugins and themes. No spam, I promise.', 'betterdocs' ),
262 - )
264 + 'extra_notice' => __( 'We collect non-sensitive diagnostic data and plugin usage information. Your site URL, WordPress & PHP version, plugins & themes and email address to send you the discount coupon. This data lets us make sure this plugin always stays compatible with the most popular plugins and themes. No spam, I promise.', 'betterdocs' )
265 + ]
263 266 );
264 267
265 268 if ( ! $prevent_init ) {
266 269 $this->insights->init();
@@ -276,77 +279,76 @@
276 279 * @throws Exception
277 280 */
278 281 public function notices() {
279 282 $notices = new Notices(
280 - array(
283 + [
281 284 'id' => 'betterdocs',
282 285 'storage_key' => 'notices',
283 286 'lifetime' => 3,
284 287 'stylesheet_url' => $this->assets->asset_url( 'admin/css/notices.css' ),
285 288 'styles' => $this->assets->asset_url( 'admin/css/notices.css' ),
286 - 'priority' => 4,
287 - )
289 + 'priority' => 4
290 + ]
288 291 );
289 292
290 293 /**
291 - * Review Notice
292 - *
293 - * @var mixed $message
294 - */
294 + * Review Notice
295 + * @var mixed $message
296 + */
295 297
296 298 $message = __( 'We hope you\'re enjoying BetterDocs! Could you please do us a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'betterdocs' );
297 299
298 - $_review_notice = array(
300 + $_review_notice = [
299 301 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
300 302 'html' => '<p>' . $message . '</p>',
301 - 'links' => array(
302 - 'later' => array(
303 + 'links' => [
304 + 'later' => [
303 305 'link' => 'https://wordpress.org/plugins/betterdocs/#reviews',
304 306 'target' => '_blank',
305 307 'label' => __( 'Sure, you deserve it!', 'betterdocs' ),
306 - 'icon_class' => 'dashicons dashicons-external',
307 - ),
308 - 'allready' => array(
308 + 'icon_class' => 'dashicons dashicons-external'
309 + ],
310 + 'allready' => [
309 311 'label' => __( 'I already did', 'betterdocs' ),
310 312 'icon_class' => 'dashicons dashicons-smiley',
311 - 'attributes' => array(
312 - 'data-dismiss' => true,
313 - ),
314 - ),
315 - 'maybe_later' => array(
313 + 'attributes' => [
314 + 'data-dismiss' => true
315 + ]
316 + ],
317 + 'maybe_later' => [
316 318 'label' => __( 'Maybe Later', 'betterdocs' ),
317 319 'icon_class' => 'dashicons dashicons-calendar-alt',
318 - 'attributes' => array(
320 + 'attributes' => [
319 321 'data-later' => true,
320 - 'class' => 'dismiss-btn',
321 - ),
322 - ),
323 - 'support' => array(
322 + 'class' => 'dismiss-btn'
323 + ]
324 + ],
325 + 'support' => [
324 326 'link' => 'https://wpdeveloper.com/support',
325 - 'attributes' => array(
326 - 'target' => '_blank',
327 - ),
327 + 'attributes' => [
328 + 'target' => '_blank'
329 + ],
328 330 'label' => __( 'I need help', 'betterdocs' ),
329 - 'icon_class' => 'dashicons dashicons-sos',
330 - ),
331 - 'never_show_again' => array(
331 + 'icon_class' => 'dashicons dashicons-sos'
332 + ],
333 + 'never_show_again' => [
332 334 'label' => __( 'Never show again', 'betterdocs' ),
333 335 'icon_class' => 'dashicons dashicons-dismiss',
334 - 'attributes' => array(
335 - 'data-dismiss' => true,
336 - ),
337 - ),
338 - ),
339 - );
336 + 'attributes' => [
337 + 'data-dismiss' => true
338 + ]
339 + ]
340 + ]
341 + ];
340 342
341 343 $notices->add(
342 344 'review',
343 345 $_review_notice,
344 - array(
346 + [
345 347 'start' => $notices->strtotime( '+10 days' ),
346 348 'recurrence' => 30,
347 - 'dismissible' => true,
348 - )
349 + 'dismissible' => true
350 + ]
349 351 );
350 352
351 353 if ( $this->kbmigration->existing_plugins && ! in_array( $this->kbmigration->existing_plugins[0][0], $this->kbmigration->migrated_plugins ) ) {
352 354 $plugin_name = '<strong>' . esc_html( $this->kbmigration->existing_plugins[0][1] ) . '</strong>';
@@ -351,9 +353,9 @@
351 353 if ( $this->kbmigration->existing_plugins && ! in_array( $this->kbmigration->existing_plugins[0][0], $this->kbmigration->migrated_plugins ) ) {
352 354 $plugin_name = '<strong>' . esc_html( $this->kbmigration->existing_plugins[0][1] ) . '</strong>';
353 355
354 356 $message = sprintf(
355 - /* translators: %s is the name of the existing knowledge base plugin. */
357 + /* translators: %s is the name of the existing knowledge base plugin. */
356 358 __( 'Already using %s? Power up your Knowledge Base by migrating all your docs and settings to BetterDocs with just 1 click.', 'betterdocs' ),
357 359 esc_html( $plugin_name )
358 360 );
359 361
@@ -363,51 +365,50 @@
363 365 esc_url( admin_url( 'admin.php?page=betterdocs-settings&tab=tab-migration' ) ),
364 366 esc_html__( 'Start Migration', 'betterdocs' )
365 367 );
366 368
367 - $_migration_notice = array(
369 + $_migration_notice = [
368 370 'thumbnail' => '',
369 371 'html' => $migration_message,
370 - 'links' => array(
371 - 'maybe_later' => array(
372 + 'links' => [
373 + 'maybe_later' => [
372 374 'label' => __( 'Maybe Later', 'betterdocs' ),
373 375 'icon_class' => 'dashicons dashicons-calendar-alt',
374 - 'attributes' => array(
376 + 'attributes' => [
375 377 'data-later' => true,
376 - 'class' => 'dismiss-btn',
377 - ),
378 - ),
379 - 'never_show_again' => array(
378 + 'class' => 'dismiss-btn'
379 + ]
380 + ],
381 + 'never_show_again' => [
380 382 'label' => __( 'Never show again', 'betterdocs' ),
381 383 'icon_class' => 'dashicons dashicons-dismiss',
382 - 'attributes' => array(
383 - 'data-dismiss' => true,
384 - ),
385 - ),
386 - ),
387 - );
384 + 'attributes' => [
385 + 'data-dismiss' => true
386 + ]
387 + ]
388 + ]
389 + ];
388 390
389 391 $notices->add(
390 392 'migration',
391 393 $_migration_notice,
392 - array(
394 + [
393 395 'start' => $notices->time(),
394 396 'recurrence' => false,
395 - 'dismissible' => true,
396 - )
397 + 'dismissible' => true
398 + ]
397 399 );
398 400 }
399 401
400 402 /**
401 - *
402 403 * Opt-In Notice
403 404 */
404 405 $allow_tracking = get_option( 'wpins_allow_tracking' );
405 - if ( null != $this->insights && ! isset( $allow_tracking['betterdocs'] ) ) {
406 + if ( $this->insights != null && ! isset( $allow_tracking['betterdocs'] ) ) {
406 407 $notices->add(
407 408 'opt_in',
408 - array( $this->insights, 'notice' ),
409 - array(
409 + [ $this->insights, 'notice' ],
410 + [
410 411 'classes' => 'updated put-dismiss-notice',
411 412 'start' => $notices->time(),
412 413 'refresh' => BETTERDOCS_VERSION,
413 414 'dismissible' => true,
@@ -412,48 +413,70 @@
412 413 'refresh' => BETTERDOCS_VERSION,
413 414 'dismissible' => true,
414 415 'do_action' => 'wpdeveloper_notice_clicked_for_betterdocs',
415 416 'display_if' => ! function_exists( 'betterdocs_pro' ),
416 - 'screens' => array( 'dashboard' ),
417 - )
417 + 'screens' => [ 'dashboard' ]
418 + ]
418 419 );
419 420 }
420 421
421 - $summer_campaign_message = '<div class="betterdocs-summer-notice-body"><p style="margin-top: 0; margin-bottom: 0;">🏖️ <strong>Summer Savings:</strong> Build AI-powered Knowledge Bases & FAQs to cut support tickets and improve user experience – now <strong>up to $100 OFF!</strong></p></div>';
422 - $_summer_campaign_notice = array(
422 + $blackfriday_message = '<div class="betterdocs-blackfriday-notice-body"><p style="margin-top: 0; margin-bottom: 0;"><strong>Black Friday Mega Sale:</strong> Build <strong>AI-Powered Knowledge Base</strong> & FAQs to empower support and improve user experience – now <strong>up to $120 OFF!</strong> 🎁</p></div>';
423 + $_blackfriday_notice = [
423 424 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
424 - 'html' => $summer_campaign_message,
425 - 'links' => array(
426 - 'support' => array(
427 - 'link' => 'https://betterdocs.co/summer2026-admin-notice',
428 - 'attributes' => array(
425 + 'html' => $blackfriday_message,
426 + 'links' => [
427 + 'support' => [
428 + 'link' => 'https://betterdocs.co/bfcm2025-admin-notice',
429 + 'attributes' => [
429 430 'target' => '_blank',
430 - 'class' => 'offer-button',
431 - ),
432 - 'label' => __( 'Upgrade To PRO Now', 'betterdocs' ),
433 - ),
434 - 'maybe_later' => array(
431 + 'class' => 'offer-button'
432 + ],
433 + 'label' => __( 'Upgrade To PRO', 'betterdocs' )
434 + ],
435 + 'maybe_later' => [
435 436 'label' => __( 'I’ll Grab It Later', 'betterdocs' ),
436 - 'attributes' => array(
437 - 'target' => '_blank',
437 + 'attributes' => [
438 + 'target' => '_blank',
438 439 'data-later' => true,
439 - 'class' => 'dismiss-btn',
440 - ),
441 - ),
442 - ),
440 + 'class' => 'dismiss-btn'
441 + ]
442 + ],
443 + ]
444 + ];
445 +
446 + $notices->add(
447 + 'blackfriday25',
448 + $_blackfriday_notice,
449 + [
450 + 'start' => $notices->time(),
451 + 'recurrence' => false,
452 + 'dismissible' => true,
453 + 'refresh' => BETTERDOCS_VERSION,
454 + 'expire' => strtotime( '11:59:59pm December 4, 2025' ),
455 + 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' )
456 + ]
443 457 );
444 458
459 + $offer_message = '<div class="betterdocs-notice-body betterdocs-holiday-notice-body"><p style="margin-top: 0; margin-bottom: 0;"><strong>🎉 BetterDocs Just Hit 40,000+ Users!</strong> Join the celebration with 20% OFF & unlock even more power with premium features today!</p><div class="betterdocs-notice-actions"><a class="button button-primary" href="https://betterdocs.co/40K-admin-notice" target="_blank"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
460 + <path d="M15.7431 10.9381L15.904 9.35966C15.9898 8.5175 16.0464 7.9614 16.002 7.61102L16.0175 7.61112C16.7442 7.61112 17.3333 6.98929 17.3333 6.22223C17.3333 5.45517 16.7442 4.83334 16.0175 4.83334C15.2908 4.83334 14.7017 5.45517 14.7017 6.22223C14.7017 6.56914 14.8222 6.88634 15.0214 7.12975C14.7354 7.31608 14.3615 7.70926 13.7987 8.30106L13.7986 8.30107L13.7986 8.30108C13.365 8.75699 13.1482 8.98495 12.9064 9.02025C12.7724 9.03981 12.6358 9.01971 12.5121 8.96219C12.2887 8.85838 12.1398 8.57656 11.842 8.01293L10.2723 5.04204C10.0886 4.69433 9.9348 4.40331 9.79616 4.16913C10.3649 3.86285 10.7543 3.23869 10.7543 2.51852C10.7543 1.49577 9.96888 0.666672 8.99996 0.666672C8.03104 0.666672 7.24557 1.49577 7.24557 2.51852C7.24557 3.23869 7.63503 3.86285 8.20376 4.16913C8.06511 4.40333 7.91137 4.6943 7.72763 5.04204L6.1579 8.01293C5.8601 8.57656 5.71119 8.85838 5.48786 8.96219C5.36411 9.01971 5.22757 9.03981 5.09355 9.02025C4.85169 8.98495 4.63488 8.75699 4.20127 8.30107C3.63844 7.70928 3.26449 7.31608 2.97849 7.12975C3.17771 6.88634 3.29821 6.56914 3.29821 6.22223C3.29821 5.45517 2.70911 4.83334 1.98242 4.83334C1.25572 4.83334 0.666626 5.45517 0.666626 6.22223C0.666626 6.98929 1.25572 7.61112 1.98242 7.61112L1.99795 7.61102C1.95348 7.96139 2.01015 8.51749 2.09596 9.35965L2.2568 10.938C2.34608 11.8142 2.42032 12.6478 2.51125 13.3982H15.4887C15.5796 12.6478 15.6538 11.8142 15.7431 10.9381Z" fill="white"/>
461 + <path d="M8.04563 17.3333H9.95429C12.4419 17.3333 13.6858 17.3333 14.5157 16.5492C14.8779 16.207 15.1073 15.59 15.2728 14.787H2.72711C2.89263 15.59 3.12201 16.207 3.48424 16.5492C4.31414 17.3333 5.55797 17.3333 8.04563 17.3333Z" fill="white"/>
462 + </svg>Upgrade To PRO</a></div></div>';
463 + $_offer_notice = [
464 + 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
465 + 'html' => $offer_message
466 + ];
467 +
445 468 $notices->add(
446 - 'summer-campaign-26',
447 - $_summer_campaign_notice,
448 - array(
469 + '40k_offer',
470 + $_offer_notice,
471 + [
449 472 'start' => $notices->time(),
450 473 'recurrence' => false,
451 474 'dismissible' => true,
452 475 'refresh' => BETTERDOCS_VERSION,
453 - 'expire' => strtotime( '11:59:59pm June 25, 2026' ),
454 - 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ),
455 - )
476 + 'expire' => strtotime( '11:59:59pm April 30, 2025' ),
477 + 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' )
478 + ]
456 479 );
457 480
458 481 self::$cache_bank->create_account( $notices );
459 482 self::$cache_bank->calculate_deposits( $notices );
@@ -458,9 +481,9 @@
458 481 self::$cache_bank->create_account( $notices );
459 482 self::$cache_bank->calculate_deposits( $notices );
460 483 if ( method_exists( self::$cache_bank, 'clear_notices_in_' ) ) {
461 484 self::$cache_bank->clear_notices_in_(
462 - array(
485 + [
463 486 'toplevel_page_betterdocs-dashboard',
464 487 'admin_page_betterdocs-admin',
465 488 'betterdocs_page_betterdocs-admin',
466 489 'betterdocs_page_betterdocs-settings',
@@ -468,10 +491,10 @@
468 491 'betterdocs_page_betterdocs-analytics',
469 492 'betterdocs_page_betterdocs-glossaries',
470 493 'betterdocs_page_betterdocs-ai-chatbot',
471 494 'edit-doc_category',
472 - 'edit-doc_tag',
473 - ),
495 + 'edit-doc_tag'
496 + ],
474 497 $notices,
475 498 true
476 499 );
477 500 }
@@ -481,26 +504,26 @@
481 504 $saved_settings = get_option( 'betterdocs_settings', false );
482 505 $dark_mode = isset( $saved_settings['dark_mode'] ) ? $saved_settings['dark_mode'] : false;
483 506 $dark_mode = ! empty( $dark_mode ) ? boolval( $dark_mode ) : false;
484 507 $current_screen_id = get_current_screen() != null ? str_replace( 'betterdocs_page_', '', str_replace( 'toplevel_page_', '', str_replace( 'admin_page_', '', get_current_screen()->id ) ) ) : '';
485 - $registered_screens = array(
486 - 'betterdocs-settings',
487 - 'betterdocs-admin',
488 - 'betterdocs-dashboard',
489 - 'betterdocs-analytics',
490 - 'betterdocs-glossaries',
491 - 'betterdocs-faq',
492 - 'edit-doc_category',
493 - 'edit-doc_tag',
494 - 'edit-knowledge_base',
495 - 'betterdocs-ai-chatbot',
496 - );
508 + $registered_screens = [
509 + 'betterdocs-settings',
510 + 'betterdocs-admin',
511 + 'betterdocs-dashboard',
512 + 'betterdocs-analytics',
513 + 'betterdocs-glossaries',
514 + 'betterdocs-faq',
515 + 'edit-doc_category',
516 + 'edit-doc_tag',
517 + 'edit-knowledge_base',
518 + 'betterdocs-ai-chatbot'
519 + ];
497 520
498 - if ( in_array( $current_screen_id, $registered_screens ) ) {
499 - $classes .= ' betterdocs-admin ';
500 - }
521 + if( in_array( $current_screen_id, $registered_screens ) ) {
522 + $classes .= ' betterdocs-admin ';
523 + }
501 524
502 - if ( true === $dark_mode && in_array( $current_screen_id, $registered_screens ) ) {
525 + if ( $dark_mode === true && in_array( $current_screen_id, $registered_screens ) ) {
503 526 $classes .= ' betterdocs-dark-mode ';
504 527 }
505 528
506 529 return $classes;
@@ -515,11 +538,11 @@
515 538 * @since 1.0.0
516 539 */
517 540 public function set_custom_edit_action_columns( $columns ) {
518 541 unset( $columns['comments'] );
519 - $new_columns = array();
542 + $new_columns = [];
520 543 foreach ( $columns as $key => $value ) {
521 - if ( 'date' == $key ) {
544 + if ( $key == 'date' ) {
522 545 $new_columns['betterdocs_word_count'] = __( 'Word Count', 'betterdocs' ); // put the tags column before it
523 546 $new_columns['betterdocs_reaction'] = __( 'Reactions', 'betterdocs' );
524 547 }
525 548 $new_columns[ $key ] = $value;
@@ -533,9 +556,9 @@
533 556 switch ( $column ) {
534 557 case 'betterdocs_word_count':
535 558 $content_without_html_tags = trim( strip_tags( get_post_field( 'post_content', $post_id ) ) );
536 559 preg_match_all( '/<[^>]*>|[\p{L}\p{M}]+/u', $content_without_html_tags, $matches );
537 - $total_words = ! empty( $matches[0] ) ? count( $matches[0] ) : count( array() );
560 + $total_words = ! empty( $matches[0] ) ? count( $matches[0] ) : count( [] );
538 561 $word_count = $total_words;
539 562 echo '<span>' . esc_html( intval( $word_count ) ) . '</span>';
540 563 break;
541 564 case 'betterdocs_reaction':
@@ -606,22 +629,22 @@
606 629 * @return void
607 630 * @since 1.0.0
608 631 */
609 632 public function styles( $hook ) {
610 - $this->assets->enqueue( 'betterdocs-global', 'admin/css/global.css', array(), 'all' );
633 + $this->assets->enqueue( 'betterdocs-global', 'admin/css/global.css', [], 'all' );
611 634
612 635 if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
613 636 return;
614 637 }
615 638
616 - $this->assets->enqueue( 'betterdocs-select2', 'vendor/css/select2.min.css', array(), 'all' );
617 - $this->assets->enqueue( 'betterdocs-daterangepicker', 'vendor/css/daterangepicker.css', array(), 'all' );
618 - $this->assets->enqueue( 'betterdocs-old', 'admin/css/betterdocs.css', array(), 'all' );
639 + $this->assets->enqueue( 'betterdocs-select2', 'vendor/css/select2.min.css', [], 'all' );
640 + $this->assets->enqueue( 'betterdocs-daterangepicker', 'vendor/css/daterangepicker.css', [], 'all' );
641 + $this->assets->enqueue( 'betterdocs-old', 'admin/css/betterdocs.css', [], 'all' );
619 642
620 643 /**
621 - * This scripts enqueued for Dashboard App.
622 - */
623 - $this->assets->enqueue( 'betterdocs', 'admin/css/dashboard.css', array( 'betterdocs-old' ), '', BETTERDOCS_VERSION );
644 + * This scripts enqueued for Dashboard App.
645 + */
646 + $this->assets->enqueue( 'betterdocs', 'admin/css/dashboard.css', [ 'betterdocs-old' ], '', BETTERDOCS_VERSION );
624 647 $this->assets->enqueue( 'betterdocs-icons', 'admin/btd-icon/style.css' );
625 648 }
626 649
627 650 /**
@@ -632,26 +655,26 @@
632 655 * @return void
633 656 * @since 1.0.0
634 657 */
635 658 public function scripts( $hook ) {
636 - if ( ( 'edit.php' === $hook ) && get_post_type() == 'docs' ) {
659 + if ( ( $hook === 'edit.php' ) && get_post_type() == 'docs' ) {
637 660 $this->assets->enqueue(
638 661 'betterdocs-switcher',
639 662 'admin/js/switcher.js',
640 - array(
641 - 'jquery',
642 - )
663 + [
664 + 'jquery'
665 + ]
643 666 );
644 667
645 668 $this->assets->localize(
646 669 'betterdocs-switcher',
647 670 'betterdocsSwitcher',
648 - array(
671 + [
649 672 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
650 673 'site_address' => get_bloginfo( 'url' ),
651 674 'betterdocs_pro_plugin' => betterdocs()->is_pro_active(),
652 - 'betterdocs_pro_version' => betterdocs()->pro_version(),
653 - )
675 + 'betterdocs_pro_version' => betterdocs()->pro_version()
676 + ]
654 677 );
655 678
656 679 return;
657 680 }
@@ -661,9 +684,9 @@
661 684 if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
662 685 return;
663 686 }
664 687
665 - wp_enqueue_media(); // load early to fix problems with media upload issues on settings for WordPress 6.0.9
688 + wp_enqueue_media(); // load early to fix problems with media upload issues on settings for wordpress 6.0.9
666 689 $this->assets->register( 'betterdocs-admin', 'admin/js/dashboard.js' );
667 690
668 691 $saved_settings = get_option( 'betterdocs_settings', false );
669 692 $dark_mode = $saved_settings['dark_mode'] ?? false;
@@ -670,55 +693,53 @@
670 693 $dark_mode = ! empty( $dark_mode ) && boolval( $dark_mode );
671 694 $this->assets->localize(
672 695 'betterdocs-admin',
673 696 'betterdocs_admin',
674 - array(
697 + [
675 698 'ajaxurl' => admin_url( 'admin-ajax.php' ),
676 699 'doc_cat_order_nonce' => wp_create_nonce( 'doc_cat_order_nonce' ),
677 700 'knowledge_base_order_nonce' => wp_create_nonce( 'knowledge_base_order_nonce' ),
678 701 'paged' => isset( $_GET['paged'] ) ? absint( wp_unslash( $_GET['paged'] ) ) : 0, // phpcs:ignore WordPress.Security.NonceVerification.Missing
679 - 'per_page_id' => 'edit_doc_category_per_page',
680 - 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
681 - 'dark_mode' => $dark_mode,
682 - 'text' => __( 'Copied!', 'betterdocs' ),
683 - 'test_report' => __( 'Test Report!', 'betterdocs' ),
684 - 'sending' => __( 'Sending...', 'betterdocs' ),
685 - 'dir_url' => BETTERDOCS_ABSURL,
686 - 'rest_url' => esc_url_raw( rest_url() ),
687 - 'free_version' => betterdocs()->version,
688 - 'generate_data_url' => get_rest_url( null, '/betterdocs/v1/create-sample-docs' ),
689 - 'nonce' => wp_create_nonce( 'wp_rest' ),
690 - 'sync_nonce' => wp_create_nonce( 'ai_chatbot_embed' ),
691 - 'count_all_docs' => array_sum( (array) wp_count_posts( 'docs' ) ),
692 - 'count_all_faq' => array_sum( (array) wp_count_posts( 'betterdocs_faq' ) ),
693 - 'count_new_docs' => $this->get_not_synced_docs_count(),
694 - 'admin_url' => admin_url(),
695 - 'ia_preview' => betterdocs()->settings->get( 'ia_enable_preview', false ),
696 - 'multiple_kb' => betterdocs()->settings->get( 'multiple_kb' ),
697 - 'previewMode' => betterdocs()->settings->get( 'ia_enable_preview', false ),
698 - 'dashboard_mode' => get_option( 'dashboard_mode' ),
699 - 'betterdocs_pro_plugin' => betterdocs()->is_pro_active(),
700 - 'betterdocs_pro_version' => betterdocs()->pro_version(),
701 - 'analytics_older' => version_compare( betterdocs()->pro_version(), '3.3.4', '<=' ),
702 - 'disabled_embed_model_option' => get_option( 'disabled_embed_model_option' ),
703 - 'betterdocs_ChatBot_plugin' => is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' ),
704 - 'total_doc_category_terms' => wp_count_terms( 'doc_category' ),
705 - 'current_admin_language' => Helper::get_current_admin_language(),
706 - 'is_multilingual' => Helper::is_multilingual_active(),
707 - )
702 + 'per_page_id' => 'edit_doc_category_per_page',
703 + 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
704 + 'dark_mode' => $dark_mode,
705 + 'text' => __( 'Copied!', 'betterdocs' ),
706 + 'test_report' => __( 'Test Report!', 'betterdocs' ),
707 + 'sending' => __( 'Sending...', 'betterdocs' ),
708 + 'dir_url' => BETTERDOCS_ABSURL,
709 + 'rest_url' => esc_url_raw( rest_url() ),
710 + 'free_version' => betterdocs()->version,
711 + 'generate_data_url' => get_rest_url( null, '/betterdocs/v1/create-sample-docs' ),
712 + 'nonce' => wp_create_nonce( 'wp_rest' ),
713 + 'sync_nonce' => wp_create_nonce( 'ai_chatbot_embed' ),
714 + 'count_all_docs' => array_sum((array) wp_count_posts('docs')),
715 + 'count_all_faq' => array_sum((array) wp_count_posts('betterdocs_faq')),
716 + 'count_new_docs' => count(get_option('saved_docs_post_ids', [])) + count(get_option('betterdocs_ai_chatbot_error_posts', [])),
717 + 'admin_url' => admin_url(),
718 + 'ia_preview' => betterdocs()->settings->get( 'ia_enable_preview', false ),
719 + 'multiple_kb' => betterdocs()->settings->get( 'multiple_kb' ),
720 + 'previewMode' => betterdocs()->settings->get( 'ia_enable_preview', false ),
721 + 'dashboard_mode' => get_option( 'dashboard_mode' ),
722 + 'betterdocs_pro_plugin' => betterdocs()->is_pro_active(),
723 + 'betterdocs_pro_version' => betterdocs()->pro_version(),
724 + 'analytics_older' => version_compare( betterdocs()->pro_version(), '3.3.4', '<=' ),
725 + 'disabled_embed_model_option' => get_option('disabled_embed_model_option'),
726 + 'betterdocs_ChatBot_plugin' => is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' ),
727 + 'total_doc_category_terms' => wp_count_terms( 'doc_category')
728 + ]
708 729 );
709 730
710 731 // If wp-date (which includes moment.js) is not registered, enqueue your custom moment.js
711 732 if ( ! wp_script_is( 'wp-date', 'registered' ) ) {
712 - $this->assets->enqueue( 'moment', 'vendor/js/moment.min.js', array() );
733 + $this->assets->enqueue( 'moment', 'vendor/js/moment.min.js', [] );
713 734 }
714 735 wp_enqueue_script( 'betterdocs-admin' );
715 736
716 737 /**
717 - * Duplicate Codes Need to Be Removed From Here Onwards
718 - */
738 + * Duplicate Codes Need to Be Removed From Here Onwards
739 + */
719 740
720 - // FAQ Builder Related Localization
741 + //FAQ Builder Related Localization
721 742 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/css/faq.css' );
722 743 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/js/faq.js' );
723 744
724 745 // removing emoji support
@@ -724,28 +745,21 @@
724 745 // removing emoji support
725 746 remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
726 747 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
727 748
728 - // Get settings and remove unnecessary keys
729 - $betterdocs_settings = get_option( 'betterdocs_settings', false );
730 - if ( is_array( $betterdocs_settings ) && ! current_user_can( 'edit_docs_settings' ) ) {
731 - unset( $betterdocs_settings['ai_autowrite_api_key'] );
732 - unset( $betterdocs_settings['ai_chatbot_api_key'] );
733 - }
734 -
735 749 betterdocs()->assets->localize(
736 750 'betterdocs-admin-faq',
737 751 'betterdocsFaq',
738 - array(
752 + [
739 753 'dir_url' => BETTERDOCS_ABSURL,
740 754 'rest_url' => esc_url_raw( rest_url() ),
741 755 'free_version' => betterdocs()->version,
742 756 'nonce' => wp_create_nonce( 'wp_rest' ),
743 - 'betterdocs_settings' => $betterdocs_settings,
744 - )
757 + 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
758 + ]
745 759 );
746 760
747 - // Glossaries Related Localization
761 + //Glossaries Related Localization
748 762 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/css/faq.css' );
749 763
750 764 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/js/glossaries.js' );
751 765
@@ -751,15 +765,15 @@
751 765
752 766 betterdocs()->assets->localize(
753 767 'betterdocs-admin-glossaries',
754 768 'betterdocsGlossary',
755 - array(
769 + [
756 770 'dir_url' => BETTERDOCS_ABSURL,
757 771 'rest_url' => esc_url_raw( rest_url() ),
758 772 'free_version' => betterdocs()->version,
759 773 'nonce' => wp_create_nonce( 'wp_rest' ),
760 - 'betterdocs_settings' => $betterdocs_settings,
761 - )
774 + 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
775 + ]
762 776 );
763 777 }
764 778
765 779 /**
@@ -768,31 +782,31 @@
768 782 * @return void
769 783 * @since 1.0.0
770 784 */
771 785 public function header( $admin_tab_name ) {
772 - $quick_links = array(
786 + $quick_links = [
773 787 'switch_view' => sprintf(
774 788 '<a href="%s" class="betterdocs-button betterdocs-button-secondary">%s</a>',
775 789 add_query_arg(
776 - array(
790 + [
777 791 'post_type' => 'docs',
778 - 'bdocs_view' => 'classic',
779 - ),
792 + 'bdocs_view' => 'classic'
793 + ],
780 794 'edit.php'
781 795 ),
782 796 __( 'Switch to Classic UI', 'betterdocs' )
783 797 ),
784 - 'add_new_doc' => sprintf( '<a href="%s" class="betterdocs-button betterdocs-button-primary">%s</a>', add_query_arg( array( 'post_type' => 'docs' ), 'post-new.php' ), __( 'Add New Doc', 'betterdocs' ) ),
785 - );
798 + 'add_new_doc' => sprintf( '<a href="%s" class="betterdocs-button betterdocs-button-primary">%s</a>', add_query_arg( [ 'post_type' => 'docs' ], 'post-new.php' ), __( 'Add New Doc', 'betterdocs' ) )
799 + ];
786 800
787 801 $quick_links = apply_filters( 'betterdocs_quick_links', $quick_links );
788 802
789 803 betterdocs()->views->get(
790 804 'admin/header',
791 - array(
805 + [
792 806 'quick_links' => $quick_links,
793 - 'active_tab' => $admin_tab_name,
794 - )
807 + 'active_tab' => $admin_tab_name
808 + ]
795 809 );
796 810 }
797 811
798 812 /**
@@ -801,17 +815,17 @@
801 815 * @return void
802 816 * @since 1.0.0
803 817 */
804 818 public function menus() {
805 - $default_args = array(
819 + $default_args = [
806 820 'page_title' => 'BetterDocs',
807 821 'menu_title' => 'BetterDocs',
808 - 'capability' => 'edit_docs', // Unified capability
822 + 'capability' => 'edit_docs', // Unified capability
809 823 'menu_slug' => $this->slug,
810 - 'callback' => array( $this, 'output' ),
824 + 'callback' => [ $this, 'output' ],
811 825 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
812 - 'position' => 5,
813 - );
826 + 'position' => 5
827 + ];
814 828
815 829 $_menu_position = 5;
816 830 global $submenu;
817 831
@@ -818,23 +832,23 @@
818 832 // Always register both UI endpoints
819 833 $this->register_modern_ui_fallback();
820 834
821 835 foreach ( $this->menu_list() as $key => $value ) {
822 - if ( 'betterdocs' === $key ) {
836 + if ( $key === 'betterdocs' ) {
823 837 $callable = 'add_menu_page';
824 838 $value = wp_parse_args( $value, $default_args );
825 839 call_user_func_array( $callable, $value );
826 840 } else {
827 - $is_core_page = strpos( $value['menu_slug'], '?' ) !== false;
841 + $is_core_page = strpos($value['menu_slug'], '?') !== false;
828 842
829 - if ( $is_core_page ) {
843 + if ($is_core_page) {
830 844 // Add classic UI directly
831 - $submenu[ $this->slug ][] = array(
845 + $submenu[$this->slug][] = [
832 846 $value['menu_title'],
833 847 $value['capability'],
834 848 $value['menu_slug'],
835 - $value['page_title'],
836 - );
849 + $value['page_title']
850 + ];
837 851 } else {
838 852 // Add modern UI through WordPress API
839 853 add_submenu_page(
840 854 $this->slug,
@@ -844,9 +858,9 @@
844 858 $value['menu_slug'],
845 859 $value['callback']
846 860 );
847 861 }
848 - ++$_menu_position;
862 + $_menu_position++;
849 863 }
850 864 }
851 865 }
852 866
@@ -853,21 +867,21 @@
853 867 private function register_modern_ui_fallback() {
854 868 // Add the submenu with valid parent slug
855 869 add_submenu_page(
856 870 'betterdocs', // Valid parent slug
857 - __( 'All Docs', 'betterdocs' ),
871 + __('All Docs', 'betterdocs'),
858 872 '', // Empty menu title hides it
859 873 'edit_docs',
860 874 'betterdocs-admin',
861 - array( $this, 'output' )
875 + [ $this, 'output' ]
862 876 );
863 877
864 878 // Hide the menu item from appearing in the admin sidebar
865 879 global $submenu;
866 - if ( isset( $submenu['betterdocs'] ) ) {
867 - foreach ( $submenu['betterdocs'] as $key => $item ) {
868 - if ( 'betterdocs-admin' === $item[2] ) {
869 - unset( $submenu['betterdocs'][ $key ] );
880 + if (isset($submenu['betterdocs'])) {
881 + foreach ($submenu['betterdocs'] as $key => $item) {
882 + if ($item[2] === 'betterdocs-admin') {
883 + unset($submenu['betterdocs'][$key]);
870 884 break;
871 885 }
872 886 }
873 887 }
@@ -880,17 +894,17 @@
880 894 * @since 1.0.0
881 895 */
882 896 public function output() {
883 897 if ( betterdocs()->is_pro_active()
884 - && version_compare( betterdocs()->pro_version(), '3.3.4', '<=' )
885 - && get_current_screen()->id == 'betterdocs_page_betterdocs-analytics' ) {
898 + && version_compare( betterdocs()->pro_version(), '3.3.4', '<=' )
899 + && get_current_screen()->id == 'betterdocs_page_betterdocs-analytics' ) {
886 900 betterdocs_pro()->views->get( 'admin/analytics-pro' );
887 901 } else {
888 902 betterdocs()->views->get(
889 903 'admin/main',
890 - array(
891 - 'admin_ui' => 'dnd',
892 - )
904 + [
905 + 'admin_ui' => 'dnd'
906 + ]
893 907 );
894 908 }
895 909 }
896 910
@@ -903,10 +917,11 @@
903 917 * @param array $callback
904 918 *
905 919 * @return array
906 920 * @since 2.5.0
921 + *
907 922 */
908 - private function normalize_menu( $title, $slug, $cap = 'edit_docs', $callback = null, $optional = array() ) {
923 + private function normalize_menu( $title, $slug, $cap = 'edit_docs', $callback = null, $optional = [] ) {
909 924 return Helper::normalize_menu( $title, $slug, $cap, $callback, $optional );
910 925 }
911 926
912 927 /**
@@ -915,34 +930,34 @@
915 930 * @return array
916 931 * @since 1.0.0
917 932 */
918 933 private function menu_list() {
919 - $parent_slug = array();
934 + $parent_slug = [];
920 935
921 - $betterdocs_admin_pages = array(
922 - 'betterdocs' => array(
936 + $betterdocs_admin_pages = [
937 + 'betterdocs' => [
923 938 'menu_slug' => $this->slug,
924 939 'page_title' => 'BetterDocs',
925 940 'menu_title' => 'BetterDocs',
926 941 'capability' => 'edit_docs',
927 - 'callback' => array( $this, 'output' ),
942 + 'callback' => [ $this, 'output' ],
928 943 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
929 - 'position' => 5,
930 - ),
931 - 'dashboard' => $this->normalize_menu(
944 + 'position' => 5
945 + ],
946 + 'dashboard' => $this->normalize_menu(
932 947 __( 'Dashboard', 'betterdocs' ),
933 948 'betterdocs-dashboard',
934 949 'edit_docs',
935 - array(
950 + [
936 951 $this,
937 - 'output',
938 - )
952 + 'output'
953 + ]
939 954 ),
940 955 'all_docs' => $this->normalize_menu(
941 956 __( 'All Docs', 'betterdocs' ),
942 957 $this->ui_slug(),
943 958 'edit_docs',
944 - array( $this, 'output' ),
959 + [ $this, 'output' ],
945 960 $parent_slug
946 961 ),
947 962 'add_new' => $this->normalize_menu(
948 963 __( 'Add New', 'betterdocs' ),
@@ -961,12 +976,12 @@
961 976 'settings' => $this->normalize_menu(
962 977 __( 'Settings', 'betterdocs' ),
963 978 'betterdocs-settings',
964 979 'edit_docs_settings',
965 - array(
980 + [
966 981 $this,
967 - 'output',
968 - ),
982 + 'output'
983 + ],
969 984 $parent_slug
970 985 ),
971 986 'analytics' => $this->normalize_menu(
972 987 __( 'Analytics', 'betterdocs' ),
@@ -971,12 +986,12 @@
971 986 'analytics' => $this->normalize_menu(
972 987 __( 'Analytics', 'betterdocs' ),
973 988 'betterdocs-analytics',
974 989 'read_docs_analytics',
975 - array(
990 + [
976 991 $this,
977 - 'output',
978 - ),
992 + 'output'
993 + ],
979 994 $parent_slug
980 995 ),
981 996 'faq' => $this->normalize_menu(
982 997 __( 'FAQ Builder', 'betterdocs' ),
@@ -981,15 +996,15 @@
981 996 'faq' => $this->normalize_menu(
982 997 __( 'FAQ Builder', 'betterdocs' ),
983 998 'betterdocs-faq',
984 999 'read_faq_builder',
985 - array(
1000 + [
986 1001 $this,
987 - 'output',
988 - ),
1002 + 'output'
1003 + ],
989 1004 $parent_slug
990 - ),
991 - );
1005 + )
1006 + ];
992 1007
993 1008 if ( betterdocs()->is_pro_active() && betterdocs()->settings->get( 'enable_glossaries' ) == true ) {
994 1009 $betterdocs_admin_pages['glossaries'] = $this->normalize_menu(
995 1010 __( 'Glossaries', 'betterdocs' ),
@@ -994,36 +1009,38 @@
994 1009 $betterdocs_admin_pages['glossaries'] = $this->normalize_menu(
995 1010 __( 'Glossaries', 'betterdocs' ),
996 1011 'betterdocs-glossaries',
997 1012 'read_docs_analytics',
998 - array(
1013 + [
999 1014 $this,
1000 - 'output',
1001 - ),
1015 + 'output'
1016 + ],
1002 1017 $parent_slug
1003 1018 );
1004 1019 }
1005 1020
1006 - if ( ! betterdocs()->is_chatbot_active() ) {
1007 - $betterdocs_admin_pages['ai_chatbot'] = $this->normalize_menu(
1008 - __( 'AI Chatbot', 'betterdocs' ),
1009 - 'betterdocs-ai-chatbot',
1010 - 'edit_docs_settings',
1011 - array(
1021 +
1022 + if (!betterdocs()->is_chatbot_active()) {
1023 + $betterdocs_admin_pages['ai_chatbot'] = $this->normalize_menu(
1024 + __('AI Chatbot', 'betterdocs'),
1025 + 'betterdocs-ai-chatbot',
1026 + 'edit_docs_settings',
1027 + [
1012 1028 $this,
1013 - 'output',
1014 - ),
1015 - $parent_slug
1016 - );
1017 - }
1029 + 'output'
1030 + ],
1031 + $parent_slug
1032 + );
1033 + }
1018 1034
1019 - return apply_filters( 'betterdocs_admin_menu', $betterdocs_admin_pages, array( $this, 'output' ), $parent_slug );
1020 - }
1035 + return apply_filters( 'betterdocs_admin_menu', $betterdocs_admin_pages, [$this, 'output'], $parent_slug);
1021 1036
1037 + }
1038 +
1022 1039 public function add_custom_classes_to_menu_items() {
1023 1040 global $menu, $submenu;
1024 1041
1025 - $menu_items = array(
1042 + $menu_items = [
1026 1043 'betterdocs' => 'betterdocs',
1027 1044 'betterdocs_page_all_docs' => 'betterdocs-all-docs',
1028 1045 'betterdocs_page_add_new' => 'betterdocs-add-new',
1029 1046 'edit-tags.php?taxonomy=doc_category&post_type=docs' => 'betterdocs-categories',
@@ -1032,10 +1049,10 @@
1032 1049 'betterdocs-analytics' => 'betterdocs-analytics',
1033 1050 'betterdocs-faq' => 'betterdocs-faq',
1034 1051 'betterdocs-glossaries' => 'betterdocs-glossaries',
1035 1052 'betterdocs-ai-chatbot' => 'betterdocs-ai-chatbot',
1036 - 'edit-tags.php?taxonomy=knowledge_base&post_type=docs' => 'betterdocs-multiplekb',
1037 - );
1053 + 'edit-tags.php?taxonomy=knowledge_base&post_type=docs' => 'betterdocs-multiplekb'
1054 + ];
1038 1055
1039 1056 foreach ( $menu as &$item ) {
1040 1057 if ( isset( $menu_items[ $item[2] ] ) ) {
1041 1058 if ( ! isset( $item[4] ) ) {
@@ -1065,12 +1082,12 @@
1065 1082 $menus['quick_setup'] = $this->normalize_menu(
1066 1083 __( 'Quick Setup', 'betterdocs' ),
1067 1084 'betterdocs-setup',
1068 1085 'delete_users',
1069 - array(
1086 + [
1070 1087 $this->container->get( SetupWizard::class ),
1071 - 'views',
1072 - )
1088 + 'views'
1089 + ]
1073 1090 );
1074 1091 }
1075 1092
1076 1093 return $menus;
@@ -1078,10 +1095,10 @@
1078 1095
1079 1096 public function insert_plugin_links( $links ) {
1080 1097 $links[] = '<a href="admin.php?page=betterdocs-settings">' . __( 'Settings', 'betterdocs' ) . '</a>';
1081 1098
1082 - if ( ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ) ) {
1083 - $links[] = '<a href="https://betterdocs.co/upgrade-to-pro-plugins-wp" target="_blank" style="color: #000; font-weight: bold;">' . __( 'Upgrade to Pro', 'betterdocs' ) . '</a>';
1099 + if (! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ) ) {
1100 + $links[] = '<a href="https://betterdocs.co/bfcm-2025-plugins-wp" target="_blank" style="color: #000; font-weight: bold;">' . __( 'Save 40% Today', 'betterdocs' ) . '</a>';
1084 1101 }
1085 1102
1086 1103 return $links;
1087 1104 }
@@ -1110,22 +1127,17 @@
1110 1127 }
1111 1128
1112 1129 $slug = $this->settings->get( 'encyclopedia_root_slug' );
1113 1130
1114 - global $wp_rewrite;
1115 - if ( $wp_rewrite->using_index_permalinks() ) {
1116 - $slug = $wp_rewrite->index . '/' . $slug;
1117 - }
1118 -
1119 1131 $encyclopedia_url = home_url( $slug );
1120 1132
1121 1133 $admin_bar->add_node(
1122 - array(
1134 + [
1123 1135 'parent' => 'site-name',
1124 1136 'id' => 'view-docs',
1125 1137 'title' => __( 'Visit Documentation', 'betterdocs' ),
1126 - 'href' => $docs_url,
1127 - )
1138 + 'href' => $docs_url
1139 + ]
1128 1140 );
1129 1141
1130 1142 $is_enable_encyclopedia = betterdocs()->settings->get( 'enable_encyclopedia' );
1131 1143
@@ -1130,14 +1142,14 @@
1130 1142 $is_enable_encyclopedia = betterdocs()->settings->get( 'enable_encyclopedia' );
1131 1143
1132 1144 if ( $is_enable_encyclopedia && betterdocs()->is_pro_active() ) {
1133 1145 $admin_bar->add_node(
1134 - array(
1146 + [
1135 1147 'parent' => 'site-name',
1136 1148 'id' => 'view-encyclopedia',
1137 1149 'title' => __( 'Visit Encyclopedia', 'betterdocs' ),
1138 - 'href' => $encyclopedia_url,
1139 - )
1150 + 'href' => $encyclopedia_url
1151 + ]
1140 1152 );
1141 1153 }
1142 1154 }
1143 1155
@@ -1144,13 +1156,14 @@
1144 1156 /**
1145 1157 * Save last visited admin ui
1146 1158 *
1147 1159 * @since 3.0.1
1160 + *
1148 1161 */
1149 1162 public function save_admin_page() {
1150 - if ( isset( $_GET['post_type'] ) && 'docs' === $_GET['post_type'] && isset( $_GET['bdocs_view'] ) && 'classic' === $_GET['bdocs_view'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1163 + if ( isset( $_GET['post_type'] ) && $_GET['post_type'] === 'docs' && isset( $_GET['bdocs_view'] ) && $_GET['bdocs_view'] === 'classic' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1151 1164 update_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', 'classic_ui' );
1152 - } elseif ( isset( $_GET['page'] ) && 'betterdocs-admin' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1165 + } elseif ( isset( $_GET['page'] ) && $_GET['page'] === 'betterdocs-admin' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1153 1166 update_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', 'modern_ui' );
1154 1167 }
1155 1168 }
1156 1169
@@ -1160,20 +1173,18 @@
1160 1173 * @return string
1161 1174 * @since 3.0.1
1162 1175 */
1163 1176 public function ui_slug() {
1164 - $last_visited = get_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', true );
1165 - $docs_exist = get_posts(
1166 - array(
1167 - 'post_type' => 'docs',
1168 - 'post_status' => 'any',
1169 - 'numberposts' => 1,
1170 - )
1171 - );
1177 + $last_visited = get_user_meta(get_current_user_id(), 'last_visited_docs_admin_page', true);
1178 + $docs_exist = get_posts([
1179 + 'post_type' => 'docs',
1180 + 'post_status' => 'any',
1181 + 'numberposts' => 1
1182 + ]);
1172 1183
1173 - return ( 'modern_ui' === $last_visited || empty( $docs_exist ) )
1174 - ? 'betterdocs-admin'
1175 - : 'edit.php?post_type=docs&bdocs_view=classic';
1184 + return ($last_visited === 'modern_ui' || empty($docs_exist))
1185 + ? 'betterdocs-admin'
1186 + : 'edit.php?post_type=docs&bdocs_view=classic';
1176 1187 }
1177 1188
1178 1189 /**
1179 1190 * Resets a duplicate submenu in WordPress if the parent main menu and the first submenu permalink are not the same.
@@ -1183,9 +1194,9 @@
1183 1194 */
1184 1195 public function reset_submenu() {
1185 1196 global $submenu;
1186 1197
1187 - $docs = get_posts( array( 'post_type' => 'docs' ) );
1198 + $docs = get_posts( [ 'post_type' => 'docs' ] );
1188 1199 if ( count( $docs ) == 0 ) {
1189 1200 return;
1190 1201 }
1191 1202
@@ -1190,9 +1201,9 @@
1190 1201 }
1191 1202
1192 1203 $last_visited = get_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', true );
1193 1204
1194 - if ( 'classic_ui' === $last_visited && isset( $submenu['betterdocs-admin'] ) && in_array( 'betterdocs-admin', $submenu['betterdocs-admin'][0] ) ) {
1205 + if ( $last_visited === 'classic_ui' && isset( $submenu['betterdocs-admin'] ) && in_array( 'betterdocs-admin', $submenu['betterdocs-admin'][0] ) ) {
1195 1206 unset( $submenu['betterdocs-admin'][0] );
1196 1207 $submenu['betterdocs-admin'] = array_values( $submenu['betterdocs-admin'] );
1197 1208 }
1198 1209 }
@@ -1218,14 +1229,14 @@
1218 1229 */
1219 1230 public function ajax_dismiss_black_friday_pointer() {
1220 1231 // Verify nonce
1221 1232 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'betterdocs_dismiss_pointer' ) ) {
1222 - wp_send_json_error( array( 'message' => __( 'Invalid nonce', 'betterdocs' ) ) );
1233 + wp_send_json_error( [ 'message' => __( 'Invalid nonce', 'betterdocs' ) ] );
1223 1234 }
1224 1235
1225 1236 // Check if user has permission
1226 1237 if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'edit_docs' ) ) {
1227 - wp_send_json_error( array( 'message' => __( 'Permission denied', 'betterdocs' ) ) );
1238 + wp_send_json_error( [ 'message' => __( 'Permission denied', 'betterdocs' ) ] );
1228 1239 }
1229 1240
1230 1241 // Get the introduction key
1231 1242 $introduction_key = isset( $_POST['introduction_key'] ) ? sanitize_text_field( $_POST['introduction_key'] ) : '';
@@ -1230,9 +1241,9 @@
1230 1241 // Get the introduction key
1231 1242 $introduction_key = isset( $_POST['introduction_key'] ) ? sanitize_text_field( $_POST['introduction_key'] ) : '';
1232 1243
1233 1244 if ( empty( $introduction_key ) ) {
1234 - wp_send_json_error( array( 'message' => __( 'Invalid introduction key', 'betterdocs' ) ) );
1245 + wp_send_json_error( [ 'message' => __( 'Invalid introduction key', 'betterdocs' ) ] );
1235 1246 }
1236 1247
1237 1248 // Set the introduction as viewed
1238 1249 NoticePointers::set_introduction_viewed( $introduction_key );
@@ -1239,39 +1250,7 @@
1239 1250
1240 1251 // Clear the priority option so other plugins can set their priority
1241 1252 delete_option( '_wpdeveloper_plugin_pointer_priority' );
1242 1253
1243 - wp_send_json_success( array( 'message' => __( 'Pointer dismissed successfully', 'betterdocs' ) ) );
1244 - }
1245 -
1246 - /**
1247 - * Get count of docs that are not yet synced
1248 - * Similar to Helper::get_not_synced_post_ids() in betterdocs-ai-chatbot plugin
1249 - *
1250 - * @return int
1251 - * @since 3.7.0
1252 - */
1253 - private function get_not_synced_docs_count() {
1254 - $new_post_ids = get_option( 'saved_docs_post_ids', array() );
1255 - $error_posts_data = get_option( 'betterdocs_ai_chatbot_error_posts', array() );
1256 -
1257 - // Extract post IDs from error posts (handle both old and new formats)
1258 - $error_post_ids = array();
1259 - if ( is_array( $error_posts_data ) && ! empty( $error_posts_data ) ) {
1260 - foreach ( $error_posts_data as $key => $value ) {
1261 - if ( is_numeric( $key ) && is_numeric( $value ) ) {
1262 - // Old format: numeric key with post ID as value
1263 - $error_post_ids[] = $value;
1264 - } elseif ( is_numeric( $key ) && is_array( $value ) && isset( $value['post_id'] ) ) {
1265 - // New format: post ID as key with structured data
1266 - $error_post_ids[] = $key;
1267 - } elseif ( is_numeric( $key ) ) {
1268 - // New format: post ID as key
1269 - $error_post_ids[] = $key;
1270 - }
1271 - }
1272 - }
1273 -
1274 - // Merge both arrays and remove duplicates, then count
1275 - return count( array_unique( array_merge( $new_post_ids, $error_post_ids ) ) );
1254 + wp_send_json_success( [ 'message' => __( 'Pointer dismissed successfully', 'betterdocs' ) ] );
1276 1255 }
1277 1256 }