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