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