PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.1.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.1.2
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / Core / Admin.php

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

1,185 lines 42.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\Core;
4
5 use Exception;
6 use PriyoMukul\WPNotice\Notices;
7 use WPDeveloper\BetterDocs\Utils\Base;
8 use PriyoMukul\WPNotice\Utils\CacheBank;
9 use WPDeveloper\BetterDocs\Utils\Helper;
10 use WPDeveloper\BetterDocs\Utils\Enqueue;
11 use WPDeveloper\BetterDocs\Utils\Insights;
12 use PriyoMukul\WPNotice\Utils\NoticeRemover;
13 use WPDeveloper\BetterDocs\Core\PluginInstaller;
14 use WPDeveloper\BetterDocs\Dependencies\DI\Container;
15
16 class Admin extends Base {
17 /**
18 * @var CacheBank
19 */
20 private static $cache_bank;
21 /**
22 * Admin Root Menu Slug
23 * @var string
24 */
25 private $slug = 'betterdocs-dashboard';
26 /**
27 * Insights
28 *
29 * @var Insights
30 */
31 private $insights = null;
32
33 /**
34 * DI\Container
35 *
36 * @var Container
37 */
38 private $container;
39
40 /**
41 * Database Wrapper
42 *
43 * @var Settings
44 */
45 private $settings;
46
47 /**
48 * KBMigration
49 *
50 * @var KBMigration
51 */
52 private $kbmigration;
53
54 /**
55 * Enqueue
56 * @var Enqueue
57 */
58 private $assets;
59
60 // modules
61 protected $installer;
62
63 /**
64 * FAQBuilder
65 * @var FAQBuilder
66 */
67 private $faq_builder;
68 private $glossaries;
69
70 public function __construct( Container $container, PostType $type, Enqueue $assets, Settings $settings, KBMigration $kbmigration ) {
71 $this->container = $container;
72 $this->assets = $assets;
73 $this->settings = $settings;
74 $this->kbmigration = $kbmigration;
75 $this->slug = 'betterdocs-dashboard';
76
77 add_action( 'init', [ $type, 'register' ], 9 );
78 add_action('rest_api_init', [$this, 'order_terms_in_wp_terms_admin_table']);
79
80 $type->init();
81 $type->admin_init();
82
83 $this->faq_builder = $this->container->get( FAQBuilder::class );
84 $this->glossaries = $this->container->get( Glossaries::class );
85
86 if ( ! is_admin() ) {
87 return;
88 }
89
90 $this->installer = new PluginInstaller();
91
92 $this->plugin_insights();
93 add_action( 'admin_notices', [ $this, 'compatibility_notices' ] );
94 // add_action( 'admin_init', [$this, 'notices'], 9 );
95 add_filter( 'admin_init', [ $this, 'save_admin_page' ], 99 );
96
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' ] );
101
102 // $this->container->get( SetupWizard::class )->init();
103
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 );
108
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 );
113
114 /**
115 * Remove Comments Column from List Table.
116 */
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 );
119
120 /**
121 * Add New Column
122 */
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 );
125 if ( is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ) ) {
126 add_action( 'admin_footer-plugins.php', array( $this, 'disable_deactivation' ) );
127 }
128
129 if ( $this->settings->get( 'enable_estimated_reading_time' ) ) {
130 add_action( 'add_meta_boxes', [ $this, 'reading_meta_box_' ], 10 );
131 }
132
133 self::$cache_bank = CacheBank::get_instance();
134
135 // Remove OLD notice from 1.0.0 (if other WPDeveloper plugin has notice)
136 NoticeRemover::get_instance( '1.0.0' );
137
138 try {
139 $this->notices();
140 } catch ( Exception $e ) {
141 unset( $e );
142 }
143 }
144
145 public function order_terms_in_wp_terms_admin_table() {
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);
152 }
153
154 public function disable_deactivation() {
155 $tooltip_text = esc_html__( 'Deactivate BetterDocs Pro First', 'betterdocs' );
156 ?>
157 <style type="text/css">
158 #deactivate-betterdocs {
159 color: #cccccc;
160 position: relative;
161 }
162
163 /* Tooltip styling */
164 #deactivate-betterdocs[title]:hover::after {
165 content: attr(title);
166 position: absolute;
167 bottom: 100%;
168 left: 50%;
169 transform: translateX(-50%);
170 background-color: #333;
171 color: #fff;
172 padding: 5px 10px;
173 border-radius: 4px;
174 font-size: 12px;
175 white-space: nowrap;
176 box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
177 z-index: 10;
178 }
179 #deactivate-betterdocs:focus {
180 box-shadow: none;
181 outline: none;
182 }
183 </style>
184 <script type="text/javascript">
185 jQuery(document).ready(function($) {
186 // Disable the default action and add class with tooltip by default
187 const tooltipText = "<?php echo esc_attr( $tooltip_text ); ?>";
188 $("#deactivate-betterdocs")
189 .addClass("disabled-tooltip")
190 .attr("title", tooltipText)
191 .on("click", function(e) {
192 e.preventDefault(); // Prevent any action on click
193 });
194 });
195 </script>
196 <?php
197 }
198
199 public function add_users_total_docs_column( $columns ) {
200 $new_column = [
201 'docs' => __( 'Docs', 'betterdocs' )
202 ];
203 $columns = array_merge( $columns, $new_column );
204 return $columns;
205 }
206
207 public function popular_users_docs_data( $output, $column_name, $user_id ) {
208 if ( $column_name == 'docs' ) {
209 $total_count = count_user_posts( $user_id, 'docs', true );
210 return '<a href="edit.php?post_type=docs&author=' . $user_id . '" class="edit"><span aria-hidden="true">' . $total_count . '</span></a>';
211 }
212 return $output;
213 }
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
227 public function render_estimated_time_markup() {
228 betterdocs()->views->get( 'admin/metabox/estimated-reading-box' );
229 }
230
231 public function compatibility_notices() {
232 if ( betterdocs()->is_pro_active() ) {
233 $plugins = Helper::get_plugins();
234 $plugin_data = $plugins['betterdocs-pro/betterdocs-pro.php'];
235
236 if ( isset( $plugin_data['Version'] ) && version_compare( $plugin_data['Version'], '2.5.0', '>=' ) ) {
237 return;
238 }
239
240 betterdocs()->views->get( 'admin/notices/compatibility', [ 'version' => $plugin_data['Version'] ] );
241 }
242 }
243
244 public function plugin_insights( $prevent_init = false ) {
245 $this->insights = Insights::get_instance(
246 BETTERDOCS_PLUGIN_FILE,
247 [
248 'opt_in' => true,
249 'goodbye_form' => true,
250 'item_id' => 'c7b16777b4f1b83f6083'
251 ]
252 );
253
254 $this->insights->set_notice_options(
255 [
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' ),
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 ]
259 );
260
261 if ( ! $prevent_init ) {
262 $this->insights->init();
263 }
264
265 return $this->insights;
266 }
267
268 /**
269 * Admin notices for Review and others.
270 *
271 * @return void
272 * @throws Exception
273 */
274 public function notices() {
275 $notices = new Notices(
276 [
277 'id' => 'betterdocs',
278 'storage_key' => 'notices',
279 'lifetime' => 3,
280 'stylesheet_url' => $this->assets->asset_url( 'admin/css/notices.css' ),
281 'styles' => $this->assets->asset_url( 'admin/css/notices.css' ),
282 'priority' => 4
283 ]
284 );
285
286 /**
287 * Review Notice
288 * @var mixed $message
289 */
290
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' );
292
293 $_review_notice = [
294 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
295 'html' => '<p>' . $message . '</p>',
296 'links' => [
297 'later' => [
298 'link' => 'https://wordpress.org/plugins/betterdocs/#reviews',
299 'target' => '_blank',
300 'label' => __( 'Sure, you deserve it!', 'betterdocs' ),
301 'icon_class' => 'dashicons dashicons-external'
302 ],
303 'allready' => [
304 'label' => __( 'I already did', 'betterdocs' ),
305 'icon_class' => 'dashicons dashicons-smiley',
306 'attributes' => [
307 'data-dismiss' => true
308 ]
309 ],
310 'maybe_later' => [
311 'label' => __( 'Maybe Later', 'betterdocs' ),
312 'icon_class' => 'dashicons dashicons-calendar-alt',
313 'attributes' => [
314 'data-later' => true,
315 'class' => 'dismiss-btn'
316 ]
317 ],
318 'support' => [
319 'link' => 'https://wpdeveloper.com/support',
320 'attributes' => [
321 'target' => '_blank'
322 ],
323 'label' => __( 'I need help', 'betterdocs' ),
324 'icon_class' => 'dashicons dashicons-sos'
325 ],
326 'never_show_again' => [
327 'label' => __( 'Never show again', 'betterdocs' ),
328 'icon_class' => 'dashicons dashicons-dismiss',
329 'attributes' => [
330 'data-dismiss' => true
331 ]
332 ]
333 ]
334 ];
335
336 $notices->add(
337 'review',
338 $_review_notice,
339 [
340 'start' => $notices->strtotime( '+10 days' ),
341 'recurrence' => 30,
342 'dismissible' => true
343 ]
344 );
345
346 if ( $this->kbmigration->existing_plugins && ! in_array( $this->kbmigration->existing_plugins[0][0], $this->kbmigration->migrated_plugins ) ) {
347 $plugin_name = '<strong>' . esc_html( $this->kbmigration->existing_plugins[0][1] ) . '</strong>';
348
349 $message = sprintf(
350 /* translators: %s is the name of the existing knowledge base plugin. */
351 __( 'Already using %s? Power up your Knowledge Base by migrating all your docs and settings to BetterDocs with just 1 click.', 'betterdocs' ),
352 esc_html( $plugin_name )
353 );
354
355 $migration_message = sprintf(
356 '<p class="migration-message">%s</p><a class="button button-primary betterdocs-migration-notice" href="%s">%s</a>',
357 $message,
358 esc_url( admin_url( 'admin.php?page=betterdocs-settings&tab=tab-migration' ) ),
359 esc_html__( 'Start Migration', 'betterdocs' )
360 );
361
362 $_migration_notice = [
363 'thumbnail' => '',
364 'html' => $migration_message,
365 'links' => [
366 'maybe_later' => [
367 'label' => __( 'Maybe Later', 'betterdocs' ),
368 'icon_class' => 'dashicons dashicons-calendar-alt',
369 'attributes' => [
370 'data-later' => true,
371 'class' => 'dismiss-btn'
372 ]
373 ],
374 'never_show_again' => [
375 'label' => __( 'Never show again', 'betterdocs' ),
376 'icon_class' => 'dashicons dashicons-dismiss',
377 'attributes' => [
378 'data-dismiss' => true
379 ]
380 ]
381 ]
382 ];
383
384 $notices->add(
385 'migration',
386 $_migration_notice,
387 [
388 'start' => $notices->time(),
389 'recurrence' => false,
390 'dismissible' => true
391 ]
392 );
393 }
394
395 /**
396 * Opt-In Notice
397 */
398 $allow_tracking = get_option( 'wpins_allow_tracking' );
399 if ( $this->insights != null && ! isset( $allow_tracking['betterdocs'] ) ) {
400 $notices->add(
401 'opt_in',
402 [ $this->insights, 'notice' ],
403 [
404 'classes' => 'updated put-dismiss-notice',
405 'start' => $notices->time(),
406 'refresh' => BETTERDOCS_VERSION,
407 'dismissible' => true,
408 'do_action' => 'wpdeveloper_notice_clicked_for_betterdocs',
409 'display_if' => ! function_exists( 'betterdocs_pro' ),
410 'screens' => [ 'dashboard' ]
411 ]
412 );
413 }
414
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 = [
442 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
443 'html' => $offer_message
444 ];
445
446 $notices->add(
447 '40k_offer',
448 $_offer_notice,
449 [
450 'start' => $notices->time(),
451 'recurrence' => false,
452 'dismissible' => true,
453 'refresh' => BETTERDOCS_VERSION,
454 'expire' => strtotime( '11:59:59pm April 30, 2025' ),
455 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' )
456 ]
457 );
458
459 self::$cache_bank->create_account( $notices );
460 self::$cache_bank->calculate_deposits( $notices );
461 if ( method_exists( self::$cache_bank, 'clear_notices_in_' ) ) {
462 self::$cache_bank->clear_notices_in_(
463 [
464 'toplevel_page_betterdocs-dashboard',
465 'admin_page_betterdocs-admin',
466 'betterdocs_page_betterdocs-admin',
467 'betterdocs_page_betterdocs-settings',
468 'betterdocs_page_betterdocs-faq',
469 'betterdocs_page_betterdocs-analytics',
470 'betterdocs_page_betterdocs-glossaries',
471 'betterdocs_page_betterdocs-ai-chatbot',
472 'edit-doc_category',
473 'edit-doc_tag'
474 ],
475 $notices,
476 true
477 );
478 }
479 }
480
481 public function body_classes( $classes ) {
482 $saved_settings = get_option( 'betterdocs_settings', false );
483 $dark_mode = isset( $saved_settings['dark_mode'] ) ? $saved_settings['dark_mode'] : false;
484 $dark_mode = ! empty( $dark_mode ) ? boolval( $dark_mode ) : false;
485 $current_screen_id = get_current_screen() != null ? str_replace( 'betterdocs_page_', '', str_replace( 'toplevel_page_', '', str_replace( 'admin_page_', '', get_current_screen()->id ) ) ) : '';
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 ];
498
499 if( in_array( $current_screen_id, $registered_screens ) ) {
500 $classes .= ' betterdocs-admin ';
501 }
502
503 if ( $dark_mode === true && in_array( $current_screen_id, $registered_screens ) ) {
504 $classes .= ' betterdocs-dark-mode ';
505 }
506
507 return $classes;
508 }
509
510 /**
511 * Remove Comments Column From List Table
512 *
513 * @param array $columns
514 *
515 * @return array
516 * @since 1.0.0
517 */
518 public function set_custom_edit_action_columns( $columns ) {
519 unset( $columns['comments'] );
520 $new_columns = [];
521 foreach ( $columns as $key => $value ) {
522 if ( $key == 'date' ) {
523 $new_columns['betterdocs_word_count'] = __( 'Word Count', 'betterdocs' ); // put the tags column before it
524 $new_columns['betterdocs_reaction'] = __( 'Reactions', 'betterdocs' );
525 }
526 $new_columns[ $key ] = $value;
527 }
528
529 return $new_columns;
530 }
531
532 public function manage_custom_columns( $column, $post_id ) {
533 global $wpdb;
534 switch ( $column ) {
535 case 'betterdocs_word_count':
536 $content_without_html_tags = trim( strip_tags( get_post_field( 'post_content', $post_id ) ) );
537 preg_match_all( '/<[^>]*>|[\p{L}\p{M}]+/u', $content_without_html_tags, $matches );
538 $total_words = ! empty( $matches[0] ) ? count( $matches[0] ) : count( [] );
539 $word_count = $total_words;
540 echo '<span>' . esc_html( intval( $word_count ) ) . '</span>';
541 break;
542 case 'betterdocs_reaction':
543 $where = "WHERE post_id='" . esc_sql( $post_id ) . "'";
544 $analytics = $wpdb->get_results(
545 "SELECT
546 sum(impressions) as totalViews,
547 sum(unique_visit) as totalUniqueViews,
548 sum(happy + sad + normal) as totalReactions,
549 sum(happy) as totalHappy,
550 sum(normal) as totalNormal,
551 sum(sad) as totalSad
552 FROM {$wpdb->prefix}betterdocs_analytics
553 $where"
554 );
555
556 echo '<ul class="reactions-count">
557 <li>
558 <a title="happy" class="betterdocs-feelings happy" data-feelings="happy" href="#">
559 <svg width="15" height="15" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
560 <path class="st0" d="M10,0.1c-5.4,0-9.9,4.4-9.9,9.8c0,5.4,4.4,9.9,9.8,9.9c5.4,0,9.9-4.4,9.9-9.8C19.9,4.5,15.4,0.1,10,0.1z
561 M13.3,6.4c0.8,0,1.5,0.7,1.5,1.5c0,0.8-0.7,1.5-1.5,1.5c-0.8,0-1.5-0.7-1.5-1.5C11.8,7.1,12.5,6.4,13.3,6.4z M6.7,6.4
562 c0.8,0,1.5,0.7,1.5,1.5c0,0.8-0.7,1.5-1.5,1.5c-0.8,0-1.5-0.7-1.5-1.5C5.2,7.1,5.9,6.4,6.7,6.4z M10,16.1c-2.6,0-4.9-1.6-5.8-4
563 l1.2-0.4c0.7,1.9,2.5,3.2,4.6,3.2s3.9-1.3,4.6-3.2l1.2,0.4C14.9,14.5,12.6,16.1,10,16.1z" />
564 <path class="st1" d="M-6.6-119.7c-7.1,0-12.9,5.8-12.9,12.9s5.8,12.9,12.9,12.9s12.9-5.8,12.9-12.9S0.6-119.7-6.6-119.7z
565 M-2.3-111.4c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C-4.3-110.5-3.4-111.4-2.3-111.4z M-10.9-111.4c1.1,0,2,0.9,2,2
566 c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C-12.9-110.5-12-111.4-10.9-111.4z M-6.6-98.7c-3.4,0-6.4-2.1-7.6-5.3l1.6-0.6
567 c0.9,2.5,3.3,4.2,6,4.2s5.1-1.7,6-4.2L1-104C-0.1-100.8-3.2-98.7-6.6-98.7z" />
568 </svg>
569 <span>' . esc_html( ( intval( $analytics[0]->totalHappy ) !== null ? intval( $analytics[0]->totalHappy ) : 0 ) ) . '</span>
570 </a>
571 </li>
572 <li>
573 <a title="normal" class="betterdocs-feelings normal" data-feelings="normal" href="#">
574 <svg width="15" height="15" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
575 <path class="st0" d="M10,0.2c-5.4,0-9.8,4.4-9.8,9.8s4.4,9.8,9.8,9.8s9.8-4.4,9.8-9.8S15.4,0.2,10,0.2z M6.7,6.5
576 c0.8,0,1.5,0.7,1.5,1.5c0,0.8-0.7,1.5-1.5,1.5C5.9,9.5,5.2,8.9,5.2,8C5.2,7.2,5.9,6.5,6.7,6.5z M14.2,14.3H5.9
577 c-0.3,0-0.6-0.3-0.6-0.6c0-0.3,0.3-0.6,0.6-0.6h8.3c0.3,0,0.6,0.3,0.6,0.6C14.8,14,14.5,14.3,14.2,14.3z M13.3,9.5
578 c-0.8,0-1.5-0.7-1.5-1.5c0-0.8,0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5C14.8,8.9,14.1,9.5,13.3,9.5z" />
579 </svg>
580 <span>' . esc_html( ( intval( $analytics[0]->totalNormal ) !== null ? intval( $analytics[0]->totalNormal ) : 0 ) ) . '</span>
581 </a>
582 </li>
583 <li>
584 <a title="sad" class="betterdocs-feelings sad" data-feelings="sad" href="#">
585 <svg width="15" height="15" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
586 <circle class="st0" cx="27.5" cy="0.6" r="1.9" />
587 <circle class="st0" cx="36" cy="0.6" r="1.9" />
588 <path class="st1" d="M10,0.3c-5.4,0-9.8,4.4-9.8,9.8s4.4,9.8,9.8,9.8s9.8-4.4,9.8-9.8S15.4,0.3,10,0.3z M13.3,6.6
589 c0.8,0,1.5,0.7,1.5,1.5c0,0.8-0.7,1.5-1.5,1.5c-0.8,0-1.5-0.7-1.5-1.5C11.8,7.3,12.4,6.6,13.3,6.6z M6.7,6.6c0.8,0,1.5,0.7,1.5,1.5
590 c0,0.8-0.7,1.5-1.5,1.5C5.9,9.6,5.2,9,5.2,8.1C5.2,7.3,5.9,6.6,6.7,6.6z M14.1,15L14.1,15c-0.2,0-0.4-0.1-0.5-0.2
591 c-0.9-1-2.2-1.7-3.7-1.7s-2.8,0.6-3.7,1.7C6.2,14.9,6,15,5.9,15h0c-0.6,0-0.8-0.6-0.5-1.1c1.1-1.3,2.8-2.1,4.6-2.1
592 c1.8,0,3.5,0.8,4.6,2.1C15,14.3,14.7,15,14.1,15z" />
593 </svg>
594 <span>' . esc_html( ( intval( $analytics[0]->totalNormal ) !== null ? intval( $analytics[0]->totalNormal ) : 0 ) ) . '</span>
595 </a>
596 </li>
597 </ul>';
598 break;
599 }
600 }
601
602 /**
603 * Enqueue Assets for Admin ( Styles )
604 *
605 * @param string $hook
606 *
607 * @return void
608 * @since 1.0.0
609 */
610 public function styles( $hook ) {
611 $this->assets->enqueue( 'betterdocs-global', 'admin/css/global.css', [], 'all' );
612
613 if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
614 return;
615 }
616
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' );
620
621 /**
622 * This scripts enqueued for Dashboard App.
623 */
624 $this->assets->enqueue( 'betterdocs', 'admin/css/dashboard.css', [ 'betterdocs-old' ], '', BETTERDOCS_VERSION );
625 $this->assets->enqueue( 'betterdocs-icons', 'admin/btd-icon/style.css' );
626 }
627
628 /**
629 * Enqueue Assets for Admin ( Scripts )
630 *
631 * @param string $hook
632 *
633 * @return void
634 * @since 1.0.0
635 */
636 public function scripts( $hook ) {
637 if ( ( $hook === 'edit.php' ) && get_post_type() == 'docs' ) {
638 $this->assets->enqueue(
639 'betterdocs-switcher',
640 'admin/js/switcher.js',
641 [
642 'jquery'
643 ]
644 );
645
646 $this->assets->localize(
647 'betterdocs-switcher',
648 'betterdocsSwitcher',
649 [
650 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
651 'site_address' => get_bloginfo( 'url' ),
652 'betterdocs_pro_plugin' => betterdocs()->is_pro_active(),
653 'betterdocs_pro_version' => betterdocs()->pro_version()
654 ]
655 );
656
657 return;
658 }
659
660 wp_enqueue_script( 'wp-editor' ); // enqueue this for yoast related issue
661
662 if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
663 return;
664 }
665
666 wp_enqueue_media(); // load early to fix problems with media upload issues on settings for wordpress 6.0.9
667 $this->assets->register( 'betterdocs-admin', 'admin/js/dashboard.js' );
668
669 $saved_settings = get_option( 'betterdocs_settings', false );
670 $dark_mode = $saved_settings['dark_mode'] ?? false;
671 $dark_mode = ! empty( $dark_mode ) && boolval( $dark_mode );
672 $this->assets->localize(
673 'betterdocs-admin',
674 'betterdocs_admin',
675 [
676 'ajaxurl' => admin_url( 'admin-ajax.php' ),
677 'doc_cat_order_nonce' => wp_create_nonce( 'doc_cat_order_nonce' ),
678 'knowledge_base_order_nonce' => wp_create_nonce( 'knowledge_base_order_nonce' ),
679 'paged' => isset( $_GET['paged'] ) ? absint( wp_unslash( $_GET['paged'] ) ) : 0, // phpcs:ignore WordPress.Security.NonceVerification.Missing
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 ]
707 );
708
709 // If wp-date (which includes moment.js) is not registered, enqueue your custom moment.js
710 if ( ! wp_script_is( 'wp-date', 'registered' ) ) {
711 $this->assets->enqueue( 'moment', 'vendor/js/moment.min.js', [] );
712 }
713 wp_enqueue_script( 'betterdocs-admin' );
714
715 /**
716 * Duplicate Codes Need to Be Removed From Here Onwards
717 */
718
719 //FAQ Builder Related Localization
720 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/css/faq.css' );
721 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/js/faq.js' );
722
723 // removing emoji support
724 remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
725 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
726
727 betterdocs()->assets->localize(
728 'betterdocs-admin-faq',
729 'betterdocsFaq',
730 [
731 'dir_url' => BETTERDOCS_ABSURL,
732 'rest_url' => esc_url_raw( rest_url() ),
733 'free_version' => betterdocs()->version,
734 'nonce' => wp_create_nonce( 'wp_rest' ),
735 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
736 ]
737 );
738
739 //Glossaries Related Localization
740 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/css/faq.css' );
741
742 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/js/glossaries.js' );
743
744 betterdocs()->assets->localize(
745 'betterdocs-admin-glossaries',
746 'betterdocsGlossary',
747 [
748 'dir_url' => BETTERDOCS_ABSURL,
749 'rest_url' => esc_url_raw( rest_url() ),
750 'free_version' => betterdocs()->version,
751 'nonce' => wp_create_nonce( 'wp_rest' ),
752 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
753 ]
754 );
755 }
756
757 /**
758 * All admin pages header
759 *
760 * @return void
761 * @since 1.0.0
762 */
763 public function header( $admin_tab_name ) {
764 $quick_links = [
765 'switch_view' => sprintf(
766 '<a href="%s" class="betterdocs-button betterdocs-button-secondary">%s</a>',
767 add_query_arg(
768 [
769 'post_type' => 'docs',
770 'bdocs_view' => 'classic'
771 ],
772 'edit.php'
773 ),
774 __( 'Switch to Classic UI', 'betterdocs' )
775 ),
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 ];
778
779 $quick_links = apply_filters( 'betterdocs_quick_links', $quick_links );
780
781 betterdocs()->views->get(
782 'admin/header',
783 [
784 'quick_links' => $quick_links,
785 'active_tab' => $admin_tab_name
786 ]
787 );
788 }
789
790 /**
791 * Register all the menus for BetterDocs
792 *
793 * @return void
794 * @since 1.0.0
795 */
796 public function menus() {
797 $default_args = [
798 'page_title' => 'BetterDocs',
799 'menu_title' => 'BetterDocs',
800 'capability' => 'edit_docs', // Unified capability
801 'menu_slug' => $this->slug,
802 'callback' => [ $this, 'output' ],
803 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
804 'position' => 5
805 ];
806
807 $_menu_position = 5;
808 global $submenu;
809
810 // Always register both UI endpoints
811 $this->register_modern_ui_fallback();
812
813 foreach ( $this->menu_list() as $key => $value ) {
814 if ( $key === 'betterdocs' ) {
815 $callable = 'add_menu_page';
816 $value = wp_parse_args( $value, $default_args );
817 call_user_func_array( $callable, $value );
818 } else {
819 $is_core_page = strpos($value['menu_slug'], '?') !== false;
820
821 if ($is_core_page) {
822 // Add classic UI directly
823 $submenu[$this->slug][] = [
824 $value['menu_title'],
825 $value['capability'],
826 $value['menu_slug'],
827 $value['page_title']
828 ];
829 } else {
830 // Add modern UI through WordPress API
831 add_submenu_page(
832 $this->slug,
833 $value['page_title'],
834 $value['menu_title'],
835 $value['capability'],
836 $value['menu_slug'],
837 $value['callback']
838 );
839 }
840 $_menu_position++;
841 }
842 }
843 }
844
845 private function register_modern_ui_fallback() {
846 // Add the submenu with valid parent slug
847 add_submenu_page(
848 'betterdocs', // Valid parent slug
849 __('All Docs', 'betterdocs'),
850 '', // Empty menu title hides it
851 'edit_docs',
852 'betterdocs-admin',
853 [ $this, 'output' ]
854 );
855
856 // Hide the menu item from appearing in the admin sidebar
857 global $submenu;
858 if (isset($submenu['betterdocs'])) {
859 foreach ($submenu['betterdocs'] as $key => $item) {
860 if ($item[2] === 'betterdocs-admin') {
861 unset($submenu['betterdocs'][$key]);
862 break;
863 }
864 }
865 }
866 }
867
868 /**
869 * BetterDocs Admin Page Output
870 *
871 * @return void
872 * @since 1.0.0
873 */
874 public function output() {
875 if ( betterdocs()->is_pro_active()
876 && version_compare( betterdocs()->pro_version(), '3.3.4', '<=' )
877 && get_current_screen()->id == 'betterdocs_page_betterdocs-analytics' ) {
878 betterdocs_pro()->views->get( 'admin/analytics-pro' );
879 } else {
880 betterdocs()->views->get(
881 'admin/main',
882 [
883 'admin_ui' => 'dnd'
884 ]
885 );
886 }
887 }
888
889 /**
890 * Menu creator helper
891 *
892 * @param string $title
893 * @param string $slug
894 * @param string $cap
895 * @param array $callback
896 *
897 * @return array
898 * @since 2.5.0
899 *
900 */
901 private function normalize_menu( $title, $slug, $cap = 'edit_docs', $callback = null, $optional = [] ) {
902 return Helper::normalize_menu( $title, $slug, $cap, $callback, $optional );
903 }
904
905 /**
906 * BetterDocs Menu List
907 *
908 * @return array
909 * @since 1.0.0
910 */
911 private function menu_list() {
912 $parent_slug = [];
913
914 $betterdocs_admin_pages = [
915 'betterdocs' => [
916 'menu_slug' => $this->slug,
917 'page_title' => 'BetterDocs',
918 'menu_title' => 'BetterDocs',
919 'capability' => 'edit_docs',
920 'callback' => [ $this, 'output' ],
921 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
922 'position' => 5
923 ],
924 'dashboard' => $this->normalize_menu(
925 __( 'Dashboard', 'betterdocs' ),
926 'betterdocs-dashboard',
927 'edit_docs',
928 [
929 $this,
930 'output'
931 ]
932 ),
933 'all_docs' => $this->normalize_menu(
934 __( 'All Docs', 'betterdocs' ),
935 $this->ui_slug(),
936 'edit_docs',
937 [ $this, 'output' ],
938 $parent_slug
939 ),
940 'add_new' => $this->normalize_menu(
941 __( 'Add New', 'betterdocs' ),
942 'post-new.php?post_type=docs'
943 ),
944 'categories' => $this->normalize_menu(
945 __( 'Categories', 'betterdocs' ),
946 'edit-tags.php?taxonomy=doc_category&post_type=docs',
947 'manage_doc_terms'
948 ),
949 'tags' => $this->normalize_menu(
950 __( 'Tags', 'betterdocs' ),
951 'edit-tags.php?taxonomy=doc_tag&post_type=docs',
952 'manage_doc_terms'
953 ),
954 'settings' => $this->normalize_menu(
955 __( 'Settings', 'betterdocs' ),
956 'betterdocs-settings',
957 'edit_docs_settings',
958 [
959 $this,
960 'output'
961 ],
962 $parent_slug
963 ),
964 'analytics' => $this->normalize_menu(
965 __( 'Analytics', 'betterdocs' ),
966 'betterdocs-analytics',
967 'read_docs_analytics',
968 [
969 $this,
970 'output'
971 ],
972 $parent_slug
973 ),
974 'faq' => $this->normalize_menu(
975 __( 'FAQ Builder', 'betterdocs' ),
976 'betterdocs-faq',
977 'read_faq_builder',
978 [
979 $this,
980 'output'
981 ],
982 $parent_slug
983 )
984 ];
985
986 if ( betterdocs()->is_pro_active() && betterdocs()->settings->get( 'enable_glossaries' ) == true ) {
987 $betterdocs_admin_pages['glossaries'] = $this->normalize_menu(
988 __( 'Glossaries', 'betterdocs' ),
989 'betterdocs-glossaries',
990 'read_docs_analytics',
991 [
992 $this,
993 'output'
994 ],
995 $parent_slug
996 );
997 }
998
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 [
1006 $this,
1007 'output'
1008 ],
1009 $parent_slug
1010 );
1011 }
1012
1013 return apply_filters( 'betterdocs_admin_menu', $betterdocs_admin_pages, [$this, 'output'], $parent_slug);
1014
1015 }
1016
1017 public function add_custom_classes_to_menu_items() {
1018 global $menu, $submenu;
1019
1020 $menu_items = [
1021 'betterdocs' => 'betterdocs',
1022 'betterdocs_page_all_docs' => 'betterdocs-all-docs',
1023 'betterdocs_page_add_new' => 'betterdocs-add-new',
1024 'edit-tags.php?taxonomy=doc_category&post_type=docs' => 'betterdocs-categories',
1025 'edit-tags.php?taxonomy=doc_tag&post_type=docs' => 'betterdocs-tags',
1026 'betterdocs-settings' => 'betterdocs-settings',
1027 'betterdocs-analytics' => 'betterdocs-analytics',
1028 'betterdocs-faq' => 'betterdocs-faq',
1029 'betterdocs-glossaries' => 'betterdocs-glossaries',
1030 'betterdocs-ai-chatbot' => 'betterdocs-ai-chatbot',
1031 'edit-tags.php?taxonomy=knowledge_base&post_type=docs' => 'betterdocs-multiplekb'
1032 ];
1033
1034 foreach ( $menu as &$item ) {
1035 if ( isset( $menu_items[ $item[2] ] ) ) {
1036 if ( ! isset( $item[4] ) ) {
1037 $item[4] = '';
1038 }
1039 $item[4] .= '' . $menu_items[ $item[2] ];
1040 }
1041 }
1042
1043 foreach ( $submenu as &$submenu_items ) {
1044 foreach ( $submenu_items as &$sub_item ) {
1045 if ( isset( $menu_items[ $sub_item[2] ] ) ) {
1046 if ( ! isset( $sub_item[4] ) ) {
1047 $sub_item[4] = '';
1048 }
1049 $sub_item[4] .= '' . $menu_items[ $sub_item[2] ];
1050 }
1051 }
1052 }
1053 }
1054
1055 public function quick_setup_menu( $menus ) {
1056 $betterdocs_settings = get_option( 'betterdocs_settings' );
1057 if ( $betterdocs_settings ) {
1058 return $menus;
1059 } else {
1060 $menus['quick_setup'] = $this->normalize_menu(
1061 __( 'Quick Setup', 'betterdocs' ),
1062 'betterdocs-setup',
1063 'delete_users',
1064 [
1065 $this->container->get( SetupWizard::class ),
1066 'views'
1067 ]
1068 );
1069 }
1070
1071 return $menus;
1072 }
1073
1074 public function insert_plugin_links( $links ) {
1075 $links[] = '<a href="admin.php?page=betterdocs-settings">' . __( 'Settings', 'betterdocs' ) . '</a>';
1076
1077 return $links;
1078 }
1079
1080 public function toolbar_menu( $admin_bar ) {
1081 if ( ! is_admin() || ! is_admin_bar_showing() ) {
1082 return;
1083 }
1084
1085 // Show only when the user is a member of this site, or they're a super admin.
1086 if ( ! is_user_member_of_blog() && ! is_super_admin() ) {
1087 return;
1088 }
1089
1090 $docs_url = '';
1091 $encyclopedia_url = '';
1092
1093 if ( $this->settings->get( 'builtin_doc_page' ) ) {
1094 $docs_url = get_post_type_archive_link( 'docs' );
1095 } elseif ( intval( $docs_page = $this->settings->get( 'docs_page' ) ) ) {
1096 $docs_url = ! empty( $docs_page ) ? get_page_link( $docs_page ) : false;
1097 }
1098
1099 if ( ! $docs_url ) {
1100 return;
1101 }
1102
1103 $slug = $this->settings->get( 'encyclopedia_root_slug' );
1104
1105 $encyclopedia_url = home_url( $slug );
1106
1107 $admin_bar->add_node(
1108 [
1109 'parent' => 'site-name',
1110 'id' => 'view-docs',
1111 'title' => __( 'Visit Documentation', 'betterdocs' ),
1112 'href' => $docs_url
1113 ]
1114 );
1115
1116 $is_enable_encyclopedia = betterdocs()->settings->get( 'enable_encyclopedia' );
1117
1118 if ( $is_enable_encyclopedia && betterdocs()->is_pro_active() ) {
1119 $admin_bar->add_node(
1120 [
1121 'parent' => 'site-name',
1122 'id' => 'view-encyclopedia',
1123 'title' => __( 'Visit Encyclopedia', 'betterdocs' ),
1124 'href' => $encyclopedia_url
1125 ]
1126 );
1127 }
1128 }
1129
1130 /**
1131 * Save last visited admin ui
1132 *
1133 * @since 3.0.1
1134 *
1135 */
1136 public function save_admin_page() {
1137 if ( isset( $_GET['post_type'] ) && $_GET['post_type'] === 'docs' && isset( $_GET['bdocs_view'] ) && $_GET['bdocs_view'] === 'classic' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1138 update_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', 'classic_ui' );
1139 } elseif ( isset( $_GET['page'] ) && $_GET['page'] === 'betterdocs-admin' ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1140 update_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', 'modern_ui' );
1141 }
1142 }
1143
1144 /**
1145 * Return last visited admin ui slug
1146 *
1147 * @return string
1148 * @since 3.0.1
1149 */
1150 public function ui_slug() {
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 ]);
1157
1158 return ($last_visited === 'modern_ui' || empty($docs_exist))
1159 ? 'betterdocs-admin'
1160 : 'edit.php?post_type=docs&bdocs_view=classic';
1161 }
1162
1163 /**
1164 * Resets a duplicate submenu in WordPress if the parent main menu and the first submenu permalink are not the same.
1165 *
1166 * @return string
1167 * @since 3.0.1
1168 */
1169 public function reset_submenu() {
1170 global $submenu;
1171
1172 $docs = get_posts( [ 'post_type' => 'docs' ] );
1173 if ( count( $docs ) == 0 ) {
1174 return;
1175 }
1176
1177 $last_visited = get_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', true );
1178
1179 if ( $last_visited === 'classic_ui' && isset( $submenu['betterdocs-admin'] ) && in_array( 'betterdocs-admin', $submenu['betterdocs-admin'][0] ) ) {
1180 unset( $submenu['betterdocs-admin'][0] );
1181 $submenu['betterdocs-admin'] = array_values( $submenu['betterdocs-admin'] );
1182 }
1183 }
1184 }
1185