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

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