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

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