PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.6.1
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.6.1
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 3.6.1, at includes/Core/Admin.php

843 lines 35.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\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\Dependencies\DI\Container;
14
15 class Admin extends Base {
16 /**
17 * @var CacheBank
18 */
19 private static $cache_bank;
20 /**
21 * Admin Root Menu Slug
22 * @var string
23 */
24 private $slug = 'betterdocs-admin';
25 /**
26 * Insights
27 *
28 * @var Insights
29 */
30 private $insights = null;
31
32 /**
33 * DI\Container
34 *
35 * @var Container
36 */
37 private $container;
38
39 /**
40 * Database Wrapper
41 *
42 * @var Settings
43 */
44 private $settings;
45
46 /**
47 * KBMigration
48 *
49 * @var KBMigration
50 */
51 private $kbmigration;
52
53 /**
54 * Enqueue
55 * @var Enqueue
56 */
57 private $assets;
58
59 /**
60 * FAQBuilder
61 * @var FAQBuilder
62 */
63 private $faq_builder;
64 private $glossaries;
65
66 public function __construct( Container $container, PostType $type, Enqueue $assets, Settings $settings, KBMigration $kbmigration ) {
67 $this->container = $container;
68 $this->assets = $assets;
69 $this->settings = $settings;
70 $this->kbmigration = $kbmigration;
71 $this->slug = 'betterdocs-admin';
72
73 add_action( 'init', [$type, 'register'], 9 );
74
75 $type->init();
76 $type->admin_init();
77
78 $this->faq_builder = $this->container->get( FAQBuilder::class );
79 $this->glossaries = $this->container->get( Glossaries::class );
80
81 if ( ! is_admin() ) {
82 return;
83 }
84
85 $this->plugin_insights();
86 add_action( 'admin_notices', [$this, 'compatibility_notices'] );
87 // add_action( 'admin_init', [$this, 'notices'], 9 );
88 add_filter( 'admin_init', [$this, 'save_admin_page'], 99 );
89
90 add_action( 'admin_menu', [$this, 'menus'] );
91 add_action( 'admin_menu', [$this, 'reset_submenu'] );
92 add_action( 'admin_head', [$this, 'add_custom_classes_to_menu_items'] );
93 add_filter( 'plugin_action_links_' . BETTERDOCS_PLUGIN_BASENAME, [$this, 'insert_plugin_links'] );
94
95 // $this->container->get( SetupWizard::class )->init();
96
97 add_action( 'admin_enqueue_scripts', [$this, 'styles'] );
98 add_action( 'admin_enqueue_scripts', [$this, 'scripts'] );
99 //add_action( 'betterdocs_listing_header', [ $this, 'header' ], 10, 1 );
100 add_action( 'admin_bar_menu', [$this, 'toolbar_menu'], 32 );
101
102 add_filter( 'admin_body_class', [$this, 'body_classes'] );
103 add_filter( 'parent_file', [$type, 'highlight_admin_menu'] );
104 add_filter( 'submenu_file', [$type, 'highlight_admin_submenu'], 10, 2 );
105 add_filter( 'betterdocs_admin_menu', [$this, 'quick_setup_menu'], 10, 1 );
106
107 /**
108 * Remove Comments Column from List Table.
109 */
110 add_filter( 'manage_docs_posts_columns', [$this, 'set_custom_edit_action_columns'] );
111 add_filter( 'manage_docs_posts_custom_column', [$this, 'manage_custom_columns'], 10, 2 );
112
113 if ( $this->settings->get( 'enable_estimated_reading_time' ) ) {
114 add_action( 'add_meta_boxes', [$this, 'reading_meta_box_'], 10 );
115 }
116
117 self::$cache_bank = CacheBank::get_instance();
118
119 // Remove OLD notice from 1.0.0 (if other WPDeveloper plugin has notice)
120 NoticeRemover::get_instance( '1.0.0' );
121
122 try {
123 add_action( 'admin_init', [$this, 'notices'] );
124 } catch ( Exception $e ) {
125 unset( $e );
126 }
127 }
128
129 public function reading_meta_box_() {
130 add_meta_box( 'betterdocs_estimated_time_metabox', __( 'Estimated Reading Time', 'betterdocs' ), [
131 $this,
132 'render_estimated_time_markup'
133 ], 'docs' );
134 }
135
136 public function render_estimated_time_markup() {
137 betterdocs()->views->get( 'admin/metabox/estimated-reading-box' );
138 }
139
140 public function compatibility_notices() {
141 if ( betterdocs()->is_pro_active() ) {
142 $plugins = Helper::get_plugins();
143 $plugin_data = $plugins['betterdocs-pro/betterdocs-pro.php'];
144
145 if ( isset( $plugin_data['Version'] ) && version_compare( $plugin_data['Version'], '2.5.0', '>=' ) ) {
146 return;
147 }
148
149 betterdocs()->views->get( 'admin/notices/compatibility', ['version' => $plugin_data['Version']] );
150 }
151 }
152
153 public function plugin_insights( $prevent_init = false ) {
154 $this->insights = Insights::get_instance( BETTERDOCS_PLUGIN_FILE, [
155 'opt_in' => true,
156 'goodbye_form' => true,
157 'item_id' => 'c7b16777b4f1b83f6083'
158 ] );
159
160 $this->insights->set_notice_options( [
161 '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' ),
162 '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' )
163 ] );
164
165 if ( ! $prevent_init ) {
166 $this->insights->init();
167 }
168
169 return $this->insights;
170 }
171
172 /**
173 * Admin notices for Review and others.
174 *
175 * @return void
176 * @throws Exception
177 */
178 public function notices() {
179 $notices = new Notices( [
180 'id' => 'betterdocs',
181 'storage_key' => 'notices',
182 'lifetime' => 3,
183 'stylesheet_url' => $this->assets->asset_url( 'admin/css/notices.css' ),
184 'styles' => $this->assets->asset_url( 'admin/css/notices.css' ),
185 'priority' => 4
186 ] );
187
188 /**
189 * Review Notice
190 * @var mixed $message
191 */
192
193 $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' );
194
195 $_review_notice = [
196 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
197 'html' => '<p>' . $message . '</p>',
198 'links' => [
199 'later' => [
200 'link' => 'https://wordpress.org/plugins/betterdocs/#reviews',
201 'target' => '_blank',
202 'label' => __( 'Sure, you deserve it!', 'betterdocs' ),
203 'icon_class' => 'dashicons dashicons-external'
204 ],
205 'allready' => [
206 'label' => __( 'I already did', 'betterdocs' ),
207 'icon_class' => 'dashicons dashicons-smiley',
208 'attributes' => [
209 'data-dismiss' => true
210 ]
211 ],
212 'maybe_later' => [
213 'label' => __( 'Maybe Later', 'betterdocs' ),
214 'icon_class' => 'dashicons dashicons-calendar-alt',
215 'attributes' => [
216 'data-later' => true,
217 'class' => 'dismiss-btn'
218 ]
219 ],
220 'support' => [
221 'link' => 'https://wpdeveloper.com/support',
222 'attributes' => [
223 'target' => '_blank'
224 ],
225 'label' => __( 'I need help', 'betterdocs' ),
226 'icon_class' => 'dashicons dashicons-sos'
227 ],
228 'never_show_again' => [
229 'label' => __( 'Never show again', 'betterdocs' ),
230 'icon_class' => 'dashicons dashicons-dismiss',
231 'attributes' => [
232 'data-dismiss' => true
233 ]
234 ]
235 ]
236 ];
237
238 $notices->add( 'review', $_review_notice, [
239 'start' => $notices->strtotime( '+10 days' ),
240 'recurrence' => 30,
241 'dismissible' => true
242 ] );
243
244 if ( $this->kbmigration->existing_plugins && ! in_array( $this->kbmigration->existing_plugins[0][0], $this->kbmigration->migrated_plugins ) ) {
245 $migration_message = sprintf( '<p class="migration-message">%s</p><a class="button button-primary betterdocs-migration-notice" href="%s">%s</a>', __( sprintf( 'Already using %s? Power up your Knowledge Base by migrating all your docs, settings to BetterDocs with just 1 click.', '<strong>' . esc_html( $this->kbmigration->existing_plugins[0][1] ) . '</strong>', '<strong>' . esc_html( $this->kbmigration->existing_plugins[0][1] ) . '</strong>' ), 'betterdocs' ), esc_url( admin_url( 'admin.php?page=betterdocs-settings&tab=tab-migration' ) ), __( 'Start Migration', 'betterdocs' ) );
246
247 $_migration_notice = [
248 'thumbnail' => '',
249 'html' => $migration_message,
250 'links' => [
251 'maybe_later' => [
252 'label' => __( 'Maybe Later', 'betterdocs' ),
253 'icon_class' => 'dashicons dashicons-calendar-alt',
254 'attributes' => [
255 'data-later' => true,
256 'class' => 'dismiss-btn'
257 ]
258 ],
259 'never_show_again' => [
260 'label' => __( 'Never show again', 'betterdocs' ),
261 'icon_class' => 'dashicons dashicons-dismiss',
262 'attributes' => [
263 'data-dismiss' => true
264 ]
265 ]
266 ]
267 ];
268
269 $notices->add( 'migration', $_migration_notice, [
270 'start' => $notices->time(),
271 'recurrence' => false,
272 'dismissible' => true,
273 'display_if' => current_user_can( 'delete_users' )
274 ] );
275 }
276
277 /**
278 * Opt-In Notice
279 */
280 if ( $this->insights != null ) {
281 $notices->add( 'opt_in', [$this->insights, 'notice'], [
282 'classes' => 'updated put-dismiss-notice',
283 'start' => $notices->time(),
284 // 'start' => $notices->strtotime( '+20 days' ),
285 'dismissible' => true,
286 'do_action' => 'wpdeveloper_notice_clicked_for_betterdocs',
287 'display_if' => ! function_exists( 'betterdocs_pro' )
288 ] );
289 }
290
291 $b_message = '<p style="margin-top: 0; margin-bottom: 10px;">Black Friday Sale: Enjoy 40% off & unlock <strong>premium features to streamline customer support</strong> & knowledge base 🎁</p><a class="button button-primary" href="https://wpdeveloper.com/upgrade/betterdocs-bfcm" target="_blank">Upgrade to pro</a> <button data-dismiss="true" class="dismiss-btn button button-link">I don’t want to save money</button>';
292 $_black_friday_notice = [
293 'thumbnail' => $this->assets->icon( 'betterdocs-logo.svg', true ),
294 'html' => $b_message
295 ];
296
297 $notices->add( 'black_friday_notice', $_black_friday_notice, [
298 'start' => $notices->time(),
299 'recurrence' => false,
300 'dismissible' => true,
301 'refresh' => BETTERDOCS_VERSION,
302 "expire" => strtotime( '11:59:59pm 2nd December, 2023' ),
303 'display_if' => ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' )
304 ] );
305
306 self::$cache_bank->create_account( $notices );
307 self::$cache_bank->calculate_deposits( $notices );
308 if ( method_exists( self::$cache_bank, 'clear_notices_in_' ) ) {
309 self::$cache_bank->clear_notices_in_( [
310 'toplevel_page_betterdocs-admin',
311 'betterdocs_page_betterdocs-admin',
312 'betterdocs_page_betterdocs-settings',
313 'betterdocs_page_betterdocs-faq',
314 'betterdocs_page_betterdocs-analytics',
315 'betterdocs_page_betterdocs-glossaries',
316 'edit-doc_category',
317 'edit-doc_tag'
318 ], $notices, true );
319 }
320 }
321
322 public function body_classes( $classes ) {
323 $saved_settings = get_option( 'betterdocs_settings', false );
324 $dark_mode = isset( $saved_settings['dark_mode'] ) ? $saved_settings['dark_mode'] : false;
325 $dark_mode = ! empty( $dark_mode ) ? boolval( $dark_mode ) : false;
326 $current_screen_id = get_current_screen() != null ? str_replace( 'toplevel_page_', '', get_current_screen()->id ) : '';
327 $registered_screens = [
328 'betterdocs-settings',
329 'betterdocs-admin',
330 'betterdocs-analytics',
331 'betterdocs-glossaries'
332 ];
333 $classes .= ' betterdocs-admin ';
334
335 if ( $dark_mode === true && in_array( $current_screen_id, $registered_screens ) ) {
336 $classes .= ' betterdocs-dark-mode ';
337 }
338
339 return $classes;
340 }
341
342 /**
343 * Remove Comments Column From List Table
344 *
345 * @param array $columns
346 *
347 * @return array
348 * @since 1.0.0
349 */
350 public function set_custom_edit_action_columns( $columns ) {
351 unset( $columns['comments'] );
352 $new_columns = [];
353 foreach ( $columns as $key => $value ) {
354 if ( $key == 'date' ) {
355 $new_columns['betterdocs_word_count'] = __( 'Word Count', 'betterdocs' ); // put the tags column before it
356 $new_columns['betterdocs_reaction'] = __( 'Reactions', 'betterdocs' );
357 }
358 $new_columns[$key] = $value;
359 }
360
361 return $new_columns;
362 }
363
364 public function manage_custom_columns( $column, $post_id ) {
365 global $wpdb;
366 switch ( $column ) {
367 case 'betterdocs_word_count':
368 $content_without_html_tags = trim( strip_tags( get_post_field( 'post_content', $post_id ) ) );
369 preg_match_all( '/<[^>]*>|[\p{L}\p{M}]+/u', $content_without_html_tags, $matches );
370 $total_words = ! empty( $matches[0] ) ? count( $matches[0] ) : count( [] );
371 $word_count = $total_words;
372 echo '<span>' . $word_count . '</span>';
373 break;
374 case 'betterdocs_reaction':
375 $where = "WHERE post_id='" . esc_sql( $post_id ) . "'";
376 $analytics = $wpdb->get_results( "SELECT
377 sum(impressions) as totalViews,
378 sum(unique_visit) as totalUniqueViews,
379 sum(happy + sad + normal) as totalReactions,
380 sum(happy) as totalHappy,
381 sum(normal) as totalNormal,
382 sum(sad) as totalSad
383 FROM {$wpdb->prefix}betterdocs_analytics
384 $where" );
385
386 echo '<ul class="reactions-count">
387 <li>
388 <a title="happy" class="betterdocs-feelings happy" data-feelings="happy" href="#">
389 <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">
390 <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
391 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
392 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
393 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" />
394 <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
395 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
396 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
397 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" />
398 </svg>
399 <span>' . ( $analytics[0]->totalHappy != null ? $analytics[0]->totalHappy : 0 ) . '</span>
400 </a>
401 </li>
402 <li>
403 <a title="normal" class="betterdocs-feelings normal" data-feelings="normal" href="#">
404 <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">
405 <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
406 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
407 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
408 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" />
409 </svg>
410 <span>' . ( $analytics[0]->totalNormal != null ? $analytics[0]->totalNormal : 0 ) . '</span>
411 </a>
412 </li>
413 <li>
414 <a title="sad" class="betterdocs-feelings sad" data-feelings="sad" href="#">
415 <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">
416 <circle class="st0" cx="27.5" cy="0.6" r="1.9" />
417 <circle class="st0" cx="36" cy="0.6" r="1.9" />
418 <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
419 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
420 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
421 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
422 c1.8,0,3.5,0.8,4.6,2.1C15,14.3,14.7,15,14.1,15z" />
423 </svg>
424 <span>' . ( $analytics[0]->totalSad != null ? $analytics[0]->totalSad : 0 ) . '</span>
425 </a>
426 </li>
427 </ul>';
428 break;
429 }
430 }
431
432 /**
433 * Enqueue Assets for Admin ( Styles )
434 *
435 * @param string $hook
436 *
437 * @return void
438 * @since 1.0.0
439 */
440 public function styles( $hook ) {
441 $this->assets->enqueue( 'betterdocs-global', 'admin/css/global.css', [], 'all' );
442
443 $this->assets->enqueue( 'betterdocs-select2', 'vendor/css/select2.min.css', [], 'all' );
444 $this->assets->enqueue( 'betterdocs-daterangepicker', 'vendor/css/daterangepicker.css', [], 'all' );
445 $this->assets->enqueue( 'betterdocs-old', 'admin/css/betterdocs.css', [], 'all' );
446
447 /**
448 * This scripts enqueued for Dashboard App.
449 */
450 $this->assets->enqueue( 'betterdocs', 'admin/css/dashboard.css', ['betterdocs-old'] );
451 $this->assets->enqueue( 'betterdocs-icons', 'admin/btd-icon/style.css' );
452 }
453
454 /**
455 * Enqueue Assets for Admin ( Scripts )
456 *
457 * @param string $hook
458 *
459 * @return void
460 * @since 1.0.0
461 */
462 public function scripts( $hook ) {
463 if ( ( $hook === 'edit.php' ) && get_post_type() == 'docs' ) {
464 $this->assets->enqueue( 'betterdocs-switcher', 'admin/js/switcher.js', [
465 'jquery'
466 ] );
467
468 $this->assets->localize( 'betterdocs-switcher', 'betterdocsSwitcher', [
469 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
470 'site_address' => get_bloginfo( 'url' ),
471 'betterdocs_pro_plugin' => betterdocs()->is_pro_active()
472 ] );
473
474 return;
475 }
476
477 if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
478 return;
479 }
480
481 $this->assets->register( 'betterdocs-admin', 'admin/js/dashboard.js' );
482
483 $saved_settings = get_option( 'betterdocs_settings', false );
484 $dark_mode = $saved_settings['dark_mode'] ?? false;
485 $dark_mode = ! empty( $dark_mode ) && boolval( $dark_mode );
486 $this->assets->localize( 'betterdocs-admin', 'betterdocs_admin', [
487 'ajaxurl' => admin_url( 'admin-ajax.php' ),
488 'doc_cat_order_nonce' => wp_create_nonce( 'doc_cat_order_nonce' ),
489 'knowledge_base_order_nonce' => wp_create_nonce( 'knowledge_base_order_nonce' ),
490 'paged' => isset( $_GET['paged'] ) ? absint( wp_unslash( $_GET['paged'] ) ) : 0,
491 'per_page_id' => "edit_doc_category_per_page",
492 'menu_title' => __( 'Switch to BetterDocs UI', 'betterdocs' ),
493 'dark_mode' => $dark_mode,
494 'text' => __( 'Copied!', 'betterdocs' ),
495 'test_report' => __( 'Test Report!', 'betterdocs' ),
496 'sending' => __( 'Sending...', 'betterdocs' ),
497 'dir_url' => BETTERDOCS_ABSURL,
498 'rest_url' => esc_url_raw( rest_url() ),
499 'free_version' => betterdocs()->version,
500 'generate_data_url' => get_rest_url( null, '/betterdocs/v1/create-sample-docs' ),
501 'nonce' => wp_create_nonce( 'wp_rest' ),
502 'admin_url' => admin_url(),
503 'ia_preview' => betterdocs()->settings->get( 'ia_enable_preview', false ),
504 'multiple_kb' => betterdocs()->settings->get( 'multiple_kb' ),
505 'previewMode' => betterdocs()->settings->get( 'ia_enable_preview', false )
506 ] );
507
508 $this->assets->enqueue( 'moment', 'vendor/js/moment.min.js', [] );
509 wp_enqueue_script( 'betterdocs-admin' );
510
511 /**
512 * Duplicate Codes Need to Be Removed From Here Onwards
513 */
514
515 //FAQ Builder Related Localization
516 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/css/faq.css' );
517 betterdocs()->assets->enqueue( 'betterdocs-admin-faq', 'admin/js/faq.js' );
518
519 // removing emoji support
520 remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
521 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
522
523 betterdocs()->assets->localize( 'betterdocs-admin-faq', 'betterdocsFaq', [
524 'dir_url' => BETTERDOCS_ABSURL,
525 'rest_url' => esc_url_raw( rest_url() ),
526 'free_version' => betterdocs()->version,
527 'nonce' => wp_create_nonce( 'wp_rest' ),
528 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
529 ] );
530
531 //Glossaries Related Localization
532 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/css/faq.css' );
533
534 betterdocs()->assets->enqueue( 'betterdocs-admin-glossaries', 'admin/js/glossaries.js' );
535
536 // removing emoji support
537 remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
538 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
539
540 betterdocs()->assets->localize( 'betterdocs-admin-glossaries', 'betterdocsGlossary', [
541 'dir_url' => BETTERDOCS_ABSURL,
542 'rest_url' => esc_url_raw( rest_url() ),
543 'free_version' => betterdocs()->version,
544 'nonce' => wp_create_nonce( 'wp_rest' ),
545 'betterdocs_settings' => get_option( 'betterdocs_settings', false )
546 ] );
547 }
548
549 /**
550 * All admin pages header
551 *
552 * @return void
553 * @since 1.0.0
554 */
555 public function header( $admin_tab_name ) {
556 $quick_links = [
557 'switch_view' => sprintf( '<a href="%s" class="betterdocs-button betterdocs-button-secondary">%s</a>', add_query_arg( [
558 'post_type' => 'docs',
559 'bdocs_view' => 'classic'
560 ], 'edit.php' ), __( 'Switch to Classic UI', 'betterdocs' ) ),
561 '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' ) )
562 ];
563
564 $quick_links = apply_filters( 'betterdocs_quick_links', $quick_links );
565
566 betterdocs()->views->get( 'admin/header', [
567 'quick_links' => $quick_links,
568 'active_tab' => $admin_tab_name
569 ] );
570 }
571
572 /**
573 * Register all the menus for BetterDocs
574 *
575 * @return void
576 * @since 1.0.0
577 */
578
579 public function menus() {
580 $default_args = [
581 'page_title' => 'BetterDocs',
582 'menu_title' => 'BetterDocs',
583 'capability' => 'edit_posts',
584 'menu_slug' => $this->slug,
585 'callback' => [$this, 'output'],
586 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
587 'position' => 5
588 ];
589
590 $_menu_position = 5;
591
592 foreach ( $this->menu_list() as $key => $value ) {
593 if ( $key === 'betterdocs' ) {
594 $callable = 'add_menu_page';
595 $value = wp_parse_args( $value, $default_args );
596 } else {
597 $callable = 'add_submenu_page';
598 $default_args['callback'] = '';
599 $default_args['position'] = $_menu_position;
600 unset( $default_args['icon_url'] );
601 $value = wp_parse_args( $value, array_merge( ['parent_slug' => $this->slug], $default_args ) );
602 }
603
604 $_menu_position++;
605
606 call_user_func_array( $callable, $value );
607 }
608 }
609
610 /**
611 * BetterDocs Admin Page Output
612 *
613 * @return void
614 * @since 1.0.0
615 */
616 public function output() {
617 betterdocs()->views->get( 'admin/main', [
618 'admin_ui' => 'dnd'
619 ] );
620 }
621
622 /**
623 * Menu creator helper
624 *
625 * @param string $title
626 * @param string $slug
627 * @param string $cap
628 * @param array $callback
629 *
630 * @return array
631 * @since 2.5.0
632 *
633 */
634 private function normalize_menu( $title, $slug, $cap = 'edit_docs', $callback = null, $optional = [] ) {
635 return Helper::normalize_menu( $title, $slug, $cap, $callback, $optional );
636 }
637
638 /**
639 * BetterDocs Menu List
640 *
641 * @return array
642 * @since 1.0.0
643 */
644 private function menu_list() {
645 $parent_slug = [];
646
647 $betterdocs_admin_pages = [
648 'betterdocs' => [
649 'menu_slug' => $this->slug,
650 'page_title' => 'BetterDocs',
651 'menu_title' => 'BetterDocs',
652 'capability' => 'edit_docs',
653 'callback' => [$this, 'output'],
654 'icon_url' => betterdocs()->assets->icon( 'betterdocs-icon-white.svg', true ),
655 'position' => 5
656 ],
657 'all_docs' => $this->normalize_menu( __( 'All Docs', 'betterdocs' ), $this->ui_slug() ),
658 'add_new' => $this->normalize_menu( __( 'Add New', 'betterdocs' ), 'post-new.php?post_type=docs' ),
659 'categories' => $this->normalize_menu( __( 'Categories', 'betterdocs' ), 'edit-tags.php?taxonomy=doc_category&post_type=docs', 'manage_doc_terms' ),
660 'tags' => $this->normalize_menu( __( 'Tags', 'betterdocs' ), 'edit-tags.php?taxonomy=doc_tag&post_type=docs', 'manage_doc_terms' ),
661 'settings' => $this->normalize_menu( __( 'Settings', 'betterdocs' ), 'betterdocs-settings', 'edit_docs_settings', [
662 $this,
663 'output'
664 ], $parent_slug ),
665 'analytics' => $this->normalize_menu( __( 'Analytics', 'betterdocs' ), 'betterdocs-analytics', 'read_docs_analytics', [
666 $this,
667 'output'
668 ], $parent_slug ),
669 'faq' => $this->normalize_menu( __( 'FAQ Builder', 'betterdocs' ), 'betterdocs-faq', 'read_docs_analytics', [
670 $this,
671 'output'
672 ], $parent_slug )
673 ];
674
675 if ( betterdocs()->settings->get( 'enable_glossaries' ) == true ) {
676 $betterdocs_admin_pages['glossaries'] = $this->normalize_menu( __( 'Glossaries', 'betterdocs' ), 'betterdocs-glossaries', 'read_docs_analytics', [
677 $this,
678 'output'
679 ], $parent_slug );
680 }
681
682 return apply_filters( 'betterdocs_admin_menu', $betterdocs_admin_pages );
683 }
684
685 public function add_custom_classes_to_menu_items() {
686 global $menu, $submenu;
687
688 $menu_items = [
689 'betterdocs' => 'betterdocs',
690 'betterdocs_page_all_docs' => 'betterdocs-all-docs',
691 'betterdocs_page_add_new' => 'betterdocs-add-new',
692 'edit-tags.php?taxonomy=doc_category&post_type=docs' => 'betterdocs-categories',
693 'edit-tags.php?taxonomy=doc_tag&post_type=docs' => 'betterdocs-tags',
694 'betterdocs-settings' => 'betterdocs-settings',
695 'betterdocs-analytics' => 'betterdocs-analytics',
696 'betterdocs-faq' => 'betterdocs-faq',
697 'betterdocs-glossaries' => 'betterdocs-glossaries',
698 'edit-tags.php?taxonomy=knowledge_base&post_type=docs' => 'betterdocs-multiplekb'
699 ];
700
701 foreach ( $menu as &$item ) {
702 if ( isset( $menu_items[$item[2]] ) ) {
703 if ( ! isset( $item[4] ) ) {
704 $item[4] = '';
705 }
706 $item[4] .= '' . $menu_items[$item[2]];
707 }
708 }
709
710 foreach ( $submenu as &$submenu_items ) {
711 foreach ( $submenu_items as &$sub_item ) {
712 if ( isset( $menu_items[$sub_item[2]] ) ) {
713 if ( ! isset( $sub_item[4] ) ) {
714 $sub_item[4] = '';
715 }
716 $sub_item[4] .= '' . $menu_items[$sub_item[2]];
717 }
718 }
719 }
720 }
721
722 public function quick_setup_menu( $menus ) {
723 $betterdocs_settings = get_option( 'betterdocs_settings' );
724 if ( $betterdocs_settings ) {
725 return $menus;
726 } else {
727 $menus['quick_setup'] = $this->normalize_menu( __( 'Quick Setup', 'betterdocs' ), 'betterdocs-setup', 'delete_users', [
728 $this->container->get( SetupWizard::class ),
729 'views'
730 ] );
731 }
732
733 return $menus;
734 }
735
736 public function insert_plugin_links( $links ) {
737 $links[] = '<a href="admin.php?page=betterdocs-settings">' . __( 'Settings', 'betterdocs' ) . '</a>';
738
739 return $links;
740 }
741
742 public function toolbar_menu( $admin_bar ) {
743 if ( ! is_admin() || ! is_admin_bar_showing() ) {
744 return;
745 }
746
747 // Show only when the user is a member of this site, or they're a super admin.
748 if ( ! is_user_member_of_blog() && ! is_super_admin() ) {
749 return;
750 }
751
752 $docs_url = '';
753 $encyclopedia_url = '';
754
755 if ( $this->settings->get( 'builtin_doc_page' ) ) {
756 $docs_url = get_post_type_archive_link( 'docs' );
757 } elseif ( intval( $docs_page = $this->settings->get( 'docs_page' ) ) ) {
758 $docs_url = ! empty( $docs_page ) ? get_page_link( $docs_page ) : false;
759 }
760
761 if ( ! $docs_url ) {
762 return;
763 }
764
765 $slug = $this->settings->get( 'encyclopedia_root_slug' );
766
767 $encyclopedia_url = home_url( $slug );
768
769 $admin_bar->add_node( [
770 'parent' => 'site-name',
771 'id' => 'view-docs',
772 'title' => __( 'Visit Documentation', 'betterdocs' ),
773 'href' => $docs_url
774 ] );
775
776 $is_enable_encyclopedia = betterdocs()->settings->get( 'enable_encyclopedia' );
777
778 if ( $is_enable_encyclopedia && betterdocs()->is_pro_active() ) {
779 $admin_bar->add_node( [
780 'parent' => 'site-name',
781 'id' => 'view-encyclopedia',
782 'title' => __( 'Visit Encyclopedia', 'betterdocs' ),
783 'href' => $encyclopedia_url
784 ] );
785 }
786 }
787
788 /**
789 * Save last visited admin ui
790 *
791 * @since 3.0.1
792 *
793 */
794 public function save_admin_page() {
795 if ( isset( $_GET['post_type'] ) && $_GET['post_type'] === 'docs' && isset( $_GET['bdocs_view'] ) && $_GET['bdocs_view'] === 'classic' ) {
796 update_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', 'classic_ui' );
797 } elseif ( isset( $_GET['page'] ) && $_GET['page'] === 'betterdocs-admin' ) {
798 update_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', 'modern_ui' );
799 }
800 }
801
802 /**
803 * Return last visited admin ui slug
804 *
805 * @return string
806 * @since 3.0.1
807 */
808 public function ui_slug() {
809 $last_visited = get_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', true );
810 $docs = get_posts( ['post_type' => 'docs', 'post_status' => 'any', 'numberposts' => 2] );
811
812 if ( $last_visited === 'modern_ui' || count( $docs ) == 0 ) {
813 $slug = 'betterdocs-admin';
814 } else {
815 $slug = admin_url( 'edit.php?post_type=docs&bdocs_view=classic' );
816 }
817
818 return $slug;
819 }
820
821 /**
822 * Resets a duplicate submenu in WordPress if the parent main menu and the first submenu permalink are not the same.
823 *
824 * @return string
825 * @since 3.0.1
826 */
827 public function reset_submenu() {
828 global $submenu;
829
830 $docs = get_posts( ['post_type' => 'docs'] );
831 if ( count( $docs ) == 0 ) {
832 return;
833 }
834
835 $last_visited = get_user_meta( get_current_user_id(), 'last_visited_docs_admin_page', true );
836
837 if ( $last_visited === 'classic_ui' && isset( $submenu['betterdocs-admin'] ) && in_array( "betterdocs-admin", $submenu['betterdocs-admin'][0] ) ) {
838 unset( $submenu['betterdocs-admin'][0] );
839 $submenu['betterdocs-admin'] = array_values( $submenu['betterdocs-admin'] );
840 }
841 }
842 }
843