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

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