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