PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.2.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.2.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
← All changes | includes/Core/Admin.php +322 -415 4.5.44.2.0 View file →
@@ -3,9 +3,8 @@
3 3 namespace WPDeveloper\BetterDocs\Core;
4 4
5 5 use Exception;
6 6 use PriyoMukul\WPNotice\Notices;
7 -use WPDeveloper\BetterDocs\Admin\NoticePointers;
8 7 use WPDeveloper\BetterDocs\Utils\Base;
9 8 use PriyoMukul\WPNotice\Utils\CacheBank;
10 9 use WPDeveloper\BetterDocs\Utils\Helper;
11 10 use WPDeveloper\BetterDocs\Utils\Enqueue;
@@ -20,9 +19,8 @@
20 19 */
21 20 private static $cache_bank;
22 21 /**
23 22 * Admin Root Menu Slug
24 - *
25 23 * @var string
26 24 */
27 25 private $slug = 'betterdocs-dashboard';
28 26 /**
@@ -54,19 +52,17 @@
54 52 private $kbmigration;
55 53
56 54 /**
57 55 * Enqueue
58 - *
59 56 * @var Enqueue
60 57 */
61 58 private $assets;
62 59
63 60 // modules
64 - protected $installer;
61 + protected $installer;
65 62
66 63 /**
67 64 * FAQBuilder
68 - *
69 65 * @var FAQBuilder
70 66 */
71 67 private $faq_builder;
72 68 private $glossaries;
@@ -77,10 +73,10 @@
77 73 $this->settings = $settings;
78 74 $this->kbmigration = $kbmigration;
79 75 $this->slug = 'betterdocs-dashboard';
80 76
81 - add_action( 'init', array( $type, 'register' ), 9 );
82 - add_action( 'rest_api_init', array( $this, 'order_terms_in_wp_terms_admin_table' ) );
77 + add_action( 'init', [ $type, 'register' ], 9 );
78 + add_action('rest_api_init', [$this, 'order_terms_in_wp_terms_admin_table']);
83 79
84 80 $type->init();
85 81 $type->admin_init();
86 82
@@ -93,47 +89,46 @@
93 89
94 90 $this->installer = new PluginInstaller();
95 91
96 92 $this->plugin_insights();
97 - add_action( 'admin_notices', array( $this, 'compatibility_notices' ) );
93 + add_action( 'admin_notices', [ $this, 'compatibility_notices' ] );
98 94 // add_action( 'admin_init', [$this, 'notices'], 9 );
99 - add_filter( 'admin_init', array( $this, 'save_admin_page' ), 99 );
95 + add_filter( 'admin_init', [ $this, 'save_admin_page' ], 99 );
100 96
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' ) );
97 + add_action( 'admin_menu', [ $this, 'menus' ] );
98 + add_action( 'admin_menu', [ $this, 'reset_submenu' ] );
99 + add_action( 'admin_head', [ $this, 'add_custom_classes_to_menu_items' ] );
100 + add_filter( 'plugin_action_links_' . BETTERDOCS_PLUGIN_BASENAME, [ $this, 'insert_plugin_links' ] );
105 101
106 102 // $this->container->get( SetupWizard::class )->init();
107 103
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 );
104 + add_action( 'admin_enqueue_scripts', [ $this, 'styles' ] );
105 + add_action( 'admin_enqueue_scripts', [ $this, 'scripts' ] );
106 + //add_action( 'betterdocs_listing_header', [ $this, 'header' ], 10, 1 );
107 + add_action( 'admin_bar_menu', [ $this, 'toolbar_menu' ], 32 );
112 108
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 );
109 + add_filter( 'admin_body_class', [ $this, 'body_classes' ] );
110 + add_filter( 'parent_file', [ $type, 'highlight_admin_menu' ] );
111 + add_filter( 'submenu_file', [ $type, 'highlight_admin_submenu' ], 10, 2 );
112 + add_filter( 'betterdocs_admin_menu', [ $this, 'quick_setup_menu' ], 10, 1 );
117 113
118 114 /**
119 115 * Remove Comments Column from List Table.
120 116 */
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 );
117 + add_filter( 'manage_docs_posts_columns', [ $this, 'set_custom_edit_action_columns' ] );
118 + add_filter( 'manage_docs_posts_custom_column', [ $this, 'manage_custom_columns' ], 10, 2 );
123 119
124 120 /**
125 121 * Add New Column
126 122 */
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 );
123 + add_filter( 'manage_users_columns', [ $this, 'add_users_total_docs_column' ], 10, 1 );
124 + add_filter( 'manage_users_custom_column', [ $this, 'popular_users_docs_data' ], 10, 3 );
129 125 if ( is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ) ) {
130 126 add_action( 'admin_footer-plugins.php', array( $this, 'disable_deactivation' ) );
131 127 }
132 128
133 129 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' ) );
130 + add_action( 'add_meta_boxes', [ $this, 'reading_meta_box_' ], 10 );
136 131 }
137 132
138 133 self::$cache_bank = CacheBank::get_instance();
139 134
@@ -144,28 +139,17 @@
144 139 $this->notices();
145 140 } catch ( Exception $e ) {
146 141 unset( $e );
147 142 }
148 -
149 - // Initialize Black Friday Pointer
150 - $this->init_black_friday_pointer();
151 -
152 - // Register AJAX handler for pointer dismissal
153 - add_action( 'wp_ajax_betterdocs_dismiss_black_friday_pointer', array( $this, 'ajax_dismiss_black_friday_pointer' ) );
154 143 }
155 144
156 145 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 - );
146 + //order the terms correctly to be shown on the admin panel categories menu with betterdocs order
147 + add_action('rest_insert_doc_category', function( $term, $request, $bool ) {
148 + $max_order = Helper::get_max_doc_category_order_from_term_meta() ?? 0;
149 + $next_order = $max_order + 1;
150 + update_term_meta( $term->term_id, 'doc_category_order', $next_order );
151 + }, 10, 3);
168 152 }
169 153
170 154 public function disable_deactivation() {
171 155 $tooltip_text = esc_html__( 'Deactivate BetterDocs Pro First', 'betterdocs' );
@@ -212,17 +196,17 @@
212 196 <?php
213 197 }
214 198
215 199 public function add_users_total_docs_column( $columns ) {
216 - $new_column = array(
217 - 'docs' => __( 'Docs', 'betterdocs' ),
218 - );
200 + $new_column = [
201 + 'docs' => __( 'Docs', 'betterdocs' )
202 + ];
219 203 $columns = array_merge( $columns, $new_column );
220 204 return $columns;
221 205 }
222 206
223 207 public function popular_users_docs_data( $output, $column_name, $user_id ) {
224 - if ( 'docs' == $column_name ) {
208 + if ( $column_name == 'docs' ) {
225 209 $total_count = count_user_posts( $user_id, 'docs', true );
226 210 return '<a href="edit.php?post_type=docs&author=' . $user_id . '" class="edit"><span aria-hidden="true">' . $total_count . '</span></a>';
227 211 }
228 212 return $output;
@@ -227,8 +211,20 @@
227 211 }
228 212 return $output;
229 213 }
230 214
215 + public function reading_meta_box_() {
216 + add_meta_box(
217 + 'betterdocs_estimated_time_metabox',
218 + __( 'Estimated Reading Time', 'betterdocs' ),
219 + [
220 + $this,
221 + 'render_estimated_time_markup'
222 + ],
223 + 'docs'
224 + );
225 + }
226 +
231 227 public function render_estimated_time_markup() {
232 228 betterdocs()->views->get( 'admin/metabox/estimated-reading-box' );
233 229 }
234 230
@@ -240,9 +236,9 @@
240 236 if ( isset( $plugin_data['Version'] ) && version_compare( $plugin_data['Version'], '2.5.0', '>=' ) ) {
241 237 return;
242 238 }
243 239
244 - betterdocs()->views->get( 'admin/notices/compatibility', array( 'version' => $plugin_data['Version'] ) );
240 + betterdocs()->views->get( 'admin/notices/compatibility', [ 'version' => $plugin_data['Version'] ] );
245 241 }
246 242 }
247 243
248 244 public function plugin_insights( $prevent_init = false ) {
@@ -247,20 +243,20 @@
247 243
248 244 public function plugin_insights( $prevent_init = false ) {
249 245 $this->insights = Insights::get_instance(
250 246 BETTERDOCS_PLUGIN_FILE,
251 - array(
247 + [
252 248 'opt_in' => true,
253 249 'goodbye_form' => true,
254 - 'item_id' => 'c7b16777b4f1b83f6083',
255 - )
250 + 'item_id' => 'c7b16777b4f1b83f6083'
251 + ]
256 252 );
257 253
258 254 $this->insights->set_notice_options(
259 - array(
255 + [
260 256 '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 - )
257 + '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' )
258 + ]
263 259 );
264 260
265 261 if ( ! $prevent_init ) {
266 262 $this->insights->init();
@@ -276,77 +272,76 @@
276 272 * @throws Exception
277 273 */
278 274 public function notices() {
279 275 $notices = new Notices(
280 - array(
276 + [
281 277 'id' => 'betterdocs',
282 278 'storage_key' => 'notices',
283 279 'lifetime' => 3,
284 280 'stylesheet_url' => $this->assets->asset_url( 'admin/css/notices.css' ),
285 281 'styles' => $this->assets->asset_url( 'admin/css/notices.css' ),
286 - 'priority' => 4,
287 - )
282 + 'priority' => 4
283 + ]
288 284 );
289 285
290 286 /**
291 - * Review Notice
292 - *
293 - * @var mixed $message
294 - */
287 + * Review Notice
288 + * @var mixed $message
289 + */
295 290
296 291 $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 292
298 - $_review_notice = array(
293 + $_review_notice = [
299 294 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
300 295 'html' => '<p>' . $message . '</p>',
301 - 'links' => array(
302 - 'later' => array(
296 + 'links' => [
297 + 'later' => [
303 298 'link' => 'https://wordpress.org/plugins/betterdocs/#reviews',
304 299 'target' => '_blank',
305 300 'label' => __( 'Sure, you deserve it!', 'betterdocs' ),
306 - 'icon_class' => 'dashicons dashicons-external',
307 - ),
308 - 'allready' => array(
301 + 'icon_class' => 'dashicons dashicons-external'
302 + ],
303 + 'allready' => [
309 304 'label' => __( 'I already did', 'betterdocs' ),
310 305 'icon_class' => 'dashicons dashicons-smiley',
311 - 'attributes' => array(
312 - 'data-dismiss' => true,
313 - ),
314 - ),
315 - 'maybe_later' => array(
306 + 'attributes' => [
307 + 'data-dismiss' => true
308 + ]
309 + ],
310 + 'maybe_later' => [
316 311 'label' => __( 'Maybe Later', 'betterdocs' ),
317 312 'icon_class' => 'dashicons dashicons-calendar-alt',
318 - 'attributes' => array(
313 + 'attributes' => [
319 314 'data-later' => true,
320 - 'class' => 'dismiss-btn',
321 - ),
322 - ),
323 - 'support' => array(
315 + 'class' => 'dismiss-btn'
316 + ]
317 + ],
318 + 'support' => [
324 319 'link' => 'https://wpdeveloper.com/support',
325 - 'attributes' => array(
326 - 'target' => '_blank',
327 - ),
320 + 'attributes' => [
321 + 'target' => '_blank'
322 + ],
328 323 'label' => __( 'I need help', 'betterdocs' ),
329 - 'icon_class' => 'dashicons dashicons-sos',
330 - ),
331 - 'never_show_again' => array(
324 + 'icon_class' => 'dashicons dashicons-sos'
325 + ],
326 + 'never_show_again' => [
332 327 'label' => __( 'Never show again', 'betterdocs' ),
333 328 'icon_class' => 'dashicons dashicons-dismiss',
334 - 'attributes' => array(
335 - 'data-dismiss' => true,
336 - ),
337 - ),
338 - ),
339 - );
329 + 'attributes' => [
330 + 'data-dismiss' => true
331 + ]
332 + ]
333 + ]
334 + ];
340 335
341 336 $notices->add(
342 337 'review',
343 338 $_review_notice,
344 - array(
339 + [
345 340 'start' => $notices->strtotime( '+10 days' ),
346 341 'recurrence' => 30,
347 - 'dismissible' => true,
348 - )
342 + 'dismissible' => true
343 + ]
349 344 );
350 345
351 346 if ( $this->kbmigration->existing_plugins && ! in_array( $this->kbmigration->existing_plugins[0][0], $this->kbmigration->migrated_plugins ) ) {
352 347 $plugin_name = '<strong>' . esc_html( $this->kbmigration->existing_plugins[0][1] ) . '</strong>';
@@ -351,9 +346,9 @@
351 346 if ( $this->kbmigration->existing_plugins && ! in_array( $this->kbmigration->existing_plugins[0][0], $this->kbmigration->migrated_plugins ) ) {
352 347 $plugin_name = '<strong>' . esc_html( $this->kbmigration->existing_plugins[0][1] ) . '</strong>';
353 348
354 349 $message = sprintf(
355 - /* translators: %s is the name of the existing knowledge base plugin. */
350 + /* translators: %s is the name of the existing knowledge base plugin. */
356 351 __( 'Already using %s? Power up your Knowledge Base by migrating all your docs and settings to BetterDocs with just 1 click.', 'betterdocs' ),
357 352 esc_html( $plugin_name )
358 353 );
359 354
@@ -363,51 +358,50 @@
363 358 esc_url( admin_url( 'admin.php?page=betterdocs-settings&tab=tab-migration' ) ),
364 359 esc_html__( 'Start Migration', 'betterdocs' )
365 360 );
366 361
367 - $_migration_notice = array(
362 + $_migration_notice = [
368 363 'thumbnail' => '',
369 364 'html' => $migration_message,
370 - 'links' => array(
371 - 'maybe_later' => array(
365 + 'links' => [
366 + 'maybe_later' => [
372 367 'label' => __( 'Maybe Later', 'betterdocs' ),
373 368 'icon_class' => 'dashicons dashicons-calendar-alt',
374 - 'attributes' => array(
369 + 'attributes' => [
375 370 'data-later' => true,
376 - 'class' => 'dismiss-btn',
377 - ),
378 - ),
379 - 'never_show_again' => array(
371 + 'class' => 'dismiss-btn'
372 + ]
373 + ],
374 + 'never_show_again' => [
380 375 'label' => __( 'Never show again', 'betterdocs' ),
381 376 'icon_class' => 'dashicons dashicons-dismiss',
382 - 'attributes' => array(
383 - 'data-dismiss' => true,
384 - ),
385 - ),
386 - ),
387 - );
377 + 'attributes' => [
378 + 'data-dismiss' => true
379 + ]
380 + ]
381 + ]
382 + ];
388 383
389 384 $notices->add(
390 385 'migration',
391 386 $_migration_notice,
392 - array(
387 + [
393 388 'start' => $notices->time(),
394 389 'recurrence' => false,
395 - 'dismissible' => true,
396 - )
390 + 'dismissible' => true
391 + ]
397 392 );
398 393 }
399 394
400 395 /**
401 - *
402 396 * Opt-In Notice
403 397 */
404 398 $allow_tracking = get_option( 'wpins_allow_tracking' );
405 - if ( null != $this->insights && ! isset( $allow_tracking['betterdocs'] ) ) {
399 + if ( $this->insights != null && ! isset( $allow_tracking['betterdocs'] ) ) {
406 400 $notices->add(
407 401 'opt_in',
408 - array( $this->insights, 'notice' ),
409 - array(
402 + [ $this->insights, 'notice' ],
403 + [
410 404 'classes' => 'updated put-dismiss-notice',
411 405 'start' => $notices->time(),
412 406 'refresh' => BETTERDOCS_VERSION,
413 407 'dismissible' => true,
@@ -412,48 +406,55 @@
412 406 'refresh' => BETTERDOCS_VERSION,
413 407 'dismissible' => true,
414 408 'do_action' => 'wpdeveloper_notice_clicked_for_betterdocs',
415 409 'display_if' => ! function_exists( 'betterdocs_pro' ),
416 - 'screens' => array( 'dashboard' ),
417 - )
410 + 'screens' => [ 'dashboard' ]
411 + ]
418 412 );
419 413 }
420 414
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(
415 + // $blackfriday_message = '<div class="betterdocs-notice-body"><p style="margin-top: 0; margin-bottom: 0;"><strong>🛍️ Black Friday Specials:</strong> Save up to 35% OFF on BetterDocs PRO plans & manage docs/FAQs seamlessly.</p><a class="button button-primary" href="https://betterdocs.co/bfcm24-pricing" target="_blank"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
416 + // <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"/>
417 + // <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"/>
418 + // </svg> Upgrade To PRO</a></div>';
419 + // $_blackfriday_notice = [
420 + // 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
421 + // 'html' => $blackfriday_message
422 + // ];
423 +
424 + // $notices->add(
425 + // 'blackfriday24',
426 + // $_blackfriday_notice,
427 + // [
428 + // 'start' => $notices->time(),
429 + // 'recurrence' => false,
430 + // 'dismissible' => true,
431 + // 'refresh' => BETTERDOCS_VERSION,
432 + // 'expire' => strtotime( '11:59:59pm December 5, 2024' ),
433 + // 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' )
434 + // ]
435 + // );
436 +
437 + $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">
438 + <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"/>
439 + <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"/>
440 + </svg>Upgrade To PRO</a></div></div>';
441 + $_offer_notice = [
423 442 '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(
429 - 'target' => '_blank',
430 - 'class' => 'offer-button',
431 - ),
432 - 'label' => __( 'Upgrade To PRO Now', 'betterdocs' ),
433 - ),
434 - 'maybe_later' => array(
435 - 'label' => __( 'I’ll Grab It Later', 'betterdocs' ),
436 - 'attributes' => array(
437 - 'target' => '_blank',
438 - 'data-later' => true,
439 - 'class' => 'dismiss-btn',
440 - ),
441 - ),
442 - ),
443 - );
443 + 'html' => $offer_message
444 + ];
444 445
445 446 $notices->add(
446 - 'summer-campaign-26',
447 - $_summer_campaign_notice,
448 - array(
447 + '40k_offer',
448 + $_offer_notice,
449 + [
449 450 'start' => $notices->time(),
450 451 'recurrence' => false,
451 452 'dismissible' => true,
452 453 'refresh' => BETTERDOCS_VERSION,
453 - 'expire' => strtotime( '11:59:59pm June 25, 2026' ),
454 - 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ),
455 - )
454 + 'expire' => strtotime( '11:59:59pm April 30, 2025' ),
455 + 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' )
456 + ]
456 457 );
457 458
458 459 self::$cache_bank->create_account( $notices );
459 460 self::$cache_bank->calculate_deposits( $notices );
@@ -458,9 +459,9 @@
458 459 self::$cache_bank->create_account( $notices );
459 460 self::$cache_bank->calculate_deposits( $notices );
460 461 if ( method_exists( self::$cache_bank, 'clear_notices_in_' ) ) {
461 462 self::$cache_bank->clear_notices_in_(
462 - array(
463 + [
463 464 'toplevel_page_betterdocs-dashboard',
464 465 'admin_page_betterdocs-admin',
465 466 'betterdocs_page_betterdocs-admin',
466 467 'betterdocs_page_betterdocs-settings',
@@ -468,10 +469,10 @@
468 469 'betterdocs_page_betterdocs-analytics',
469 470 'betterdocs_page_betterdocs-glossaries',
470 471 'betterdocs_page_betterdocs-ai-chatbot',
471 472 'edit-doc_category',
472 - 'edit-doc_tag',
473 - ),
473 + 'edit-doc_tag'
474 + ],
474 475 $notices,
475 476 true
476 477 );
477 478 }
@@ -481,26 +482,26 @@
481 482 $saved_settings = get_option( 'betterdocs_settings', false );
482 483 $dark_mode = isset( $saved_settings['dark_mode'] ) ? $saved_settings['dark_mode'] : false;
483 484 $dark_mode = ! empty( $dark_mode ) ? boolval( $dark_mode ) : false;
484 485 $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 - );
486 + $registered_screens = [
487 + 'betterdocs-settings',
488 + 'betterdocs-admin',
489 + 'betterdocs-dashboard',
490 + 'betterdocs-analytics',
491 + 'betterdocs-glossaries',
492 + 'betterdocs-faq',
493 + 'edit-doc_category',
494 + 'edit-doc_tag',
495 + 'edit-knowledge_base',
496 + 'betterdocs-ai-chatbot'
497 + ];
497 498
498 - if ( in_array( $current_screen_id, $registered_screens ) ) {
499 - $classes .= ' betterdocs-admin ';
500 - }
499 + if( in_array( $current_screen_id, $registered_screens ) ) {
500 + $classes .= ' betterdocs-admin ';
501 + }
501 502
502 - if ( true === $dark_mode && in_array( $current_screen_id, $registered_screens ) ) {
503 + if ( $dark_mode === true && in_array( $current_screen_id, $registered_screens ) ) {
503 504 $classes .= ' betterdocs-dark-mode ';
504 505 }
505 506
506 507 return $classes;
@@ -515,11 +516,11 @@
515 516 * @since 1.0.0
516 517 */
517 518 public function set_custom_edit_action_columns( $columns ) {
518 519 unset( $columns['comments'] );
519 - $new_columns = array();
520 + $new_columns = [];
520 521 foreach ( $columns as $key => $value ) {
521 - if ( 'date' == $key ) {
522 + if ( $key == 'date' ) {
522 523 $new_columns['betterdocs_word_count'] = __( 'Word Count', 'betterdocs' ); // put the tags column before it
523 524 $new_columns['betterdocs_reaction'] = __( 'Reactions', 'betterdocs' );
524 525 }
525 526 $new_columns[ $key ] = $value;
@@ -533,9 +534,9 @@
533 534 switch ( $column ) {
534 535 case 'betterdocs_word_count':
535 536 $content_without_html_tags = trim( strip_tags( get_post_field( 'post_content', $post_id ) ) );
536 537 preg_match_all( '/<[^>]*>|[\p{L}\p{M}]+/u', $content_without_html_tags, $matches );
537 - $total_words = ! empty( $matches[0] ) ? count( $matches[0] ) : count( array() );
538 + $total_words = ! empty( $matches[0] ) ? count( $matches[0] ) : count( [] );
538 539 $word_count = $total_words;
539 540 echo '<span>' . esc_html( intval( $word_count ) ) . '</span>';
540 541 break;
541 542 case 'betterdocs_reaction':
@@ -606,22 +607,22 @@
606 607 * @return void
607 608 * @since 1.0.0
608 609 */
609 610 public function styles( $hook ) {
610 - $this->assets->enqueue( 'betterdocs-global', 'admin/css/global.css', array(), 'all' );
611 + $this->assets->enqueue( 'betterdocs-global', 'admin/css/global.css', [], 'all' );
611 612
612 613 if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
613 614 return;
614 615 }
615 616
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' );
617 + $this->assets->enqueue( 'betterdocs-select2', 'vendor/css/select2.min.css', [], 'all' );
618 + $this->assets->enqueue( 'betterdocs-daterangepicker', 'vendor/css/daterangepicker.css', [], 'all' );
619 + $this->assets->enqueue( 'betterdocs-old', 'admin/css/betterdocs.css', [], 'all' );
619 620
620 621 /**
621 - * This scripts enqueued for Dashboard App.
622 - */
623 - $this->assets->enqueue( 'betterdocs', 'admin/css/dashboard.css', array( 'betterdocs-old' ), '', BETTERDOCS_VERSION );
622 + * This scripts enqueued for Dashboard App.
623 + */
624 + $this->assets->enqueue( 'betterdocs', 'admin/css/dashboard.css', [ 'betterdocs-old' ], '', BETTERDOCS_VERSION );
624 625 $this->assets->enqueue( 'betterdocs-icons', 'admin/btd-icon/style.css' );
625 626 }
626 627
627 628 /**
@@ -632,26 +633,26 @@
632 633 * @return void
633 634 * @since 1.0.0
634 635 */
635 636 public function scripts( $hook ) {
636 - if ( ( 'edit.php' === $hook ) && get_post_type() == 'docs' ) {
637 + if ( ( $hook === 'edit.php' ) && get_post_type() == 'docs' ) {
637 638 $this->assets->enqueue(
638 639 'betterdocs-switcher',
639 640 'admin/js/switcher.js',
640 - array(
641 - 'jquery',
642 - )
641 + [
642 + 'jquery'
643 + ]
643 644 );
644 645
645 646 $this->assets->localize(
646 647 'betterdocs-switcher',
647 648 'betterdocsSwitcher',
648 - array(
649 + [
649 650 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
650 651 'site_address' => get_bloginfo( 'url' ),
651 652 'betterdocs_pro_plugin' => betterdocs()->is_pro_active(),
652 - 'betterdocs_pro_version' => betterdocs()->pro_version(),
653 - )
653 + 'betterdocs_pro_version' => betterdocs()->pro_version()
654 + ]
654 655 );
655 656
656 657 return;
657 658 }
@@ -661,9 +662,9 @@
661 662 if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
662 663 return;
663 664 }
664 665
665 - wp_enqueue_media(); // load early to fix problems with media upload issues on settings for WordPress 6.0.9
666 + wp_enqueue_media(); // load early to fix problems with media upload issues on settings for wordpress 6.0.9
666 667 $this->assets->register( 'betterdocs-admin', 'admin/js/dashboard.js' );
667 668
668 669 $saved_settings = get_option( 'betterdocs_settings', false );
669 670 $dark_mode = $saved_settings['dark_mode'] ?? false;
@@ -670,55 +671,53 @@
670 671 $dark_mode = ! empty( $dark_mode ) && boolval( $dark_mode );
671 672 $this->assets->localize(
672 673 'betterdocs-admin',
673 674 'betterdocs_admin',
674 - array(
675 + [
675 676 'ajaxurl' => admin_url( 'admin-ajax.php' ),
676 677 'doc_cat_order_nonce' => wp_create_nonce( 'doc_cat_order_nonce' ),
677 678 'knowledge_base_order_nonce' => wp_create_nonce( 'knowledge_base_order_nonce' ),
678 679 '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 - )
680 + 'per_page_id' => 'edit_doc_category_per_page',
681 + 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
682 + 'dark_mode' => $dark_mode,
683 + 'text' => __( 'Copied!', 'betterdocs' ),
684 + 'test_report' => __( 'Test Report!', 'betterdocs' ),
685 + 'sending' => __( 'Sending...', 'betterdocs' ),
686 + 'dir_url' => BETTERDOCS_ABSURL,
687 + 'rest_url' => esc_url_raw( rest_url() ),
688 + 'free_version' => betterdocs()->version,
689 + 'generate_data_url' => get_rest_url( null, '/betterdocs/v1/create-sample-docs' ),
690 + 'nonce' => wp_create_nonce( 'wp_rest' ),
691 + 'sync_nonce' => wp_create_nonce( 'ai_chatbot_embed' ),
692 + 'count_all_docs' => array_sum((array) wp_count_posts('docs')),
693 + 'count_all_faq' => array_sum((array) wp_count_posts('betterdocs_faq')),
694 + 'count_new_docs' => count(get_option('saved_docs_post_ids', [])) + count(get_option('betterdocs_ai_chatbot_error_posts', [])),
695 + 'admin_url' => admin_url(),
696 + 'ia_preview' => betterdocs()->settings->get( 'ia_enable_preview', false ),
697 + 'multiple_kb' => betterdocs()->settings->get( 'multiple_kb' ),
698 + 'previewMode' => betterdocs()->settings->get( 'ia_enable_preview', false ),
699 + 'dashboard_mode' => get_option( 'dashboard_mode' ),
700 + 'betterdocs_pro_plugin' => betterdocs()->is_pro_active(),
701 + 'betterdocs_pro_version' => betterdocs()->pro_version(),
702 + 'analytics_older' => version_compare( betterdocs()->pro_version(), '3.3.4', '<=' ),
703 + 'disabled_embed_model_option' => get_option('disabled_embed_model_option'),
704 + 'betterdocs_ChatBot_plugin' => is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' ),
705 + 'total_doc_category_terms' => wp_count_terms( 'doc_category')
706 + ]
708 707 );
709 708
710 709 // If wp-date (which includes moment.js) is not registered, enqueue your custom moment.js
711 710 if ( ! wp_script_is( 'wp-date', 'registered' ) ) {
712 - $this->assets->enqueue( 'moment', 'vendor/js/moment.min.js', array() );
711 + $this->assets->enqueue( 'moment', 'vendor/js/moment.min.js', [] );
713 712 }
714 713 wp_enqueue_script( 'betterdocs-admin' );
715 714
716 715 /**
717 - * Duplicate Codes Need to Be Removed From Here Onwards
718 - */
716 + * Duplicate Codes Need to Be Removed From Here Onwards
717 + */
719 718
720 - // FAQ Builder Related Localization
719 + //FAQ Builder Related Localization
721 720 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/css/faq.css' );
722 721 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/js/faq.js' );
723 722
724 723 // removing emoji support
@@ -724,28 +723,21 @@
724 723 // removing emoji support
725 724 remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
726 725 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
727 726
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 727 betterdocs()->assets->localize(
736 728 'betterdocs-admin-faq',
737 729 'betterdocsFaq',
738 - array(
730 + [
739 731 'dir_url' => BETTERDOCS_ABSURL,
740 732 'rest_url' => esc_url_raw( rest_url() ),
741 733 'free_version' => betterdocs()->version,
742 734 'nonce' => wp_create_nonce( 'wp_rest' ),
743 - 'betterdocs_settings' => $betterdocs_settings,
744 - )
735 + 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
736 + ]
745 737 );
746 738
747 - // Glossaries Related Localization
739 + //Glossaries Related Localization
748 740 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/css/faq.css' );
749 741
750 742 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/js/glossaries.js' );
751 743
@@ -751,15 +743,15 @@
751 743
752 744 betterdocs()->assets->localize(
753 745 'betterdocs-admin-glossaries',
754 746 'betterdocsGlossary',
755 - array(
747 + [
756 748 'dir_url' => BETTERDOCS_ABSURL,
757 749 'rest_url' => esc_url_raw( rest_url() ),
758 750 'free_version' => betterdocs()->version,
759 751 'nonce' => wp_create_nonce( 'wp_rest' ),
760 - 'betterdocs_settings' => $betterdocs_settings,
761 - )
752 + 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
753 + ]
762 754 );
763 755 }
764 756
765 757 /**
@@ -768,31 +760,31 @@
768 760 * @return void
769 761 * @since 1.0.0
770 762 */
771 763 public function header( $admin_tab_name ) {
772 - $quick_links = array(
764 + $quick_links = [
773 765 'switch_view' => sprintf(
774 766 '<a href="%s" class="betterdocs-button betterdocs-button-secondary">%s</a>',
775 767 add_query_arg(
776 - array(
768 + [
777 769 'post_type' => 'docs',
778 - 'bdocs_view' => 'classic',
779 - ),
770 + 'bdocs_view' => 'classic'
771 + ],
780 772 'edit.php'
781 773 ),
782 774 __( 'Switch to Classic UI', 'betterdocs' )
783 775 ),
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 - );
776 + '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' ) )
777 + ];
786 778
787 779 $quick_links = apply_filters( 'betterdocs_quick_links', $quick_links );
788 780
789 781 betterdocs()->views->get(
790 782 'admin/header',
791 - array(
783 + [
792 784 'quick_links' => $quick_links,
793 - 'active_tab' => $admin_tab_name,
794 - )
785 + 'active_tab' => $admin_tab_name
786 + ]
795 787 );
796 788 }
797 789
798 790 /**
@@ -801,17 +793,17 @@
801 793 * @return void
802 794 * @since 1.0.0
803 795 */
804 796 public function menus() {
805 - $default_args = array(
797 + $default_args = [
806 798 'page_title' => 'BetterDocs',
807 799 'menu_title' => 'BetterDocs',
808 - 'capability' => 'edit_docs', // Unified capability
800 + 'capability' => 'edit_docs', // Unified capability
809 801 'menu_slug' => $this->slug,
810 - 'callback' => array( $this, 'output' ),
802 + 'callback' => [ $this, 'output' ],
811 803 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
812 - 'position' => 5,
813 - );
804 + 'position' => 5
805 + ];
814 806
815 807 $_menu_position = 5;
816 808 global $submenu;
817 809
@@ -818,23 +810,23 @@
818 810 // Always register both UI endpoints
819 811 $this->register_modern_ui_fallback();
820 812
821 813 foreach ( $this->menu_list() as $key => $value ) {
822 - if ( 'betterdocs' === $key ) {
814 + if ( $key === 'betterdocs' ) {
823 815 $callable = 'add_menu_page';
824 816 $value = wp_parse_args( $value, $default_args );
825 817 call_user_func_array( $callable, $value );
826 818 } else {
827 - $is_core_page = strpos( $value['menu_slug'], '?' ) !== false;
819 + $is_core_page = strpos($value['menu_slug'], '?') !== false;
828 820
829 - if ( $is_core_page ) {
821 + if ($is_core_page) {
830 822 // Add classic UI directly
831 - $submenu[ $this->slug ][] = array(
823 + $submenu[$this->slug][] = [
832 824 $value['menu_title'],
833 825 $value['capability'],
834 826 $value['menu_slug'],
835 - $value['page_title'],
836 - );
827 + $value['page_title']
828 + ];
837 829 } else {
838 830 // Add modern UI through WordPress API
839 831 add_submenu_page(
840 832 $this->slug,
@@ -844,9 +836,9 @@
844 836 $value['menu_slug'],
845 837 $value['callback']
846 838 );
847 839 }
848 - ++$_menu_position;
840 + $_menu_position++;
849 841 }
850 842 }
851 843 }
852 844
@@ -853,21 +845,21 @@
853 845 private function register_modern_ui_fallback() {
854 846 // Add the submenu with valid parent slug
855 847 add_submenu_page(
856 848 'betterdocs', // Valid parent slug
857 - __( 'All Docs', 'betterdocs' ),
849 + __('All Docs', 'betterdocs'),
858 850 '', // Empty menu title hides it
859 851 'edit_docs',
860 852 'betterdocs-admin',
861 - array( $this, 'output' )
853 + [ $this, 'output' ]
862 854 );
863 855
864 856 // Hide the menu item from appearing in the admin sidebar
865 857 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 ] );
858 + if (isset($submenu['betterdocs'])) {
859 + foreach ($submenu['betterdocs'] as $key => $item) {
860 + if ($item[2] === 'betterdocs-admin') {
861 + unset($submenu['betterdocs'][$key]);
870 862 break;
871 863 }
872 864 }
873 865 }
@@ -880,17 +872,17 @@
880 872 * @since 1.0.0
881 873 */
882 874 public function output() {
883 875 if ( betterdocs()->is_pro_active()
884 - && version_compare( betterdocs()->pro_version(), '3.3.4', '<=' )
885 - && get_current_screen()->id == 'betterdocs_page_betterdocs-analytics' ) {
876 + && version_compare( betterdocs()->pro_version(), '3.3.4', '<=' )
877 + && get_current_screen()->id == 'betterdocs_page_betterdocs-analytics' ) {
886 878 betterdocs_pro()->views->get( 'admin/analytics-pro' );
887 879 } else {
888 880 betterdocs()->views->get(
889 881 'admin/main',
890 - array(
891 - 'admin_ui' => 'dnd',
892 - )
882 + [
883 + 'admin_ui' => 'dnd'
884 + ]
893 885 );
894 886 }
895 887 }
896 888
@@ -903,10 +895,11 @@
903 895 * @param array $callback
904 896 *
905 897 * @return array
906 898 * @since 2.5.0
899 + *
907 900 */
908 - private function normalize_menu( $title, $slug, $cap = 'edit_docs', $callback = null, $optional = array() ) {
901 + private function normalize_menu( $title, $slug, $cap = 'edit_docs', $callback = null, $optional = [] ) {
909 902 return Helper::normalize_menu( $title, $slug, $cap, $callback, $optional );
910 903 }
911 904
912 905 /**
@@ -915,34 +908,34 @@
915 908 * @return array
916 909 * @since 1.0.0
917 910 */
918 911 private function menu_list() {
919 - $parent_slug = array();
912 + $parent_slug = [];
920 913
921 - $betterdocs_admin_pages = array(
922 - 'betterdocs' => array(
914 + $betterdocs_admin_pages = [
915 + 'betterdocs' => [
923 916 'menu_slug' => $this->slug,
924 917 'page_title' => 'BetterDocs',
925 918 'menu_title' => 'BetterDocs',
926 919 'capability' => 'edit_docs',
927 - 'callback' => array( $this, 'output' ),
920 + 'callback' => [ $this, 'output' ],
928 921 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
929 - 'position' => 5,
930 - ),
931 - 'dashboard' => $this->normalize_menu(
922 + 'position' => 5
923 + ],
924 + 'dashboard' => $this->normalize_menu(
932 925 __( 'Dashboard', 'betterdocs' ),
933 926 'betterdocs-dashboard',
934 927 'edit_docs',
935 - array(
928 + [
936 929 $this,
937 - 'output',
938 - )
930 + 'output'
931 + ]
939 932 ),
940 933 'all_docs' => $this->normalize_menu(
941 934 __( 'All Docs', 'betterdocs' ),
942 935 $this->ui_slug(),
943 936 'edit_docs',
944 - array( $this, 'output' ),
937 + [ $this, 'output' ],
945 938 $parent_slug
946 939 ),
947 940 'add_new' => $this->normalize_menu(
948 941 __( 'Add New', 'betterdocs' ),
@@ -961,12 +954,12 @@
961 954 'settings' => $this->normalize_menu(
962 955 __( 'Settings', 'betterdocs' ),
963 956 'betterdocs-settings',
964 957 'edit_docs_settings',
965 - array(
958 + [
966 959 $this,
967 - 'output',
968 - ),
960 + 'output'
961 + ],
969 962 $parent_slug
970 963 ),
971 964 'analytics' => $this->normalize_menu(
972 965 __( 'Analytics', 'betterdocs' ),
@@ -971,12 +964,12 @@
971 964 'analytics' => $this->normalize_menu(
972 965 __( 'Analytics', 'betterdocs' ),
973 966 'betterdocs-analytics',
974 967 'read_docs_analytics',
975 - array(
968 + [
976 969 $this,
977 - 'output',
978 - ),
970 + 'output'
971 + ],
979 972 $parent_slug
980 973 ),
981 974 'faq' => $this->normalize_menu(
982 975 __( 'FAQ Builder', 'betterdocs' ),
@@ -981,15 +974,15 @@
981 974 'faq' => $this->normalize_menu(
982 975 __( 'FAQ Builder', 'betterdocs' ),
983 976 'betterdocs-faq',
984 977 'read_faq_builder',
985 - array(
978 + [
986 979 $this,
987 - 'output',
988 - ),
980 + 'output'
981 + ],
989 982 $parent_slug
990 - ),
991 - );
983 + )
984 + ];
992 985
993 986 if ( betterdocs()->is_pro_active() && betterdocs()->settings->get( 'enable_glossaries' ) == true ) {
994 987 $betterdocs_admin_pages['glossaries'] = $this->normalize_menu(
995 988 __( 'Glossaries', 'betterdocs' ),
@@ -994,36 +987,38 @@
994 987 $betterdocs_admin_pages['glossaries'] = $this->normalize_menu(
995 988 __( 'Glossaries', 'betterdocs' ),
996 989 'betterdocs-glossaries',
997 990 'read_docs_analytics',
998 - array(
991 + [
999 992 $this,
1000 - 'output',
1001 - ),
993 + 'output'
994 + ],
1002 995 $parent_slug
1003 996 );
1004 997 }
1005 998
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(
999 +
1000 + if (!betterdocs()->is_chatbot_active()) {
1001 + $betterdocs_admin_pages['ai_chatbot'] = $this->normalize_menu(
1002 + __('AI Chatbot', 'betterdocs'),
1003 + 'betterdocs-ai-chatbot',
1004 + 'edit_docs_settings',
1005 + [
1012 1006 $this,
1013 - 'output',
1014 - ),
1015 - $parent_slug
1016 - );
1017 - }
1007 + 'output'
1008 + ],
1009 + $parent_slug
1010 + );
1011 + }
1018 1012
1019 - return apply_filters( 'betterdocs_admin_menu', $betterdocs_admin_pages, array( $this, 'output' ), $parent_slug );
1020 - }
1013 + return apply_filters( 'betterdocs_admin_menu', $betterdocs_admin_pages, [$this, 'output'], $parent_slug);
1021 1014
1015 + }
1016 +
1022 1017 public function add_custom_classes_to_menu_items() {
1023 1018 global $menu, $submenu;
1024 1019
1025 - $menu_items = array(
1020 + $menu_items = [
1026 1021 'betterdocs' => 'betterdocs',
1027 1022 'betterdocs_page_all_docs' => 'betterdocs-all-docs',
1028 1023 'betterdocs_page_add_new' => 'betterdocs-add-new',
1029 1024 'edit-tags.php?taxonomy=doc_category&post_type=docs' => 'betterdocs-categories',
@@ -1032,10 +1027,10 @@
1032 1027 'betterdocs-analytics' => 'betterdocs-analytics',
1033 1028 'betterdocs-faq' => 'betterdocs-faq',
1034 1029 'betterdocs-glossaries' => 'betterdocs-glossaries',
1035 1030 'betterdocs-ai-chatbot' => 'betterdocs-ai-chatbot',
1036 - 'edit-tags.php?taxonomy=knowledge_base&post_type=docs' => 'betterdocs-multiplekb',
1037 - );
1031 + 'edit-tags.php?taxonomy=knowledge_base&post_type=docs' => 'betterdocs-multiplekb'
1032 + ];
1038 1033
1039 1034 foreach ( $menu as &$item ) {
1040 1035 if ( isset( $menu_items[ $item[2] ] ) ) {
1041 1036 if ( ! isset( $item[4] ) ) {
@@ -1065,12 +1060,12 @@
1065 1060 $menus['quick_setup'] = $this->normalize_menu(
1066 1061 __( 'Quick Setup', 'betterdocs' ),
1067 1062 'betterdocs-setup',
1068 1063 'delete_users',
1069 - array(
1064 + [
1070 1065 $this->container->get( SetupWizard::class ),
1071 - 'views',
1072 - )
1066 + 'views'
1067 + ]
1073 1068 );
1074 1069 }
1075 1070
1076 1071 return $menus;
@@ -1078,12 +1073,8 @@
1078 1073
1079 1074 public function insert_plugin_links( $links ) {
1080 1075 $links[] = '<a href="admin.php?page=betterdocs-settings">' . __( 'Settings', 'betterdocs' ) . '</a>';
1081 1076
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>';
1084 - }
1085 -
1086 1077 return $links;
1087 1078 }
1088 1079
1089 1080 public function toolbar_menu( $admin_bar ) {
@@ -1110,22 +1101,17 @@
1110 1101 }
1111 1102
1112 1103 $slug = $this->settings->get( 'encyclopedia_root_slug' );
1113 1104
1114 - global $wp_rewrite;
1115 - if ( $wp_rewrite->using_index_permalinks() ) {
1116 - $slug = $wp_rewrite->index . '/' . $slug;
1117 - }
1118 -
1119 1105 $encyclopedia_url = home_url( $slug );
1120 1106
1121 1107 $admin_bar->add_node(
1122 - array(
1108 + [
1123 1109 'parent' => 'site-name',
1124 1110 'id' => 'view-docs',
1125 1111 'title' => __( 'Visit Documentation', 'betterdocs' ),
1126 - 'href' => $docs_url,
1127 - )
1112 + 'href' => $docs_url
1113 + ]
1128 1114 );
1129 1115
1130 1116 $is_enable_encyclopedia = betterdocs()->settings->get( 'enable_encyclopedia' );
1131 1117
@@ -1130,14 +1116,14 @@
1130 1116 $is_enable_encyclopedia = betterdocs()->settings->get( 'enable_encyclopedia' );
1131 1117
1132 1118 if ( $is_enable_encyclopedia && betterdocs()->is_pro_active() ) {
1133 1119 $admin_bar->add_node(
1134 - array(
1120 + [
1135 1121 'parent' => 'site-name',
1136 1122 'id' => 'view-encyclopedia',
1137 1123 'title' => __( 'Visit Encyclopedia', 'betterdocs' ),
1138 - 'href' => $encyclopedia_url,
1139 - )
1124 + 'href' => $encyclopedia_url
1125 + ]
1140 1126 );
1141 1127 }
1142 1128 }
1143 1129
@@ -1144,13 +1130,14 @@
1144 1130 /**
1145 1131 * Save last visited admin ui
1146 1132 *
1147 1133 * @since 3.0.1
1134 + *
1148 1135 */
1149 1136 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
1137 + if ( isset( $_GET['post_type'] ) && $_GET['post_type'] === 'docs' && isset( $_GET['bdocs_view'] ) && $_GET['bdocs_view'] === 'classic' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1151 1138 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
1139 + } elseif ( isset( $_GET['page'] ) && $_GET['page'] === 'betterdocs-admin' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1153 1140 update_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', 'modern_ui' );
1154 1141 }
1155 1142 }
1156 1143
@@ -1160,20 +1147,18 @@
1160 1147 * @return string
1161 1148 * @since 3.0.1
1162 1149 */
1163 1150 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 - );
1151 + $last_visited = get_user_meta(get_current_user_id(), 'last_visited_docs_admin_page', true);
1152 + $docs_exist = get_posts([
1153 + 'post_type' => 'docs',
1154 + 'post_status' => 'any',
1155 + 'numberposts' => 1
1156 + ]);
1172 1157
1173 - return ( 'modern_ui' === $last_visited || empty( $docs_exist ) )
1174 - ? 'betterdocs-admin'
1175 - : 'edit.php?post_type=docs&bdocs_view=classic';
1158 + return ($last_visited === 'modern_ui' || empty($docs_exist))
1159 + ? 'betterdocs-admin'
1160 + : 'edit.php?post_type=docs&bdocs_view=classic';
1176 1161 }
1177 1162
1178 1163 /**
1179 1164 * Resets a duplicate submenu in WordPress if the parent main menu and the first submenu permalink are not the same.
@@ -1183,9 +1168,9 @@
1183 1168 */
1184 1169 public function reset_submenu() {
1185 1170 global $submenu;
1186 1171
1187 - $docs = get_posts( array( 'post_type' => 'docs' ) );
1172 + $docs = get_posts( [ 'post_type' => 'docs' ] );
1188 1173 if ( count( $docs ) == 0 ) {
1189 1174 return;
1190 1175 }
1191 1176
@@ -1190,88 +1175,10 @@
1190 1175 }
1191 1176
1192 1177 $last_visited = get_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', true );
1193 1178
1194 - if ( 'classic_ui' === $last_visited && isset( $submenu['betterdocs-admin'] ) && in_array( 'betterdocs-admin', $submenu['betterdocs-admin'][0] ) ) {
1179 + if ( $last_visited === 'classic_ui' && isset( $submenu['betterdocs-admin'] ) && in_array( 'betterdocs-admin', $submenu['betterdocs-admin'][0] ) ) {
1195 1180 unset( $submenu['betterdocs-admin'][0] );
1196 1181 $submenu['betterdocs-admin'] = array_values( $submenu['betterdocs-admin'] );
1197 1182 }
1198 - }
1199 -
1200 - /**
1201 - * Initialize Black Friday Pointer
1202 - *
1203 - * @return void
1204 - * @since 3.7.0
1205 - */
1206 - private function init_black_friday_pointer() {
1207 - // Only initialize if conditions are met
1208 - if ( NoticePointers::should_display_notice() ) {
1209 - new NoticePointers();
1210 - }
1211 - }
1212 -
1213 - /**
1214 - * AJAX handler for dismissing Black Friday pointer
1215 - *
1216 - * @return void
1217 - * @since 3.7.0
1218 - */
1219 - public function ajax_dismiss_black_friday_pointer() {
1220 - // Verify nonce
1221 - if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'betterdocs_dismiss_pointer' ) ) {
1222 - wp_send_json_error( array( 'message' => __( 'Invalid nonce', 'betterdocs' ) ) );
1223 - }
1224 -
1225 - // Check if user has permission
1226 - if ( ! current_user_can( 'manage_options' ) && ! current_user_can( 'edit_docs' ) ) {
1227 - wp_send_json_error( array( 'message' => __( 'Permission denied', 'betterdocs' ) ) );
1228 - }
1229 -
1230 - // Get the introduction key
1231 - $introduction_key = isset( $_POST['introduction_key'] ) ? sanitize_text_field( $_POST['introduction_key'] ) : '';
1232 -
1233 - if ( empty( $introduction_key ) ) {
1234 - wp_send_json_error( array( 'message' => __( 'Invalid introduction key', 'betterdocs' ) ) );
1235 - }
1236 -
1237 - // Set the introduction as viewed
1238 - NoticePointers::set_introduction_viewed( $introduction_key );
1239 -
1240 - // Clear the priority option so other plugins can set their priority
1241 - delete_option( '_wpdeveloper_plugin_pointer_priority' );
1242 -
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 ) ) );
1276 1183 }
1277 1184 }