PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.8.9
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.8.9
4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 All 200 releases
← All changes | includes/Core/Settings.php +2391 -3124 4.8.03.8.9 View file →
@@ -1,3250 +1,2517 @@
1 1 <?php
2 +
2 3 namespace WPDeveloper\BetterDocs\Core;
3 4
4 -if ( ! defined( 'ABSPATH' ) ) {
5 - exit;
6 -}
7 -
8 -
9 5 use WP_Error;
10 6 use WP_User;
11 7 use WPDeveloper\BetterDocs\Admin\Builder\GlobalFields;
12 8 use WPDeveloper\BetterDocs\Admin\Builder\Rules;
13 -use WPDeveloper\BetterDocs\AI\ModelRegistry;
14 -use WPDeveloper\BetterDocs\REST\AIEdit;
15 -use WPDeveloper\BetterDocs\Utils\AIHelper;
16 9 use WPDeveloper\BetterDocs\Utils\Base;
17 10 use WPDeveloper\BetterDocs\Utils\Database;
18 -use WPDeveloper\BetterDocs\Utils\Helper;
19 11
12 +
20 13 class Settings extends Base {
21 - public $base_key = 'betterdocs_settings';
14 + public $base_key = 'betterdocs_settings';
22 15
23 - /**
24 - * Database class
25 - * @var Database
26 - */
27 - protected $database;
16 + /**
17 + * Database class
18 + * @var Database
19 + */
20 + protected $database;
28 21
29 - private $deprecated = array();
22 + private $deprecated = [];
30 23
31 - private $cannot_be_empty = array(
32 - 'breadcrumb_doc_title',
33 - 'docs_slug',
34 - 'category_slug',
35 - 'tag_slug',
36 - 'permalink_structure',
37 - 'docs_page'
38 - );
24 + private $cannot_be_empty = [
25 + 'breadcrumb_doc_title',
26 + 'docs_slug',
27 + 'category_slug',
28 + 'tag_slug',
29 + 'permalink_structure',
30 + 'docs_page'
31 + ];
39 32
40 - public function __construct( Database $database ) {
41 - $this->database = $database;
42 - $this->deprecated = $this->deprecated_settings();
33 + public function __construct( Database $database ) {
34 + $this->database = $database;
35 + $this->deprecated = $this->deprecated_settings();
43 36
44 - add_filter( 'betterdocs_settings_tabs', array( $this, 'import_export_settings' ) );
45 - add_filter( 'betterdocs_settings_tabs', array( $this, 'maybe_remove_git_tab' ), 20 );
37 + add_filter( 'betterdocs_settings_tabs', [ $this, 'import_export_settings' ] );
46 38
47 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_old' ), 99 );
48 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 99 );
39 + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_old' ], 99 );
40 + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ], 99 );
49 41
50 - // if ( isset( $_GET['page'] ) && $_GET['page'] === 'betterdocs-settings' && ! has_action( 'betterdocs_settings_header' ) ) {
51 - // add_action( 'betterdocs_settings_header', [ $this, 'header' ] );
52 - // }
42 + // if ( isset( $_GET['page'] ) && $_GET['page'] === 'betterdocs-settings' && ! has_action( 'betterdocs_settings_header' ) ) {
43 + // add_action( 'betterdocs_settings_header', [ $this, 'header' ] );
44 + // }
53 45
54 - add_action( 'wp_ajax_betterdocs_dark_mode', array( $this, 'dark_mode' ) );
55 - add_filter( 'betterdocs_settings_tab_advance', array( $this, 'hide_roles_management' ), 11, 1 );
56 - add_action( 'betterdocs::settings::saved', array( $this, 'fallback_slugs' ), 99, 3 );
57 - add_action( 'admin_init', array( $this, 'maybe_migrate_ai_platform_settings' ) );
58 - }
46 + add_action( 'wp_ajax_betterdocs_dark_mode', [ $this, 'dark_mode' ] );
47 + add_filter( 'betterdocs_settings_tab_advance', [ $this, 'hide_roles_management' ], 11, 1 );
48 + add_action( 'betterdocs::settings::saved', [ $this, 'fallback_slugs' ], 99, 3 );
49 + }
59 50
60 - public function fallback_slugs( $_saved, $_settings, $_old_settings = array() ) {
61 - $_default = $this->get_default();
62 - foreach ( $this->cannot_be_empty as $key ) {
63 - if ( 'docs_page' === $key && ! $_settings[ 'builtin_doc_page' ] && empty( $_settings[ $key ] ) ) {
64 - $this->save( 'builtin_doc_page', true );
65 - continue;
66 - }
51 + public function fallback_slugs( $_saved, $_settings, $_old_settings = [] ) {
52 + $_default = $this->get_default();
53 + foreach ( $this->cannot_be_empty as $key ) {
54 + if ( $key === 'docs_page' && ! $_settings['builtin_doc_page'] && empty( $_settings[ $key ] ) ) {
55 + $this->save( 'builtin_doc_page', true );
56 + continue;
57 + }
67 58
68 - if ( empty( $_settings[ $key ] ) ) {
69 - $this->save( $key, $_default[ $key ] );
70 - }
71 - }
72 - }
59 + if ( empty( $_settings[ $key ] ) ) {
60 + $this->save( $key, $_default[ $key ] );
61 + }
62 + }
63 + }
73 64
74 - /**
75 - * Get the settings URL for admin
76 - * @return string
77 - */
78 - public function url() {
79 - return esc_url( admin_url( 'admin.php?page=betterdocs-settings' ) );
80 - }
65 + /**
66 + * Get the settings URL for admin
67 + * @return string
68 + */
69 + public function url() {
70 + return esc_url( admin_url( 'admin.php?page=betterdocs-settings' ) );
71 + }
81 72
82 - /**
83 - * Settings keys holding secret API keys. These are masked before reaching
84 - * the browser, stripped for non-admins, and never persisted as their mask.
85 - *
86 - * Includes the legacy single-key fields plus the per-platform content-suite
87 - * keys introduced with multi-platform support.
88 - *
89 - * @return array<int,string>
90 - */
91 - public static function sensitive_api_key_fields() {
92 - $fields = array(
93 - 'ai_autowrite_api_key',
94 - 'ai_chatbot_api_key',
95 - );
96 - foreach ( array_keys( ModelRegistry::platforms() ) as $platform ) {
97 - $fields[] = 'ai_api_key_' . $platform;
98 - }
99 - // Add-ons (e.g. the AI Chatbot) register their own per-platform keys here
100 - // so they are masked in the browser and stripped for non-admins.
101 - return apply_filters( 'betterdocs_sensitive_api_key_fields', $fields );
102 - }
73 + /**
74 + * This method is responsible for enqueueing scripts in settings panel
75 + *
76 + * @param string $hook
77 + *
78 + * @return void
79 + * @since 2.5.0
80 + */
81 + public function enqueue( $hook ) {
82 + if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
83 + return;
84 + }
103 85
104 - /**
105 - * One-time copy of pre-multi-platform AI settings onto the new keys so the
106 - * settings UI shows the user's existing OpenAI key and model under the new
107 - * platform-aware fields. Runtime already falls back via ProviderFactory, so
108 - * this only affects what the admin sees. Guarded by an option flag.
109 - *
110 - * Runs on `admin_init`, which fires for every logged-in user who loads
111 - * /wp-admin/ — including a Subscriber. Since this writes settings (and copies
112 - * the legacy OpenAI key onto `ai_api_key_openai`), it is gated on the same
113 - * `edit_docs_settings` capability used everywhere else for settings writes.
114 - * The one-shot flag is deliberately NOT set when the capability check fails,
115 - * otherwise the first low-privilege page load would permanently skip the
116 - * migration for administrators too.
117 - *
118 - * @return void
119 - */
120 - public function maybe_migrate_ai_platform_settings() {
121 - if ( get_option( 'betterdocs_ai_platform_migrated' ) ) {
122 - return;
123 - }
86 + wp_enqueue_media();
87 + wp_enqueue_script( 'betterdocs-admin' );
88 + betterdocs()->assets->localize( 'betterdocs-admin', 'betterdocsAdminSettings', GlobalFields::normalize( $this->settings_args() ) );
89 + betterdocs()->assets->enqueue( 'betterdocs-icons', 'admin/btd-icon/style.css' );
124 90
125 - if ( ! current_user_can( 'edit_docs_settings' ) ) {
126 - return;
127 - }
91 + // betterdocs()->assets->enqueue( 'betterdocs-settings', 'admin/css/settings.css' );
92 + // betterdocs()->assets->enqueue( 'betterdocs-settings', 'admin/js/settings.js' );
93 + }
128 94
129 - if ( '' === (string) $this->get_raw_field( 'ai_platform', '' ) ) {
130 - $this->save( 'ai_platform', 'openai' );
131 - }
95 + public function enqueue_old( $hook ) {
96 + // FREE & Pro Version Compatibility Check
97 + if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
98 + return;
99 + }
132 100
133 - $legacy_key = (string) $this->get( 'ai_autowrite_api_key', '' );
134 - if ( '' !== $legacy_key && '' === (string) $this->get_raw_field( 'ai_api_key_openai', '' ) ) {
135 - $this->save( 'ai_api_key_openai', $legacy_key );
136 - }
101 + $this->enqueue( 'betterdocs_page_betterdocs-settings' );
102 + }
137 103
138 - if ( '' === (string) $this->get_raw_field( 'ai_model', '' ) ) {
139 - $legacy_model = (string) $this->get( 'write_with_ai_model', '' );
140 - if ( '' === $legacy_model ) {
141 - $legacy_model = (string) $this->get( 'article_summary_model', 'gpt-4o-mini' );
142 - }
143 - $this->save( 'ai_model', $legacy_model !== '' ? $legacy_model : 'gpt-4o-mini' );
144 - }
104 + /**
105 + * This method is responsible for printing header in dashboard settings page.
106 + *
107 + * @param string $hook
108 + *
109 + * @return void
110 + * @since 2.5.0
111 + */
112 + public function header( $hook ) {
113 + if ( $hook !== 'settings' ) {
114 + return;
115 + }
145 116
146 - update_option( 'betterdocs_ai_platform_migrated', 1 );
147 - }
117 + betterdocs()->views->get( 'admin/template-parts/settings-header' );
118 + betterdocs()->views->get( 'admin/template-parts/settings-header-2' );
119 + }
148 120
149 - /**
150 - * This method is responsible for enqueueing scripts in settings panel
151 - *
152 - * @param string $hook
153 - *
154 - * @return void
155 - * @since 2.5.0
156 - */
157 - public function enqueue( $hook ) {
158 - if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
159 - return;
160 - }
121 + /**
122 + * A list of deprecated settings keys.
123 + *
124 + * @return array
125 + * @since 2.5.0
126 + */
127 + public function deprecated_settings() {
128 + return [];
129 + }
161 130
162 - wp_enqueue_media();
163 - wp_enqueue_script( 'betterdocs-admin' );
131 + /**
132 + * Dynamic migration caller.
133 + *
134 + * @return void
135 + * @since 2.5.0
136 + */
137 + public function migration( $version ) {
138 + if ( $version > 250 ) {
139 + for ( $v = 250; $v <= $version; $v ++ ) {
140 + $_func = "v{$v}";
141 + if ( method_exists( $this, $_func ) ) {
142 + call_user_func( [ $this, $_func ] );
143 + }
144 + }
145 + }
146 + }
164 147
165 - $settings = GlobalFields::normalize( $this->settings_args() );
148 + /**
149 + * Migration for version 2.5.0
150 + *
151 + * @return void
152 + * @since 2.5.0
153 + */
154 + public function v250() {
155 + if ( $this->get( 'alphabetically_order_term', false ) ) {
156 + $this->save( 'terms_orderby', 'name' );
157 + }
166 158
167 - // Mask sensitive API keys before they reach the browser. Non-admins still get them stripped entirely below.
168 - $sensitive_api_keys = self::sensitive_api_key_fields();
169 - foreach ( $sensitive_api_keys as $api_key_field ) {
170 - if ( ! empty( $settings[ 'values' ][ $api_key_field ] ) ) {
171 - $settings[ 'values' ][ $api_key_field ] = Helper::mask_api_key( $settings[ 'values' ][ $api_key_field ] );
172 - }
173 - }
159 + if ( $orderby = $this->get( 'alphabetically_order_post', false ) ) {
160 + if ( $orderby === '1' ) {
161 + $this->save( 'alphabetically_order_post', 'title' );
162 + }
163 + }
164 + }
174 165
175 - if ( ! current_user_can( 'edit_docs_settings' ) ) {
176 - foreach ( $sensitive_api_keys as $api_key_field ) {
177 - if ( isset( $settings[ 'values' ][ $api_key_field ] ) ) {
178 - unset( $settings[ 'values' ][ $api_key_field ] );
179 - }
180 - }
181 - }
166 + /**
167 + * A list of default settings data.
168 + *
169 + * @return array
170 + * @since 1.0.0
171 + *
172 + */
173 + public function get_default() {
174 + $_default = [
175 + 'multiple_kb' => '',
176 + 'enable_export_faq' => true,
177 + 'builtin_doc_page' => true,
178 + 'breadcrumb_doc_title' => __( 'Docs', 'betterdocs' ),
179 + 'docs_slug' => 'docs',
180 + 'docs_page' => 0,
181 + 'category_slug' => 'docs-category',
182 + 'tag_slug' => 'docs-tag',
183 + 'permalink_structure' => 'docs/',
184 + 'enable_faq_schema' => false,
185 + 'live_search' => true,
186 + 'advance_search' => false,
187 + 'popular_keyword_limit' => 5,
188 + 'search_letter_limit' => 3,
189 + 'search_placeholder' => __( 'Search...', 'betterdocs' ),
190 + 'search_not_found_text' => __( 'Sorry, no docs were found.', 'betterdocs' ),
191 + 'search_result_image' => true,
192 + 'masonry_layout' => true,
193 + 'docs_list_icon' => [],
194 + 'category_title_link' => false,
195 + 'terms_orderby' => 'betterdocs_order',
196 + 'alphabetically_order_term' => false,
197 + 'terms_order' => 'ASC',
198 + 'alphabetically_order_post' => 'betterdocs_order',
199 + 'docs_order' => 'ASC',
200 + 'nested_subcategory' => false,
201 + 'column_number' => 3,
202 + 'posts_number' => 10,
203 + 'post_count' => true,
204 + 'count_text' => __( 'Docs', 'betterdocs' ),
205 + 'count_text_singular' => __( 'Doc', 'betterdocs' ),
206 + 'exploremore_btn' => true,
207 + 'exploremore_btn_txt' => __( 'Explore More', 'betterdocs' ),
208 + 'doc_single' => 1,
209 + 'enable_toc' => true,
210 + 'toc_title' => __( 'Table of Contents', 'betterdocs' ),
211 + 'toc_hierarchy' => true,
212 + 'toc_list_number' => false,
213 + 'toc_dynamic_title' => false,
214 + 'enable_sticky_toc' => true,
215 + 'sticky_toc_offset' => 100,
216 + 'collapsible_toc_mobile' => false,
217 + 'supported_heading_tag' => [ '1', '2', '3', '4', '5', '6' ],
218 + 'enable_post_title' => true,
219 + 'title_link_ctc' => true,
220 + 'enable_breadcrumb' => true,
221 + 'breadcrumb_home_text' => __( 'Home', 'betterdocs' ),
222 + 'enable_breadcrumb_home_text' => true,
223 + 'breadcrumb_home_url' => get_home_url(),
224 + 'enable_breadcrumb_category' => true,
225 + 'enable_breadcrumb_title' => true,
226 + 'enable_sidebar_cat_list' => true,
227 + 'enable_print_icon' => true,
228 + 'enable_tags' => true,
229 + 'email_feedback' => true,
230 + 'feedback_link_text' => __( 'Still stuck? How can we help?', 'betterdocs' ),
231 + 'reaction_feedback_text' => __( 'Thanks for your feedback', 'betterdocs' ),
232 + 'feedback_url' => '',
233 + 'feedback_form_title' => __( 'How can we help?', 'betterdocs' ),
234 + 'email_address' => get_option( 'admin_email' ),
235 + 'show_last_update_time' => true,
236 + 'enable_navigation' => true,
237 + 'enable_comment' => true,
238 + 'enable_credit' => false,
239 + 'enable_archive_sidebar' => true,
240 + 'archive_nested_subcategory' => true,
241 + 'archive_enable_pagination' => false,
242 + 'enable_content_restriction' => false,
243 + 'enable_reporting' => false,
244 + 'enable_sample_data' => false,
245 + 'reporting_day' => 'monday',
246 + 'reporting_email' => get_option( 'admin_email' ),
247 + 'enable_write_with_ai' => true,
248 + 'enable_faq_write_with_ai' => true,
249 + 'ai_autowrite_api_key' => '',
250 + 'ai_autowrite_max_token' => 1500,
251 + 'enable_estimated_reading_time' => true,
252 + 'enable_encyclopedia' => false,
253 + 'enable_glossaries' => false,
254 + 'show_glossary_suggestions' => true,
255 + 'enable_ai_chatbot' => false,
256 + 'estimated_reading_time_title' => '',
257 + 'estimated_reading_time_text' => __( 'min read', 'betterdocs' ),
258 + 'singular_estimated_reading_time_text' => __( 'min read', 'betterdocs' )
259 + ];
182 260
183 - // Inject raw git settings to bypass get() fallback (e.g., '' -> 'docs')
184 - if ( isset( $settings[ 'values' ] ) ) {
185 - $settings[ 'values' ][ 'git_provider' ] = $this->get_raw_field( 'git_provider', 'github' );
186 - $settings[ 'values' ][ 'git_repository_url' ] = $this->get_raw_field( 'git_repository_url', '' );
187 - $settings[ 'values' ][ 'git_branch' ] = $this->get_raw_field( 'git_branch', '' );
188 - $settings[ 'values' ][ 'git_docs_directory' ] = $this->get_raw_field( 'git_docs_directory', '' );
189 - }
261 + $_default = apply_filters( 'betterdocs_default_settings', $_default );
262 + // $_default = apply_filters_deprecated(
263 + // 'betterdocs_option_default_settings', [$_default], '2.5.0',
264 + // 'betterdocs_default_settings', 'betterdocs_option_default_settings will be removed from v3.5.0.'
265 + // );
190 266
191 - betterdocs()->assets->localize( 'betterdocs-admin', 'betterdocsAdminSettings', $settings );
192 - betterdocs()->assets->enqueue( 'betterdocs-icons', 'admin/btd-icon/style.css' );
193 - }
267 + return $_default;
268 + }
194 269
195 - public function enqueue_old( $hook ) {
196 - // FREE & Pro Version Compatibility Check
197 - if ( ! betterdocs()->is_betterdocs_screen( $hook ) ) {
198 - return;
199 - }
270 + /**
271 + * A list of default settings for pro plugins.
272 + *
273 + * @return array
274 + * @since 2.5.0
275 + */
276 + public function get_pro_defaults() {
277 + return [];
278 + }
200 279
201 - $this->enqueue( 'betterdocs_page_betterdocs-settings' );
202 - }
280 + public function is_elementor_pro() {
281 + return is_plugin_active( 'elementor-pro/elementor-pro.php' );
282 + }
203 283
204 - /**
205 - * This method is responsible for printing header in dashboard settings page.
206 - *
207 - * @param string $hook
208 - *
209 - * @return void
210 - * @since 2.5.0
211 - */
212 - public function header( $hook ) {
213 - if ( 'settings' !== $hook ) {
214 - return;
215 - }
284 + /**
285 + * Get full site editor links for docs page.
286 + *
287 + * @return string
288 + * @since 3.5.8
289 + */
290 + public function gutenberg_link() {
291 + if ( betterdocs()->helper->current_theme_is_fse_theme() ) {
292 + return admin_url( 'site-editor.php?postType=wp_template&postId=betterdocs/betterdocs//archive-docs' );
293 + } else {
294 + return 'https://betterdocs.co/docs/betterdocs-provides-full-site-editor-support/';
295 + }
296 + }
216 297
217 - betterdocs()->views->get( 'admin/template-parts/settings-header' );
218 - betterdocs()->views->get( 'admin/template-parts/settings-header-2' );
219 - }
298 + /**
299 + * Get elementor theme builder link for docs page.
300 + *
301 + * @return string
302 + * @since 3.5.8
303 + */
304 + public function elementor_link() {
305 + if ( $this->is_elementor_pro() ) {
306 + return admin_url( 'admin.php?page=elementor-app#/site-editor/templates/doc-archive' );
307 + } else {
308 + return 'https://betterdocs.co/docs/docs-page-with-elementor/';
309 + }
310 + }
220 311
221 - /**
222 - * A list of deprecated settings keys.
223 - *
224 - * @return array
225 - * @since 2.5.0
226 - */
227 - public function deprecated_settings() {
228 - return array();
229 - }
312 + public function customizer_link() {
313 + $query['autofocus[panel]'] = 'betterdocs_customize_options';
314 + $query['return'] = admin_url( 'edit.php?post_type=docs' );
315 + $builtin_doc_page = betterdocs()->settings->get( 'builtin_doc_page' );
316 + $docs_slug = betterdocs()->settings->get( 'docs_slug' );
317 + $docs_page = betterdocs()->settings->get( 'builtin_doc_page' );
230 318
231 - /**
232 - * Dynamic migration caller.
233 - *
234 - * @return void
235 - * @since 2.5.0
236 - */
237 - public function migration( $version ) {
238 - if ( $version > 250 ) {
239 - for ( $v = 250; $v <= $version; ++$v ) {
240 - $_func = "v{$v}";
241 - if ( method_exists( $this, $_func ) ) {
242 - call_user_func( array( $this, $_func ) );
243 - }
244 - }
245 - }
246 - }
319 + if ( $builtin_doc_page == 1 && $docs_slug ) {
320 + $query['url'] = site_url( '/' . $docs_slug );
321 + } elseif ( $builtin_doc_page != 1 && $docs_page ) {
322 + $post_info = get_post( $docs_page );
323 + $query['url'] = site_url( '/' . $post_info->post_name );
324 + }
247 325
248 - /**
249 - * Migration for version 2.5.0
250 - *
251 - * @return void
252 - * @since 2.5.0
253 - */
254 - public function v250() {
255 - if ( $this->get( 'alphabetically_order_term', false ) ) {
256 - $this->save( 'terms_orderby', 'name' );
257 - }
326 + return add_query_arg( $query, admin_url( 'customize.php' ) );
327 + }
258 328
259 - if ( $orderby = $this->get( 'alphabetically_order_post', false ) ) {
260 - if ( '1' === $orderby ) {
261 - $this->save( 'alphabetically_order_post', 'title' );
262 - }
263 - }
264 - }
329 + public function design_tab() {
330 + $settings = [];
265 331
266 - /**
267 - * A list of default settings data.
268 - *
269 - * @return array
270 - * @since 1.0.0
271 - *
272 - */
273 - public function get_default() {
274 - $_default = array(
275 - 'multiple_kb' => '',
276 - 'enable_ai_sample_docs' => true,
277 - 'enable_export_faq' => true,
278 - 'builtin_doc_page' => true,
279 - 'breadcrumb_doc_title' => __( 'Docs', 'betterdocs' ),
280 - 'enable_category_hierarchy_slugs' => false,
281 - 'docs_slug' => 'docs',
282 - 'docs_page' => 0,
283 - 'category_slug' => 'docs-category',
284 - 'tag_slug' => 'docs-tag',
285 - 'permalink_structure' => 'docs/',
286 - 'enable_faq_schema' => false,
287 - 'live_search' => true,
288 - 'advance_search' => false,
289 - 'popular_keyword_limit' => 5,
290 - 'search_letter_limit' => 3,
291 - 'search_placeholder' => __( 'Search...', 'betterdocs' ),
292 - 'search_not_found_text' => __( 'Sorry, no docs were found.', 'betterdocs' ),
293 - 'search_result_image' => true,
294 - 'search_modal_search_type' => 'all',
295 - 'masonry_layout' => true,
296 - 'docs_list_icon' => array(),
297 - 'category_title_link' => false,
298 - 'terms_orderby' => 'betterdocs_order',
299 - 'alphabetically_order_term' => false,
300 - 'terms_order' => 'ASC',
301 - 'alphabetically_order_post' => 'betterdocs_order',
302 - 'docs_order' => 'ASC',
303 - 'nested_subcategory' => false,
304 - 'column_number' => 3,
305 - 'posts_number' => 10,
306 - 'post_count' => true,
307 - 'count_text' => __( 'Docs', 'betterdocs' ),
308 - 'count_text_singular' => __( 'Doc', 'betterdocs' ),
309 - 'exploremore_btn' => true,
310 - 'exploremore_btn_txt' => __( 'Explore More', 'betterdocs' ),
311 - 'doc_single' => 1,
312 - 'enable_toc' => true,
313 - 'toc_title' => __( 'Table of Contents', 'betterdocs' ),
314 - 'toc_hierarchy' => true,
315 - 'toc_list_number' => false,
316 - 'toc_dynamic_title' => false,
317 - 'enable_sticky_toc' => true,
318 - 'sticky_toc_offset' => 100,
319 - 'collapsible_toc_mobile' => false,
320 - 'supported_heading_tag' => array( '1', '2', '3', '4', '5', '6' ),
321 - 'enable_post_title' => true,
322 - 'title_link_ctc' => true,
323 - 'enable_breadcrumb' => true,
324 - 'breadcrumb_home_text' => __( 'Home', 'betterdocs' ),
325 - 'enable_breadcrumb_home_text' => true,
326 - 'breadcrumb_home_url' => get_home_url(),
327 - 'enable_breadcrumb_category' => true,
328 - 'enable_breadcrumb_title' => true,
329 - 'enable_sidebar_cat_list' => true,
330 - 'enable_print_icon' => true,
331 - 'enable_tags' => true,
332 - 'email_feedback' => true,
333 - 'feedback_link_text' => __( 'Still stuck? How can we help?', 'betterdocs' ),
334 - 'reaction_feedback_text' => __( 'Thanks for your feedback', 'betterdocs' ),
335 - 'feedback_url' => '',
336 - 'feedback_form_title' => __( 'How can we help?', 'betterdocs' ),
337 - 'email_address' => get_option( 'admin_email' ),
338 - 'show_last_update_time' => true,
339 - 'enable_navigation' => true,
340 - 'enable_comment' => true,
341 - 'enable_credit' => false,
342 - 'enable_archive_sidebar' => true,
343 - 'archive_nested_subcategory' => true,
344 - 'archive_enable_pagination' => false,
345 - 'archive_lazy_load_descendants' => false,
346 - 'enable_content_restriction' => false,
347 - 'enable_reporting' => false,
348 - 'enable_sample_data' => false,
349 - 'reporting_day' => 'monday',
350 - 'reporting_email' => get_option( 'admin_email' ),
351 - 'enable_write_with_ai' => true,
352 - 'enable_faq_write_with_ai' => true,
353 - 'enable_glossaries_write_with_ai' => true,
354 - 'enable_docs_ai_suite' => true,
355 - 'write_with_ai_model' => 'gpt-4o-mini',
356 - 'ai_autowrite_api_key' => '',
357 - 'ai_autowrite_max_token' => 2500,
358 - 'write_with_ai_instructions' => array(
359 - array(
360 - 'id' => 'default',
361 - 'title' => __( 'Default/Core', 'betterdocs' ),
362 - 'content' => WriteWithAI::default_instruction_content()
363 - )
364 - ),
365 - 'ai_edit_actions' => AIEdit::default_actions(),
366 - 'enable_article_summary' => false,
367 - 'article_summary_model' => 'gpt-4o-mini',
368 - 'article_summary_max_token' => 1500,
369 - // Multi-platform AI (content suite). `ai_platform` selects the active
370 - // provider; `ai_model` is the single global model; keys are stored
371 - // per platform so switching never loses a saved key. Legacy keys
372 - // above are kept for back-compat and migrated on upgrade.
373 - 'ai_platform' => 'openai',
374 - 'ai_model' => 'gpt-4o-mini',
375 - 'ai_api_key_openai' => '',
376 - 'ai_api_key_gemini' => '',
377 - 'ai_api_key_claude' => '',
378 - 'ai_api_key_deepseek' => '',
379 - 'ai_api_key_openrouter' => '',
380 - 'enable_estimated_reading_time' => true,
381 - 'enable_encyclopedia' => false,
382 - 'enable_glossaries' => false,
383 - 'show_glossary_suggestions' => true,
384 - 'enable_ai_chatbot' => false,
385 - 'estimated_reading_time_title' => '',
386 - 'estimated_reading_time_text' => __( 'min read', 'betterdocs' ),
387 - 'singular_estimated_reading_time_text' => __( 'min read', 'betterdocs' ),
388 - 'betterdocs_access_control_repeater' => array(),
389 - 'internal_knowledge_base_type' => 'basic',
390 - 'betterdocs_access_control_repeater_kb' => array(),
391 - 'enable_git_integration' => false
392 - );
332 + $settings['gutenberg_link'] = [
333 + 'name' => 'gutenberg_link',
334 + 'type' => 'action',
335 + 'action' => 'betterdocs_settings_gutenberg_link',
336 + 'button' => betterdocs()->helper->current_theme_is_fse_theme() ? __( 'Design with Gutenberg', 'betterdocs' ) : __( 'Learn More', 'betterdocs' ),
337 + 'url' => $this->gutenberg_link(),
338 + 'customizer_img' => betterdocs()->assets->icon( 'customizer/gutenberg-preview.png', true ),
339 + 'priority' => 1
340 + ];
393 341
394 - $_default = apply_filters( 'betterdocs_default_settings', $_default );
395 - // $_default = apply_filters_deprecated(
396 - // 'betterdocs_option_default_settings', [$_default], '2.5.0',
397 - // 'betterdocs_default_settings', 'betterdocs_option_default_settings will be removed from v3.5.0.'
398 - // );
342 + $settings['elementor_link'] = [
343 + 'name' => 'elementor_link',
344 + 'type' => 'action',
345 + 'action' => 'betterdocs_settings_elementor_link',
346 + 'button' => $this->is_elementor_pro() ? __( 'Design with Elementor', 'betterdocs' ) : __( 'Learn More', 'betterdocs' ),
347 + 'url' => $this->elementor_link(),
348 + 'customizer_img' => betterdocs()->assets->icon( 'customizer/elementor-preview.png', true ),
349 + 'priority' => 2
350 + ];
399 351
400 - return $_default;
401 - }
352 + if ( ! betterdocs()->helper->current_theme_is_fse_theme() ) {
353 + $settings['customizer_link'] = [
354 + 'name' => 'customizer_link',
355 + 'type' => 'action',
356 + 'action' => 'betterdocs_settings_customizer_link',
357 + 'button' => __( 'Customize in BetterDocs', 'betterdocs' ),
358 + 'url' => $this->customizer_link(),
359 + 'customizer_img' => betterdocs()->assets->icon( 'customizer/customizer-preview.png', true ),
360 + 'priority' => 3
361 + ];
362 + }
402 363
403 - /**
404 - * A list of default settings for pro plugins.
405 - *
406 - * @return array
407 - * @since 2.5.0
408 - */
409 - public function get_pro_defaults() {
410 - return array();
411 - }
364 + return $settings;
365 + }
412 366
413 - public function is_elementor_pro() {
414 - return is_plugin_active( 'elementor-pro/elementor-pro.php' );
415 - }
367 + /**
368 + * Get All Roles
369 + * dynamically
370 + *
371 + * @return array
372 + */
373 + public function get_roles() {
374 + $roles = wp_roles()->role_names;
375 + unset( $roles['subscriber'] );
416 376
417 - /**
418 - * Get full site editor links for docs page.
419 - *
420 - * @return string
421 - * @since 3.5.8
422 - */
423 - public function gutenberg_link() {
424 - if ( betterdocs()->helper->current_theme_is_fse_theme() ) {
425 - return admin_url( 'site-editor.php?postType=wp_template&postId=betterdocs/betterdocs//archive-docs' );
426 - } else {
427 - return 'https://betterdocs.co/docs/betterdocs-provides-full-site-editor-support/';
428 - }
429 - }
377 + return $roles;
378 + }
430 379
431 - /**
432 - * Get elementor theme builder link for docs page.
433 - *
434 - * @return string
435 - * @since 3.5.8
436 - */
437 - public function elementor_link() {
438 - if ( $this->is_elementor_pro() ) {
439 - return admin_url( 'admin.php?page=elementor-app#/site-editor/templates/doc-archive' );
440 - } else {
441 - return 'https://betterdocs.co/docs/docs-page-with-elementor/';
442 - }
443 - }
380 + /**
381 + * Set dark mode
382 + *
383 + * @return void
384 + * @since 1.0.0
385 + */
386 + public function dark_mode() {
387 + if ( ! check_ajax_referer( 'doc_cat_order_nonce', 'nonce', false ) ) {
388 + wp_send_json_error();
389 + }
444 390
445 - public function customizer_link() {
446 - $query[ 'autofocus[panel]' ] = 'betterdocs_customize_options';
447 - $query[ 'return' ] = admin_url( 'edit.php?post_type=docs' );
448 - $builtin_doc_page = betterdocs()->settings->get( 'builtin_doc_page' );
449 - $docs_slug = betterdocs()->settings->get( 'docs_slug' );
450 - $docs_page = betterdocs()->settings->get( 'builtin_doc_page' );
391 + if ( isset( $_POST['mode'] ) ) {
392 + if ( $this->save( 'dark_mode', rest_sanitize_boolean( $_POST['mode'] ) ) ) { // phpcs:ignore
393 + wp_send_json_success();
394 + }
395 + }
451 396
452 - if ( 1 == $builtin_doc_page && $docs_slug ) {
453 - $query[ 'url' ] = site_url( '/' . $docs_slug );
454 - } elseif ( 1 != $builtin_doc_page && $docs_page ) {
455 - $post_info = get_post( $docs_page );
456 - $query[ 'url' ] = site_url( '/' . $post_info->post_name );
457 - }
397 + wp_send_json_error();
398 + }
458 399
459 - return add_query_arg( $query, admin_url( 'customize.php' ) );
460 - }
400 + public function get_normalized_value( $key, $value, $default = null ) {
401 + $_origin_value = $_value = $value;
461 402
462 - public function design_tab() {
463 - $settings = array();
403 + if ( in_array( $_value, [ 'on', 'off', '1', 'false', 'true' ], true ) ) {
404 + switch ( $_value ) {
405 + case 'on':
406 + case 'ON':
407 + case '1':
408 + case 'true':
409 + $_value = true;
410 + break;
411 + case 'off':
412 + case 'OFF':
413 + case '':
414 + case 'false':
415 + $_value = false;
416 + break;
417 + }
418 + }
464 419
465 - $settings[ 'gutenberg_link' ] = array(
466 - 'name' => 'gutenberg_link',
467 - 'type' => 'action',
468 - 'action' => 'betterdocs_settings_gutenberg_link',
469 - 'button' => betterdocs()->helper->current_theme_is_fse_theme() ? __( 'Design with Gutenberg', 'betterdocs' ) : __( 'Learn More', 'betterdocs' ),
470 - 'url' => $this->gutenberg_link(),
471 - 'customizer_img' => betterdocs()->assets->icon( 'customizer/gutenberg-preview.png', true ),
472 - 'priority' => 1
473 - );
420 + $this->type_validation( $_value, $default );
474 421
475 - $settings[ 'elementor_link' ] = array(
476 - 'name' => 'elementor_link',
477 - 'type' => 'action',
478 - 'action' => 'betterdocs_settings_elementor_link',
479 - 'button' => $this->is_elementor_pro() ? __( 'Design with Elementor', 'betterdocs' ) : __( 'Learn More', 'betterdocs' ),
480 - 'url' => $this->elementor_link(),
481 - 'customizer_img' => betterdocs()->assets->icon( 'customizer/elementor-preview.png', true ),
482 - 'priority' => 2
483 - );
422 + return $_value;
423 + }
484 424
485 - if ( ! betterdocs()->helper->current_theme_is_fse_theme() ) {
486 - $settings[ 'customizer_link' ] = array(
487 - 'name' => 'customizer_link',
488 - 'type' => 'action',
489 - 'action' => 'betterdocs_settings_customizer_link',
490 - 'button' => __( 'Customize in BetterDocs', 'betterdocs' ),
491 - 'url' => $this->customizer_link(),
492 - 'customizer_img' => betterdocs()->assets->icon( 'customizer/customizer-preview.png', true ),
493 - 'priority' => 3
494 - );
495 - }
425 + public function get_normalized_values( $values, $default_values = [] ) {
426 + if ( empty( $values ) ) {
427 + return [];
428 + }
496 429
497 - return $settings;
498 - }
430 + $_settings = [];
431 + foreach ( $values as $key => $value ) {
432 + $_default_value = isset( $default_values[ $key ] ) ? $default_values[ $key ] : null;
433 + $_settings[ $key ] = $this->get_normalized_value( $key, $value, $_default_value );
434 + }
499 435
500 - /**
501 - * Get All Roles
502 - * dynamically
503 - *
504 - * @return array
505 - */
506 - public function get_roles() {
507 - $roles = wp_roles()->role_names;
508 - unset( $roles[ 'subscriber' ] );
436 + return $_settings;
437 + }
509 438
510 - return $roles;
511 - }
439 + public function get_all( $raw = false ) {
440 + $_default_settings = $raw ? [] : array_merge( $this->get_default(), $this->get_pro_defaults() );
441 + $_settings = $this->database->get( $this->base_key, $_default_settings );
512 442
513 - /**
514 - * Set dark mode
515 - *
516 - * @return void
517 - * @since 1.0.0
518 - */
519 - public function dark_mode() {
520 - if ( ! check_ajax_referer( 'doc_cat_order_nonce', 'nonce', false ) ) {
521 - wp_send_json_error();
522 - }
443 + return $this->get_normalized_values( $_settings, $_default_settings );
444 + }
523 445
524 - if ( isset( $_POST[ 'mode' ] ) ) {
525 - $mode = sanitize_text_field( wp_unslash( $_POST[ 'mode' ] ) );
526 - if ( $this->save( 'dark_mode', rest_sanitize_boolean( $mode ) ) ) {
527 - wp_send_json_success();
528 - }
529 - }
446 + public function type_validation( &$value, $defaultValue = null ) {
447 + if ( $defaultValue !== null ) {
448 + /**
449 + * Check if value is not in same type
450 + */
451 + $_default_type = gettype( $defaultValue );
530 452
531 - wp_send_json_error();
532 - }
453 + if ( ! ( is_scalar( $defaultValue ) && is_scalar( $value ) ) && empty( $value ) ) {
454 + $value = $defaultValue;
455 + }
533 456
534 - public function get_normalized_value( $key, $value, $default = null ) {
535 - $_origin_value = $_value = $value;
457 + settype( $value, $_default_type );
458 + }
459 + }
536 460
537 - if ( in_array( $_value, array( 'on', 'off', '1', 'false', 'true' ), true ) ) {
538 - switch ( $_value ) {
539 - case 'on':
540 - case 'ON':
541 - case '1':
542 - case 'true':
543 - $_value = true;
544 - break;
545 - case 'off':
546 - case 'OFF':
547 - case '':
548 - case 'false':
549 - $_value = false;
550 - break;
551 - }
552 - }
461 + /**
462 + * Get settings value by key
463 + *
464 + * @param string $key
465 + * @param mixed $default
466 + * @param bool $get_all
467 + *
468 + * @return mixed
469 + * @since 2.5.0
470 + *
471 + */
472 + public function get( $key, $default = null ) {
473 + $_default_settings = array_merge( $this->get_default(), $this->get_pro_defaults() );
474 + $_settings = $this->database->get( $this->base_key, $_default_settings );
553 475
554 - $this->type_validation( $_value, $default );
476 + $_value = $default;
477 + switch ( true ) {
478 + // Check if it's a PRO Option
479 + case ! isset( $_default_settings[ $key ] ):
480 + $_value = $default;
481 + break;
482 + // Check if it's a FREE Option and not in DB.
483 + case ! isset( $_settings[ $key ] ) && isset( $_default_settings[ $key ] ):
484 + $_value = $default !== null ? $default : $_default_settings[ $key ];
485 + break;
486 + // Check if it's a FREE Option
487 + case isset( $_settings[ $key ] ) && isset( $_default_settings[ $key ] ):
488 + $_value = $_settings[ $key ];
489 + break;
490 + }
555 491
556 - return $_value;
557 - }
492 + $_value = $this->get_normalized_value( $key, $_value, isset( $_default_settings[ $key ] ) ? $_default_settings[ $key ] : null );
558 493
559 - public function get_normalized_values( $values, $default_values = array() ) {
560 - if ( empty( $values ) ) {
561 - return array();
562 - }
494 + if ( gettype( $_value ) === 'string' ) {
495 + if ( empty( $_value ) && $default != null ) {
496 + $_value = $default;
497 + } elseif ( empty( $_value ) && $default === null && isset( $_default_settings[ $key ] ) ) {
498 + $_value = $_default_settings[ $key ];
499 + }
500 + }
563 501
564 - $_settings = array();
565 - foreach ( $values as $key => $value ) {
566 - $_default_value = isset( $default_values[ $key ] ) ? $default_values[ $key ] : null;
567 - $_settings[ $key ] = $this->get_normalized_value( $key, $value, $_default_value );
568 - }
502 + return $_value;
503 + }
569 504
570 - return $_settings;
571 - }
505 + public function get_raw_field( $key, $default = null ) {
506 + $_settings = $this->database->get( $this->base_key, [] );
572 507
573 - public function get_all( $raw = false ) {
574 - $_default_settings = $raw ? array() : array_merge( $this->get_default(), $this->get_pro_defaults() );
575 - $_settings = $this->database->get( $this->base_key, $_default_settings );
508 + if ( isset( $_settings[ $key ] ) ) {
509 + return $this->get_normalized_value( $key, $_settings[ $key ], $default );
510 + }
576 511
577 - return $this->get_normalized_values( $_settings, $_default_settings );
578 - }
512 + return $default;
513 + }
579 514
580 - public function type_validation( &$value, $defaultValue = null ) {
581 - if ( null !== $defaultValue ) {
582 - /**
583 - * Check if value is not in same type
584 - */
585 - $_default_type = gettype( $defaultValue );
515 + public function save( $key, $value ) {
516 + $_settings = $this->database->get( $this->base_key, [] );
517 + $_settings[ $key ] = $value;
586 518
587 - if ( ! ( is_scalar( $defaultValue ) && is_scalar( $value ) ) && empty( $value ) ) {
588 - $value = $defaultValue;
589 - }
519 + return $this->database->save( $this->base_key, $_settings );
520 + }
590 521
591 - settype( $value, $_default_type );
592 - }
593 - }
522 + public function save_settings( $settings ) {
523 + $existing_plugins = betterdocs()->kbmigration->knowledge_base_plugins();
524 + if ( ! current_user_can( 'edit_docs_settings' ) ) {
525 + return new WP_Error( 'unauthorized_action', __( 'You don\'t have any rights for saving settings.', 'betterdocs' ) );
526 + }
594 527
595 - /**
596 - * Get settings value by key
597 - *
598 - * @param string $key
599 - * @param mixed $default
600 - * @param bool $get_all
601 - *
602 - * @return mixed
603 - * @since 2.5.0
604 - *
605 - */
606 - public function get( $key, $default = null ) {
607 - $_default_settings = array_merge( $this->get_default(), $this->get_pro_defaults() );
608 - $_settings = $this->database->get( $this->base_key, $_default_settings );
528 + $_old_settings = $this->database->get( $this->base_key, $this->get_default() );
529 + // @todo: sanitize the data before inject in DB.
530 + $_normalized_settings = $this->get_normalized_values( $settings );
531 + if ( $existing_plugins && isset( $_normalized_settings['migration_step'] ) && $_normalized_settings['migration_step'] == true ) {
532 + betterdocs()->kbmigration->migrate();
533 + }
534 + $_settings = wp_parse_args( $_normalized_settings, $_old_settings );
535 + $_saved = $this->database->save( $this->base_key, $_settings );
609 536
610 - $_value = $default;
611 - switch ( true ) {
612 - // Check if it's a PRO Option
613 - case ! isset( $_default_settings[ $key ] ):
614 - $_value = $default;
615 - break;
616 - // Check if it's a FREE Option and not in DB.
617 - case ! isset( $_settings[ $key ] ) && isset( $_default_settings[ $key ] ):
618 - $_value = null !== $default ? $default : $_default_settings[ $key ];
619 - break;
620 - // Check if it's a FREE Option
621 - case isset( $_settings[ $key ] ) && isset( $_default_settings[ $key ] ):
622 - $_value = $_settings[ $key ];
623 - break;
624 - }
537 + do_action_ref_array( 'betterdocs::settings::saved', [ $_saved, $_settings, $_old_settings, &$this ] );
625 538
626 - $_value = $this->get_normalized_value( $key, $_value, isset( $_default_settings[ $key ] ) ? $_default_settings[ $key ] : null );
539 + return $_saved;
540 + }
627 541
628 - if ( gettype( $_value ) === 'string' ) {
629 - if ( empty( $_value ) && null != $default ) {
630 - $_value = $default;
631 - } elseif ( empty( $_value ) && null === $default && isset( $_default_settings[ $key ] ) ) {
632 - $_value = $_default_settings[ $key ];
633 - }
634 - }
542 + public function views( $hook ) {
543 + return betterdocs()->views->get( 'admin/settings' );
544 + }
635 545
636 - return $_value;
637 - }
546 + public function save_default_settings() {
547 + $_settings = $this->get_all();
638 548
639 - public function get_raw_field( $key, $default = null ) {
640 - $_settings = $this->database->get( $this->base_key, array() );
549 + return $this->database->save( $this->base_key, $_settings );
550 + }
641 551
642 - if ( isset( $_settings[ $key ] ) ) {
643 - return $this->get_normalized_value( $key, $_settings[ $key ], $default );
644 - }
552 + public function get_pages() {
553 + $_pages = betterdocs()->query->get_posts( [
554 + 'post_type' => 'page',
555 + 'numberposts' => - 1,
556 + 'post_status' => 'publish',
557 + 'posts_per_page' => - 1
558 + ] );
645 559
646 - return $default;
647 - }
560 + $__pages = [];
648 561
649 - public function save( $key, $value ) {
650 - $_settings = $this->database->get( $this->base_key, array() );
651 - $_settings[ $key ] = $value;
562 + if ( ! empty( $_pages ) ) {
563 + $__pages[0] = __( 'Select a Page', 'betterdocs' );
564 + foreach ( $_pages->posts as $page ) {
565 + $__pages[ $page->ID ] = esc_html( $page->post_title );
566 + }
567 + }
652 568
653 - return $this->database->save( $this->base_key, $_settings );
654 - }
569 + return $__pages;
570 + }
655 571
656 - public function save_settings( $settings ) {
657 - $existing_plugins = betterdocs()->kbmigration->knowledge_base_plugins();
658 - if ( ! current_user_can( 'edit_docs_settings' ) ) {
659 - return new WP_Error( 'unauthorized_action', __( 'You don\'t have any rights for saving settings.', 'betterdocs' ) );
660 - }
572 + public function settings_args() {
573 + $wp_roles = $this->normalize_options( $this->get_roles() );
661 574
662 - // The frontend sends the currently-active settings tab as a transport-only hint so
663 - // tab-scoped validation (the AI min-token floor below) only runs when that tab is being
664 - // saved. It must never be persisted into the settings option.
665 - $active_tab = '';
666 - if ( array_key_exists( '_active_tab', $settings ) ) {
667 - $active_tab = (string) $settings[ '_active_tab' ];
668 - unset( $settings[ '_active_tab' ] );
669 - }
575 + $settings = [
576 + 'id' => 'betterdocs_settings_metabox_wrapper',
577 + 'title' => __( 'betterdocs', 'betterdocs' ),
578 + 'object_types' => [ 'betterdocs' ],
579 + 'context' => 'normal',
580 + 'priority' => 'high',
581 + 'show_header' => false,
582 + 'tabnumber' => false,
583 + 'is_pro_active' => betterdocs()->is_pro_active(),
584 + 'logoURL' => betterdocs()->assets->icon( 'betterdocs-icon.svg', true ),
585 + 'layout' => 'vertical',
586 + 'config' => [
587 + 'active' => 'tab-general',
588 + 'sidebar' => true,
589 + 'title' => false
590 + ],
591 + 'submit' => [
592 + 'show' => true,
593 + 'label' => __( 'Save', 'betterdocs' ),
594 + 'loadingLabel' => __( 'Saving...', 'betterdocs' ),
595 + 'class' => 'save-settings',
596 + 'rules' => Rules::logicalRule( [
597 + Rules::is( 'config.active', 'tab-design', true ),
598 + Rules::is( 'config.active', 'tab-shortcodes', true ),
599 + Rules::is( 'config.active', 'tab-instant-answer', true ),
600 + Rules::is( 'config.active', 'tab-import-export', true ),
601 + Rules::is( 'config.active', 'tab-migration', true )
602 + ], 'and' )
603 + ],
604 + 'values' => betterdocs()->is_pro_active() ? $this->get_all() : array_merge( $this->get_all(), $this->pro_settings_default_values() ),
605 + 'tabs' => apply_filters( 'betterdocs_settings_tabs', [
606 + 'tab-general' => apply_filters( 'betterdocs_settings_tab_general', [
607 + 'id' => 'tab-general',
608 + 'label' => __( 'General', 'betterdocs' ),
609 + 'classes' => 'tab-general',
610 + 'priority' => 10,
611 + 'fields' => [
612 + 'title-general' => apply_filters( 'betterdocs_encyclopedia_settings', [
613 + 'name' => 'title-general-tab',
614 + 'type' => 'section',
615 + 'label' => __( 'General Settings', 'betterdocs' ),
616 + 'priority' => 10,
617 + 'fields' => [
618 + 'multiple_kb' => apply_filters( 'betterdocs_multi_kb_settings', [
619 + 'name' => 'multiple_kb',
620 + 'type' => 'toggle',
621 + 'label' => __( 'Multiple Knowledge Base', 'betterdocs' ),
622 + 'enable_disable_text_active' => true,
623 + 'default' => '',
624 + 'priority' => 1,
625 + 'is_pro' => true
626 + ] ),
627 + 'builtin_doc_page' => [
628 + 'name' => 'builtin_doc_page',
629 + 'type' => 'toggle',
630 + 'label' => __( 'Built-in Documentation Page', 'betterdocs' ),
631 + 'enable_disable_text_active' => true,
632 + 'default' => 1,
633 + 'priority' => 2
634 + ],
635 + 'breadcrumb_doc_title' => [
636 + 'name' => 'breadcrumb_doc_title',
637 + 'type' => 'text',
638 + 'label' => __( 'Documentation Page Title', 'betterdocs' ),
639 + 'default' => __( 'Docs', 'betterdocs' ),
640 + 'priority' => 3,
641 + 'rules' => Rules::is( 'builtin_doc_page', true )
642 + ],
643 + 'docs_slug' => [
644 + 'name' => 'docs_slug',
645 + 'type' => 'text',
646 + 'label' => __( 'BetterDocs Root Slug', 'betterdocs' ),
647 + 'default' => 'docs',
648 + 'priority' => 4,
649 + 'rules' => Rules::is( 'builtin_doc_page', true )
650 + ],
651 + 'docs_page' => [
652 + 'name' => 'docs_page',
653 + 'label' => __( 'Docs Page', 'betterdocs' ),
654 + 'type' => 'select',
655 + 'default' => 0,
656 + 'priority' => 5,
657 + 'search' => true,
658 + 'options' => $this->normalize_options( $this->get_pages() ),
659 + 'label_subtitle' => __( 'You will need to insert BetterDocs Shortcode inside the page. This page will be used as docs permalink.', 'betterdocs' ),
660 + 'rules' => Rules::is( 'builtin_doc_page', false )
661 + ],
670 662
671 - // Quickbuilder sends back the full UI-loaded payload. To avoid overwriting values that we
672 - // asynchronously updated in the DB via AJAX (like Git integration fields), we strictly remove them
673 - // from the incoming save payload so that the freshly loaded `$_old_settings` values persist.
674 - $exclude_ajax_keys = array( 'git_provider', 'git_repository_url', 'git_branch', 'git_docs_directory' );
675 - foreach ( $exclude_ajax_keys as $key ) {
676 - if ( array_key_exists( $key, $settings ) ) {
677 - unset( $settings[ $key ] );
678 - }
679 - if ( isset( $settings[ 'values' ] ) && is_array( $settings[ 'values' ] ) && array_key_exists( $key, $settings[ 'values' ] ) ) {
680 - unset( $settings[ 'values' ][ $key ] );
681 - }
682 - }
663 + 'category_slug' => [
664 + 'name' => 'category_slug',
665 + 'type' => 'text',
666 + 'label' => __( 'Custom Category Slug', 'betterdocs' ),
667 + 'default' => 'docs-category',
668 + 'priority' => 6
669 + ],
670 + 'tag_slug' => [
671 + 'name' => 'tag_slug',
672 + 'type' => 'text',
673 + 'label' => __( 'Custom Tag Slug', 'betterdocs' ),
674 + 'default' => 'docs-tag',
675 + 'priority' => 7
676 + ],
677 + 'permalink_structure' => [
678 + 'name' => 'permalink_structure',
679 + 'type' => 'permalink_structure',
680 + 'label' => __( 'Single Docs Permalink', 'betterdocs' ),
681 + 'default' => PostType::permalink_structure(),
682 + 'priority' => 8,
683 + 'tags' => $this->normalize_options( [
684 + '%doc_category%' => '%doc_category%',
685 + '%knowledge_base%' => '%knowledge_base%'
686 + ] ),
687 + 'label_subtitle' => __( 'Make sure to keep Docs Root Slug in the Single Docs Permalink. You are not able to keep it blank. You can use the available tags from below.', 'betterdocs' )
688 + ],
689 + 'enable_glossaries' => [
690 + 'name' => 'enable_glossaries',
691 + 'type' => 'toggle',
692 + 'label' => __( 'Show Glossary', 'betterdocs' ),
693 + 'label_subtitle' => __( 'Enable the glossary feature to allow users to look up definitions for terms used within your encyclopedia or glossaries themselves.', 'betterdocs' ),
694 + 'enable_disable_text_active' => true,
695 + 'default' => false,
696 + 'priority' => 9,
697 + 'is_pro' => true
698 + ],
699 + 'enable_encyclopedia' => [
700 + 'name' => 'enable_encyclopedia',
701 + 'type' => 'toggle',
702 + 'label' => __( 'Built-in Encyclopedia Page', 'betterdocs' ),
703 + 'enable_disable_text_active' => true,
704 + 'default' => false,
705 + 'priority' => 10,
706 + 'is_pro' => true
707 + ],
708 + 'enable_faq_schema' => [
709 + 'name' => 'enable_faq_schema',
710 + 'type' => 'toggle',
711 + 'label' => __( 'FAQ Schema', 'betterdocs' ),
712 + 'enable_disable_text_active' => true,
713 + 'default' => '',
714 + 'priority' => 14
715 + ],
716 + 'analytics_from' => [
717 + 'name' => 'analytics_from',
718 + 'type' => 'select',
719 + 'label' => __( 'Analytics From', 'betterdocs' ),
720 + 'options' => $this->normalize_options( [
721 + 'everyone' => __( 'Everyone', 'betterdocs' ),
722 + 'guests' => __( 'Guests Only', 'betterdocs' ),
723 + 'registered_users' => __( 'Registered Users Only', 'betterdocs' )
724 + ] ),
725 + 'default' => 'everyone',
726 + 'priority' => 15,
727 + 'is_pro' => true
728 + ],
729 + 'unique_visitor_count' => [
730 + 'name' => 'unique_visitor_count',
731 + 'type' => 'toggle',
732 + 'label' => __( 'Unique Visitor Count', 'betterdocs' ),
733 + 'enable_disable_text_active' => true,
734 + 'default' => false,
735 + 'priority' => 16,
736 + 'is_pro' => true
737 + ],
738 + 'exclude_bot_analytics' => [
739 + 'name' => 'exclude_bot_analytics',
740 + 'type' => 'toggle',
741 + 'label' => __( 'Exclude Bot Analytics', 'betterdocs' ),
742 + 'enable_disable_text_active' => true,
743 + 'default' => false,
744 + 'priority' => 17,
745 + 'is_pro' => true
746 + ]
683 747
684 - $_old_settings = $this->database->get( $this->base_key, $this->get_default() );
748 + ]
749 + ] )
750 + ]
751 + ] ),
752 + 'tab-layout' => apply_filters( 'betterdocs_settings_tab_layout', [
753 + 'id' => 'tab-layout',
754 + 'label' => __( 'Layout', 'betterdocs' ),
755 + 'classes' => 'tab-layout',
756 + 'priority' => 20,
757 + 'fields' => [
758 + 'title-layout' => [
759 + 'name' => 'title-layout-tab',
760 + 'type' => 'section',
761 + 'label' => __( 'Layout Settings', 'betterdocs' ),
762 + 'priority' => 20,
763 + 'fields' => [
764 + 'tab-sidebar-layout' => apply_filters( 'betterdocs_settings_tab_sidebar_layout', [
765 + 'id' => 'tab-sidebar-layout',
766 + 'name' => 'tab_sidebar_layout',
767 + 'label' => __( 'Layout Settings', 'betterdocs' ),
768 + 'classes' => 'tab-layout',
769 + 'type' => 'tab',
770 + 'active' => 'layout_documentation_page',
771 + 'completionTrack' => true,
772 + 'sidebar' => false,
773 + 'save' => false,
774 + 'title' => false,
775 + 'config' => [
776 + 'active' => 'layout_documentation_page',
777 + 'sidebar' => false,
778 + 'title' => false
779 + ],
780 + 'submit' => [
781 + 'show' => false
782 + ],
783 + 'step' => [
784 + 'show' => false
785 + ],
786 + 'priority' => 20,
787 + 'fields' => [
788 + 'layout_documentation_page' => [
789 + 'id' => 'layout_documentation_page',
790 + 'name' => 'layout_documentation_page',
791 + 'type' => 'section',
792 + 'label' => __( 'Documentation Page', 'betterdocs' ),
793 + 'priority' => 1,
794 + 'fields' => [
795 + 'tab-nested-layout-1' => [
796 + 'id' => 'tab-nested-layout-1',
797 + 'name' => 'tab_nested_layout_1',
798 + 'label' => __( 'Documentation Page', 'betterdocs' ),
799 + 'classes' => 'tab-nested-layout',
800 + 'type' => 'tab',
801 + 'active' => 'layout_documentation_page_general',
802 + 'completionTrack' => true,
803 + 'sidebar' => false,
804 + 'save' => false,
805 + 'title' => false,
806 + 'config' => [
807 + 'active' => 'layout_documentation_page_general',
808 + 'sidebar' => false,
809 + 'title' => false
810 + ],
811 + 'submit' => [
812 + 'show' => false
813 + ],
814 + 'step' => [
815 + 'show' => false
816 + ],
817 + 'priority' => 1,
818 + 'fields' => [
819 + 'layout_documentation_page_general' => [
820 + 'id' => 'layout_documentation_page_general',
821 + 'name' => 'layout_documentation_page_general',
822 + 'type' => 'section',
823 + 'label' => __( 'General', 'betterdocs' ),
824 + 'priority' => 1,
825 + 'fields' => [
826 + 'docs_list_icon' => [
827 + 'name' => 'docs_list_icon',
828 + 'type' => 'media',
829 + 'value' => '',
830 + 'label' => __( 'Docs List Icon', 'betterdocs' ),
831 + 'label_subtitle' => __( 'Upload your own preferred document list icon', 'betterdocs' ),
832 + 'priority' => 0
833 + ],
834 + 'category_title_link' => [
835 + 'name' => 'category_title_link',
836 + 'type' => 'toggle',
837 + 'label' => __( 'Category Title Link', 'betterdocs' ),
838 + 'label_subtitle' => __( 'This setting is applicable for category grid layout', 'betterdocs' ),
839 + 'enable_disable_text_active' => true,
840 + 'default' => false,
841 + 'priority' => 0
842 + ],
843 + 'masonry_layout' => [
844 + 'name' => 'masonry_layout',
845 + 'type' => 'toggle',
846 + 'label' => __( 'Masonry', 'betterdocs' ),
847 + 'enable_disable_text_active' => true,
848 + 'default' => 1,
849 + 'priority' => 1
850 + ],
851 + 'nested_subcategory' => [
852 + 'name' => 'nested_subcategory',
853 + 'type' => 'toggle',
854 + 'label' => __( 'Nested Sub Category', 'betterdocs' ),
855 + 'enable_disable_text_active' => true,
856 + 'default' => '',
857 + 'priority' => 2
858 + ],
859 + 'column_number' => [
860 + 'name' => 'column_number',
861 + 'type' => 'number',
862 + 'label' => __( 'Number Of Columns', 'betterdocs' ),
863 + 'label_subtitle' => __( 'This setting is not applicable for sleek layout.', 'betterdocs' ),
864 + 'default' => 3,
865 + 'priority' => 3
866 + ],
867 + 'posts_number' => apply_filters( 'betterdocs_posts_number', [
868 + 'name' => 'posts_number',
869 + 'type' => 'number',
870 + 'label' => __( 'Number Of Docs', 'betterdocs' ),
871 + 'label_subtitle' => __( 'This setting is not applicable for handbook layout.', 'betterdocs' ),
872 + 'default' => 10,
873 + 'priority' => 4
874 + ] ),
875 + 'post_count' => [
876 + 'name' => 'post_count',
877 + 'type' => 'toggle',
878 + 'label' => __( 'Doc Count', 'betterdocs' ),
879 + 'enable_disable_text_active' => true,
880 + 'default' => 1,
881 + 'priority' => 5
882 + ],
883 + 'count_text' => [
884 + 'name' => 'count_text',
885 + 'type' => 'text',
886 + 'label' => __( 'Count Text', 'betterdocs' ),
887 + 'default' => __( 'Docs', 'betterdocs' ),
888 + 'priority' => 6
889 + ],
890 + 'count_text_singular' => [
891 + 'name' => 'count_text_singular',
892 + 'type' => 'text',
893 + 'label' => __( 'Count Text Singular', 'betterdocs' ),
894 + 'default' => __( 'Doc', 'betterdocs' ),
895 + 'priority' => 7
896 + ],
897 + 'exploremore_btn' => [
898 + 'name' => 'exploremore_btn',
899 + 'type' => 'toggle',
900 + 'label' => __( 'Explore More Button', 'betterdocs' ),
901 + 'enable_disable_text_active' => true,
902 + 'default' => true,
903 + 'priority' => 8
904 + ],
905 + 'exploremore_btn_txt' => [
906 + 'name' => 'exploremore_btn_txt',
907 + 'type' => 'text',
908 + 'label' => __( 'Explore More Button Text', 'betterdocs' ),
909 + 'default' => __( 'Explore More', 'betterdocs' ),
910 + 'priority' => 9,
911 + 'rules' => Rules::is( 'exploremore_btn', true )
912 + ],
913 + 'betterdocs_popular_docs_text' => [
914 + 'name' => 'betterdocs_popular_docs_text',
915 + 'type' => 'text',
916 + 'label' => __( 'Popular Docs Text', 'betterdocs' ),
917 + 'default' => __( 'Popular Docs', 'betterdocs' ),
918 + 'priority' => 10,
919 + 'is_pro' => true
920 + ],
921 + 'betterdocs_popular_docs_number' => [
922 + 'name' => 'betterdocs_popular_docs_number',
923 + 'type' => 'number',
924 + 'label' => __( 'Popular Docs Number', 'betterdocs' ),
925 + 'default' => 10,
926 + 'priority' => 11,
927 + 'is_pro' => true
928 + ]
929 + ]
930 + ],
931 + 'layout_documentation_page_search' => [
932 + 'id' => 'layout_documentation_page_search',
933 + 'name' => 'layout_documentation_page_search',
934 + 'type' => 'section',
935 + 'label' => __( 'Search', 'betterdocs' ),
936 + 'priority' => 2,
937 + 'fields' => [
938 + 'live_search' => [
939 + 'name' => 'live_search',
940 + 'type' => 'toggle',
941 + 'label' => __( 'Live Search', 'betterdocs' ),
942 + 'enable_disable_text_active' => true,
943 + 'default' => 1,
944 + 'priority' => 1
945 + ],
946 + 'advance_search' => apply_filters( 'betterdocs_advance_search_settings', [
947 + 'name' => 'advance_search',
948 + 'type' => 'toggle',
949 + 'label' => __( 'Advanced Search', 'betterdocs' ),
950 + 'enable_disable_text_active' => true,
951 + 'default' => '',
952 + 'priority' => 2,
953 + 'is_pro' => true
954 + ] ),
955 + 'child_category_exclude' => apply_filters( 'child_category_exclude', [
956 + 'name' => 'child_category_exclude',
957 + 'type' => 'toggle',
958 + 'label' => __( 'Exclude Child Terms In Category Search', 'betterdocs' ),
959 + 'enable_disable_text_active' => true,
960 + 'default' => '',
961 + 'priority' => 3,
962 + 'is_pro' => true
963 + ] ),
964 + 'popular_keyword_limit' => apply_filters( 'betterdocs_popular_keyword_limit_settings', [
965 + 'name' => 'popular_keyword_limit',
966 + 'type' => 'number',
967 + 'label' => __( 'Minimum amount of Keywords Search', 'betterdocs' ),
968 + 'default' => 5,
969 + 'priority' => 4,
970 + 'is_pro' => true
971 + ] ),
972 + 'search_letter_limit' => [
973 + 'name' => 'search_letter_limit',
974 + 'type' => 'number',
975 + 'label' => __( 'Minimum Character Limit For Search Result', 'betterdocs' ),
976 + 'priority' => 5,
977 + 'default' => 3
978 + ],
979 + 'search_placeholder' => [
980 + 'name' => 'search_placeholder',
981 + 'type' => 'text',
982 + 'label' => __( 'Search Placeholder', 'betterdocs' ),
983 + 'default' => __( 'Search..', 'betterdocs' ),
984 + 'priority' => 6
985 + ],
986 + 'search_button_text' => apply_filters( 'betterdocs_search_button_text', [
987 + 'name' => 'search_button_text',
988 + 'type' => 'text',
989 + 'label' => __( 'Search Button Text', 'betterdocs' ),
990 + 'priority' => 7,
991 + 'default' => __( 'Search', 'betterdocs' ),
992 + 'is_pro' => true
993 + ] ),
994 + 'search_not_found_text' => [
995 + 'name' => 'search_not_found_text',
996 + 'type' => 'text',
997 + 'label' => __( 'Search Not Found Text', 'betterdocs' ),
998 + 'default' => 'Sorry, no docs were found.',
999 + 'priority' => 8
1000 + ],
1001 + 'search_result_image' => [
1002 + 'name' => 'search_result_image',
1003 + 'type' => 'toggle',
1004 + 'label' => __( 'Search Result Image', 'betterdocs' ),
1005 + 'enable_disable_text_active' => true,
1006 + 'default' => 1,
1007 + 'priority' => 9
1008 + ],
1009 + 'kb_based_search' => apply_filters( 'betterdocs_kb_based_search_settings', [
1010 + 'name' => 'kb_based_search',
1011 + 'type' => 'toggle',
1012 + 'label' => __( 'KB Based Search', 'betterdocs' ),
1013 + 'enable_disable_text_active' => true,
1014 + 'default' => '',
1015 + 'priority' => 10,
1016 + 'is_pro' => true,
1017 + 'rules' => Rules::is( 'multiple_kb', true )
1018 + ] )
1019 + ]
1020 + ],
1021 + 'layout_documentation_page_order_by' => [
1022 + 'id' => 'layout_documentation_page_order_by',
1023 + 'name' => 'layout_documentation_page_order_by',
1024 + 'type' => 'section',
1025 + 'label' => __( 'Order By', 'betterdocs' ),
1026 + 'priority' => 3,
1027 + 'fields' => [
1028 + 'terms_orderby' => [
1029 + 'name' => 'terms_orderby',
1030 + 'type' => 'select',
1031 + 'label' => __( 'Terms Order By', 'betterdocs' ),
1032 + 'default' => 'betterdocs_order',
1033 + 'options' => $this->normalize_options( apply_filters( 'betterdocs_terms_orderby_options', [
1034 + 'none' => __( 'No order', 'betterdocs' ),
1035 + 'name' => __( 'Name', 'betterdocs' ),
1036 + 'slug' => __( 'Slug', 'betterdocs' ),
1037 + 'term_group' => __( 'Term Group', 'betterdocs' ),
1038 + 'term_id' => __( 'Term ID', 'betterdocs' ),
1039 + 'id' => __( 'ID', 'betterdocs' ),
1040 + 'description' => __( 'Description', 'betterdocs' ),
1041 + 'parent' => __( 'Parent', 'betterdocs' ),
1042 + 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
1043 + ] ) ),
1044 + 'priority' => 1
1045 + ],
1046 + 'terms_order' => [
1047 + 'name' => 'terms_order',
1048 + 'type' => 'select',
1049 + 'label' => __( 'Terms Order', 'betterdocs' ),
1050 + 'default' => 'ASC',
1051 + 'options' => $this->normalize_options( [
1052 + 'ASC' => 'Ascending',
1053 + 'DESC' => 'Descending'
1054 + ] ),
1055 + 'priority' => 3,
1056 + 'rules' => Rules::includes( 'terms_orderby', 'betterdocs_order', true )
1057 + ],
1058 + 'alphabetically_order_post' => [
1059 + 'name' => 'alphabetically_order_post',
1060 + 'type' => 'select',
1061 + 'label' => __( 'Docs Order By', 'betterdocs' ),
1062 + 'default' => 'betterdocs_order',
1063 + 'options' => $this->normalize_options( [
1064 + 'none' => __( 'No order', 'betterdocs' ),
1065 + 'ID' => __( 'Docs ID', 'betterdocs' ),
1066 + 'author' => __( 'Docs Author', 'betterdocs' ),
1067 + 'title' => __( 'Title', 'betterdocs' ),
1068 + 'date' => __( 'Date', 'betterdocs' ),
1069 + 'modified' => __( 'Last Modified Date', 'betterdocs' ),
1070 + 'parent' => __( 'Parent Id', 'betterdocs' ),
1071 + 'rand' => __( 'Random', 'betterdocs' ),
1072 + 'comment_count' => __( 'Comment Count', 'betterdocs' ),
1073 + 'menu_order' => __( 'Menu Order', 'betterdocs' ),
1074 + 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
1075 + ] ),
1076 + 'priority' => 4
1077 + ],
1078 + 'docs_order' => [
1079 + 'name' => 'docs_order',
1080 + 'type' => 'select',
1081 + 'label' => __( 'Docs Order', 'betterdocs' ),
1082 + 'default' => 'ASC',
1083 + 'options' => $this->normalize_options( [
1084 + 'ASC' => 'Ascending',
1085 + 'DESC' => 'Descending'
1086 + ] ),
1087 + 'priority' => 5,
1088 + 'rules' => Rules::includes( 'alphabetically_order_post', 'betterdocs_order', true )
1089 + ]
1090 + ]
1091 + ]
1092 + ]
1093 + ]
1094 + ]
1095 + ],
1096 + 'layout_single_doc' => apply_filters( 'single_doc_setting_section', [
1097 + 'id' => 'layout_single_doc',
1098 + 'name' => 'layout_single_doc',
1099 + 'type' => 'section',
1100 + 'label' => __( 'Single Doc', 'betterdocs' ),
1101 + 'priority' => 2,
1102 + 'fields' => [
1103 + 'tab-nested-layout-2' => [
1104 + 'id' => 'tab-nested-layout-2',
1105 + 'name' => 'tab_nested_layout_2',
1106 + 'label' => __( 'Single Doc', 'betterdocs' ),
1107 + 'classes' => 'tab-nested-layout',
1108 + 'type' => 'tab',
1109 + 'active' => 'layout_single_doc_general',
1110 + 'completionTrack' => true,
1111 + 'sidebar' => false,
1112 + 'save' => false,
1113 + 'title' => false,
1114 + 'config' => [
1115 + 'active' => 'layout_single_doc_general',
1116 + 'sidebar' => false,
1117 + 'title' => false
1118 + ],
1119 + 'submit' => [
1120 + 'show' => false
1121 + ],
1122 + 'step' => [
1123 + 'show' => false
1124 + ],
1125 + 'priority' => 20,
1126 + 'fields' => [
1127 + 'layout_single_doc_general' => [
1128 + 'id' => 'layout_single_doc_general',
1129 + 'name' => 'layout_single_doc_general',
1130 + 'type' => 'section',
1131 + 'label' => __( 'General', 'betterdocs' ),
1132 + 'priority' => 5,
1133 + 'fields' => [
1134 + 'enable_post_title' => [
1135 + 'name' => 'enable_post_title',
1136 + 'type' => 'toggle',
1137 + 'label' => __( 'Doc Title', 'betterdocs' ),
1138 + 'enable_disable_text_active' => true,
1139 + 'default' => 1,
1140 + 'priority' => 1
1141 + ],
1142 + 'enable_sidebar_cat_list' => [
1143 + 'name' => 'enable_sidebar_cat_list',
1144 + 'type' => 'toggle',
1145 + 'label' => __( 'Sidebar Category List', 'betterdocs' ),
1146 + 'enable_disable_text_active' => true,
1147 + 'default' => 1,
1148 + 'priority' => 2
1149 + ],
1150 + 'enable_print_icon' => [
1151 + 'name' => 'enable_print_icon',
1152 + 'type' => 'toggle',
1153 + 'label' => __( 'Print Icon', 'betterdocs' ),
1154 + 'enable_disable_text_active' => true,
1155 + 'default' => 1,
1156 + 'priority' => 3
1157 + ],
1158 + 'enable_tags' => [
1159 + 'name' => 'enable_tags',
1160 + 'type' => 'toggle',
1161 + 'label' => __( 'Tags', 'betterdocs' ),
1162 + 'enable_disable_text_active' => true,
1163 + 'default' => 1,
1164 + 'priority' => 4
1165 + ],
1166 + 'show_last_update_time' => [
1167 + 'name' => 'show_last_update_time',
1168 + 'type' => 'toggle',
1169 + 'label' => __( 'Last Update Time', 'betterdocs' ),
1170 + 'enable_disable_text_active' => true,
1171 + 'default' => 1,
1172 + 'priority' => 5
1173 + ],
1174 + 'enable_navigation' => [
1175 + 'name' => 'enable_navigation',
1176 + 'type' => 'toggle',
1177 + 'label' => __( 'Navigation', 'betterdocs' ),
1178 + 'enable_disable_text_active' => true,
1179 + 'default' => 1,
1180 + 'priority' => 6
1181 + ],
1182 + 'enable_comment' => [
1183 + 'name' => 'enable_comment',
1184 + 'type' => 'toggle',
1185 + 'label' => __( 'Comment', 'betterdocs' ),
1186 + 'enable_disable_text_active' => true,
1187 + 'default' => '',
1188 + 'priority' => 7
1189 + ],
1190 + 'enable_credit' => [
1191 + 'name' => 'enable_credit',
1192 + 'type' => 'toggle',
1193 + 'label' => __( 'Show Powered by BetterDocs', 'betterdocs' ),
1194 + 'enable_disable_text_active' => true,
1195 + 'default' => '',
1196 + 'priority' => 8
1197 + ],
1198 + 'reaction_feedback_text' => [
1199 + 'name' => 'reaction_feedback_text',
1200 + 'type' => 'text',
1201 + 'label' => __( 'Reaction Feedback Text', 'betterdocs' ),
1202 + 'default' => __( 'Thanks for your feedback.', 'betterdocs' ),
1203 + 'priority' => 9
1204 + ],
1205 + 'enable_estimated_reading_time' => [
1206 + 'name' => 'enable_estimated_reading_time',
1207 + 'type' => 'toggle',
1208 + 'label' => __( 'Estimated Reading Time', 'betterdocs' ),
1209 + 'enable_disable_text_active' => true,
1210 + 'default' => 0,
1211 + 'priority' => 10
1212 + ],
1213 + 'estimated_reading_time_title' => [
1214 + 'name' => 'estimated_reading_time_title',
1215 + 'type' => 'text',
1216 + 'label' => __( 'Estimated Reading Time Title', 'betterdocs' ),
1217 + 'default' => '',
1218 + 'priority' => 11,
1219 + 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1220 + ],
1221 + 'estimated_reading_time_text' => [
1222 + 'name' => 'estimated_reading_time_text',
1223 + 'type' => 'text',
1224 + 'label' => __( 'Estimated Reading Time Text', 'betterdocs' ),
1225 + 'default' => __( 'min read', 'betterdocs' ),
1226 + 'priority' => 12,
1227 + 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1228 + ],
1229 + 'singular_estimated_reading_time_text' => [
1230 + 'name' => 'singular_estimated_reading_time_text',
1231 + 'type' => 'text',
1232 + 'label' => __( 'Estimated Reading Time Text Singular', 'betterdocs' ),
1233 + 'default' => __( 'min read', 'betterdocs' ),
1234 + 'priority' => 13,
1235 + 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1236 + ]
1237 + ]
1238 + ],
1239 + 'layout_single_doc_TOC' => [
1240 + 'id' => 'layout_single_doc_TOC',
1241 + 'name' => 'layout_single_doc_TOC',
1242 + 'type' => 'section',
1243 + 'label' => __( 'TOC', 'betterdocs' ),
1244 + 'priority' => 5,
1245 + 'fields' => [
1246 + 'enable_toc' => [
1247 + 'name' => 'enable_toc',
1248 + 'type' => 'toggle',
1249 + 'label' => __( 'Table of Contents', 'betterdocs' ),
1250 + 'enable_disable_text_active' => true,
1251 + 'default' => 1,
1252 + 'priority' => 1
1253 + ],
1254 + 'toc_title' => [
1255 + 'name' => 'toc_title',
1256 + 'type' => 'text',
1257 + 'label' => __( 'TOC Title', 'betterdocs' ),
1258 + 'default' => __( 'Table of Contents', 'betterdocs' ),
1259 + 'priority' => 2,
1260 + 'rules' => Rules::is( 'enable_toc', true )
685 1261
686 - // The frontend only ever sees masked API keys. A submitted value that still looks like a
687 - // mask (contains a run of asterisks — no real key does) means "unchanged": restore the
688 - // stored original so a mask string is never persisted. Guarding on the mask SHAPE rather
689 - // than strict equality with mask(stored) closes the corruption loop QA hit: once a mask
690 - // slips into storage, mask(mask) === mask, so an equality-only guard would faithfully
691 - // preserve the corrupted value forever (round-2 follow-up #1). When the stored value is
692 - // itself mask-shaped it is unrecoverable — clear it so the UI and the GeoIP/GA4 status
693 - // surfaces honestly report a missing key instead of failing downstream with 401s.
694 - $sensitive_api_keys = self::sensitive_api_key_fields();
695 - foreach ( $sensitive_api_keys as $api_key_field ) {
696 - if ( ! isset( $settings[ $api_key_field ] ) ) {
697 - continue;
698 - }
699 - $incoming = trim( (string) $settings[ $api_key_field ] );
700 - $stored = isset( $_old_settings[ $api_key_field ] ) ? (string) $_old_settings[ $api_key_field ] : '';
701 - $stored_is_mask = '' !== $stored && preg_match( '/\*{4,}/', $stored );
1262 + ],
1263 + 'toc_hierarchy' => [
1264 + 'name' => 'toc_hierarchy',
1265 + 'type' => 'toggle',
1266 + 'label' => __( 'TOC Hierarchy', 'betterdocs' ),
1267 + 'enable_disable_text_active' => true,
1268 + 'default' => 1,
1269 + 'priority' => 3,
1270 + 'rules' => Rules::is( 'enable_toc', true )
1271 + ],
1272 + 'toc_list_number' => [
1273 + 'name' => 'toc_list_number',
1274 + 'type' => 'toggle',
1275 + 'label' => __( 'TOC List Number', 'betterdocs' ),
1276 + 'enable_disable_text_active' => true,
1277 + 'default' => 1,
1278 + 'priority' => 4,
1279 + 'rules' => Rules::is( 'enable_toc', true )
1280 + ],
1281 + 'toc_dynamic_title' => [
1282 + 'name' => 'toc_dynamic_title',
1283 + 'type' => 'toggle',
1284 + 'label' => __( 'Show TOC Title in Anchor Links', 'betterdocs' ),
1285 + 'enable_disable_text_active' => true,
1286 + 'default' => 0,
1287 + 'priority' => 5,
1288 + 'rules' => Rules::is( 'enable_toc', true )
1289 + ],
1290 + 'enable_sticky_toc' => [
1291 + 'name' => 'enable_sticky_toc',
1292 + 'type' => 'toggle',
1293 + 'label' => __( 'Sticky TOC', 'betterdocs' ),
1294 + 'enable_disable_text_active' => true,
1295 + 'default' => 1,
1296 + 'priority' => 6,
1297 + 'rules' => Rules::is( 'enable_toc', true )
1298 + ],
1299 + 'collapsible_toc_mobile' => [
1300 + 'name' => 'collapsible_toc_mobile',
1301 + 'type' => 'toggle',
1302 + 'label' => __( 'Collapsible TOC on small devices', 'betterdocs' ),
1303 + 'enable_disable_text_active' => true,
1304 + 'default' => '',
1305 + 'priority' => 7,
1306 + 'rules' => Rules::is( 'enable_toc', true )
1307 + ],
1308 + 'title_link_ctc' => [
1309 + 'name' => 'title_link_ctc',
1310 + 'type' => 'toggle',
1311 + 'label' => __( 'Title Link Copy To Clipboard', 'betterdocs' ),
1312 + 'enable_disable_text_active' => true,
1313 + 'default' => 1,
1314 + 'priority' => 8
1315 + ],
1316 + 'supported_heading_tag' => [
1317 + 'name' => 'supported_heading_tag',
1318 + 'label' => __( 'TOC Supported Heading Tag', 'betterdocs' ),
1319 + 'type' => 'checkbox-select',
1320 + 'multiple' => true,
1321 + 'priority' => 10,
1322 + 'default' => [
1323 + '1',
1324 + '2',
1325 + '3',
1326 + '4',
1327 + '5',
1328 + '6'
1329 + ],
1330 + 'options' => $this->normalize_options( [
1331 + '1' => 'H1',
1332 + '2' => 'H2',
1333 + '3' => 'H3',
1334 + '4' => 'H4',
1335 + '5' => 'H5',
1336 + '6' => 'H6'
1337 + ] ),
1338 + 'priority' => 9,
1339 + 'rules' => Rules::is( 'enable_toc', true )
1340 + ],
1341 + 'sticky_toc_offset' => [
1342 + 'name' => 'sticky_toc_offset',
1343 + 'type' => 'number',
1344 + 'label' => __( 'Content Offset', 'betterdocs' ),
1345 + 'default' => 100,
1346 + 'priority' => 10,
1347 + 'label_subtitle' => __( 'content offset from top on scroll.', 'betterdocs' ),
1348 + 'rules' => Rules::is( 'enable_toc', true )
1349 + ]
1350 + ]
1351 + ],
1352 + 'layout_single_doc_breadcrumb' => [
1353 + 'id' => 'layout_single_doc_breadcrumb',
1354 + 'name' => 'layout_single_doc_breadcrumb',
1355 + 'type' => 'section',
1356 + 'label' => __( 'Breadcrumb', 'betterdocs' ),
1357 + 'priority' => 5,
1358 + 'fields' => [
1359 + 'enable_breadcrumb' => [
1360 + 'name' => 'enable_breadcrumb',
1361 + 'type' => 'toggle',
1362 + 'label' => __( 'Breadcrumb', 'betterdocs' ),
1363 + 'enable_disable_text_active' => true,
1364 + 'default' => 1,
1365 + 'priority' => 1
1366 + ],
1367 + 'enable_breadcrumb_home_text' => [
1368 + 'name' => 'enable_breadcrumb_home_text',
1369 + 'type' => 'toggle',
1370 + 'label' => __( 'Enable Breadcrumb Home Text', 'betterdocs' ),
1371 + 'enable_disable_text_active' => true,
1372 + 'default' => true,
1373 + 'priority' => 2,
1374 + 'rules' => Rules::is( 'enable_breadcrumb', true )
1375 + ],
1376 + 'breadcrumb_home_text' => [
1377 + 'name' => 'breadcrumb_home_text',
1378 + 'type' => 'text',
1379 + 'label' => __( 'Breadcrumb Home Text', 'betterdocs' ),
1380 + 'default' => __( 'Home', 'betterdocs' ),
1381 + 'priority' => 3,
1382 + 'rules' => Rules::logicalRule(
1383 + [
1384 + Rules::is( 'enable_breadcrumb', true ),
1385 + Rules::is( 'enable_breadcrumb_home_text', true )
1386 + ],
1387 + 'and'
1388 + )
1389 + ],
1390 + 'breadcrumb_home_url' => [
1391 + 'name' => 'breadcrumb_home_url',
1392 + 'type' => 'text',
1393 + 'label' => __( 'Breadcrumb Home URL', 'betterdocs' ),
1394 + 'priority' => 4,
1395 + 'default' => get_home_url(),
1396 + 'rules' => Rules::is( 'enable_breadcrumb', true )
1397 + ],
1398 + 'enable_breadcrumb_category' => [
1399 + 'name' => 'enable_breadcrumb_category',
1400 + 'type' => 'toggle',
1401 + 'label' => __( 'Category on Breadcrumb', 'betterdocs' ),
1402 + 'enable_disable_text_active' => true,
1403 + 'default' => 1,
1404 + 'priority' => 5,
1405 + 'rules' => Rules::is( 'enable_breadcrumb', true )
1406 + ],
1407 + 'enable_breadcrumb_title' => [
1408 + 'name' => 'enable_breadcrumb_title',
1409 + 'type' => 'toggle',
1410 + 'label' => __( 'Title on Breadcrumb', 'betterdocs' ),
1411 + 'enable_disable_text_active' => true,
1412 + 'default' => 1,
1413 + 'priority' => 6,
1414 + 'rules' => Rules::is( 'enable_breadcrumb', true )
1415 + ]
1416 + ]
1417 + ],
1418 + 'layout_single_doc_email_feedback' => [
1419 + 'id' => 'layout_single_doc_email_feedback',
1420 + 'name' => 'layout_single_doc_email_feedback',
1421 + 'type' => 'section',
1422 + 'label' => __( 'Email Feedback', 'betterdocs' ),
1423 + 'priority' => 5,
1424 + 'fields' => [
1425 + 'email_feedback' => [
1426 + 'name' => 'email_feedback',
1427 + 'type' => 'toggle',
1428 + 'label' => __( 'Email Feedback', 'betterdocs' ),
1429 + 'enable_disable_text_active' => true,
1430 + 'default' => 1,
1431 + 'priority' => 1
1432 + ],
1433 + 'feedback_link_text' => [
1434 + 'name' => 'feedback_link_text',
1435 + 'type' => 'text',
1436 + 'label' => __( 'Feedback Link Text', 'betterdocs' ),
1437 + 'default' => __( 'Still stuck? How can we help?', 'betterdocs' ),
1438 + 'priority' => 2,
1439 + 'rules' => Rules::is( 'email_feedback', true )
1440 + ],
1441 + 'feedback_form_title' => [
1442 + 'name' => 'feedback_form_title',
1443 + 'type' => 'text',
1444 + 'label' => __( 'Feedback Form Title', 'betterdocs' ),
1445 + 'default' => __( 'Still stuck? How can we help?', 'betterdocs' ),
1446 + 'priority' => 3,
1447 + 'rules' => Rules::is( 'email_feedback', true )
1448 + ],
1449 + 'email_address' => [
1450 + 'name' => 'email_address',
1451 + 'type' => 'text',
1452 + 'label' => __( 'Email Address', 'betterdocs' ),
1453 + 'default' => get_option( 'admin_email' ),
1454 + 'priority' => 4,
1455 + 'label_subtitle' => __( 'The email address where the Feedback form will be sent', 'betterdocs' ),
1456 + 'rules' => Rules::is( 'email_feedback', true )
1457 + ],
1458 + 'feedback_url' => [
1459 + 'name' => 'feedback_url',
1460 + 'type' => 'text',
1461 + 'label' => __( 'Feedback URL', 'betterdocs' ),
1462 + 'default' => '',
1463 + 'priority' => 5,
1464 + 'rules' => Rules::is( 'email_feedback', true )
1465 + ]
1466 + ]
1467 + ],
1468 + [
1469 + 'id' => 'layout_single_doc_attachments',
1470 + 'name' => 'layout_single_doc_attachments',
1471 + 'type' => 'section',
1472 + 'label' => __( 'Attachments', 'betterdocs' ),
1473 + 'priority' => 6,
1474 + 'fields' => apply_filters( 'betterdocs_single_doc_attachments', [
1475 + 'show_attachment' => [
1476 + 'name' => 'show_attachment',
1477 + 'type' => 'toggle',
1478 + 'is_pro' => true,
1479 + 'priority' => 1,
1480 + 'label' => __( 'Show Attachment', 'betterdocs' ),
1481 + 'enable_disable_text_active' => true,
1482 + 'default' => false
1483 + ]
1484 + ] )
1485 + ],
1486 + [
1487 + 'id' => 'layout_single_doc_related_docs',
1488 + 'name' => 'layout_single_doc_related_docs',
1489 + 'type' => 'section',
1490 + 'label' => __( 'Related Docs', 'betterdocs' ),
1491 + 'priority' => 7,
1492 + 'fields' => apply_filters( 'betterdocs_single_doc_related_docs', [
1493 + 'show_related_docs' => [
1494 + 'name' => 'show_related_docs',
1495 + 'type' => 'toggle',
1496 + 'is_pro' => true,
1497 + 'priority' => 1,
1498 + 'label' => __( 'Show Related Docs', 'betterdocs' ),
1499 + 'enable_disable_text_active' => true,
1500 + 'default' => false
1501 + ]
1502 + ] )
1503 + ]
1504 + ]
1505 + ]
1506 + ]
1507 + ] ),
1508 + 'layout_archive_page' => [
1509 + 'id' => 'layout_archive_page',
1510 + 'name' => 'layout_archive_page',
1511 + 'type' => 'section',
1512 + 'label' => __( 'Archive Page', 'betterdocs' ),
1513 + 'priority' => 3,
1514 + 'fields' => [
1515 + 'enable_archive_sidebar' => [
1516 + 'name' => 'enable_archive_sidebar',
1517 + 'type' => 'toggle',
1518 + 'label' => __( 'Sidebar Category List', 'betterdocs' ),
1519 + 'enable_disable_text_active' => true,
1520 + 'default' => 1,
1521 + 'priority' => 31
1522 + ],
1523 + 'archive_nested_subcategory' => [
1524 + 'name' => 'archive_nested_subcategory',
1525 + 'type' => 'toggle',
1526 + 'label' => __( 'Nested Subcategory', 'betterdocs' ),
1527 + 'enable_disable_text_active' => true,
1528 + 'default' => 1,
1529 + 'priority' => 32
1530 + ],
1531 + 'archive_enable_pagination' => [
1532 + 'name' => 'archive_enable_pagination',
1533 + 'type' => 'toggle',
1534 + 'label' => __( 'Enable Pagination', 'betterdocs' ),
1535 + 'enable_disable_text_active' => true,
1536 + 'default' => false,
1537 + 'priority' => 33
1538 + ]
1539 + ]
1540 + ]
1541 + ]
1542 + ] )
1543 + ]
1544 + ]
1545 + ]
1546 + ] ),
1547 + 'tab-design' => apply_filters( 'betterdocs_settings_tab_design', [
1548 + 'id' => 'tab-design',
1549 + 'label' => __( 'Design', 'betterdocs' ),
1550 + 'priority' => 30,
1551 + 'fields' => [
1552 + 'title-design' => [
1553 + 'name' => 'title-design-tab',
1554 + 'type' => 'section',
1555 + 'label' => __( 'Design', 'betterdocs' ),
1556 + 'priority' => 30,
1557 + 'fields' => $this->design_tab()
1558 + ]
1559 + ]
1560 + ] ),
1561 + 'tab-shortcodes' => apply_filters( 'betterdocs_settings_tab_shortcodes', [
1562 + 'label' => __( 'Shortcodes', 'betterdocs' ),
1563 + 'id' => 'tab-shortcodes',
1564 + 'classes' => 'tab-shortcodes',
1565 + 'priority' => 40,
1566 + 'fields' => [
1567 + 'title-shortcodes' => [
1568 + 'name' => 'title-shortcodes-tab',
1569 + 'type' => 'section',
1570 + 'label' => __( 'Shortcodes', 'betterdocs' ),
1571 + 'priority' => 40,
1572 + 'searchable' => true,
1573 + 'searchPlaceholder' => __( 'Search for shortcode', 'betterdocs' ),
1574 + 'searchNotFoundMessage' => '<img src="' . betterdocs()->assets->icon( 'not-found.svg', true ) . '"/><p>' . __( 'No Shortcodes Found with these keywords', 'betterdocs' ) . '</p>',
1575 + 'fields' => apply_filters( 'betterdocs_shortcode_fields', [
1576 + 'search_form' => [
1577 + 'name' => 'search_form',
1578 + 'type' => 'copy-to-clipboard',
1579 + 'label' => __( 'Search Form', 'betterdocs' ),
1580 + 'default' => '[betterdocs_search_form]',
1581 + 'readOnly' => true,
1582 + 'priority' => 1,
1583 + 'description' => __( '[betterdocs_search_form placeholder="Search..." heading="Heading" subheading="Subheading" category_search="true" search_button="true" popular_search="true"]', 'betterdocs' ),
1584 + 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1585 + 'descriptionCopyable' => true
1586 + ],
1587 + 'feedback_form' => [
1588 + 'name' => 'feedback_form',
1589 + 'type' => 'copy-to-clipboard',
1590 + 'label' => __( 'Feedback Form', 'betterdocs' ),
1591 + 'default' => '[betterdocs_feedback_form]',
1592 + 'readOnly' => true,
1593 + 'priority' => 2,
1594 + 'description' => __( '[betterdocs_feedback_form button_text="Send"]', 'betterdocs' ),
1595 + 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1596 + 'descriptionCopyable' => true
1597 + ],
1598 + 'category_grid' => [
1599 + 'name' => 'category_grid',
1600 + 'type' => 'copy-to-clipboard',
1601 + 'label' => __( 'Category Grid- Layout 1', 'betterdocs' ),
1602 + 'default' => '[betterdocs_category_grid]',
1603 + 'readOnly' => true,
1604 + 'priority' => 3,
1605 + 'description' => __( '[betterdocs_category_grid show_count="true" show_icon="true" masonry="true" column="3" posts_per_page="5" nested_subcategory="true" terms="term_ID, term_ID" terms_orderby="" terms_order="" multiple_knowledge_base="" kb_slug="" title_tag="h2" orderby="" order="" ]', 'betterdocs' ),
1606 + 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1607 + 'descriptionCopyable' => true
1608 + ],
1609 + 'category_box' => [
1610 + 'name' => 'category_box',
1611 + 'type' => 'copy-to-clipboard',
1612 + 'label' => __( 'Category Box- Layout 2', 'betterdocs' ),
1613 + 'default' => '[betterdocs_category_box]',
1614 + 'readOnly' => true,
1615 + 'priority' => 4,
1616 + 'description' => __( '[betterdocs_category_box orderby="" column="" nested_subcategory="" terms="" terms_orderby="" show_icon="" kb_slug="" title_tag="h2" multiple_knowledge_base="false" border_bottom="false"]', 'betterdocs' ),
1617 + 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1618 + 'descriptionCopyable' => true
1619 + ],
1620 + 'category_list' => [
1621 + 'name' => 'category_list',
1622 + 'type' => 'copy-to-clipboard',
1623 + 'label' => __( 'Category List', 'betterdocs' ),
1624 + 'default' => '[betterdocs_category_list]',
1625 + 'readOnly' => true,
1626 + 'priority' => 5,
1627 + 'description' => __( '[betterdocs_category_list orderby="" order="" posts_per_page="" nested_subcategory="" terms="" terms_orderby="" terms_order="" kb_slug="" multiple_knowledge_base="false" title_tag="h2"]', 'betterdocs' ),
1628 + 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1629 + 'descriptionCopyable' => true
1630 + ],
1631 + 'faq_modern_layout' => [
1632 + 'name' => 'faq_modern_layout',
1633 + 'type' => 'copy-to-clipboard',
1634 + 'label' => __( 'FAQ Layout - 1', 'betterdocs' ),
1635 + 'default' => '[betterdocs_faq_list_modern]',
1636 + 'readOnly' => true,
1637 + 'priority' => 13,
1638 + 'description' => __( '[betterdocs_faq_list_modern groups="group_id" class="" group_exclude="group_id" faq_heading="Frequently Asked Questions"]', 'betterdocs' ),
1639 + 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1640 + 'descriptionCopyable' => true
1641 + ],
1642 + 'faq_classic_layout' => [
1643 + 'name' => 'faq_classic_layout',
1644 + 'type' => 'copy-to-clipboard',
1645 + 'label' => __( 'FAQ Layout - 2', 'betterdocs' ),
1646 + 'default' => '[betterdocs_faq_list_classic]',
1647 + 'readOnly' => true,
1648 + 'priority' => 14,
1649 + 'description' => __( '[betterdocs_faq_list_classic groups="group_id" class="" group_exclude="group_id" faq_heading="Frequently Asked Questions"]', 'betterdocs' ),
1650 + 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1651 + 'descriptionCopyable' => true
1652 + ]
1653 + ] )
1654 + ]
1655 + ]
1656 + ] ),
1657 + 'tab-advance-settings' => apply_filters( 'betterdocs_settings_tab_advance', [
1658 + 'id' => 'tab-advance-settings',
1659 + 'label' => __( 'Advanced Settings', 'betterdocs' ),
1660 + 'priority' => 50,
1661 + 'fields' => [
1662 + 'title-advance-settings' => [
1663 + 'name' => 'title-advance-settings-tab',
1664 + 'type' => 'section',
1665 + 'label' => __( 'Advanced Settings', 'betterdocs' ),
1666 + 'priority' => 50,
1667 + 'fields' => apply_filters( 'betterdocs_internal_kb_fields', [
1668 + 'article_roles' => [
1669 + 'name' => 'article_roles',
1670 + 'type' => 'checkbox-select',
1671 + 'label' => __( 'Who Can Write Docs?', 'betterdocs' ),
1672 + 'priority' => 1,
1673 + 'multiple' => true,
1674 + 'search' => true,
1675 + 'is_pro' => true,
1676 + 'default' => [ 'administrator' ],
1677 + 'options' => $wp_roles
1678 + ],
1679 + 'settings_roles' => [
1680 + 'name' => 'settings_roles',
1681 + 'type' => 'checkbox-select',
1682 + 'label' => __( 'Who Can Edit Settings?', 'betterdocs' ),
1683 + 'priority' => 2,
1684 + 'multiple' => true,
1685 + 'is_pro' => true,
1686 + 'search' => true,
1687 + 'default' => [ 'administrator' ],
1688 + 'options' => $wp_roles
1689 + ],
1690 + 'analytics_roles' => [
1691 + 'name' => 'analytics_roles',
1692 + 'type' => 'checkbox-select',
1693 + 'label' => __( 'Who Can Check Analytics?', 'betterdocs' ),
1694 + 'priority' => 3,
1695 + 'multiple' => true,
1696 + 'is_pro' => true,
1697 + 'search' => true,
1698 + 'default' => [ 'administrator' ],
1699 + 'options' => $wp_roles
1700 + ],
1701 + 'enable_content_restriction' => [
1702 + 'name' => 'enable_content_restriction',
1703 + 'type' => 'toggle',
1704 + 'is_pro' => true,
1705 + 'priority' => 4,
1706 + 'label' => __( 'Internal Knowledge Base', 'betterdocs' ),
1707 + 'enable_disable_text_active' => true,
1708 + 'default' => [ 'all' ]
1709 + ],
1710 + 'content_visibility' => [
1711 + 'name' => 'content_visibility',
1712 + 'type' => 'checkbox-select',
1713 + 'label' => __( 'Restrict Access to', 'betterdocs' ),
1714 + 'label_subtitle' => __( 'Only selected User Roles will be able to view your Knowledge Base', 'betterdocs' ),
1715 + 'is_pro' => true,
1716 + 'priority' => 5,
1717 + 'multiple' => true,
1718 + 'search' => true,
1719 + 'default' => [ 'all' ],
1720 + 'placeholder' => __( 'Select any', 'betterdocs' ),
1721 + 'options' => $this->normalize_options( array_merge( [
1722 + 'all' => __( 'All logged in users', 'betterdocs' )
1723 + ], wp_roles()->role_names ) ),
1724 + 'rules' => Rules::is( 'enable_content_restriction', true ),
1725 + 'filterValue' => 'all'
1726 + ],
1727 + 'restrict_template' => [
1728 + 'name' => 'restrict_template',
1729 + 'type' => 'checkbox-select',
1730 + 'label' => __( 'Restriction on Docs', 'betterdocs' ),
1731 + 'label_subtitle' => __( 'Selected Docs pages will be restricted', 'betterdocs' ),
1732 + 'is_pro' => true,
1733 + 'priority' => 6,
1734 + 'multiple' => true,
1735 + 'search' => true,
1736 + 'default' => [ 'all' ],
1737 + 'placeholder' => __( 'Select any', 'betterdocs' ),
1738 + 'options' => $this->get_texanomy(),
1739 + 'rules' => Rules::is( 'enable_content_restriction', true ),
1740 + 'filterValue' => 'all'
1741 + ],
1742 + 'restrict_category' => [
1743 + 'name' => 'restrict_category',
1744 + 'type' => 'checkbox-select',
1745 + 'label' => __( 'Restriction on Docs Categories', 'betterdocs' ),
1746 + 'label_subtitle' => __( 'Selected Docs categories will be restricted', 'betterdocs' ),
1747 + 'is_pro' => true,
1748 + 'priority' => 7,
1749 + 'multiple' => true,
1750 + 'search' => true,
1751 + 'default' => [ 'all' ],
1752 + 'placeholder' => __( 'Select any', 'betterdocs' ),
1753 + 'options' => $this->get_terms( 'doc_category' ),
1754 + 'rules' => Rules::is( 'enable_content_restriction', true ),
1755 + 'filterValue' => 'all'
1756 + ],
1757 + 'restricted_redirect_url' => [
1758 + 'name' => 'restricted_redirect_url',
1759 + 'type' => 'text',
1760 + 'label' => __( 'Redirect URL', 'betterdocs' ),
1761 + 'label_subtitle' => __( 'Set a custom URL to redirect users without permissions when they try to access internal knowledge base. By default, restricted content will redirect to the "404 not found" page', 'betterdocs' ),
1762 + 'default' => '',
1763 + 'placeholder' => 'https://',
1764 + 'is_pro' => true,
1765 + 'priority' => 9,
1766 + 'rules' => Rules::is( 'enable_content_restriction', true )
1767 + ]
1768 + ] )
1769 + ]
1770 + ]
1771 + ] ),
1772 + 'tab-email-reporting' => apply_filters( 'betterdocs_settings_tab_email_reporting', [
1773 + 'id' => 'tab-email-reporting',
1774 + 'label' => __( 'Email Reporting', 'betterdocs' ),
1775 + 'priority' => 60,
1776 + 'fields' => [
1777 + 'title-email-reporting' => [
1778 + 'name' => 'title-email-reporting-tab',
1779 + 'type' => 'section',
1780 + 'label' => __( 'Email Reporting', 'betterdocs' ),
1781 + 'priority' => 60,
1782 + 'fields' => [
1783 + 'enable_reporting' => [
1784 + 'name' => 'enable_reporting',
1785 + 'label' => __( 'Email Reporting', 'betterdocs' ),
1786 + 'enable_disable_text_active' => true,
1787 + 'type' => 'toggle',
1788 + 'priority' => 1,
1789 + 'default' => 0
1790 + ],
1791 + 'reporting_frequency' => apply_filters( 'betterdocs_reporting_frequency_settings', [
1792 + 'name' => 'reporting_frequency',
1793 + 'type' => 'select',
1794 + 'label' => __( 'Reporting Frequency', 'betterdocs' ),
1795 + 'default' => 'betterdocs_weekly',
1796 + 'priority' => 2,
1797 + 'is_pro' => true,
1798 + 'options' => $this->normalize_options( [
1799 + 'betterdocs_daily' => __( 'Once Daily', 'betterdocs' ),
1800 + 'betterdocs_weekly' => __( 'Once Weekly', 'betterdocs' ),
1801 + 'betterdocs_monthly' => __( 'Once Monthly', 'betterdocs' )
1802 + ] ),
1803 + 'rules' => Rules::is( 'enable_reporting', true )
1804 + ] ),
1805 + 'reporting_day' => [
1806 + 'name' => 'reporting_day',
1807 + 'type' => 'select',
1808 + 'label' => __( 'Reporting Day', 'betterdocs' ),
1809 + 'default' => 'monday',
1810 + 'rules' => Rules::logicalRule( [
1811 + Rules::is( 'enable_reporting', true ),
1812 + Rules::is( 'reporting_frequency', 'betterdocs_weekly' )
1813 + ], 'and' ),
1814 + 'priority' => 3,
1815 + 'options' => $this->normalize_options( [
1816 + 'sunday' => __( 'Sunday', 'betterdocs' ),
1817 + 'monday' => __( 'Monday', 'betterdocs' ),
1818 + 'tuesday' => __( 'Tuesday', 'betterdocs' ),
1819 + 'wednesday' => __( 'Wednesday', 'betterdocs' ),
1820 + 'thursday' => __( 'Thursday', 'betterdocs' ),
1821 + 'friday' => __( 'Friday', 'betterdocs' ),
1822 + 'saturday' => __( 'Saturday', 'betterdocs' )
1823 + ] ),
1824 + 'label_subtitle' => __( 'This is only applicable for the “Weekly” report', 'betterdocs' )
1825 + ],
1826 + 'select_reporting_data' => apply_filters( 'betterdocs_select_reporting_data_settings', [
1827 + 'name' => 'select_reporting_data',
1828 + 'type' => 'checkbox-select',
1829 + 'label' => __( 'Select Reporting Data', 'betterdocs' ),
1830 + 'priority' => 4,
1831 + 'multiple' => true,
1832 + 'options' => $this->normalize_options( [
1833 + 'overview' => 'Overview',
1834 + 'top-docs' => 'Top Docs',
1835 + 'most-search' => 'Most Searched Keywords'
1836 + ] ),
1837 + 'default' => [ 'overview', 'top-docs', 'most-search' ],
1838 + 'is_pro' => true,
1839 + 'rules' => Rules::is( 'enable_reporting', true )
1840 + ] ),
1841 + 'reporting_email' => [
1842 + 'name' => 'reporting_email',
1843 + 'type' => 'text',
1844 + 'label' => __( 'Reporting Email', 'betterdocs' ),
1845 + 'default' => get_option( 'admin_email' ),
1846 + 'priority' => 5,
1847 + 'rules' => Rules::is( 'enable_reporting', true )
1848 + ],
1849 + 'reporting_subject' => apply_filters( 'betterdocs_reporting_subject_settings', [
1850 + 'name' => 'reporting_subject',
1851 + 'type' => 'textarea',
1852 + 'label' => __( 'Reporting Email Subject', 'betterdocs' ),
1853 + 'default' => wp_sprintf( // Translators: %s is replaced with the website name.
1854 + __( 'Your Documentation Performance of %s Website', 'betterdocs' ), get_bloginfo( 'name' ) ),
1855 + 'priority' => 6,
1856 + 'is_pro' => true,
1857 + 'rules' => Rules::is( 'enable_reporting', true )
1858 + ] ),
1859 + 'test_report' => [
1860 + 'name' => 'test_report',
1861 + 'label' => __( 'Reporting Test', 'betterdocs' ),
1862 + 'text' => __( 'Test Report', 'betterdocs' ),
1863 + 'type' => 'button',
1864 + 'priority' => 7,
1865 + 'rules' => Rules::is( 'enable_reporting', true ),
1866 + 'ajax' => [
1867 + 'on' => 'click',
1868 + 'api' => '/betterdocs/v1/reporting-test',
1869 + 'data' => [
1870 + 'enable_reporting' => '@enable_reporting',
1871 + 'select_reporting_data' => '@select_reporting_data',
1872 + 'reporting_subject' => '@reporting_subject',
1873 + 'reporting_email' => '@reporting_email',
1874 + 'reporting_day' => '@reporting_day',
1875 + 'reporting_frequency' => '@reporting_frequency'
1876 + ],
1877 + 'swal' => [
1878 + 'text' => __( 'Successfully Sent a Test Report in Your Email.', 'betterdocs' ),
1879 + 'icon' => 'success',
1880 + 'autoClose' => 2000
1881 + ]
1882 + ]
1883 + ]
1884 + ]
1885 + ]
1886 + ]
1887 + ] ),
1888 + 'tab-instant-answer' => apply_filters( 'betterdocs_settings_tab_instant_answer', [
1889 + 'id' => 'tab-instant-answer',
1890 + 'name' => 'tab-instant-answer',
1891 + 'type' => 'section',
1892 + 'label' => __( 'Instant Answer', 'betterdocs' ),
1893 + 'save' => false,
1894 + 'priority' => 70,
1895 + 'fields' => [
1896 + 'title-instant-answer' => [
1897 + 'name' => 'title-instant-answer-tab',
1898 + 'type' => 'section',
1899 + 'label' => __( 'Instant Answer', 'betterdocs' ),
1900 + 'priority' => 80,
1901 + 'save' => false,
1902 + 'showSubmit' => false,
1903 + 'fields' => apply_filters( 'betterdocs_instant_answer_fields', [
1904 + 'enable_disable_wrapper' => [
1905 + 'name' => 'enable_disable_wrapper',
1906 + 'type' => 'section',
1907 + 'priority' => 0,
1908 + 'save' => false,
1909 + 'fields' => [
1910 + 'enable_disable' => [
1911 + 'name' => 'enable_disable',
1912 + 'type' => 'toggle',
1913 + 'priority' => 100,
1914 + 'description' => __( 'Enable Instant Answer', 'betterdocs' ),
1915 + 'enable_disable_text_active' => false,
1916 + 'default' => false,
1917 + 'is_pro' => true
1918 + ]
1919 + ]
1920 + ]
1921 + ] )
1922 + ]
1923 + ]
1924 + ] ),
1925 + 'tab-ai-chatbot' => [
1926 + 'id' => 'tab-ai-chatbot',
1927 + 'name' => 'tab-ai-chatbot',
1928 + 'type' => 'section',
1929 + 'label' => __( 'AI Chatbot', 'betterdocs' ),
1930 + // 'is_pro' => ! defined('BETTERDOCS_PRO_VERSION'),
1931 + 'priority' => 75,
1932 + 'save' => false,
1933 + 'submit' => [
1934 + 'show' => false
1935 + ],
702 1936
703 - if ( '' !== $incoming && preg_match( '/\*{4,}/', $incoming ) ) {
704 - $settings[ $api_key_field ] = $stored_is_mask ? '' : $stored;
705 - }
706 - }
1937 + 'fields' => [
1938 + 'title-ai-chatbot' => apply_filters( 'betterdocs_settings_ai_chatbot_fields', [
1939 + 'name' => 'title-ai-chatbot-tab',
1940 + 'type' => 'section',
1941 + 'label' => __( 'AI Chatbot', 'betterdocs' ),
1942 + 'priority' => 60,
1943 + 'save' => false,
1944 + 'submit' => [
1945 + 'show' => false
1946 + ],
707 1947
708 - // Minimum-token policy: reject saves where a feature's max_token field is below the
709 - // per-model floor defined by AIHelper::get_min_tokens(). The model may be unchanged in
710 - // this submission, so fall back to the stored value when it isn't part of the payload.
711 - // Both token fields live under the AI Content Suite tab, so enforce the floor only when
712 - // that tab is the one being saved — saving any other settings page never trips it (e.g.
713 - // old users whose stored value predates the floor). When the active-tab hint is absent
714 - // (stale cached JS, the quick-setup wizard, or any programmatic caller) the loop is
715 - // skipped and the save is allowed through.
716 - $token_pairs = array(
717 - array(
718 - 'tab' => 'tab-betterdocs-ai',
719 - 'context' => 'write_with_ai',
720 - 'token_key' => 'ai_autowrite_max_token',
721 - 'model_key' => 'ai_model',
722 - 'label' => __( 'Write with AI', 'betterdocs' )
723 - ),
724 - array(
725 - 'tab' => 'tab-betterdocs-ai',
726 - 'context' => 'article_summary',
727 - 'token_key' => 'article_summary_max_token',
728 - 'model_key' => 'ai_model',
729 - 'label' => __( 'AI Doc Summarizer', 'betterdocs' )
730 - )
731 - );
732 - foreach ( $token_pairs as $pair ) {
733 - if ( $active_tab !== $pair[ 'tab' ] ) {
734 - continue;
735 - }
736 - if ( ! array_key_exists( $pair[ 'token_key' ], $settings ) ) {
737 - continue;
738 - }
739 - $incoming_tokens = (int) $settings[ $pair[ 'token_key' ] ];
740 - $incoming_model = isset( $settings[ $pair[ 'model_key' ] ] )
741 - ? $settings[ $pair[ 'model_key' ] ]
742 - : ( isset( $_old_settings[ $pair[ 'model_key' ] ] ) ? $_old_settings[ $pair[ 'model_key' ] ] : '' );
743 - $min = AIHelper::get_min_tokens( $pair[ 'context' ], $incoming_model );
744 - if ( $min > 0 && $incoming_tokens < $min ) {
745 - return new WP_Error(
746 - 'min_tokens_below_threshold',
747 - sprintf(
748 - /* translators: 1: feature label, 2: minimum tokens, 3: model id */
749 - __( '%1$s max tokens must be at least %2$d for %3$s.', 'betterdocs' ),
750 - $pair[ 'label' ],
751 - $min,
752 - $incoming_model
753 - )
754 - );
755 - }
756 - }
1948 + 'fields' => [
1949 + 'enable_ai_chatbot' => [
1950 + 'name' => 'enable_ai_chatbot',
1951 + 'label' => __( 'AI Chatbot', 'betterdocs' ),
1952 + 'description' => __( 'Enable AI Chatbot', 'betterdocs' ),
1953 + 'type' => 'toggle',
1954 + 'priority' => 5,
1955 + 'default' => 0,
1956 + 'is_pro' => true,
1957 + 'is_license_active' => false,
1958 + 'disabled' => ! betterdocs()->is_pro_active() || ! defined( 'BETTERDOCS_CHATBOT_FILE' )
1959 + ],
1960 + ]
1961 + ] ),
1962 + ]
1963 + ],
1964 + 'tab-ai-autowrite' => [
1965 + 'id' => 'tab-ai-autowrite',
1966 + 'name' => 'tab-ai-autowrite',
1967 + 'type' => 'section',
1968 + 'label' => __( 'Write with AI', 'betterdocs' ),
1969 + 'priority' => 75,
1970 + 'fields' => [
1971 + 'title-ai-autowrite' => apply_filters( 'betterdocs_settings_ai_autowrite_fields', [
1972 + 'name' => 'title-ai-autowrite-tab',
1973 + 'type' => 'section',
1974 + 'label' => __( 'Write with AI', 'betterdocs' ),
1975 + 'priority' => 60,
1976 + 'fields' => [
1977 + 'enable_write_with_ai' => [
1978 + 'name' => 'enable_write_with_ai',
1979 + 'type' => 'toggle',
1980 + 'priority' => 0,
1981 + 'label' => __( 'Write Docs with AI', 'betterdocs' ),
1982 + 'label_subtitle' => __( 'Generate AI based Documentation in your Gutenberg Editor', 'betterdocs' ),
1983 + 'enable_disable_text_active' => true,
1984 + 'default' => true
1985 + ],
1986 + 'enable_faq_write_with_ai' => [
1987 + 'name' => 'enable_faq_write_with_ai',
1988 + 'type' => 'toggle',
1989 + 'priority' => 5,
1990 + 'label' => __( 'Write FAQ with AI', 'betterdocs' ),
1991 + 'label_subtitle' => __( 'Generate AI based FAQ in your Editor', 'betterdocs' ),
1992 + 'enable_disable_text_active' => true,
1993 + 'default' => true
1994 + ],
1995 + 'ai_autowrite_api_key' => [
1996 + 'name' => 'ai_autowrite_api_key',
1997 + 'type' => 'text',
1998 + 'label' => __( 'API Key', 'betterdocs' ),
1999 + 'label_subtitle' => sprintf( /* translators: %s is a link to the documentation about generating an OpenAI API key. */ __( 'Check out this <a target="_blank" href="%s">documentation</a> to find out how to generate your OpenAI API Key.', 'betterdocs' ), esc_url( 'https://betterdocs.co/docs/write-with-ai/' ) ),
2000 + 'default' => '',
2001 + 'priority' => 10
2002 + ],
2003 + 'ai_autowrite_max_token' => [
2004 + 'name' => 'ai_autowrite_max_token',
2005 + 'type' => 'number',
2006 + 'label' => __( 'Set Max Tokens', 'betterdocs' ),
2007 + 'label_subtitle' => sprintf( // translators: %s is a link to more information about token limits.
2008 + __( 'Documentation will be generated based on the Token Limits you have set. For more information on Token Limits, you can check out this <a target="_blank" href="%s">link</a>.', 'betterdocs' ), esc_url( 'https://platform.openai.com/account/limits' ) ),
2009 + 'default' => 1500,
2010 + 'priority' => 15
2011 + ]
2012 + ]
2013 + ] )
2014 + ]
2015 + ]
2016 + ] ),
2017 + 'TAB_AI_CHATBOT' => get_option( 'enable_ai_chatbot' ),
2018 + 'CHATBOT_LICENSE' => get_option( 'betterdocs_chatbot_software__license_status' ),
2019 + 'PRO_ACTIVE' => is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ),
2020 + 'PRO_LICENSE' => get_option( 'betterdocs_pro_software__license_status' ),
2021 + ];
757 2022
758 - // @todo: sanitize the data before inject in DB.
759 - $_normalized_settings = $this->get_normalized_values( $settings );
760 - if ( $existing_plugins && isset( $_normalized_settings[ 'migration_step' ] ) && true == $_normalized_settings[ 'migration_step' ] ) {
761 - betterdocs()->kbmigration->migrate();
762 - }
763 - $_settings = wp_parse_args( $_normalized_settings, $_old_settings );
2023 + $settings = array_merge( $settings, $this->chatbot_active_localize() );
764 2024
765 - // Check if there are actual changes before saving.
766 - // update_option returns false when values serialize identically, which can happen
767 - // due to object caching or type normalization even when user made changes.
768 - $_has_changes = $_settings != $_old_settings;
2025 + return apply_filters( 'betterdocs_settings_args', $settings );
2026 + }
769 2027
770 - $_saved = $this->database->save( $this->base_key, $_settings );
2028 + /**
2029 + * @return array
2030 + */
2031 + public function chatbot_active_localize() {
2032 + return [
2033 + 'CHATBOT_ACTIVE' => is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' )
2034 + ];
2035 + }
771 2036
772 - do_action_ref_array( 'betterdocs::settings::saved', array( $_saved, $_settings, $_old_settings, &$this ) );
2037 + /**
2038 + * Call This Function As Helper, When Pro Is Deactivated, To Be Used As Settings Default Values, When Betterdocs Pro Is Deactivated
2039 + *
2040 + * @return array
2041 + */
2042 + public function pro_settings_default_values() {
2043 + return [
2044 + 'multiple_kb' => false,
2045 + 'enable_glossaries' => false,
2046 + 'enable_encyclopedia' => false,
2047 + 'analytics_from' => false,
2048 + 'unique_visitor_count' => false,
2049 + 'exclude_bot_analytics' => false,
2050 + 'show_attachment' => false,
2051 + 'show_related_docs' => false,
2052 + 'advance_search' => false,
2053 + 'child_category_exclude' => false,
2054 + 'kb_based_search' => false,
2055 + 'enable_disable' => false,
2056 + 'enable_content_restriction' => false
2057 + ];
2058 + }
773 2059
774 - // Return true if save succeeded OR if there were changes to attempt saving.
775 - // This handles cases where update_option returns false due to identical serialization
776 - // (e.g., object caching, type coercion during serialization).
777 - return $_saved || $_has_changes;
778 - }
2060 + public function import_export_settings( $settings ) {
2061 + if ( ! current_user_can( 'import' ) ) {
2062 + return $settings;
2063 + }
779 2064
780 - public function views( $hook ) {
781 - return betterdocs()->views->get( 'admin/settings' );
782 - }
2065 + $settings['tab-import-export'] = apply_filters( 'betterdocs_settings_tab_import_export', [
2066 + 'id' => 'tab-import-export',
2067 + 'name' => 'tab-import-export',
2068 + 'classes' => 'tab-import-export',
2069 + 'label' => __( 'Import / Export', 'betterdocs' ),
2070 + 'priority' => 80,
2071 + 'fields' => [
2072 + 'sections-import-export' => [
2073 + 'name' => 'sections-import-export',
2074 + 'type' => 'section',
2075 + 'label' => __( 'Import / Export', 'betterdocs' ),
2076 + 'priority' => 30,
2077 + 'fields' => [
2078 + 'all-tab-import-export' => [
2079 + 'id' => 'all-tab-import-export',
2080 + 'name' => 'all-tab-import-export',
2081 + 'label' => __( 'Import Export Settings', 'betterdocs' ),
2082 + 'classes' => 'tab-layout',
2083 + 'type' => 'tab',
2084 + 'active' => 'import',
2085 + 'completionTrack' => true,
2086 + 'sidebar' => false,
2087 + 'save' => false,
2088 + 'title' => false,
2089 + 'config' => [
2090 + 'active' => 'import',
2091 + 'sidebar' => false,
2092 + 'title' => false
2093 + ],
2094 + 'submit' => [
2095 + 'show' => false
2096 + ],
2097 + 'step' => [
2098 + 'show' => false
2099 + ],
2100 + 'priority' => 20,
2101 + 'fields' => [
2102 + 'import' => [
2103 + 'id' => 'import',
2104 + 'name' => 'import',
2105 + 'type' => 'section',
2106 + 'label' => __( 'Import', 'betterdocs' ),
2107 + 'priority' => 1,
2108 + 'fields' => [
2109 + 'import_tab_nested' => [
2110 + 'id' => 'import_tab_nested',
2111 + 'name' => 'import_tab_nested',
2112 + 'label' => __( 'Import', 'betterdocs' ),
2113 + 'classes' => 'tab-nested-layout',
2114 + 'type' => 'tab',
2115 + 'active' => 'import_docs_nested',
2116 + 'completionTrack' => true,
2117 + 'sidebar' => false,
2118 + 'save' => false,
2119 + 'title' => false,
2120 + 'config' => [
2121 + 'active' => 'import_docs_nested',
2122 + 'sidebar' => false,
2123 + 'title' => false
2124 + ],
2125 + 'submit' => [
2126 + 'show' => false
2127 + ],
2128 + 'step' => [
2129 + 'show' => false
2130 + ],
2131 + 'priority' => 1,
2132 + 'fields' => [
2133 + 'import_docs_nested' => [
2134 + 'id' => 'import_docs_nested',
2135 + 'name' => 'import_docs_nested',
2136 + 'type' => 'section',
2137 + 'label' => __( 'Import Docs', 'betterdocs' ),
2138 + 'priority' => 1,
2139 + 'fields' => [
2140 + 'import_docs' => [
2141 + 'name' => 'import_docs',
2142 + 'type' => 'importerupload',
2143 + 'label' => __( 'Import Docs', 'betterdocs' ),
2144 + 'label_subtitle' => wp_sprintf( // Translators: %1$s is a link to download a sample CSV file.
2145 + __( 'To import your Docs, please upload the .xml / .csv file here. <a href="%1$s">Download sample csv file</a>', 'betterdocs' ), betterdocs()->assets->icon( 'BetterDocs-sample-data.csv', true ) ),
2146 + 'text' => [
2147 + 'normal' => __( 'Proceed', 'betterdocs' ),
2148 + 'saved' => __( 'Proceed', 'betterdocs' ),
2149 + 'loading' => __( 'Importing...', 'betterdocs' ),
2150 + 'exists_notice' => __( 'It seems like documentations with same slugs already exist on your website. What would you like to do?', 'betterdocs' )
2151 + ],
2152 + 'ajax' => [
2153 + 'on' => 'click',
2154 + 'api' => '/betterdocs/v1/import-docs',
2155 + 'swal' => [
2156 + 'text' => __( 'Import completed successfully.', 'betterdocs' ),
2157 + 'icon' => 'success',
2158 + 'autoClose' => 2000
2159 + ]
2160 + ],
2161 + 'file_type' => '.xml, .csv',
2162 + 'priority' => 1
2163 + ]
2164 + ]
2165 + ],
783 2166
784 - public function save_default_settings() {
785 - $_settings = $this->get_all();
2167 + 'import_settings_nested' => [
2168 + 'id' => 'import_settings_nested',
2169 + 'name' => 'import_settings_nested',
2170 + 'type' => 'section',
2171 + 'label' => __( 'Import Settings', 'betterdocs' ),
2172 + 'priority' => 1,
2173 + 'fields' => [
2174 + 'settings_importer' => [
2175 + 'name' => 'settings_importer',
2176 + 'type' => 'settingsuploader',
2177 + 'label' => __( 'Import Settings', 'betterdocs' ),
2178 + 'label_subtitle' => __( 'To import BetterDocs Settings, please upload BetterDocs settings you have exported from another website in .json format', 'betterdocs' ),
2179 + 'reset' => __( 'Change', 'betterdocs' ),
2180 + 'priority' => 1
2181 + ],
2182 + 'import_settings' => [
2183 + 'name' => 'import_settings',
2184 + 'type' => 'button',
2185 + 'rules' => Rules::is( 'settings_importer', null, true ),
2186 + 'text' => [
2187 + 'normal' => __( 'Proceed', 'betterdocs' ),
2188 + 'saved' => __( 'Proceed', 'betterdocs' ),
2189 + 'loading' => __( 'Importing...', 'betterdocs' )
2190 + ],
2191 + 'ajax' => [
2192 + 'on' => 'click',
2193 + 'api' => '/betterdocs/v1/import-settings',
2194 + 'data' => [
2195 + 'settings' => '@settings_importer'
2196 + ],
2197 + 'swal' => [
2198 + 'text' => __( 'Import completed successfully.', 'betterdocs' ),
2199 + 'icon' => 'success',
2200 + 'autoClose' => 1000
2201 + ],
2202 + 'reload' => true
2203 + ],
2204 + 'priority' => 2
2205 + ]
2206 + ]
2207 + ]
2208 + ]
2209 + ]
2210 + ]
2211 + ],
2212 + 'export' => [
2213 + 'id' => 'export',
2214 + 'name' => 'export',
2215 + 'type' => 'section',
2216 + 'label' => __( 'Export', 'betterdocs' ),
2217 + 'priority' => 1,
2218 + 'fields' => [
2219 + 'export_tab_nested' => [
2220 + 'id' => 'export_tab_nested',
2221 + 'name' => 'export_tab_nested',
2222 + 'label' => __( 'Export', 'betterdocs' ),
2223 + 'classes' => 'tab-nested-layout',
2224 + 'type' => 'tab',
2225 + 'active' => 'export_docs_nested',
2226 + 'completionTrack' => true,
2227 + 'sidebar' => false,
2228 + 'save' => false,
2229 + 'title' => false,
2230 + 'config' => [
2231 + 'active' => 'export_docs_nested',
2232 + 'sidebar' => false,
2233 + 'title' => false
2234 + ],
2235 + 'submit' => [
2236 + 'show' => false
2237 + ],
2238 + 'step' => [
2239 + 'show' => false
2240 + ],
2241 + 'priority' => 1,
2242 + 'fields' => [
2243 + 'export_docs_nested' => [
2244 + 'id' => 'export_docs_nested',
2245 + 'name' => 'export_docs_nested',
2246 + 'type' => 'section',
2247 + 'label' => __( 'Export Docs', 'betterdocs' ),
2248 + 'priority' => 1,
2249 + 'fields' => apply_filters( 'betterdocs_export_fields', [
2250 + 'export_type' => [
2251 + 'name' => 'export_type',
2252 + 'label' => __( 'Select Docs Type', 'betterdocs' ),
2253 + 'label_subtitle' => __( 'Choose an export type: All Docs, a specific Knowledge Base, or a Doc Category', 'betterdocs' ),
2254 + 'type' => 'select',
2255 + 'default' => 'docs',
2256 + 'priority' => 3,
2257 + 'search' => true,
2258 + 'options' => $this->normalize_options( apply_filters( 'betterdocs_export_type_options', [
2259 + 'docs' => __( 'Docs', 'betterdocs' ),
2260 + 'doc_category' => __( 'Docs Category', 'betterdocs' ),
2261 + 'glossaries' => __( 'Glossaries', 'betterdocs' )
2262 + ] ) )
2263 + ],
2264 + 'export_docs' => [
2265 + 'name' => 'export_docs',
2266 + 'type' => 'checkbox-select',
2267 + 'label' => __( 'Select Docs', 'betterdocs' ),
2268 + 'label_subtitle' => __( 'Selected docs will be included in the export.', 'betterdocs' ),
2269 + 'priority' => 4,
2270 + 'multiple' => true,
2271 + 'search' => true,
2272 + 'default' => [ 'all' ],
2273 + 'placeholder' => __( 'Select any', 'betterdocs' ),
2274 + 'options' => array_merge( [
2275 + [
2276 + 'value' => 'all',
2277 + 'label' => 'All'
2278 + ]
2279 + ], $this->docs() ),
2280 + 'filterValue' => 'all',
2281 + 'rules' => Rules::is( 'export_type', 'docs' )
2282 + ],
2283 + 'export_categories' => [
2284 + 'name' => 'export_categories',
2285 + 'type' => 'checkbox-select',
2286 + 'label' => __( 'Select Categories', 'betterdocs' ),
2287 + 'label_subtitle' => __( 'Selected categories and its docs will be included in the export.', 'betterdocs' ),
2288 + 'priority' => 6,
2289 + 'multiple' => true,
2290 + 'search' => true,
2291 + 'default' => [ 'all' ],
2292 + 'placeholder' => __( 'Select any', 'betterdocs' ),
2293 + 'options' => $this->get_terms( 'doc_category' ),
2294 + 'filterValue' => 'all',
2295 + 'rules' => Rules::is( 'export_type', 'doc_category' )
2296 + ],
2297 + 'export_glossaries' => [
2298 + 'name' => 'export_glossaries',
2299 + 'type' => 'checkbox-select',
2300 + 'label' => __( 'Select Glossaries', 'betterdocs' ),
2301 + 'label_subtitle' => __( 'Selected glossary terms will be exported.', 'betterdocs' ),
2302 + 'priority' => 7,
2303 + 'multiple' => true,
2304 + 'search' => true,
2305 + 'default' => [ 'all' ],
2306 + 'placeholder' => __( 'Select any', 'betterdocs' ),
2307 + 'options' => $this->get_terms( 'glossaries' ),
2308 + 'filterValue' => 'all',
2309 + 'rules' => Rules::is( 'export_type', 'glossaries' )
2310 + ],
2311 + 'file_type' => [
2312 + 'name' => 'file_type',
2313 + 'label' => __( 'Select File Type', 'betterdocs' ),
2314 + 'label_subtitle' => __( 'Choose a file type', 'betterdocs' ),
2315 + 'type' => 'select',
2316 + 'default' => 'xml',
2317 + 'priority' => 8,
2318 + 'search' => true,
2319 + 'options' => $this->normalize_options( apply_filters( 'betterdocs_export_file_type_options', [
2320 + 'xml' => __( '.xml', 'betterdocs' ),
2321 + 'csv' => __( '.csv', 'betterdocs' )
2322 + ] ) )
2323 + ],
2324 + 'enable_export_faq' => [
2325 + 'name' => 'enable_export_faq',
2326 + 'type' => 'toggle',
2327 + 'priority' => 9,
2328 + 'label' => __( 'Export FAQ', 'betterdocs' ),
2329 + 'label_subtitle' => __( 'Export FAQ Related Terms & Posts', 'betterdocs' ),
2330 + 'enable_disable_text_active' => true,
2331 + 'default' => true,
2332 + 'rules' => Rules::is( 'export_type', 'glossaries', true )
2333 + ],
2334 + 'export_docs_btn' => [
2335 + 'name' => 'export_docs_btn',
2336 + 'text' => [
2337 + 'normal' => __( 'Proceed', 'betterdocs' ),
2338 + 'saved' => __( 'Proceed', 'betterdocs' ),
2339 + 'loading' => __( 'Exporting...', 'betterdocs' )
2340 + ],
2341 + 'type' => 'button',
2342 + 'priority' => 10,
2343 + 'ajax' => [
2344 + 'on' => 'click',
2345 + 'api' => '/betterdocs/v1/export-docs',
2346 + 'data' => [
2347 + 'export_type' => '@export_type',
2348 + 'export_docs' => '@export_docs',
2349 + 'export_kbs' => '@export_kbs',
2350 + 'export_categories' => '@export_categories',
2351 + 'export_glossaries' => '@export_glossaries',
2352 + 'file_type' => '@file_type',
2353 + 'enable_export_faq' => '@enable_export_faq'
2354 + ],
2355 + 'swal' => [
2356 + 'text' => __( 'Exported Successfully.', 'betterdocs' ),
2357 + 'icon' => 'success',
2358 + 'autoClose' => 2000
2359 + ]
2360 + ]
2361 + ]
2362 + ] )
2363 + ],
786 2364
787 - return $this->database->save( $this->base_key, $_settings );
788 - }
2365 + 'export_settings_nested' => [
2366 + 'id' => 'export_settings_nested',
2367 + 'name' => 'export_settings_nested',
2368 + 'type' => 'section',
2369 + 'label' => __( 'Export Settings', 'betterdocs' ),
2370 + 'priority' => 1,
2371 + 'fields' => [
2372 + 'export_settings' => [
2373 + 'name' => 'export_settings',
2374 + 'label' => __( 'Export Settings', 'betterdocs' ),
2375 + 'label_subtitle' => __( 'Simply click on “Export Settings” button to download your BetterDocs settings in .json format', 'betterdocs' ),
2376 + 'text' => [
2377 + 'normal' => __( 'Export Settings', 'betterdocs' ),
2378 + 'saved' => __( 'Export Settings', 'betterdocs' ),
2379 + 'loading' => __( 'Exporting...', 'betterdocs' )
2380 + ],
2381 + 'type' => 'button',
2382 + 'priority' => 8,
2383 + 'ajax' => [
2384 + 'on' => 'click',
2385 + 'api' => '/betterdocs/v1/export-settings',
2386 + 'data' => [
2387 + 'betterdocs_settings' => get_option( 'betterdocs_settings' )
2388 + ],
2389 + 'swal' => [
2390 + 'text' => __( 'File downloaded successfully.', 'betterdocs' ),
2391 + 'icon' => 'success',
2392 + 'autoClose' => 2000
2393 + ]
2394 + ]
2395 + ]
2396 + ]
2397 + ]
2398 + ]
2399 + ]
2400 + ]
2401 + ]
2402 + ]
2403 + ]
2404 + ]
2405 + ]
2406 + ]
2407 + ] );
789 2408
790 - public function get_pages() {
791 - $_pages = betterdocs()->query->get_posts( array(
792 - 'post_type' => 'page',
793 - 'numberposts' => -1,
794 - 'post_status' => 'publish',
795 - 'posts_per_page' => -1
796 - ) );
2409 + return $settings;
2410 + }
797 2411
798 - $__pages = array();
2412 + public function normalize_options( $options ) {
2413 + return GlobalFields::normalize_fields( $options );
2414 + }
799 2415
800 - if ( ! empty( $_pages ) ) {
801 - $__pages[ 0 ] = __( 'Select a Page', 'betterdocs' );
802 - foreach ( $_pages->posts as $page ) {
803 - $__pages[ $page->ID ] = esc_html( $page->post_title );
804 - }
805 - }
2416 + public function get_texanomy() {
2417 + $docs_tax = $this->database->get_cache( 'betterdocs::settings::taxonomies' );
806 2418
807 - return $__pages;
808 - }
2419 + if ( $docs_tax ) {
2420 + return $docs_tax;
2421 + }
809 2422
810 - public function settings_args() {
811 - $wp_roles = $this->normalize_options( $this->get_roles() );
2423 + $taxonomies = get_taxonomies( [
2424 + 'object_type' => [ 'docs' ]
2425 + ], 'objects' );
812 2426
813 - $roles_for_ikb = $this->normalize_options( array_merge( array( 'all' => __( 'All logged in users', 'betterdocs' ) ), wp_roles()->role_names ) );
2427 + $docs_tax = [
2428 + 'all' => 'All Docs Archive',
2429 + 'docs' => 'Docs Page'
2430 + ];
2431 + foreach ( $taxonomies as $key => $value ) {
2432 + $docs_tax[ $key ] = $value->label;
2433 + }
2434 + unset( $docs_tax['doc_tag'] );
814 2435
815 - unset( $roles_for_ikb[ 'administrator' ] );
2436 + $docs_tax = $this->normalize_options( $docs_tax );
2437 + if ( count( $docs_tax ) > 2 ) {
2438 + $this->database->set_cache( 'betterdocs::settings::taxonomies', $docs_tax );
2439 + }
816 2440
817 - $settings = array(
818 - 'id' => 'betterdocs_settings_metabox_wrapper',
819 - 'title' => __( 'betterdocs', 'betterdocs' ),
820 - 'object_types' => array( 'betterdocs' ),
821 - 'context' => 'normal',
822 - 'priority' => 'high',
823 - 'show_header' => false,
824 - 'tabnumber' => false,
825 - 'is_pro_active' => betterdocs()->is_pro_active(),
826 - 'logoURL' => betterdocs()->assets->icon( 'betterdocs-icon.svg', true ),
827 - 'layout' => 'vertical',
828 - 'config' => array(
829 - 'active' => 'tab-general',
830 - 'sidebar' => true,
831 - 'title' => false
832 - ),
833 - 'submit' => array(
834 - 'show' => true,
835 - 'label' => __( 'Save', 'betterdocs' ),
836 - 'loadingLabel' => __( 'Saving...', 'betterdocs' ),
837 - 'class' => 'save-settings',
838 - 'rules' => Rules::logicalRule( array(
839 - Rules::is( 'config.active', 'tab-design', true ),
840 - Rules::is( 'config.active', 'tab-shortcodes', true ),
841 - Rules::is( 'config.active', 'tab-instant-answer', true ),
842 - Rules::is( 'config.active', 'tab-import-export', true ),
843 - Rules::is( 'config.active', 'tab-migration', true )
844 - ), 'and' )
845 - ),
846 - 'values' => betterdocs()->is_pro_active() ? $this->get_all() : array_merge( $this->get_all(), $this->pro_settings_default_values() ),
847 - 'tabs' => apply_filters( 'betterdocs_settings_tabs', array(
848 - 'tab-general' => apply_filters( 'betterdocs_settings_tab_general', array(
849 - 'id' => 'tab-general',
850 - 'label' => __( 'General', 'betterdocs' ),
851 - 'classes' => 'tab-general',
852 - 'priority' => 10,
853 - 'fields' => array(
854 - 'title-general' => apply_filters( 'betterdocs_encyclopedia_settings', array(
855 - 'name' => 'title-general-tab',
856 - 'type' => 'section',
857 - 'label' => __( 'General Settings', 'betterdocs' ),
858 - 'priority' => 10,
859 - 'fields' => array(
860 - 'multiple_kb' => apply_filters( 'betterdocs_multi_kb_settings', array(
861 - 'name' => 'multiple_kb',
862 - 'type' => 'toggle',
863 - 'label' => __( 'Multiple Knowledge Base', 'betterdocs' ),
864 - 'enable_disable_text_active' => true,
865 - 'default' => '',
866 - 'priority' => 1,
867 - 'is_pro' => true
868 - ) ),
869 - 'builtin_doc_page' => array(
870 - 'name' => 'builtin_doc_page',
871 - 'type' => 'toggle',
872 - 'label' => __( 'Built-in Documentation Page', 'betterdocs' ),
873 - 'enable_disable_text_active' => true,
874 - 'default' => 1,
875 - 'priority' => 2
876 - ),
877 - 'enable_category_hierarchy_slugs' => array(
878 - 'name' => 'enable_category_hierarchy_slugs',
879 - 'type' => 'toggle',
880 - 'label' => __( 'Enable Category Hierarchy Slug', 'betterdocs' ),
881 - 'enable_disable_text_active' => true,
882 - 'default' => false,
883 - 'priority' => 3,
884 - 'label_subtitle' => __( "Shows Hierarchy Based Permalink Slugs For Doc Categories & Single Doc Page", 'betterdocs' )
885 - ),
886 - 'breadcrumb_doc_title' => array(
887 - 'name' => 'breadcrumb_doc_title',
888 - 'type' => 'text',
889 - 'label' => __( 'Documentation Page Title', 'betterdocs' ),
890 - 'default' => __( 'Docs', 'betterdocs' ),
891 - 'priority' => 4,
892 - 'rules' => Rules::is( 'builtin_doc_page', true )
893 - ),
894 - 'docs_slug' => array(
895 - 'name' => 'docs_slug',
896 - 'type' => 'text',
897 - 'label' => __( 'BetterDocs Root Slug', 'betterdocs' ),
898 - 'default' => 'docs',
899 - 'priority' => 5,
900 - 'rules' => Rules::is( 'builtin_doc_page', true )
901 - ),
902 - 'docs_page' => array(
903 - 'name' => 'docs_page',
904 - 'label' => __( 'Docs Page', 'betterdocs' ),
905 - 'type' => 'select',
906 - 'default' => 0,
907 - 'priority' => 6,
908 - 'search' => true,
909 - 'options' => $this->normalize_options( $this->get_pages() ),
910 - 'label_subtitle' => __( 'You will need to insert BetterDocs Shortcode inside the page. This page will be used as docs permalink.', 'betterdocs' ),
911 - 'rules' => Rules::is( 'builtin_doc_page', false )
912 - ),
2441 + return $docs_tax;
2442 + }
913 2443
914 - 'category_slug' => array(
915 - 'name' => 'category_slug',
916 - 'type' => 'text',
917 - 'label' => __( 'Custom Category Slug', 'betterdocs' ),
918 - 'default' => 'docs-category',
919 - 'priority' => 7
920 - ),
921 - 'tag_slug' => array(
922 - 'name' => 'tag_slug',
923 - 'type' => 'text',
924 - 'label' => __( 'Custom Tag Slug', 'betterdocs' ),
925 - 'default' => 'docs-tag',
926 - 'priority' => 8
927 - ),
928 - 'permalink_structure' => array(
929 - 'name' => 'permalink_structure',
930 - 'type' => 'permalink_structure',
931 - 'label' => __( 'Single Docs Permalink', 'betterdocs' ),
932 - 'default' => PostType::permalink_structure(),
933 - 'priority' => 9,
934 - 'tags' => $this->normalize_options( array(
935 - '%doc_category%' => '%doc_category%',
936 - '%knowledge_base%' => '%knowledge_base%'
937 - ) ),
938 - 'label_subtitle' => __( 'Make sure to keep Docs Root Slug in the Single Docs Permalink. You are not able to keep it blank. You can use the available tags from below.', 'betterdocs' )
939 - ),
940 - 'enable_glossaries' => array(
941 - 'name' => 'enable_glossaries',
942 - 'type' => 'toggle',
943 - 'label' => __( 'Show Glossary', 'betterdocs' ),
944 - 'label_subtitle' => __( 'Enable the glossary feature to allow users to look up definitions for terms used within your encyclopedia or glossaries themselves.', 'betterdocs' ),
945 - 'enable_disable_text_active' => true,
946 - 'default' => false,
947 - 'priority' => 10,
948 - 'is_pro' => true
949 - ),
950 - 'enable_encyclopedia' => array(
951 - 'name' => 'enable_encyclopedia',
952 - 'type' => 'toggle',
953 - 'label' => __( 'Built-in Encyclopedia Page', 'betterdocs' ),
954 - 'enable_disable_text_active' => true,
955 - 'default' => false,
956 - 'priority' => 11,
957 - 'is_pro' => true
958 - ),
959 - 'enable_faq_schema' => array(
960 - 'name' => 'enable_faq_schema',
961 - 'type' => 'toggle',
962 - 'label' => __( 'FAQ Schema', 'betterdocs' ),
963 - 'enable_disable_text_active' => true,
964 - 'default' => '',
965 - 'priority' => 12
966 - ),
967 - 'analytics_from' => array(
968 - 'name' => 'analytics_from',
969 - 'type' => 'select',
970 - 'label' => __( 'Analytics From', 'betterdocs' ),
971 - 'options' => $this->normalize_options( array(
972 - 'everyone' => __( 'Everyone', 'betterdocs' ),
973 - 'guests' => __( 'Guests Only', 'betterdocs' ),
974 - 'registered_users' => __( 'Registered Users Only', 'betterdocs' )
975 - ) ),
976 - 'default' => 'everyone',
977 - 'priority' => 13,
978 - 'is_pro' => true
979 - ),
980 - 'unique_visitor_count' => array(
981 - 'name' => 'unique_visitor_count',
982 - 'type' => 'toggle',
983 - 'label' => __( 'Unique Visitor Count', 'betterdocs' ),
984 - 'enable_disable_text_active' => true,
985 - 'default' => false,
986 - 'priority' => 14,
987 - 'is_pro' => true
988 - ),
989 - 'exclude_bot_analytics' => array(
990 - 'name' => 'exclude_bot_analytics',
991 - 'type' => 'toggle',
992 - 'label' => __( 'Exclude Bot Analytics', 'betterdocs' ),
993 - 'enable_disable_text_active' => true,
994 - 'default' => false,
995 - 'priority' => 15,
996 - 'is_pro' => true
997 - )
2444 + public function get_terms( $taxonomy ) {
2445 + $_cache_key = 'betterdocs::settings::terms::' . trim( $taxonomy );
2446 + $docs_tax = $this->database->get_cache( $_cache_key );
998 2447
999 - )
1000 - ) )
1001 - )
1002 - ) ),
1003 - 'tab-layout' => apply_filters( 'betterdocs_settings_tab_layout', array(
1004 - 'id' => 'tab-layout',
1005 - 'label' => __( 'Layout', 'betterdocs' ),
1006 - 'classes' => 'tab-layout',
1007 - 'priority' => 20,
1008 - 'fields' => array(
1009 - 'title-layout' => array(
1010 - 'name' => 'title-layout-tab',
1011 - 'type' => 'section',
1012 - 'label' => __( 'Layout Settings', 'betterdocs' ),
1013 - 'priority' => 20,
1014 - 'fields' => array(
1015 - 'tab-sidebar-layout' => apply_filters( 'betterdocs_settings_tab_sidebar_layout', array(
1016 - 'id' => 'tab-sidebar-layout',
1017 - 'name' => 'tab_sidebar_layout',
1018 - 'label' => __( 'Layout Settings', 'betterdocs' ),
1019 - 'classes' => 'tab-layout',
1020 - 'type' => 'tab',
1021 - 'active' => 'layout_documentation_page',
1022 - 'completionTrack' => true,
1023 - 'sidebar' => false,
1024 - 'save' => false,
1025 - 'title' => false,
1026 - 'config' => array(
1027 - 'active' => 'layout_documentation_page',
1028 - 'sidebar' => false,
1029 - 'title' => false
1030 - ),
1031 - 'submit' => array(
1032 - 'show' => false
1033 - ),
1034 - 'step' => array(
1035 - 'show' => false
1036 - ),
1037 - 'priority' => 20,
1038 - 'fields' => array(
1039 - 'layout_documentation_page' => array(
1040 - 'id' => 'layout_documentation_page',
1041 - 'name' => 'layout_documentation_page',
1042 - 'type' => 'section',
1043 - 'label' => __( 'Documentation Page', 'betterdocs' ),
1044 - 'priority' => 1,
1045 - 'fields' => array(
1046 - 'tab-nested-layout-1' => array(
1047 - 'id' => 'tab-nested-layout-1',
1048 - 'name' => 'tab_nested_layout_1',
1049 - 'label' => __( 'Documentation Page', 'betterdocs' ),
1050 - 'classes' => 'tab-nested-layout',
1051 - 'type' => 'tab',
1052 - 'active' => 'layout_documentation_page_general',
1053 - 'completionTrack' => true,
1054 - 'sidebar' => false,
1055 - 'save' => false,
1056 - 'title' => false,
1057 - 'config' => array(
1058 - 'active' => 'layout_documentation_page_general',
1059 - 'sidebar' => false,
1060 - 'title' => false
1061 - ),
1062 - 'submit' => array(
1063 - 'show' => false
1064 - ),
1065 - 'step' => array(
1066 - 'show' => false
1067 - ),
1068 - 'priority' => 1,
1069 - 'fields' => array(
1070 - 'layout_documentation_page_general' => array(
1071 - 'id' => 'layout_documentation_page_general',
1072 - 'name' => 'layout_documentation_page_general',
1073 - 'type' => 'section',
1074 - 'label' => __( 'General', 'betterdocs' ),
1075 - 'priority' => 1,
1076 - 'fields' => array(
1077 - 'docs_list_icon' => array(
1078 - 'name' => 'docs_list_icon',
1079 - 'type' => 'media',
1080 - 'value' => '',
1081 - 'label' => __( 'Docs List Icon', 'betterdocs' ),
1082 - 'label_subtitle' => __( 'Upload your own preferred document list icon', 'betterdocs' ),
1083 - 'priority' => 0
1084 - ),
1085 - 'category_title_link' => array(
1086 - 'name' => 'category_title_link',
1087 - 'type' => 'toggle',
1088 - 'label' => __( 'Category Title Link', 'betterdocs' ),
1089 - 'label_subtitle' => __( 'This setting is applicable for category grid layout', 'betterdocs' ),
1090 - 'enable_disable_text_active' => true,
1091 - 'default' => false,
1092 - 'priority' => 0
1093 - ),
1094 - 'masonry_layout' => array(
1095 - 'name' => 'masonry_layout',
1096 - 'type' => 'toggle',
1097 - 'label' => __( 'Masonry', 'betterdocs' ),
1098 - 'enable_disable_text_active' => true,
1099 - 'default' => 1,
1100 - 'priority' => 1
1101 - ),
1102 - 'archive_lazy_load_descendants' => array(
1103 - 'name' => 'archive_lazy_load_descendants',
1104 - 'type' => 'toggle',
1105 - 'label' => __( 'Lazy Load Sidebar Docs & Subcategories', 'betterdocs' ),
1106 - 'label_subtitle' => __( 'Applies to the Sidebar layout wherever it appears — single docs, category archives, and the Sidebar widget/block. Off by default: enable to render only the active category upfront and fetch the rest on click (or on scroll for the Memphis layout), cutting initial HTML size on large knowledge bases.', 'betterdocs' ),
1107 - 'enable_disable_text_active' => true,
1108 - 'default' => false,
1109 - 'priority' => 2
1110 - ),
1111 - 'nested_subcategory' => array(
1112 - 'name' => 'nested_subcategory',
1113 - 'type' => 'toggle',
1114 - 'label' => __( 'Nested Sub Category', 'betterdocs' ),
1115 - 'enable_disable_text_active' => true,
1116 - 'default' => '',
1117 - 'priority' => 3
1118 - ),
1119 - 'column_number' => array(
1120 - 'name' => 'column_number',
1121 - 'type' => 'number',
1122 - 'label' => __( 'Number Of Columns', 'betterdocs' ),
1123 - 'label_subtitle' => __( 'This setting is not applicable for sleek layout.', 'betterdocs' ),
1124 - 'default' => 3,
1125 - 'priority' => 4
1126 - ),
1127 - 'posts_number' => apply_filters( 'betterdocs_posts_number', array(
1128 - 'name' => 'posts_number',
1129 - 'type' => 'number',
1130 - 'label' => __( 'Number Of Docs', 'betterdocs' ),
1131 - 'label_subtitle' => __( 'This setting is not applicable for handbook layout.', 'betterdocs' ),
1132 - 'default' => 10,
1133 - 'priority' => 5
1134 - ) ),
1135 - 'post_count' => array(
1136 - 'name' => 'post_count',
1137 - 'type' => 'toggle',
1138 - 'label' => __( 'Doc Count', 'betterdocs' ),
1139 - 'enable_disable_text_active' => true,
1140 - 'default' => 1,
1141 - 'priority' => 6
1142 - ),
1143 - 'count_text' => array(
1144 - 'name' => 'count_text',
1145 - 'type' => 'text',
1146 - 'label' => __( 'Count Text', 'betterdocs' ),
1147 - 'default' => __( 'Docs', 'betterdocs' ),
1148 - 'priority' => 7
1149 - ),
1150 - 'count_text_singular' => array(
1151 - 'name' => 'count_text_singular',
1152 - 'type' => 'text',
1153 - 'label' => __( 'Count Text Singular', 'betterdocs' ),
1154 - 'default' => __( 'Doc', 'betterdocs' ),
1155 - 'priority' => 8
1156 - ),
1157 - 'exploremore_btn' => array(
1158 - 'name' => 'exploremore_btn',
1159 - 'type' => 'toggle',
1160 - 'label' => __( 'Explore More Button', 'betterdocs' ),
1161 - 'enable_disable_text_active' => true,
1162 - 'default' => true,
1163 - 'priority' => 9
1164 - ),
1165 - 'exploremore_btn_txt' => array(
1166 - 'name' => 'exploremore_btn_txt',
1167 - 'type' => 'text',
1168 - 'label' => __( 'Explore More Button Text', 'betterdocs' ),
1169 - 'default' => __( 'Explore More', 'betterdocs' ),
1170 - 'priority' => 10,
1171 - 'rules' => Rules::is( 'exploremore_btn', true )
1172 - ),
1173 - 'betterdocs_popular_docs_text' => array(
1174 - 'name' => 'betterdocs_popular_docs_text',
1175 - 'type' => 'text',
1176 - 'label' => __( 'Popular Docs Text', 'betterdocs' ),
1177 - 'default' => __( 'Popular Docs', 'betterdocs' ),
1178 - 'priority' => 11,
1179 - 'is_pro' => true
1180 - ),
1181 - 'betterdocs_popular_docs_number' => array(
1182 - 'name' => 'betterdocs_popular_docs_number',
1183 - 'type' => 'number',
1184 - 'label' => __( 'Popular Docs Number', 'betterdocs' ),
1185 - 'default' => 10,
1186 - 'priority' => 12,
1187 - 'is_pro' => true
1188 - )
1189 - )
1190 - ),
1191 - 'layout_documentation_page_search' => array(
1192 - 'id' => 'layout_documentation_page_search',
1193 - 'name' => 'layout_documentation_page_search',
1194 - 'type' => 'section',
1195 - 'label' => __( 'Search', 'betterdocs' ),
1196 - 'priority' => 2,
1197 - 'fields' => array(
1198 - 'live_search' => array(
1199 - 'name' => 'live_search',
1200 - 'type' => 'toggle',
1201 - 'label' => __( 'Live Search', 'betterdocs' ),
1202 - 'enable_disable_text_active' => true,
1203 - 'default' => 1,
1204 - 'priority' => 1
1205 - ),
1206 - 'advance_search' => apply_filters( 'betterdocs_advance_search_settings', array(
1207 - 'name' => 'advance_search',
1208 - 'type' => 'toggle',
1209 - 'label' => __( 'Advanced Search', 'betterdocs' ),
1210 - 'enable_disable_text_active' => true,
1211 - 'default' => '',
1212 - 'priority' => 2,
1213 - 'is_pro' => true
1214 - ) ),
1215 - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- legacy public filter name for category-exclude settings field, retained for back-compat.
1216 - 'child_category_exclude' => apply_filters( 'child_category_exclude', array(
1217 - 'name' => 'child_category_exclude',
1218 - 'type' => 'toggle',
1219 - 'label' => __( 'Exclude Child Terms In Category Search', 'betterdocs' ),
1220 - 'enable_disable_text_active' => true,
1221 - 'default' => '',
1222 - 'priority' => 3,
1223 - 'is_pro' => true
1224 - ) ),
1225 - 'popular_keyword_limit' => apply_filters( 'betterdocs_popular_keyword_limit_settings', array(
1226 - 'name' => 'popular_keyword_limit',
1227 - 'type' => 'number',
1228 - 'label' => __( 'Minimum amount of Keywords Search', 'betterdocs' ),
1229 - 'default' => 5,
1230 - 'priority' => 4,
1231 - 'is_pro' => true
1232 - ) ),
1233 - 'search_letter_limit' => array(
1234 - 'name' => 'search_letter_limit',
1235 - 'type' => 'number',
1236 - 'label' => __( 'Minimum Character Limit For Search Result', 'betterdocs' ),
1237 - 'priority' => 5,
1238 - 'default' => 3
1239 - ),
1240 - 'search_placeholder' => array(
1241 - 'name' => 'search_placeholder',
1242 - 'type' => 'text',
1243 - 'label' => __( 'Search Placeholder', 'betterdocs' ),
1244 - 'default' => __( 'Search..', 'betterdocs' ),
1245 - 'priority' => 6
1246 - ),
1247 - 'search_button_text' => apply_filters( 'betterdocs_search_button_text', array(
1248 - 'name' => 'search_button_text',
1249 - 'type' => 'text',
1250 - 'label' => __( 'Search Button Text', 'betterdocs' ),
1251 - 'priority' => 7,
1252 - 'default' => __( 'Search', 'betterdocs' )
1253 - ) ),
1254 - 'search_not_found_text' => array(
1255 - 'name' => 'search_not_found_text',
1256 - 'type' => 'text',
1257 - 'label' => __( 'Search Not Found Text', 'betterdocs' ),
1258 - 'default' => 'Sorry, no docs were found.',
1259 - 'priority' => 8
1260 - ),
1261 - 'search_result_image' => array(
1262 - 'name' => 'search_result_image',
1263 - 'type' => 'toggle',
1264 - 'label' => __( 'Search Result Image', 'betterdocs' ),
1265 - 'enable_disable_text_active' => true,
1266 - 'default' => 1,
1267 - 'priority' => 9
1268 - ),
1269 - 'kb_based_search' => apply_filters( 'betterdocs_kb_based_search_settings', array(
1270 - 'name' => 'kb_based_search',
1271 - 'type' => 'toggle',
1272 - 'label' => __( 'KB Based Search', 'betterdocs' ),
1273 - 'enable_disable_text_active' => true,
1274 - 'default' => '',
1275 - 'priority' => 10,
1276 - 'is_pro' => true,
1277 - 'rules' => Rules::is( 'multiple_kb', true )
1278 - ) ),
1279 - 'search_modal_search_type' => array(
1280 - 'name' => 'search_modal_search_type',
1281 - 'type' => 'select',
1282 - 'label' => __( 'Search Modal Source', 'betterdocs' ),
1283 - 'label_subtitle' => __( 'Choose the content type to be shown in the search modal. <br> <b>Note:</b> This is only applicable on Modal Search.', 'betterdocs' ),
1284 - 'default' => 'all',
1285 - 'options' => $this->normalize_options( array(
1286 - 'all' => __( 'Both (Docs + FAQs)', 'betterdocs' ),
1287 - 'docs' => __( 'Docs only', 'betterdocs' ),
1288 - 'faq' => __( 'FAQs only', 'betterdocs' )
1289 - ) ),
1290 - 'priority' => 11
1291 - )
1292 - )
1293 - ),
1294 - 'layout_documentation_page_order_by' => array(
1295 - 'id' => 'layout_documentation_page_order_by',
1296 - 'name' => 'layout_documentation_page_order_by',
1297 - 'type' => 'section',
1298 - 'label' => __( 'Order By', 'betterdocs' ),
1299 - 'priority' => 3,
1300 - 'fields' => array(
1301 - 'terms_orderby' => array(
1302 - 'name' => 'terms_orderby',
1303 - 'type' => 'select',
1304 - 'label' => __( 'Terms Order By', 'betterdocs' ),
1305 - 'default' => 'betterdocs_order',
1306 - 'options' => $this->normalize_options( apply_filters( 'betterdocs_terms_orderby_options', array(
1307 - 'none' => __( 'No order', 'betterdocs' ),
1308 - 'name' => __( 'Name', 'betterdocs' ),
1309 - 'slug' => __( 'Slug', 'betterdocs' ),
1310 - 'term_group' => __( 'Term Group', 'betterdocs' ),
1311 - 'term_id' => __( 'Term ID', 'betterdocs' ),
1312 - 'id' => __( 'ID', 'betterdocs' ),
1313 - 'description' => __( 'Description', 'betterdocs' ),
1314 - 'parent' => __( 'Parent', 'betterdocs' ),
1315 - 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
1316 - ) ) ),
1317 - 'priority' => 1
1318 - ),
1319 - 'terms_order' => array(
1320 - 'name' => 'terms_order',
1321 - 'type' => 'select',
1322 - 'label' => __( 'Terms Order', 'betterdocs' ),
1323 - 'default' => 'ASC',
1324 - 'options' => $this->normalize_options( array(
1325 - 'ASC' => 'Ascending',
1326 - 'DESC' => 'Descending'
1327 - ) ),
1328 - 'priority' => 3,
1329 - 'rules' => Rules::includes( 'terms_orderby', 'betterdocs_order', true )
1330 - ),
1331 - 'alphabetically_order_post' => array(
1332 - 'name' => 'alphabetically_order_post',
1333 - 'type' => 'select',
1334 - 'label' => __( 'Docs Order By', 'betterdocs' ),
1335 - 'default' => 'betterdocs_order',
1336 - 'options' => $this->normalize_options( array(
1337 - 'none' => __( 'No order', 'betterdocs' ),
1338 - 'ID' => __( 'Docs ID', 'betterdocs' ),
1339 - 'author' => __( 'Docs Author', 'betterdocs' ),
1340 - 'title' => __( 'Title', 'betterdocs' ),
1341 - 'date' => __( 'Date', 'betterdocs' ),
1342 - 'modified' => __( 'Last Modified Date', 'betterdocs' ),
1343 - 'parent' => __( 'Parent Id', 'betterdocs' ),
1344 - 'rand' => __( 'Random', 'betterdocs' ),
1345 - 'comment_count' => __( 'Comment Count', 'betterdocs' ),
1346 - 'menu_order' => __( 'Menu Order', 'betterdocs' ),
1347 - 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
1348 - ) ),
1349 - 'priority' => 4
1350 - ),
1351 - 'docs_order' => array(
1352 - 'name' => 'docs_order',
1353 - 'type' => 'select',
1354 - 'label' => __( 'Docs Order', 'betterdocs' ),
1355 - 'default' => 'ASC',
1356 - 'options' => $this->normalize_options( array(
1357 - 'ASC' => 'Ascending',
1358 - 'DESC' => 'Descending'
1359 - ) ),
1360 - 'priority' => 5,
1361 - 'rules' => Rules::includes( 'alphabetically_order_post', 'betterdocs_order', true )
1362 - )
1363 - )
1364 - )
1365 - )
1366 - )
1367 - )
1368 - ),
1369 - // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- legacy public filter name for single-doc setting section, retained for back-compat.
1370 - 'layout_single_doc' => apply_filters( 'single_doc_setting_section', array(
1371 - 'id' => 'layout_single_doc',
1372 - 'name' => 'layout_single_doc',
1373 - 'type' => 'section',
1374 - 'label' => __( 'Single Doc', 'betterdocs' ),
1375 - 'priority' => 2,
1376 - 'fields' => array(
1377 - 'tab-nested-layout-2' => array(
1378 - 'id' => 'tab-nested-layout-2',
1379 - 'name' => 'tab_nested_layout_2',
1380 - 'label' => __( 'Single Doc', 'betterdocs' ),
1381 - 'classes' => 'tab-nested-layout',
1382 - 'type' => 'tab',
1383 - 'active' => 'layout_single_doc_general',
1384 - 'completionTrack' => true,
1385 - 'sidebar' => false,
1386 - 'save' => false,
1387 - 'title' => false,
1388 - 'config' => array(
1389 - 'active' => 'layout_single_doc_general',
1390 - 'sidebar' => false,
1391 - 'title' => false
1392 - ),
1393 - 'submit' => array(
1394 - 'show' => false
1395 - ),
1396 - 'step' => array(
1397 - 'show' => false
1398 - ),
1399 - 'priority' => 20,
1400 - 'fields' => array(
1401 - 'layout_single_doc_general' => array(
1402 - 'id' => 'layout_single_doc_general',
1403 - 'name' => 'layout_single_doc_general',
1404 - 'type' => 'section',
1405 - 'label' => __( 'General', 'betterdocs' ),
1406 - 'priority' => 5,
1407 - 'fields' => array(
1408 - 'enable_post_title' => array(
1409 - 'name' => 'enable_post_title',
1410 - 'type' => 'toggle',
1411 - 'label' => __( 'Doc Title', 'betterdocs' ),
1412 - 'enable_disable_text_active' => true,
1413 - 'default' => 1,
1414 - 'priority' => 1
1415 - ),
1416 - 'enable_sidebar_cat_list' => array(
1417 - 'name' => 'enable_sidebar_cat_list',
1418 - 'type' => 'toggle',
1419 - 'label' => __( 'Sidebar Category List', 'betterdocs' ),
1420 - 'enable_disable_text_active' => true,
1421 - 'default' => 1,
1422 - 'priority' => 2
1423 - ),
1424 - 'enable_print_icon' => array(
1425 - 'name' => 'enable_print_icon',
1426 - 'type' => 'toggle',
1427 - 'label' => __( 'Print Icon', 'betterdocs' ),
1428 - 'enable_disable_text_active' => true,
1429 - 'default' => 1,
1430 - 'priority' => 3
1431 - ),
1432 - 'enable_tags' => array(
1433 - 'name' => 'enable_tags',
1434 - 'type' => 'toggle',
1435 - 'label' => __( 'Tags', 'betterdocs' ),
1436 - 'enable_disable_text_active' => true,
1437 - 'default' => 1,
1438 - 'priority' => 4
1439 - ),
1440 - 'show_last_update_time' => array(
1441 - 'name' => 'show_last_update_time',
1442 - 'type' => 'toggle',
1443 - 'label' => __( 'Last Update Time', 'betterdocs' ),
1444 - 'enable_disable_text_active' => true,
1445 - 'default' => 1,
1446 - 'priority' => 5
1447 - ),
1448 - 'enable_navigation' => array(
1449 - 'name' => 'enable_navigation',
1450 - 'type' => 'toggle',
1451 - 'label' => __( 'Navigation', 'betterdocs' ),
1452 - 'enable_disable_text_active' => true,
1453 - 'default' => 1,
1454 - 'priority' => 6
1455 - ),
1456 - 'enable_comment' => array(
1457 - 'name' => 'enable_comment',
1458 - 'type' => 'toggle',
1459 - 'label' => __( 'Comment', 'betterdocs' ),
1460 - 'enable_disable_text_active' => true,
1461 - 'default' => '',
1462 - 'priority' => 7
1463 - ),
1464 - 'enable_credit' => array(
1465 - 'name' => 'enable_credit',
1466 - 'type' => 'toggle',
1467 - 'label' => __( 'Show Powered by BetterDocs', 'betterdocs' ),
1468 - 'enable_disable_text_active' => true,
1469 - 'default' => '',
1470 - 'priority' => 8
1471 - ),
1472 - 'reaction_feedback_text' => array(
1473 - 'name' => 'reaction_feedback_text',
1474 - 'type' => 'text',
1475 - 'label' => __( 'Reaction Feedback Text', 'betterdocs' ),
1476 - 'default' => __( 'Thanks for your feedback.', 'betterdocs' ),
1477 - 'priority' => 9
1478 - ),
1479 - 'enable_estimated_reading_time' => array(
1480 - 'name' => 'enable_estimated_reading_time',
1481 - 'type' => 'toggle',
1482 - 'label' => __( 'Estimated Reading Time', 'betterdocs' ),
1483 - 'enable_disable_text_active' => true,
1484 - 'default' => 0,
1485 - 'priority' => 10
1486 - ),
1487 - 'estimated_reading_time_title' => array(
1488 - 'name' => 'estimated_reading_time_title',
1489 - 'type' => 'text',
1490 - 'label' => __( 'Estimated Reading Time Title', 'betterdocs' ),
1491 - 'default' => '',
1492 - 'priority' => 11,
1493 - 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1494 - ),
1495 - 'estimated_reading_time_text' => array(
1496 - 'name' => 'estimated_reading_time_text',
1497 - 'type' => 'text',
1498 - 'label' => __( 'Estimated Reading Time Text', 'betterdocs' ),
1499 - 'default' => __( 'min read', 'betterdocs' ),
1500 - 'priority' => 12,
1501 - 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1502 - ),
1503 - 'singular_estimated_reading_time_text' => array(
1504 - 'name' => 'singular_estimated_reading_time_text',
1505 - 'type' => 'text',
1506 - 'label' => __( 'Estimated Reading Time Text Singular', 'betterdocs' ),
1507 - 'default' => __( 'min read', 'betterdocs' ),
1508 - 'priority' => 13,
1509 - 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1510 - )
1511 - )
1512 - ),
1513 - 'layout_single_doc_TOC' => array(
1514 - 'id' => 'layout_single_doc_TOC',
1515 - 'name' => 'layout_single_doc_TOC',
1516 - 'type' => 'section',
1517 - 'label' => __( 'TOC', 'betterdocs' ),
1518 - 'priority' => 5,
1519 - 'fields' => array(
1520 - 'enable_toc' => array(
1521 - 'name' => 'enable_toc',
1522 - 'type' => 'toggle',
1523 - 'label' => __( 'Table of Contents', 'betterdocs' ),
1524 - 'enable_disable_text_active' => true,
1525 - 'default' => 1,
1526 - 'priority' => 1
1527 - ),
1528 - 'toc_title' => array(
1529 - 'name' => 'toc_title',
1530 - 'type' => 'text',
1531 - 'label' => __( 'TOC Title', 'betterdocs' ),
1532 - 'default' => __( 'Table of Contents', 'betterdocs' ),
1533 - 'priority' => 2,
1534 - 'rules' => Rules::is( 'enable_toc', true )
2448 + if ( $docs_tax ) {
2449 + return $docs_tax;
2450 + }
1535 2451
1536 - ),
1537 - 'toc_hierarchy' => array(
1538 - 'name' => 'toc_hierarchy',
1539 - 'type' => 'toggle',
1540 - 'label' => __( 'TOC Hierarchy', 'betterdocs' ),
1541 - 'enable_disable_text_active' => true,
1542 - 'default' => 1,
1543 - 'priority' => 3,
1544 - 'rules' => Rules::is( 'enable_toc', true )
1545 - ),
1546 - 'toc_list_number' => array(
1547 - 'name' => 'toc_list_number',
1548 - 'type' => 'toggle',
1549 - 'label' => __( 'TOC List Number', 'betterdocs' ),
1550 - 'enable_disable_text_active' => true,
1551 - 'default' => 1,
1552 - 'priority' => 4,
1553 - 'rules' => Rules::is( 'enable_toc', true )
1554 - ),
1555 - 'toc_dynamic_title' => array(
1556 - 'name' => 'toc_dynamic_title',
1557 - 'type' => 'toggle',
1558 - 'label' => __( 'Show TOC Title in Anchor Links', 'betterdocs' ),
1559 - 'enable_disable_text_active' => true,
1560 - 'default' => 0,
1561 - 'priority' => 5,
1562 - 'rules' => Rules::is( 'enable_toc', true )
1563 - ),
1564 - 'enable_sticky_toc' => array(
1565 - 'name' => 'enable_sticky_toc',
1566 - 'type' => 'toggle',
1567 - 'label' => __( 'Sticky TOC', 'betterdocs' ),
1568 - 'enable_disable_text_active' => true,
1569 - 'default' => 1,
1570 - 'priority' => 6,
1571 - 'rules' => Rules::is( 'enable_toc', true )
1572 - ),
1573 - 'collapsible_toc_mobile' => array(
1574 - 'name' => 'collapsible_toc_mobile',
1575 - 'type' => 'toggle',
1576 - 'label' => __( 'Collapsible TOC on small devices', 'betterdocs' ),
1577 - 'enable_disable_text_active' => true,
1578 - 'default' => '',
1579 - 'priority' => 7,
1580 - 'rules' => Rules::is( 'enable_toc', true )
1581 - ),
1582 - 'title_link_ctc' => array(
1583 - 'name' => 'title_link_ctc',
1584 - 'type' => 'toggle',
1585 - 'label' => __( 'Title Link Copy To Clipboard', 'betterdocs' ),
1586 - 'enable_disable_text_active' => true,
1587 - 'default' => 1,
1588 - 'priority' => 8
1589 - ),
1590 - 'supported_heading_tag' => array(
1591 - 'name' => 'supported_heading_tag',
1592 - 'label' => __( 'TOC Supported Heading Tag', 'betterdocs' ),
1593 - 'type' => 'checkbox-select',
1594 - 'multiple' => true,
1595 - 'priority' => 10,
1596 - 'default' => array(
1597 - '1',
1598 - '2',
1599 - '3',
1600 - '4',
1601 - '5',
1602 - '6'
1603 - ),
1604 - 'options' => $this->normalize_options( array(
1605 - '1' => 'H1',
1606 - '2' => 'H2',
1607 - '3' => 'H3',
1608 - '4' => 'H4',
1609 - '5' => 'H5',
1610 - '6' => 'H6'
1611 - ) ),
1612 - 'priority' => 9,
1613 - 'rules' => Rules::is( 'enable_toc', true )
1614 - ),
1615 - 'sticky_toc_offset' => array(
1616 - 'name' => 'sticky_toc_offset',
1617 - 'type' => 'number',
1618 - 'label' => __( 'Content Offset', 'betterdocs' ),
1619 - 'default' => 100,
1620 - 'priority' => 10,
1621 - 'label_subtitle' => __( 'content offset from top on scroll.', 'betterdocs' ),
1622 - 'rules' => Rules::is( 'enable_toc', true )
1623 - )
1624 - )
1625 - ),
1626 - 'layout_single_doc_breadcrumb' => array(
1627 - 'id' => 'layout_single_doc_breadcrumb',
1628 - 'name' => 'layout_single_doc_breadcrumb',
1629 - 'type' => 'section',
1630 - 'label' => __( 'Breadcrumb', 'betterdocs' ),
1631 - 'priority' => 5,
1632 - 'fields' => array(
1633 - 'enable_breadcrumb' => array(
1634 - 'name' => 'enable_breadcrumb',
1635 - 'type' => 'toggle',
1636 - 'label' => __( 'Breadcrumb', 'betterdocs' ),
1637 - 'enable_disable_text_active' => true,
1638 - 'default' => 1,
1639 - 'priority' => 1
1640 - ),
1641 - 'enable_breadcrumb_home_text' => array(
1642 - 'name' => 'enable_breadcrumb_home_text',
1643 - 'type' => 'toggle',
1644 - 'label' => __( 'Enable Breadcrumb Home Text', 'betterdocs' ),
1645 - 'enable_disable_text_active' => true,
1646 - 'default' => true,
1647 - 'priority' => 2,
1648 - 'rules' => Rules::is( 'enable_breadcrumb', true )
1649 - ),
1650 - 'breadcrumb_home_text' => array(
1651 - 'name' => 'breadcrumb_home_text',
1652 - 'type' => 'text',
1653 - 'label' => __( 'Breadcrumb Home Text', 'betterdocs' ),
1654 - 'default' => __( 'Home', 'betterdocs' ),
1655 - 'priority' => 3,
1656 - 'rules' => Rules::logicalRule(
1657 - array(
1658 - Rules::is( 'enable_breadcrumb', true ),
1659 - Rules::is( 'enable_breadcrumb_home_text', true )
1660 - ),
1661 - 'and'
1662 - )
1663 - ),
1664 - 'breadcrumb_home_url' => array(
1665 - 'name' => 'breadcrumb_home_url',
1666 - 'type' => 'text',
1667 - 'label' => __( 'Breadcrumb Home URL', 'betterdocs' ),
1668 - 'priority' => 4,
1669 - 'default' => get_home_url(),
1670 - 'rules' => Rules::is( 'enable_breadcrumb', true )
1671 - ),
1672 - 'enable_breadcrumb_category' => array(
1673 - 'name' => 'enable_breadcrumb_category',
1674 - 'type' => 'toggle',
1675 - 'label' => __( 'Category on Breadcrumb', 'betterdocs' ),
1676 - 'enable_disable_text_active' => true,
1677 - 'default' => 1,
1678 - 'priority' => 5,
1679 - 'rules' => Rules::is( 'enable_breadcrumb', true )
1680 - ),
1681 - 'enable_breadcrumb_title' => array(
1682 - 'name' => 'enable_breadcrumb_title',
1683 - 'type' => 'toggle',
1684 - 'label' => __( 'Title on Breadcrumb', 'betterdocs' ),
1685 - 'enable_disable_text_active' => true,
1686 - 'default' => 1,
1687 - 'priority' => 6,
1688 - 'rules' => Rules::is( 'enable_breadcrumb', true )
1689 - )
1690 - )
1691 - ),
1692 - 'layout_single_doc_email_feedback' => array(
1693 - 'id' => 'layout_single_doc_email_feedback',
1694 - 'name' => 'layout_single_doc_email_feedback',
1695 - 'type' => 'section',
1696 - 'label' => __( 'Email Feedback', 'betterdocs' ),
1697 - 'priority' => 5,
1698 - 'fields' => array(
1699 - 'email_feedback' => array(
1700 - 'name' => 'email_feedback',
1701 - 'type' => 'toggle',
1702 - 'label' => __( 'Email Feedback', 'betterdocs' ),
1703 - 'enable_disable_text_active' => true,
1704 - 'default' => 1,
1705 - 'priority' => 1
1706 - ),
1707 - 'feedback_link_text' => array(
1708 - 'name' => 'feedback_link_text',
1709 - 'type' => 'text',
1710 - 'label' => __( 'Feedback Link Text', 'betterdocs' ),
1711 - 'default' => __( 'Still stuck? How can we help?', 'betterdocs' ),
1712 - 'priority' => 2,
1713 - 'rules' => Rules::is( 'email_feedback', true )
1714 - ),
1715 - 'feedback_form_title' => array(
1716 - 'name' => 'feedback_form_title',
1717 - 'type' => 'text',
1718 - 'label' => __( 'Feedback Form Title', 'betterdocs' ),
1719 - 'default' => __( 'Still stuck? How can we help?', 'betterdocs' ),
1720 - 'priority' => 3,
1721 - 'rules' => Rules::is( 'email_feedback', true )
1722 - ),
1723 - 'email_address' => array(
1724 - 'name' => 'email_address',
1725 - 'type' => 'text',
1726 - 'label' => __( 'Email Address', 'betterdocs' ),
1727 - 'default' => get_option( 'admin_email' ),
1728 - 'priority' => 4,
1729 - 'label_subtitle' => __( 'The email address where the Feedback form will be sent', 'betterdocs' ),
1730 - 'rules' => Rules::is( 'email_feedback', true )
1731 - ),
1732 - 'feedback_url' => array(
1733 - 'name' => 'feedback_url',
1734 - 'type' => 'text',
1735 - 'label' => __( 'Feedback URL', 'betterdocs' ),
1736 - 'default' => '',
1737 - 'priority' => 5,
1738 - 'rules' => Rules::is( 'email_feedback', true )
1739 - )
1740 - )
1741 - ),
1742 - array(
1743 - 'id' => 'layout_single_doc_attachments',
1744 - 'name' => 'layout_single_doc_attachments',
1745 - 'type' => 'section',
1746 - 'label' => __( 'Attachments', 'betterdocs' ),
1747 - 'priority' => 6,
1748 - 'fields' => apply_filters( 'betterdocs_single_doc_attachments', array(
1749 - 'show_attachment' => array(
1750 - 'name' => 'show_attachment',
1751 - 'type' => 'toggle',
1752 - 'is_pro' => true,
1753 - 'priority' => 1,
1754 - 'label' => __( 'Show Attachment', 'betterdocs' ),
1755 - 'enable_disable_text_active' => true,
1756 - 'default' => false
1757 - )
1758 - ) )
1759 - ),
1760 - array(
1761 - 'id' => 'layout_single_doc_related_docs',
1762 - 'name' => 'layout_single_doc_related_docs',
1763 - 'type' => 'section',
1764 - 'label' => __( 'Related Docs', 'betterdocs' ),
1765 - 'priority' => 7,
1766 - 'fields' => apply_filters( 'betterdocs_single_doc_related_docs', array(
1767 - 'show_related_docs' => array(
1768 - 'name' => 'show_related_docs',
1769 - 'type' => 'toggle',
1770 - 'is_pro' => true,
1771 - 'priority' => 1,
1772 - 'label' => __( 'Show Related Docs', 'betterdocs' ),
1773 - 'enable_disable_text_active' => true,
1774 - 'default' => false
1775 - )
1776 - ) )
1777 - )
1778 - )
1779 - )
1780 - )
1781 - ) ),
1782 - 'layout_archive_page' => array(
1783 - 'id' => 'layout_archive_page',
1784 - 'name' => 'layout_archive_page',
1785 - 'type' => 'section',
1786 - 'label' => __( 'Archive Page', 'betterdocs' ),
1787 - 'priority' => 3,
1788 - 'fields' => array(
1789 - 'enable_archive_sidebar' => array(
1790 - 'name' => 'enable_archive_sidebar',
1791 - 'type' => 'toggle',
1792 - 'label' => __( 'Sidebar Category List', 'betterdocs' ),
1793 - 'enable_disable_text_active' => true,
1794 - 'default' => 1,
1795 - 'priority' => 31
1796 - ),
1797 - 'archive_nested_subcategory' => array(
1798 - 'name' => 'archive_nested_subcategory',
1799 - 'type' => 'toggle',
1800 - 'label' => __( 'Nested Subcategory', 'betterdocs' ),
1801 - 'enable_disable_text_active' => true,
1802 - 'default' => 1,
1803 - 'priority' => 32
1804 - ),
1805 - 'archive_enable_pagination' => array(
1806 - 'name' => 'archive_enable_pagination',
1807 - 'type' => 'toggle',
1808 - 'label' => __( 'Enable Pagination', 'betterdocs' ),
1809 - 'enable_disable_text_active' => true,
1810 - 'default' => false,
1811 - 'priority' => 33
1812 - )
1813 - )
1814 - )
1815 - )
1816 - ) )
1817 - )
1818 - )
1819 - )
1820 - ) ),
1821 - 'tab-design' => apply_filters( 'betterdocs_settings_tab_design', array(
1822 - 'id' => 'tab-design',
1823 - 'label' => __( 'Design', 'betterdocs' ),
1824 - 'priority' => 30,
1825 - 'fields' => array(
1826 - 'title-design' => array(
1827 - 'name' => 'title-design-tab',
1828 - 'type' => 'section',
1829 - 'label' => __( 'Design', 'betterdocs' ),
1830 - 'priority' => 30,
1831 - 'fields' => $this->design_tab()
1832 - )
1833 - )
1834 - ) ),
1835 - 'tab-shortcodes' => apply_filters( 'betterdocs_settings_tab_shortcodes', array(
1836 - 'label' => __( 'Shortcodes', 'betterdocs' ),
1837 - 'id' => 'tab-shortcodes',
1838 - 'classes' => 'tab-shortcodes',
1839 - 'priority' => 40,
1840 - 'fields' => array(
1841 - 'title-shortcodes' => array(
1842 - 'name' => 'title-shortcodes-tab',
1843 - 'type' => 'section',
1844 - 'label' => __( 'Shortcodes', 'betterdocs' ),
1845 - 'priority' => 40,
1846 - 'searchable' => true,
1847 - 'searchPlaceholder' => __( 'Search for shortcode', 'betterdocs' ),
1848 - 'searchNotFoundMessage' => '<img src="' . betterdocs()->assets->icon( 'not-found.svg', true ) . '"/><p>' . __( 'No Shortcodes Found with these keywords', 'betterdocs' ) . '</p>',
1849 - 'fields' => apply_filters( 'betterdocs_shortcode_fields', array(
1850 - 'search_form' => array(
1851 - 'name' => 'search_form',
1852 - 'type' => 'copy-to-clipboard',
1853 - 'label' => __( 'Search Form', 'betterdocs' ),
1854 - 'default' => '[betterdocs_search_form]',
1855 - 'readOnly' => true,
1856 - 'priority' => 1,
1857 - 'description' => __( '[betterdocs_search_form placeholder="Search..." heading="Heading" subheading="Subheading" category_search="true" search_button="true" popular_search="true"]', 'betterdocs' ),
1858 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1859 - 'descriptionCopyable' => true
1860 - ),
1861 - 'feedback_form' => array(
1862 - 'name' => 'feedback_form',
1863 - 'type' => 'copy-to-clipboard',
1864 - 'label' => __( 'Feedback Form', 'betterdocs' ),
1865 - 'default' => '[betterdocs_feedback_form]',
1866 - 'readOnly' => true,
1867 - 'priority' => 2,
1868 - 'description' => __( '[betterdocs_feedback_form button_text="Send"]', 'betterdocs' ),
1869 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1870 - 'descriptionCopyable' => true
1871 - ),
1872 - 'category_grid' => array(
1873 - 'name' => 'category_grid',
1874 - 'type' => 'copy-to-clipboard',
1875 - 'label' => __( 'Category Grid- Layout 1', 'betterdocs' ),
1876 - 'default' => '[betterdocs_category_grid]',
1877 - 'readOnly' => true,
1878 - 'priority' => 3,
1879 - 'description' => __( '[betterdocs_category_grid show_count="true" show_icon="true" masonry="true" column="3" posts_per_page="5" nested_subcategory="true" terms="term_ID, term_ID" terms_orderby="" terms_order="" multiple_knowledge_base="" kb_slug="" title_tag="h2" orderby="" order="" ]', 'betterdocs' ),
1880 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1881 - 'descriptionCopyable' => true
1882 - ),
1883 - 'category_box' => array(
1884 - 'name' => 'category_box',
1885 - 'type' => 'copy-to-clipboard',
1886 - 'label' => __( 'Category Box- Layout 2', 'betterdocs' ),
1887 - 'default' => '[betterdocs_category_box]',
1888 - 'readOnly' => true,
1889 - 'priority' => 4,
1890 - 'description' => __( '[betterdocs_category_box orderby="" column="" nested_subcategory="" terms="" terms_orderby="" show_icon="" kb_slug="" title_tag="h2" multiple_knowledge_base="false" border_bottom="false"]', 'betterdocs' ),
1891 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1892 - 'descriptionCopyable' => true
1893 - ),
1894 - 'category_list' => array(
1895 - 'name' => 'category_list',
1896 - 'type' => 'copy-to-clipboard',
1897 - 'label' => __( 'Category List', 'betterdocs' ),
1898 - 'default' => '[betterdocs_category_list]',
1899 - 'readOnly' => true,
1900 - 'priority' => 5,
1901 - 'description' => __( '[betterdocs_category_list orderby="" order="" posts_per_page="" nested_subcategory="" terms="" terms_orderby="" terms_order="" kb_slug="" multiple_knowledge_base="false" title_tag="h2"]', 'betterdocs' ),
1902 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1903 - 'descriptionCopyable' => true
1904 - ),
1905 - 'faq_modern_layout' => array(
1906 - 'name' => 'faq_modern_layout',
1907 - 'type' => 'copy-to-clipboard',
1908 - 'label' => __( 'FAQ Layout - 1', 'betterdocs' ),
1909 - 'default' => '[betterdocs_faq_list_modern]',
1910 - 'readOnly' => true,
1911 - 'priority' => 13,
1912 - 'description' => __( '[betterdocs_faq_list_modern groups="group_id" class="" group_exclude="group_id" faq_heading="Frequently Asked Questions"]', 'betterdocs' ),
1913 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1914 - 'descriptionCopyable' => true
1915 - ),
1916 - 'faq_classic_layout' => array(
1917 - 'name' => 'faq_classic_layout',
1918 - 'type' => 'copy-to-clipboard',
1919 - 'label' => __( 'FAQ Layout - 2', 'betterdocs' ),
1920 - 'default' => '[betterdocs_faq_list_classic]',
1921 - 'readOnly' => true,
1922 - 'priority' => 14,
1923 - 'description' => __( '[betterdocs_faq_list_classic groups="group_id" class="" group_exclude="group_id" faq_heading="Frequently Asked Questions"]', 'betterdocs' ),
1924 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1925 - 'descriptionCopyable' => true
1926 - ),
1927 - 'betterdocs_faq_list_layout_3' => array(
1928 - 'name' => 'betterdocs_faq_list_layout_3',
1929 - 'type' => 'copy-to-clipboard',
1930 - 'label' => __( 'FAQ Layout - 3', 'betterdocs' ),
1931 - 'default' => '[betterdocs_faq_list_layout_3 class="faq-doc betterdocs-faq-layout-3"]',
1932 - 'readOnly' => true,
1933 - 'priority' => 15,
1934 - 'description' => __( '[betterdocs_faq_list_layout_3 class="faq-doc betterdocs-faq-layout-3" groups="group_id" class="" group_exclude="group_id" faq_heading="Frequently Asked Questions"]', 'betterdocs' ),
1935 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1936 - 'descriptionCopyable' => true
1937 - ),
1938 - 'betterdocs_faq_tab' => array(
1939 - 'name' => 'betterdocs_faq_tab',
1940 - 'type' => 'copy-to-clipboard',
1941 - 'label' => __( 'FAQ Layout - 4', 'betterdocs' ),
1942 - 'default' => '[betterdocs_faq_tab class="faq-doc betterdocs-faq-layout-4"]',
1943 - 'readOnly' => true,
1944 - 'priority' => 16,
1945 - 'description' => __( '[betterdocs_faq_tab class="faq-doc betterdocs-faq-layout-4" groups="group_id" group_exclude="group_id" faq_heading="Frequently Asked Questions"]', 'betterdocs' ),
1946 - 'descriptionLabel' => __( 'Example with parameters:', 'betterdocs' ),
1947 - 'descriptionCopyable' => true
1948 - )
1949 - ) )
1950 - )
1951 - )
1952 - ) ),
1953 - 'tab-advance-settings' => apply_filters( 'betterdocs_settings_tab_advance', array(
1954 - 'id' => 'tab-advance-settings',
1955 - 'label' => __( 'Access & Restrictions', 'betterdocs' ),
1956 - 'classes' => 'tab-layout',
1957 - 'priority' => 50,
1958 - 'fields' => array(
1959 - 'title_advance_settings' => array(
1960 - 'name' => 'title-advance-settings-tab',
1961 - 'type' => 'section',
1962 - 'label' => __( 'Access & Restrictions', 'betterdocs' ),
1963 - 'priority' => 50,
1964 - 'fields' => array(
1965 - 'tab-advanced-settings' => array(
1966 - 'id' => 'tab-advanced-settings',
1967 - 'name' => 'tab-advanced-settings',
1968 - 'label' => __( 'Access & Restrictions', 'betterdocs' ),
1969 - 'classes' => 'tab-layout',
1970 - 'type' => 'tab',
1971 - 'active' => 'global_role_management',
1972 - 'completionTrack' => true,
1973 - 'sidebar' => false,
1974 - 'save' => false,
1975 - 'title' => false,
1976 - 'config' => array(
1977 - 'active' => '',
1978 - 'sidebar' => false,
1979 - 'title' => false
1980 - ),
1981 - 'submit' => array(
1982 - 'show' => false
1983 - ),
1984 - 'step' => array(
1985 - 'show' => false
1986 - ),
1987 - 'priority' => 50,
1988 - 'fields' => array(
1989 - 'global_role_management' => array(
1990 - 'id' => 'global_role_management',
1991 - 'name' => 'global_role_management',
1992 - 'type' => 'section',
1993 - 'label' => __( 'Global Role Management', 'betterdocs' ),
1994 - 'priority' => 1,
1995 - 'fields' => array(
1996 - 'article_roles' => array(
1997 - 'name' => 'article_roles',
1998 - 'type' => 'checkbox-select',
1999 - 'label' => __( 'Who Can Write Docs?', 'betterdocs' ),
2000 - 'priority' => 1,
2001 - 'multiple' => true,
2002 - 'search' => true,
2003 - 'is_pro' => true,
2004 - 'default' => array( 'administrator' ),
2005 - 'options' => $wp_roles
2006 - ),
2007 - 'settings_roles' => array(
2008 - 'name' => 'settings_roles',
2009 - 'type' => 'checkbox-select',
2010 - 'label' => __( 'Who Can Edit Settings?', 'betterdocs' ),
2011 - 'priority' => 2,
2012 - 'multiple' => true,
2013 - 'is_pro' => true,
2014 - 'search' => true,
2015 - 'default' => array( 'administrator' ),
2016 - 'options' => $wp_roles
2017 - ),
2018 - 'analytics_roles' => array(
2019 - 'name' => 'analytics_roles',
2020 - 'type' => 'checkbox-select',
2021 - 'label' => __( 'Who Can Check Analytics?', 'betterdocs' ),
2022 - 'priority' => 3,
2023 - 'multiple' => true,
2024 - 'is_pro' => true,
2025 - 'search' => true,
2026 - 'default' => array( 'administrator' ),
2027 - 'options' => $wp_roles
2028 - ),
2029 - 'faq_roles' => array(
2030 - 'name' => 'faq_roles',
2031 - 'type' => 'checkbox-select',
2032 - 'label' => __( 'Who Can Check FAQ Builder?', 'betterdocs' ),
2033 - 'priority' => 4,
2034 - 'multiple' => true,
2035 - 'is_pro' => true,
2036 - 'search' => true,
2037 - 'default' => array( 'administrator' ),
2038 - 'options' => $wp_roles
2039 - )
2452 + $get_terms = get_terms( [
2453 + 'taxonomy' => $taxonomy,
2454 + 'hide_empty' => false
2455 + ] );
2040 2456
2041 - )
2042 - ),
2043 - 'internal_knowledge_base' => array(
2044 - 'id' => 'internal_knowledge_base',
2045 - 'name' => 'internal_knowledge_base',
2046 - 'type' => 'section',
2047 - 'label' => __( 'Internal Knowledge Base', 'betterdocs' ),
2048 - 'priority' => 1,
2049 - 'fields' => apply_filters( 'betterdocs_settings_content_restriction_fields', array(
2050 - 'enable_content_restriction' => array(
2051 - 'name' => 'enable_content_restriction',
2052 - 'type' => 'toggle',
2053 - 'is_pro' => true,
2054 - 'priority' => 5,
2055 - 'label' => __( 'Internal Knowledge Base', 'betterdocs' ),
2056 - 'enable_disable_text_active' => true,
2057 - 'default' => array( 'all' )
2058 - ),
2059 - 'internal_knowledge_base_type' => array(
2060 - 'name' => 'internal_knowledge_base_type',
2061 - 'type' => 'radio-card',
2062 - 'label' => __( 'Choose a Rule Type', 'betterdocs' ),
2063 - 'label_subtitle' => __( 'Choose a rule type: apply access globally (Basic), or configure detailed restrictions (Advanced) for docs, categories, and KBs.', 'betterdocs' ),
2064 - 'priority' => 6,
2065 - 'multiple' => true,
2066 - 'search' => true,
2067 - 'default' => array( 'all' ),
2068 - 'placeholder' => __( 'Select any', 'betterdocs' ),
2069 - 'options' => array(
2070 - array(
2071 - 'label' => 'Basic',
2072 - 'value' => 'basic'
2073 - ),
2074 - array(
2075 - 'label' => 'Advanced',
2076 - 'value' => 'advanced'
2077 - )
2078 - ),
2079 - 'filterValue' => 'all',
2080 - 'rules' => Rules::is( 'enable_content_restriction', true )
2081 - ),
2082 - 'content_visibility' => array(
2083 - 'name' => 'content_visibility',
2084 - 'type' => 'checkbox-select',
2085 - 'label' => __( 'Restrict Access to', 'betterdocs' ),
2086 - 'label_subtitle' => __( 'Only selected User Roles will be able to view your Knowledge Base', 'betterdocs' ),
2087 - 'is_pro' => true,
2088 - 'priority' => 7,
2089 - 'multiple' => true,
2090 - 'search' => true,
2091 - 'default' => array( 'all' ),
2092 - 'placeholder' => __( 'Select any', 'betterdocs' ),
2093 - 'options' => $roles_for_ikb,
2094 - 'rules' => Rules::logicalRule(
2095 - array(
2096 - Rules::is( 'enable_content_restriction', true ),
2097 - Rules::is( 'internal_knowledge_base_type', 'basic' )
2098 - ),
2099 - 'and'
2100 - ),
2101 - 'filterValue' => 'all'
2102 - ),
2103 - 'restrict_template' => array(
2104 - 'name' => 'restrict_template',
2105 - 'type' => 'checkbox-select',
2106 - 'label' => __( 'Restriction on Docs', 'betterdocs' ),
2107 - 'label_subtitle' => __( 'Selected Docs pages will be restricted', 'betterdocs' ),
2108 - 'is_pro' => true,
2109 - 'priority' => 8,
2110 - 'multiple' => true,
2111 - 'search' => true,
2112 - 'default' => array( 'all' ),
2113 - 'placeholder' => __( 'Select any', 'betterdocs' ),
2114 - 'options' => $this->get_texanomy(),
2115 - 'rules' => Rules::logicalRule(
2116 - array(
2117 - Rules::is( 'enable_content_restriction', true ),
2118 - Rules::is( 'internal_knowledge_base_type', 'basic' )
2119 - ),
2120 - 'and'
2121 - ),
2122 - 'filterValue' => 'all'
2123 - ),
2124 - 'restrict_category' => array(
2125 - 'name' => 'restrict_category',
2126 - 'type' => 'checkbox-select',
2127 - 'label' => __( 'Restriction on Docs Categories', 'betterdocs' ),
2128 - 'label_subtitle' => __( 'Selected Docs categories will be restricted', 'betterdocs' ),
2129 - 'is_pro' => true,
2130 - 'priority' => 9,
2131 - 'multiple' => true,
2132 - 'search' => true,
2133 - 'default' => array( 'all' ),
2134 - 'placeholder' => __( 'Select any', 'betterdocs' ),
2135 - 'options' => $this->get_terms( 'doc_category' ),
2136 - 'rules' => Rules::logicalRule(
2137 - array(
2138 - Rules::is( 'enable_content_restriction', true ),
2139 - Rules::is( 'internal_knowledge_base_type', 'basic' )
2140 - ),
2141 - 'and'
2142 - ),
2143 - 'filterValue' => 'all'
2144 - ),
2145 - 'restricted_redirect_url' => array(
2146 - 'name' => 'restricted_redirect_url',
2147 - 'type' => 'text',
2148 - 'label' => __( 'Redirect URL', 'betterdocs' ),
2149 - 'label_subtitle' => __( 'Set a custom URL to redirect users without permissions when they try to access internal knowledge base. By default, restricted content will redirect to the "404 not found" page', 'betterdocs' ),
2150 - 'default' => '',
2151 - 'placeholder' => 'https://',
2152 - 'is_pro' => true,
2153 - 'priority' => 20,
2154 - 'rules' => Rules::logicalRule(
2155 - array(
2156 - Rules::is( 'enable_content_restriction', true )
2157 - ),
2158 - 'and'
2159 - )
2160 - )
2161 - ) )
2162 - )
2163 - )
2164 - )
2165 - )
2166 - )
2167 - )
2168 - ) ),
2169 - 'tab-email-reporting' => apply_filters( 'betterdocs_settings_tab_email_reporting', array(
2170 - 'id' => 'tab-email-reporting',
2171 - 'label' => __( 'Email Reporting', 'betterdocs' ),
2172 - 'priority' => 60,
2173 - 'fields' => array(
2174 - 'title-email-reporting' => array(
2175 - 'name' => 'title-email-reporting-tab',
2176 - 'type' => 'section',
2177 - 'label' => __( 'Email Reporting', 'betterdocs' ),
2178 - 'priority' => 60,
2179 - 'fields' => array(
2180 - 'enable_reporting' => array(
2181 - 'name' => 'enable_reporting',
2182 - 'label' => __( 'Email Reporting', 'betterdocs' ),
2183 - 'enable_disable_text_active' => true,
2184 - 'type' => 'toggle',
2185 - 'priority' => 1,
2186 - 'default' => 0
2187 - ),
2188 - 'reporting_frequency' => apply_filters( 'betterdocs_reporting_frequency_settings', array(
2189 - 'name' => 'reporting_frequency',
2190 - 'type' => 'select',
2191 - 'label' => __( 'Reporting Frequency', 'betterdocs' ),
2192 - 'default' => 'betterdocs_weekly',
2193 - 'priority' => 2,
2194 - 'is_pro' => true,
2195 - 'options' => $this->normalize_options( array(
2196 - 'betterdocs_daily' => __( 'Once Daily', 'betterdocs' ),
2197 - 'betterdocs_weekly' => __( 'Once Weekly', 'betterdocs' ),
2198 - 'betterdocs_monthly' => __( 'Once Monthly', 'betterdocs' )
2199 - ) ),
2200 - 'rules' => Rules::is( 'enable_reporting', true )
2201 - ) ),
2202 - 'reporting_day' => array(
2203 - 'name' => 'reporting_day',
2204 - 'type' => 'select',
2205 - 'label' => __( 'Reporting Day', 'betterdocs' ),
2206 - 'default' => 'monday',
2207 - 'rules' => Rules::logicalRule( array(
2208 - Rules::is( 'enable_reporting', true ),
2209 - Rules::is( 'reporting_frequency', 'betterdocs_weekly' )
2210 - ), 'and' ),
2211 - 'priority' => 3,
2212 - 'options' => $this->normalize_options( array(
2213 - 'sunday' => __( 'Sunday', 'betterdocs' ),
2214 - 'monday' => __( 'Monday', 'betterdocs' ),
2215 - 'tuesday' => __( 'Tuesday', 'betterdocs' ),
2216 - 'wednesday' => __( 'Wednesday', 'betterdocs' ),
2217 - 'thursday' => __( 'Thursday', 'betterdocs' ),
2218 - 'friday' => __( 'Friday', 'betterdocs' ),
2219 - 'saturday' => __( 'Saturday', 'betterdocs' )
2220 - ) ),
2221 - 'label_subtitle' => __( 'This is only applicable for the “Weekly” report', 'betterdocs' )
2222 - ),
2223 - 'select_reporting_data' => apply_filters( 'betterdocs_select_reporting_data_settings', array(
2224 - 'name' => 'select_reporting_data',
2225 - 'type' => 'checkbox-select',
2226 - 'label' => __( 'Select Reporting Data', 'betterdocs' ),
2227 - 'priority' => 4,
2228 - 'multiple' => true,
2229 - 'options' => $this->normalize_options( array(
2230 - 'overview' => 'Overview',
2231 - 'top-docs' => 'Top Docs',
2232 - 'most-search' => 'Most Searched Keywords'
2233 - ) ),
2234 - 'default' => array( 'overview', 'top-docs', 'most-search' ),
2235 - 'is_pro' => true,
2236 - 'rules' => Rules::is( 'enable_reporting', true )
2237 - ) ),
2238 - 'reporting_email' => array(
2239 - 'name' => 'reporting_email',
2240 - 'type' => 'text',
2241 - 'label' => __( 'Reporting Email', 'betterdocs' ),
2242 - 'default' => get_option( 'admin_email' ),
2243 - 'priority' => 5,
2244 - 'rules' => Rules::is( 'enable_reporting', true )
2245 - ),
2246 - 'reporting_subject' => apply_filters( 'betterdocs_reporting_subject_settings', array(
2247 - 'name' => 'reporting_subject',
2248 - 'type' => 'textarea',
2249 - 'label' => __( 'Reporting Email Subject', 'betterdocs' ),
2250 - 'default' => wp_sprintf( // Translators: %s is replaced with the website name.
2251 - __( 'Your Documentation Performance of %s Website', 'betterdocs' ), get_bloginfo( 'name' ) ),
2252 - 'priority' => 6,
2253 - 'is_pro' => true,
2254 - 'rules' => Rules::is( 'enable_reporting', true )
2255 - ) ),
2256 - 'test_report' => array(
2257 - 'name' => 'test_report',
2258 - 'label' => __( 'Reporting Test', 'betterdocs' ),
2259 - 'text' => __( 'Test Report', 'betterdocs' ),
2260 - 'type' => 'button',
2261 - 'priority' => 7,
2262 - 'rules' => Rules::is( 'enable_reporting', true ),
2263 - 'ajax' => array(
2264 - 'on' => 'click',
2265 - 'api' => '/betterdocs/v1/reporting-test',
2266 - 'data' => array(
2267 - 'enable_reporting' => '@enable_reporting',
2268 - 'select_reporting_data' => '@select_reporting_data',
2269 - 'reporting_subject' => '@reporting_subject',
2270 - 'reporting_email' => '@reporting_email',
2271 - 'reporting_day' => '@reporting_day',
2272 - 'reporting_frequency' => '@reporting_frequency'
2273 - ),
2274 - 'swal' => array(
2275 - 'text' => __( 'Successfully Sent a Test Report in Your Email.', 'betterdocs' ),
2276 - 'icon' => 'success',
2277 - 'autoClose' => 2000
2278 - )
2279 - )
2280 - )
2281 - )
2282 - )
2283 - )
2284 - ) ),
2285 - 'tab-git-sync' => apply_filters( 'betterdocs_settings_tab_github_integration', array(
2286 - 'id' => 'tab-git-sync',
2287 - 'label' => __( 'Git Sync', 'betterdocs' ),
2288 - 'priority' => 60,
2289 - 'fields' => array(
2290 - 'title-git-sync' => array(
2291 - 'name' => 'title-git-sync-tab',
2292 - 'type' => 'section',
2293 - 'label' => __( 'Git Sync Settings', 'betterdocs' ),
2294 - 'priority' => 60,
2295 - 'fields' => array(
2296 - 'enable_git_integration' => array(
2297 - 'name' => 'enable_git_integration',
2298 - 'type' => 'toggle',
2299 - 'label' => __( 'Enable Git Sync', 'betterdocs' ),
2300 - 'enable_disable_text_active' => true,
2301 - 'default' => false,
2302 - 'priority' => 1,
2303 - 'is_pro' => true,
2304 - 'label_subtitle' => __( 'Enable bidirectional synchronization between BetterDocs and Git repositories', 'betterdocs' )
2305 - )
2306 - )
2307 - )
2308 - )
2309 - ) ),
2310 - 'tab-instant-answer' => apply_filters( 'betterdocs_settings_tab_instant_answer', array(
2311 - 'id' => 'tab-instant-answer',
2312 - 'name' => 'tab-instant-answer',
2313 - 'type' => 'section',
2314 - 'label' => __( 'Instant Answer', 'betterdocs' ),
2315 - 'save' => false,
2316 - 'priority' => 70,
2317 - 'fields' => array(
2318 - 'title-instant-answer' => array(
2319 - 'name' => 'title-instant-answer-tab',
2320 - 'type' => 'section',
2321 - 'label' => __( 'Instant Answer', 'betterdocs' ),
2322 - 'priority' => 80,
2323 - 'save' => false,
2324 - 'showSubmit' => false,
2325 - 'fields' => apply_filters( 'betterdocs_instant_answer_fields', array(
2326 - 'enable_disable_wrapper' => array(
2327 - 'name' => 'enable_disable_wrapper',
2328 - 'type' => 'section',
2329 - 'priority' => 0,
2330 - 'save' => false,
2331 - 'fields' => array(
2332 - 'enable_disable' => array(
2333 - 'name' => 'enable_disable',
2334 - 'type' => 'toggle',
2335 - 'priority' => 100,
2336 - 'description' => __( 'Enable Instant Answer', 'betterdocs' ),
2337 - 'enable_disable_text_active' => false,
2338 - 'default' => false,
2339 - 'is_pro' => true
2340 - )
2341 - )
2342 - )
2343 - ) )
2344 - )
2345 - )
2346 - ) ),
2347 - 'tab-betterdocs-ai' => array(
2348 - 'id' => 'tab-betterdocs-ai',
2349 - 'name' => 'tab-betterdocs-ai',
2350 - 'type' => 'section',
2351 - 'label' => __( 'AI Content Suite', 'betterdocs' ),
2352 - 'priority' => 74,
2353 - 'fields' => array(
2354 - 'sections-betterdocs-ai' => array(
2355 - 'name' => 'sections-betterdocs-ai',
2356 - 'type' => 'section',
2357 - 'label' => __( 'AI Content Suite', 'betterdocs' ),
2358 - 'priority' => 10,
2359 - 'fields' => array(
2360 - 'all-betterdocs-ai' => array(
2361 - 'id' => 'all-tab-betterdocs-ai',
2362 - 'name' => 'all-tab-betterdocs-ai',
2363 - 'label' => __( 'AI Content Suite Settings', 'betterdocs' ),
2364 - 'classes' => 'tab-layout',
2365 - 'type' => 'tab',
2366 - 'active' => 'open-ai-settings',
2367 - 'completionTrack' => true,
2368 - 'sidebar' => false,
2369 - 'save' => false,
2370 - 'title' => false,
2371 - 'config' => array(
2372 - 'active' => 'open-ai-settings',
2373 - 'sidebar' => false,
2374 - 'title' => false
2375 - ),
2376 - 'submit' => array(
2377 - 'show' => false
2378 - ),
2379 - 'step' => array(
2380 - 'show' => false
2381 - ),
2382 - 'priority' => 20,
2383 - 'fields' => apply_filters(
2384 - 'betterdocs_migration_tab_sections',
2385 - array(
2386 - 'open-ai-settings' => array(
2387 - 'id' => 'open-ai-settings',
2388 - 'name' => 'open-ai-settings',
2389 - 'type' => 'section',
2390 - 'label' => __( 'AI Platform & API', 'betterdocs' ),
2391 - 'priority' => 1,
2392 - 'fields' => array(
2393 - 'ai_platform' => array(
2394 - 'name' => 'ai_platform',
2395 - 'type' => 'select',
2396 - 'label' => __( 'AI Platform', 'betterdocs' ),
2397 - 'label_subtitle' => __( 'Choose which AI platform powers Write with AI, AI Edit, the Doc Summarizer and Quality Score. The model list and API key field below adapt to your choice.', 'betterdocs' ),
2398 - 'priority' => 1,
2399 - 'multiple' => false,
2400 - 'default' => 'openai',
2401 - // DeepSeek and OpenRouter are temporarily hidden from the
2402 - // dropdown. Filter the options here, NOT ModelRegistry::platforms() —
2403 - // sensitive_api_key_fields() loops the registry to mask each
2404 - // ai_api_key_{platform}, so trimming the registry would silently
2405 - // un-mask those keys. Re-enable later by dropping the array_diff_key.
2406 - 'options' => GlobalFields::normalize_fields(
2407 - array_diff_key( ModelRegistry::platforms(), array_flip( array( 'deepseek', 'openrouter' ) ) )
2408 - )
2409 - ),
2410 - 'ai_api_key_openai' => array(
2411 - 'name' => 'ai_api_key_openai',
2412 - 'type' => 'text',
2413 - 'label' => __( 'OpenAI API Key', 'betterdocs' ),
2414 - 'label_subtitle' => sprintf( /* translators: %s: documentation URL */ __( 'Check out this <a target="_blank" href="%s">documentation</a> to generate your OpenAI API key.', 'betterdocs' ), esc_url( 'https://betterdocs.co/docs/write-with-ai/' ) ),
2415 - 'default' => '',
2416 - 'priority' => 2,
2417 - 'rules' => Rules::is( 'ai_platform', 'openai' )
2418 - ),
2419 - 'ai_api_key_gemini' => array(
2420 - 'name' => 'ai_api_key_gemini',
2421 - 'type' => 'text',
2422 - 'label' => __( 'Google Gemini API Key', 'betterdocs' ),
2423 - 'label_subtitle' => sprintf( /* translators: %s: Google AI Studio URL */ __( 'Generate a key from <a target="_blank" href="%s">Google AI Studio</a>.', 'betterdocs' ), esc_url( 'https://aistudio.google.com/app/apikey' ) ),
2424 - 'default' => '',
2425 - 'priority' => 2,
2426 - 'rules' => Rules::is( 'ai_platform', 'gemini' )
2427 - ),
2428 - 'ai_api_key_claude' => array(
2429 - 'name' => 'ai_api_key_claude',
2430 - 'type' => 'text',
2431 - 'label' => __( 'Anthropic Claude API Key', 'betterdocs' ),
2432 - 'label_subtitle' => sprintf( /* translators: %s: Anthropic Console URL */ __( 'Generate a key from the <a target="_blank" href="%s">Anthropic Console</a>.', 'betterdocs' ), esc_url( 'https://console.anthropic.com/settings/keys' ) ),
2433 - 'default' => '',
2434 - 'priority' => 2,
2435 - 'rules' => Rules::is( 'ai_platform', 'claude' )
2436 - ),
2437 - 'ai_api_key_deepseek' => array(
2438 - 'name' => 'ai_api_key_deepseek',
2439 - 'type' => 'text',
2440 - 'label' => __( 'DeepSeek API Key', 'betterdocs' ),
2441 - 'label_subtitle' => sprintf( /* translators: %s: DeepSeek platform URL */ __( 'Generate a key from the <a target="_blank" href="%s">DeepSeek platform</a>.', 'betterdocs' ), esc_url( 'https://platform.deepseek.com/api_keys' ) ),
2442 - 'default' => '',
2443 - 'priority' => 2,
2444 - 'rules' => Rules::is( 'ai_platform', 'deepseek' )
2445 - ),
2446 - 'ai_api_key_openrouter' => array(
2447 - 'name' => 'ai_api_key_openrouter',
2448 - 'type' => 'text',
2449 - 'label' => __( 'OpenRouter API Key', 'betterdocs' ),
2450 - 'label_subtitle' => sprintf( /* translators: %s: OpenRouter keys URL */ __( 'Generate a key from <a target="_blank" href="%s">OpenRouter</a>.', 'betterdocs' ), esc_url( 'https://openrouter.ai/keys' ) ),
2451 - 'default' => '',
2452 - 'priority' => 2,
2453 - 'rules' => Rules::is( 'ai_platform', 'openrouter' )
2454 - ),
2455 - 'ai_model' => array(
2456 - 'name' => 'ai_model',
2457 - 'type' => 'platform_model_select',
2458 - 'label' => __( 'Model', 'betterdocs' ),
2459 - 'label_subtitle' => __( 'Available models depend on the selected platform.', 'betterdocs' ),
2460 - 'priority' => 10,
2461 - 'default' => 'gpt-4o-mini',
2462 - 'catalogue' => ModelRegistry::catalogue(),
2463 - 'defaults' => ModelRegistry::defaults()
2464 - )
2465 - )
2466 - ),
2467 - 'write-with-ai' => array(
2468 - 'id' => 'write-with-ai',
2469 - 'name' => 'write-with-ai',
2470 - 'type' => 'section',
2471 - 'label' => __( 'Write with AI', 'betterdocs' ),
2472 - 'priority' => 5,
2473 - 'fields' => array(
2474 - 'write-with-ai-subtabs' => array(
2475 - 'id' => 'write-with-ai-subtabs',
2476 - 'name' => 'write_with_ai_subtabs',
2477 - 'label' => __( 'Write with AI', 'betterdocs' ),
2478 - 'classes' => 'tab-nested-layout',
2479 - 'type' => 'tab',
2480 - 'active' => 'wwa-configuration',
2481 - 'completionTrack' => true,
2482 - 'sidebar' => false,
2483 - 'save' => false,
2484 - 'title' => false,
2485 - 'config' => array(
2486 - 'active' => 'wwa-configuration',
2487 - 'sidebar' => false,
2488 - 'title' => false
2489 - ),
2490 - 'submit' => array(
2491 - 'show' => false
2492 - ),
2493 - 'step' => array(
2494 - 'show' => false
2495 - ),
2496 - 'priority' => 5,
2497 - 'fields' => array(
2498 - 'wwa-configuration' => array(
2499 - 'id' => 'wwa-configuration',
2500 - 'name' => 'wwa-configuration',
2501 - 'type' => 'section',
2502 - 'label' => __( 'Configuration', 'betterdocs' ),
2503 - 'priority' => 1,
2504 - 'fields' => array(
2505 - 'enable_write_with_ai' => array(
2506 - 'name' => 'enable_write_with_ai',
2507 - 'type' => 'toggle',
2508 - 'priority' => 0,
2509 - 'label' => __( 'Write Docs with AI', 'betterdocs' ),
2510 - 'label_subtitle' => __( 'Generate AI based Documentation in your Gutenberg Editor', 'betterdocs' ),
2511 - 'enable_disable_text_active' => true,
2512 - 'default' => true
2513 - ),
2514 - 'enable_faq_write_with_ai' => array(
2515 - 'name' => 'enable_faq_write_with_ai',
2516 - 'type' => 'toggle',
2517 - 'priority' => 5,
2518 - 'label' => __( 'Write FAQ with AI', 'betterdocs' ),
2519 - 'label_subtitle' => __( 'Generate AI based FAQ in your Editor', 'betterdocs' ),
2520 - 'enable_disable_text_active' => true,
2521 - 'default' => true
2522 - ),
2523 - 'enable_glossaries_write_with_ai' => array(
2524 - 'name' => 'enable_glossaries_write_with_ai',
2525 - 'type' => 'toggle',
2526 - 'priority' => 6,
2527 - 'label' => __( 'Write Glossaries with AI', 'betterdocs' ),
2528 - 'label_subtitle' => __( 'Generate AI based Glossary definitions from the Glossaries admin page', 'betterdocs' ),
2529 - 'enable_disable_text_active' => true,
2530 - 'default' => true
2531 - ),
2532 - 'enable_docs_ai_suite' => array(
2533 - 'name' => 'enable_docs_ai_suite',
2534 - 'type' => 'toggle',
2535 - 'priority' => 7,
2536 - 'label' => __( 'Enhance Docs with AI', 'betterdocs' ),
2537 - 'label_subtitle' => __( 'Add BetterDocs AI actions for suggesting categories, tags and excerpts inside the native Docs editor panels.', 'betterdocs' ),
2538 - 'enable_disable_text_active' => true,
2539 - 'default' => true
2540 - ),
2541 - 'ai_autowrite_max_token' => array(
2542 - 'name' => 'ai_autowrite_max_token',
2543 - 'type' => 'min_token_number',
2544 - 'label' => __( 'Set Max Tokens', 'betterdocs' ),
2545 - 'label_subtitle' => sprintf( // translators: %s is a link to more information about token limits.
2546 - __( 'Documentation will be generated based on the Token Limits you have set. For more information on Token Limits, you can check out this <a target="_blank" href="%s">link</a>.', 'betterdocs' ), esc_url( 'https://platform.openai.com/account/limits' ) ),
2547 - 'default' => 2500,
2548 - 'priority' => 10,
2549 - 'model_field' => 'ai_model',
2550 - 'context' => 'write_with_ai',
2551 - 'min_token_map' => AIHelper::get_min_tokens_map( 'write_with_ai' ),
2552 - 'classes' => 'wprf-type-text'
2553 - )
2554 - )
2555 - ),
2556 - 'wwa-personalize' => array(
2557 - 'id' => 'wwa-personalize',
2558 - 'name' => 'wwa-personalize',
2559 - 'type' => 'section',
2560 - 'label' => __( 'Write AI Personalize', 'betterdocs' ),
2561 - 'priority' => 5,
2562 - 'fields' => array(
2563 - 'write_with_ai_instructions' => array(
2564 - 'name' => 'write_with_ai_instructions',
2565 - 'type' => 'wwa_instructions',
2566 - 'label' => __( 'Instructions', 'betterdocs' ),
2567 - 'label_subtitle' => __( 'Add reusable instruction sets to steer how BetterDocs AI writes. The "Default/Core" set is always applied; extra sets can be picked in the Write with AI popup.', 'betterdocs' ),
2568 - 'priority' => 1,
2569 - 'default' => array(
2570 - array(
2571 - 'id' => 'default',
2572 - 'title' => __( 'Default/Core', 'betterdocs' ),
2573 - 'content' => WriteWithAI::default_instruction_content()
2574 - )
2575 - )
2576 - )
2577 - )
2578 - ),
2579 - 'edit-ai-personalize' => array(
2580 - 'id' => 'edit-ai-personalize',
2581 - 'name' => 'edit-ai-personalize',
2582 - 'type' => 'section',
2583 - 'label' => __( 'Edit AI Personalize', 'betterdocs' ),
2584 - 'priority' => 7,
2585 - 'fields' => array(
2586 - 'ai_edit_actions' => array(
2587 - 'name' => 'ai_edit_actions',
2588 - 'type' => 'ai_edit_actions',
2589 - 'label' => __( 'Actions', 'betterdocs' ),
2590 - 'label_subtitle' => __( 'Choose which Edit with AI actions appear in the editor. Toggle actions on or off, edit each action\'s instruction, or add your own custom actions. All predefined actions are enabled by default.', 'betterdocs' ),
2591 - 'priority' => 1,
2592 - 'default' => AIEdit::default_actions()
2593 - )
2594 - )
2595 - )
2596 - )
2597 - )
2598 - )
2599 - ),
2600 - 'article-summary' => array(
2601 - 'id' => 'article-summary',
2602 - 'name' => 'article-summary',
2603 - 'type' => 'section',
2604 - 'label' => __( 'AI Doc Summarizer', 'betterdocs' ),
2605 - 'priority' => 10,
2606 - 'fields' => array(
2607 - 'enable_article_summary' => array(
2608 - 'name' => 'enable_article_summary',
2609 - 'type' => 'toggle',
2610 - 'priority' => 1,
2611 - 'label' => __( 'AI Powered Doc Summarizer', 'betterdocs' ),
2612 - 'label_subtitle' => __( 'Enable AI-powered article summaries on single doc pages. Requires OpenAI API key.', 'betterdocs' ),
2613 - 'enable_disable_text_active' => true,
2614 - 'default' => false
2615 - ),
2616 - 'article_summary_max_token' => array(
2617 - 'name' => 'article_summary_max_token',
2618 - 'type' => 'min_token_number',
2619 - 'label' => __( 'Set Max Tokens', 'betterdocs' ),
2620 - 'label_subtitle' => sprintf( // translators: %s is a link to more information about token limits.
2621 - __( 'Single Doc summarizer will be generated based on the token limits you have set. For more information on Token Limits, you can check out this <a target="_blank" href="%s">link</a>.', 'betterdocs' ), esc_url( 'https://platform.openai.com/account/limits' ) ),
2622 - 'default' => 1500,
2623 - 'priority' => 5,
2624 - 'model_field' => 'ai_model',
2625 - 'context' => 'article_summary',
2626 - 'min_token_map' => AIHelper::get_min_tokens_map( 'article_summary' ),
2627 - 'classes' => 'wprf-type-text'
2628 - )
2629 - )
2630 - )
2631 - )
2632 - )
2633 - )
2634 - )
2635 - )
2636 - )
2637 - ),
2638 - 'tab-ai-chatbot' => apply_filters( 'betterdocs_settings_tab_ai_chatbot', array(
2639 - 'id' => 'tab-ai-chatbot',
2640 - 'name' => 'tab-ai-chatbot',
2641 - 'type' => 'section',
2642 - 'label' => __( 'AI Chatbot', 'betterdocs' ),
2643 - 'submit' => array(
2644 - 'show' => false
2645 - ),
2646 - 'save' => false,
2647 - 'priority' => 75,
2648 - 'fields' => array(
2649 - 'title-ai-chatbot-tab' => array(
2650 - 'name' => 'title-ai-chatbot-tab',
2651 - 'type' => 'section',
2652 - 'label' => __( 'AI Chatbot', 'betterdocs' ),
2653 - 'priority' => 80,
2654 - 'submit' => array(
2655 - 'show' => false
2656 - ),
2657 - 'save' => false,
2658 - 'fields' => apply_filters( 'betterdocs_ai_chatbot_fields', array(
2659 - 'ai_chatbot_fields' => array(
2660 - 'name' => 'ai_chatbot_fields',
2661 - 'type' => 'section',
2662 - 'priority' => 0,
2663 - 'fields' => array(
2664 - 'enable_ai_chatbot' => array(
2665 - 'name' => 'enable_ai_chatbot',
2666 - 'label' => __( 'AI Chatbot', 'betterdocs' ),
2667 - 'description' => __( 'Enable AI Chatbot', 'betterdocs' ),
2668 - 'type' => 'toggle',
2669 - 'priority' => 5,
2670 - 'default' => 0,
2671 - 'is_pro' => true,
2672 - 'is_license_active' => false,
2673 - 'disabled' => ! betterdocs()->is_pro_active() || ! defined( 'BETTERDOCS_CHATBOT_FILE' )
2674 - ),
2675 - 'instant_answer_warning' => array(
2676 - 'name' => 'instant_answer_warning',
2677 - 'type' => 'html',
2678 - 'priority' => 6,
2679 - 'html' => sprintf(
2680 - '<div class="betterdocs-ia-warning" style="margin:8px 0 0;padding:12px 16px;background:#fffaeb;border-left:4px solid #fdb022;border-radius:4px;display:flex;align-items:flex-start;gap:10px;"><span style="font-size:18px;line-height:1;flex-shrink:0;color:#b54708;">&#9888;</span><div style="font-size:13px;color:#202223;line-height:1.5;">%1$s<br><a href="?page=betterdocs-settings&amp;tab=tab-instant-answer" style="display:inline-block;margin-top:6px;color:#5a6bff;text-decoration:none;font-weight:500;">%2$s &rarr;</a></div></div>',
2681 - esc_html__( 'Instant Answer is currently disabled. The AI Chatbot won\'t appear on your site until Instant Answer is enabled.', 'betterdocs' ),
2682 - esc_html__( 'Enable Instant Answer', 'betterdocs' )
2683 - ),
2684 - 'rules' => Rules::logicalRule( array(
2685 - Rules::is( 'enable_ai_chatbot', true ),
2686 - Rules::is( 'enable_disable', false ),
2687 - ), 'and' ),
2688 - )
2689 - )
2690 - )
2691 - ) )
2692 - )
2693 - )
2694 - ) )
2695 - ) ),
2696 - 'TAB_AI_CHATBOT' => get_option( 'enable_ai_chatbot' ),
2697 - 'CHATBOT_LICENSE' => get_option( 'betterdocs_chatbot_software__license_status' ),
2698 - 'PRO_ACTIVE' => is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ),
2699 - 'PRO_LICENSE' => get_option( 'betterdocs_pro_software__license_status' )
2700 - );
2457 + $terms = [
2458 + 'all' => 'All'
2459 + ];
2701 2460
2702 - $settings = array_merge( $settings, $this->chatbot_active_localize() );
2461 + if ( ! empty( $get_terms ) && ! is_wp_error( $get_terms ) ) {
2462 + foreach ( $get_terms as $value ) {
2463 + if ( isset( $value->slug ) && isset( $value->name ) ) {
2464 + $terms[ $value->slug ] = $value->name;
2465 + }
2466 + }
2467 + }
2703 2468
2704 - return apply_filters( 'betterdocs_settings_args', $settings );
2705 - }
2469 + $terms = $this->normalize_options( $terms );
2470 + if ( count( $terms ) > 1 ) {
2471 + $this->database->set_cache( $_cache_key, $terms );
2472 + }
2706 2473
2707 - /**
2708 - * @return array
2709 - */
2710 - public function chatbot_active_localize() {
2711 - $chatbot_active = is_plugin_active( 'betterdocs-ai-chatbot/betterdocs-ai-chatbot.php' );
2712 - $chatbot_license_valid = get_option( 'betterdocs_chatbot_software__license_status' ) === 'valid';
2713 - $chatbot_enabled = $this->get( 'enable_ai_chatbot', false );
2474 + return $terms;
2475 + }
2714 2476
2715 - // AI Search Suggestions are enabled if all conditions are met
2716 - $ai_search_suggestions_enabled = betterdocs()->helper->is_ai_chatbot_enabled();
2477 + /**
2478 + * Get all docs
2479 + */
2480 + public function docs() {
2481 + $docs = $this->database->get_cache( 'betterdocs::settings::all_docs' );
2717 2482
2718 - return array(
2719 - 'CHATBOT_ACTIVE' => $chatbot_active,
2720 - 'CHATBOT_LICENSE_VALID' => $chatbot_license_valid,
2721 - 'CHATBOT_ENABLED' => $chatbot_enabled,
2722 - 'AI_SEARCH_SUGGESTIONS_ENABLED' => $ai_search_suggestions_enabled
2723 - );
2724 - }
2483 + if ( $docs ) {
2484 + return $docs;
2485 + }
2725 2486
2726 - /**
2727 - * Call This Function As Helper, When Pro Is Deactivated, To Be Used As Settings Default Values, When Betterdocs Pro Is Deactivated
2728 - *
2729 - * @return array
2730 - */
2731 - public function pro_settings_default_values() {
2732 - return array(
2733 - 'multiple_kb' => false,
2734 - 'enable_glossaries' => false,
2735 - 'enable_encyclopedia' => false,
2736 - 'analytics_from' => false,
2737 - 'unique_visitor_count' => false,
2738 - 'exclude_bot_analytics' => false,
2739 - 'show_attachment' => false,
2740 - 'show_related_docs' => false,
2741 - 'advance_search' => false,
2742 - 'child_category_exclude' => false,
2743 - 'kb_based_search' => false,
2744 - 'enable_disable' => false,
2745 - 'enable_content_restriction' => false
2746 - );
2747 - }
2487 + $docs = [];
2748 2488
2749 - public function import_export_settings( $settings ) {
2750 - if ( ! current_user_can( 'import' ) ) {
2751 - return $settings;
2752 - }
2489 + $_docs = get_posts( [
2490 + 'post_type' => 'docs',
2491 + 'numberposts' => - 1,
2492 + 'posts_per_page' => - 1
2493 + ] );
2753 2494
2754 - $settings[ 'tab-import-export' ] = apply_filters( 'betterdocs_settings_tab_import_export', array(
2755 - 'id' => 'tab-import-export',
2756 - 'name' => 'tab-import-export',
2757 - 'classes' => 'tab-import-export',
2758 - 'label' => __( 'Import / Export', 'betterdocs' ),
2759 - 'priority' => 80,
2760 - 'fields' => array(
2761 - 'sections-import-export' => array(
2762 - 'name' => 'sections-import-export',
2763 - 'type' => 'section',
2764 - 'label' => __( 'Import / Export', 'betterdocs' ),
2765 - 'priority' => 30,
2766 - 'fields' => array(
2767 - 'all-tab-import-export' => array(
2768 - 'id' => 'all-tab-import-export',
2769 - 'name' => 'all-tab-import-export',
2770 - 'label' => __( 'Import Export Settings', 'betterdocs' ),
2771 - 'classes' => 'tab-layout',
2772 - 'type' => 'tab',
2773 - 'active' => 'import',
2774 - 'completionTrack' => true,
2775 - 'sidebar' => false,
2776 - 'save' => false,
2777 - 'title' => false,
2778 - 'config' => array(
2779 - 'active' => 'import',
2780 - 'sidebar' => false,
2781 - 'title' => false
2782 - ),
2783 - 'submit' => array(
2784 - 'show' => false
2785 - ),
2786 - 'step' => array(
2787 - 'show' => false
2788 - ),
2789 - 'priority' => 20,
2790 - 'fields' => array(
2791 - 'import' => array(
2792 - 'id' => 'import',
2793 - 'name' => 'import',
2794 - 'type' => 'section',
2795 - 'label' => __( 'Import', 'betterdocs' ),
2796 - 'priority' => 1,
2797 - 'fields' => array(
2798 - 'import_tab_nested' => array(
2799 - 'id' => 'import_tab_nested',
2800 - 'name' => 'import_tab_nested',
2801 - 'label' => __( 'Import', 'betterdocs' ),
2802 - 'classes' => 'tab-nested-layout',
2803 - 'type' => 'tab',
2804 - 'active' => 'import_docs_nested',
2805 - 'completionTrack' => true,
2806 - 'sidebar' => false,
2807 - 'save' => false,
2808 - 'title' => false,
2809 - 'config' => array(
2810 - 'active' => 'import_docs_nested',
2811 - 'sidebar' => false,
2812 - 'title' => false
2813 - ),
2814 - 'submit' => array(
2815 - 'show' => false
2816 - ),
2817 - 'step' => array(
2818 - 'show' => false
2819 - ),
2820 - 'priority' => 1,
2821 - 'fields' => array(
2822 - 'import_docs_nested' => array(
2823 - 'id' => 'import_docs_nested',
2824 - 'name' => 'import_docs_nested',
2825 - 'type' => 'section',
2826 - 'label' => __( 'Import Docs', 'betterdocs' ),
2827 - 'priority' => 1,
2828 - 'fields' => array(
2829 - 'import_docs' => array(
2830 - 'name' => 'import_docs',
2831 - 'type' => 'importerupload',
2832 - 'label' => __( 'Import Docs', 'betterdocs' ),
2833 - 'label_subtitle' => wp_sprintf( // Translators: %1$s is a link to download a sample CSV file.
2834 - __( 'To import your Docs, please upload the .xml / .csv file here. <a href="%1$s">Download sample csv file</a>', 'betterdocs' ), betterdocs()->assets->icon( 'BetterDocs-sample-data.csv', true ) ),
2835 - 'text' => array(
2836 - 'normal' => __( 'Proceed', 'betterdocs' ),
2837 - 'saved' => __( 'Proceed', 'betterdocs' ),
2838 - 'loading' => __( 'Importing...', 'betterdocs' ),
2839 - 'exists_notice' => __( 'It seems like documentations with same slugs already exist on your website. What would you like to do?', 'betterdocs' )
2840 - ),
2841 - 'ajax' => array(
2842 - 'on' => 'click',
2843 - 'api' => '/betterdocs/v1/import-docs',
2844 - 'swal' => array(
2845 - 'text' => __( 'Import completed successfully.', 'betterdocs' ),
2846 - 'icon' => 'success',
2847 - 'autoClose' => 2000
2848 - )
2849 - ),
2850 - 'file_type' => '.xml, .csv',
2851 - 'priority' => 1
2852 - )
2853 - )
2854 - ),
2495 + if ( ! empty( $_docs ) ) {
2496 + foreach ( $_docs as $doc ) {
2497 + $docs[ $doc->ID ] = betterdocs()->template_helper->kses( $doc->post_title );
2498 + }
2499 + $docs = GlobalFields::normalize_fields( $docs );
2500 + $this->database->set_cache( 'betterdocs::settings::all_docs', $docs );
2501 + }
2855 2502
2856 - 'import_settings_nested' => array(
2857 - 'id' => 'import_settings_nested',
2858 - 'name' => 'import_settings_nested',
2859 - 'type' => 'section',
2860 - 'label' => __( 'Import Settings', 'betterdocs' ),
2861 - 'priority' => 1,
2862 - 'fields' => array(
2863 - 'settings_importer' => array(
2864 - 'name' => 'settings_importer',
2865 - 'type' => 'settingsuploader',
2866 - 'label' => __( 'Import Settings', 'betterdocs' ),
2867 - 'label_subtitle' => __( 'To import BetterDocs Settings, please upload BetterDocs settings you have exported from another website in .json format', 'betterdocs' ),
2868 - 'reset' => __( 'Change', 'betterdocs' ),
2869 - 'priority' => 1
2870 - ),
2871 - 'import_settings' => array(
2872 - 'name' => 'import_settings',
2873 - 'type' => 'button',
2874 - 'rules' => Rules::is( 'settings_importer', null, true ),
2875 - 'text' => array(
2876 - 'normal' => __( 'Proceed', 'betterdocs' ),
2877 - 'saved' => __( 'Proceed', 'betterdocs' ),
2878 - 'loading' => __( 'Importing...', 'betterdocs' )
2879 - ),
2880 - 'ajax' => array(
2881 - 'on' => 'click',
2882 - 'api' => '/betterdocs/v1/import-settings',
2883 - 'data' => array(
2884 - 'settings' => '@settings_importer'
2885 - ),
2886 - 'swal' => array(
2887 - 'text' => __( 'Import completed successfully.', 'betterdocs' ),
2888 - 'icon' => 'success',
2889 - 'autoClose' => 1000
2890 - ),
2891 - 'reload' => true
2892 - ),
2893 - 'priority' => 2
2894 - )
2895 - )
2896 - )
2897 - )
2898 - )
2899 - )
2900 - ),
2901 - 'export' => array(
2902 - 'id' => 'export',
2903 - 'name' => 'export',
2904 - 'type' => 'section',
2905 - 'label' => __( 'Export', 'betterdocs' ),
2906 - 'priority' => 1,
2907 - 'fields' => array(
2908 - 'export_tab_nested' => array(
2909 - 'id' => 'export_tab_nested',
2910 - 'name' => 'export_tab_nested',
2911 - 'label' => __( 'Export', 'betterdocs' ),
2912 - 'classes' => 'tab-nested-layout',
2913 - 'type' => 'tab',
2914 - 'active' => 'export_docs_nested',
2915 - 'completionTrack' => true,
2916 - 'sidebar' => false,
2917 - 'save' => false,
2918 - 'title' => false,
2919 - 'config' => array(
2920 - 'active' => 'export_docs_nested',
2921 - 'sidebar' => false,
2922 - 'title' => false
2923 - ),
2924 - 'submit' => array(
2925 - 'show' => false
2926 - ),
2927 - 'step' => array(
2928 - 'show' => false
2929 - ),
2930 - 'priority' => 1,
2931 - 'fields' => array(
2932 - 'export_docs_nested' => array(
2933 - 'id' => 'export_docs_nested',
2934 - 'name' => 'export_docs_nested',
2935 - 'type' => 'section',
2936 - 'label' => __( 'Export Docs', 'betterdocs' ),
2937 - 'priority' => 1,
2938 - 'fields' => apply_filters( 'betterdocs_export_fields', array(
2939 - 'export_type' => array(
2940 - 'name' => 'export_type',
2941 - 'label' => __( 'Select Docs Type', 'betterdocs' ),
2942 - 'label_subtitle' => __( 'Choose an export type: All Docs, a specific Knowledge Base, or a Doc Category', 'betterdocs' ),
2943 - 'type' => 'select',
2944 - 'default' => 'docs',
2945 - 'priority' => 3,
2946 - 'search' => true,
2947 - 'options' => $this->normalize_options( apply_filters( 'betterdocs_export_type_options', array(
2948 - 'docs' => __( 'Docs', 'betterdocs' ),
2949 - 'doc_category' => __( 'Docs Category', 'betterdocs' ),
2950 - 'glossaries' => __( 'Glossaries', 'betterdocs' )
2951 - ) ) )
2952 - ),
2953 - 'export_docs' => array(
2954 - 'name' => 'export_docs',
2955 - 'type' => 'checkbox-select',
2956 - 'label' => __( 'Select Docs', 'betterdocs' ),
2957 - 'label_subtitle' => __( 'Selected docs will be included in the export.', 'betterdocs' ),
2958 - 'priority' => 4,
2959 - 'multiple' => true,
2960 - 'search' => true,
2961 - 'default' => array( 'all' ),
2962 - 'placeholder' => __( 'Select any', 'betterdocs' ),
2963 - 'options' => array_merge( array(
2964 - array(
2965 - 'value' => 'all',
2966 - 'label' => 'All'
2967 - )
2968 - ), $this->docs() ),
2969 - 'filterValue' => 'all',
2970 - 'rules' => Rules::is( 'export_type', 'docs' )
2971 - ),
2972 - 'export_categories' => array(
2973 - 'name' => 'export_categories',
2974 - 'type' => 'checkbox-select',
2975 - 'label' => __( 'Select Categories', 'betterdocs' ),
2976 - 'label_subtitle' => __( 'Selected categories and its docs will be included in the export.', 'betterdocs' ),
2977 - 'priority' => 6,
2978 - 'multiple' => true,
2979 - 'search' => true,
2980 - 'default' => array( 'all' ),
2981 - 'placeholder' => __( 'Select any', 'betterdocs' ),
2982 - 'options' => $this->get_terms( 'doc_category', false ),
2983 - 'filterValue' => 'all',
2984 - 'rules' => Rules::is( 'export_type', 'doc_category' )
2985 - ),
2986 - 'export_glossaries' => array(
2987 - 'name' => 'export_glossaries',
2988 - 'type' => 'checkbox-select',
2989 - 'label' => __( 'Select Glossaries', 'betterdocs' ),
2990 - 'label_subtitle' => __( 'Selected glossary terms will be exported.', 'betterdocs' ),
2991 - 'priority' => 7,
2992 - 'multiple' => true,
2993 - 'search' => true,
2994 - 'default' => array( 'all' ),
2995 - 'placeholder' => __( 'Select any', 'betterdocs' ),
2996 - 'options' => $this->get_terms( 'glossaries' ),
2997 - 'filterValue' => 'all',
2998 - 'rules' => Rules::is( 'export_type', 'glossaries' )
2999 - ),
3000 - 'file_type' => array(
3001 - 'name' => 'file_type',
3002 - 'label' => __( 'Select File Type', 'betterdocs' ),
3003 - 'label_subtitle' => __( 'Choose a file type', 'betterdocs' ),
3004 - 'type' => 'select',
3005 - 'default' => 'xml',
3006 - 'priority' => 8,
3007 - 'search' => true,
3008 - 'options' => $this->normalize_options( apply_filters( 'betterdocs_export_file_type_options', array(
3009 - 'xml' => __( '.xml', 'betterdocs' ),
3010 - 'csv' => __( '.csv', 'betterdocs' )
3011 - ) ) )
3012 - ),
3013 - 'enable_export_faq' => array(
3014 - 'name' => 'enable_export_faq',
3015 - 'type' => 'toggle',
3016 - 'priority' => 9,
3017 - 'label' => __( 'Export FAQ', 'betterdocs' ),
3018 - 'label_subtitle' => __( 'Export FAQ Related Terms & Posts', 'betterdocs' ),
3019 - 'enable_disable_text_active' => true,
3020 - 'default' => true,
3021 - 'rules' => Rules::is( 'export_type', 'glossaries', true )
3022 - ),
3023 - 'export_docs_btn' => array(
3024 - 'name' => 'export_docs_btn',
3025 - 'text' => array(
3026 - 'normal' => __( 'Proceed', 'betterdocs' ),
3027 - 'saved' => __( 'Proceed', 'betterdocs' ),
3028 - 'loading' => __( 'Exporting...', 'betterdocs' )
3029 - ),
3030 - 'type' => 'button',
3031 - 'priority' => 10,
3032 - 'ajax' => array(
3033 - 'on' => 'click',
3034 - 'api' => '/betterdocs/v1/export-docs',
3035 - 'data' => array(
3036 - 'export_type' => '@export_type',
3037 - 'export_docs' => '@export_docs',
3038 - 'export_kbs' => '@export_kbs',
3039 - 'export_categories' => '@export_categories',
3040 - 'export_glossaries' => '@export_glossaries',
3041 - 'file_type' => '@file_type',
3042 - 'enable_export_faq' => '@enable_export_faq'
3043 - ),
3044 - 'swal' => array(
3045 - 'text' => __( 'Exported Successfully.', 'betterdocs' ),
3046 - 'icon' => 'success',
3047 - 'autoClose' => 2000
3048 - )
3049 - )
3050 - )
3051 - ) )
3052 - ),
2503 + return $docs;
2504 + }
3053 2505
3054 - 'export_settings_nested' => array(
3055 - 'id' => 'export_settings_nested',
3056 - 'name' => 'export_settings_nested',
3057 - 'type' => 'section',
3058 - 'label' => __( 'Export Settings', 'betterdocs' ),
3059 - 'priority' => 1,
3060 - 'fields' => array(
3061 - 'export_settings' => array(
3062 - 'name' => 'export_settings',
3063 - 'label' => __( 'Export Settings', 'betterdocs' ),
3064 - 'label_subtitle' => __( 'Simply click on “Export Settings” button to download your BetterDocs settings in .json format', 'betterdocs' ),
3065 - 'text' => array(
3066 - 'normal' => __( 'Export Settings', 'betterdocs' ),
3067 - 'saved' => __( 'Export Settings', 'betterdocs' ),
3068 - 'loading' => __( 'Exporting...', 'betterdocs' )
3069 - ),
3070 - 'type' => 'button',
3071 - 'priority' => 8,
3072 - 'ajax' => array(
3073 - 'on' => 'click',
3074 - 'api' => '/betterdocs/v1/export-settings',
3075 - 'data' => array(
3076 - 'betterdocs_settings' => get_option( 'betterdocs_settings' )
3077 - ),
3078 - 'swal' => array(
3079 - 'text' => __( 'File downloaded successfully.', 'betterdocs' ),
3080 - 'icon' => 'success',
3081 - 'autoClose' => 2000
3082 - )
3083 - )
3084 - )
3085 - )
3086 - )
3087 - )
3088 - )
3089 - )
3090 - )
3091 - )
3092 - )
3093 - )
3094 - )
3095 - )
3096 - ) );
2506 + public function hide_roles_management( $tabData = [] ) {
2507 + global $current_user;
3097 2508
3098 - return $settings;
3099 - }
2509 + if ( $current_user instanceof WP_User && ! in_array( 'administrator', $current_user->roles ) ) {
2510 + unset( $tabData['fields']['title-advance-settings']['fields']['article_roles'] );
2511 + unset( $tabData['fields']['title-advance-settings']['fields']['settings_roles'] );
2512 + unset( $tabData['fields']['title-advance-settings']['fields']['analytics_roles'] );
2513 + }
3100 2514
3101 - public function maybe_remove_git_tab( $tabs ) {
3102 - $pro_active = is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' );
3103 - $pro_has_git = apply_filters( 'betterdocs_pro_has_git_integration', false );
3104 -
3105 - if ( $pro_active && ! $pro_has_git ) {
3106 - unset( $tabs[ 'tab-git-sync' ] );
3107 - }
3108 -
3109 - return $tabs;
3110 - }
3111 -
3112 - public function normalize_options( $options ) {
3113 - return GlobalFields::normalize_fields( $options );
3114 - }
3115 -
3116 - public function get_texanomy() {
3117 - $docs_tax = $this->database->get_cache( 'betterdocs::settings::taxonomies' );
3118 -
3119 - if ( $docs_tax ) {
3120 - return $docs_tax;
3121 - }
3122 -
3123 - $taxonomies = get_taxonomies( array(
3124 - 'object_type' => array( 'docs' )
3125 - ), 'objects' );
3126 -
3127 - $docs_tax = array(
3128 - 'all' => 'All Docs Archive',
3129 - 'docs' => 'Docs Page'
3130 - );
3131 - foreach ( $taxonomies as $key => $value ) {
3132 - $docs_tax[ $key ] = $value->label;
3133 - }
3134 - unset( $docs_tax[ 'doc_tag' ] );
3135 -
3136 - $docs_tax = $this->normalize_options( $docs_tax );
3137 - if ( count( $docs_tax ) > 2 ) {
3138 - $this->database->set_cache( 'betterdocs::settings::taxonomies', $docs_tax );
3139 - }
3140 -
3141 - return $docs_tax;
3142 - }
3143 -
3144 - public function get_terms( $taxonomy, $hide_empty = true ) {
3145 - $_cache_key = 'betterdocs::settings::terms::' . trim( $taxonomy );
3146 - $docs_tax = $this->database->get_cache( $_cache_key );
3147 -
3148 - if ( $docs_tax ) {
3149 - return $docs_tax;
3150 - }
3151 -
3152 - $get_terms = get_terms( array(
3153 - 'taxonomy' => $taxonomy,
3154 - 'hide_empty' => $hide_empty
3155 - ) );
3156 -
3157 - $terms = array(
3158 - 'all' => 'All'
3159 - );
3160 -
3161 - if ( ! empty( $get_terms ) && ! is_wp_error( $get_terms ) ) {
3162 - foreach ( $get_terms as $value ) {
3163 - if ( isset( $value->slug ) && isset( $value->name ) ) {
3164 - $terms[ $value->slug ] = $value->name;
3165 - }
3166 - }
3167 - }
3168 -
3169 - $terms = $this->normalize_options( $terms );
3170 - if ( count( $terms ) > 1 ) {
3171 - $this->database->set_cache( $_cache_key, $terms );
3172 - }
3173 -
3174 - return $terms;
3175 - }
3176 -
3177 - public function get_terms_with_ids( $taxonomy ) {
3178 - $_cache_key = 'betterdocs::settings::terms::ids' . trim( $taxonomy );
3179 - $docs_tax = $this->database->get_cache( $_cache_key );
3180 -
3181 - if ( $docs_tax ) {
3182 - return $docs_tax;
3183 - }
3184 -
3185 - $get_terms = get_terms( array(
3186 - 'taxonomy' => $taxonomy,
3187 - 'hide_empty' => false,
3188 - 'suppress_filter' => true
3189 - ) );
3190 -
3191 - $terms = array();
3192 -
3193 - if ( ! empty( $get_terms ) && ! is_wp_error( $get_terms ) ) {
3194 - foreach ( $get_terms as $value ) {
3195 - if ( isset( $value->term_id ) && isset( $value->name ) ) {
3196 - $terms[ $value->term_id ] = $value->name;
3197 - }
3198 - }
3199 - }
3200 -
3201 - $terms = $this->normalize_options( $terms );
3202 - if ( count( $terms ) > 1 ) {
3203 - $this->database->set_cache( $_cache_key, $terms );
3204 - }
3205 -
3206 - return $terms;
3207 - }
3208 -
3209 - /**
3210 - * Get all docs
3211 - */
3212 - public function docs() {
3213 - $docs = $this->database->get_cache( 'betterdocs::settings::all_docs' );
3214 -
3215 - if ( $docs ) {
3216 - return $docs;
3217 - }
3218 -
3219 - $docs = array();
3220 -
3221 - $_docs = get_posts( array(
3222 - 'post_type' => 'docs',
3223 - 'numberposts' => -1,
3224 - 'posts_per_page' => -1
3225 - ) );
3226 -
3227 - if ( ! empty( $_docs ) ) {
3228 - foreach ( $_docs as $doc ) {
3229 - $docs[ $doc->ID ] = betterdocs()->template_helper->kses( $doc->post_title );
3230 - }
3231 - $docs = GlobalFields::normalize_fields( $docs );
3232 - $this->database->set_cache( 'betterdocs::settings::all_docs', $docs );
3233 - }
3234 -
3235 - return $docs;
3236 - }
3237 -
3238 - public function hide_roles_management( $tabData = array() ) {
3239 - global $current_user;
3240 -
3241 - if ( $current_user instanceof WP_User && ! in_array( 'administrator', $current_user->roles ) ) {
3242 - unset( $tabData[ 'fields' ][ 'title-advance-settings' ][ 'fields' ][ 'article_roles' ] );
3243 - unset( $tabData[ 'fields' ][ 'title-advance-settings' ][ 'fields' ][ 'settings_roles' ] );
3244 - unset( $tabData[ 'fields' ][ 'title-advance-settings' ][ 'fields' ][ 'analytics_roles' ] );
3245 - unset( $tabData[ 'fields' ][ 'title-advance-settings' ][ 'fields' ][ 'faq_roles' ] );
3246 - }
3247 -
3248 - return $tabData;
3249 - }
2515 + return $tabData;
2516 + }
3250 2517 }