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 +88 -19 4.8.2 → 4.9.3 View file →
@@ -283,8 +283,12 @@
283 283 'enable_breadcrumb_category' => true,
284 284 'enable_breadcrumb_title' => true,
285 285 'enable_sidebar_cat_list' => true,
286 286 'enable_print_icon' => true,
287 + 'print_enable_logo' => false,
288 + 'print_logo' => array(),
289 + 'print_enable_footer' => false,
290 + 'print_footer_text' => '',
287 291 'enable_tags' => true,
288 292 'email_feedback' => true,
289 293 'feedback_link_text' => __( 'Still stuck? How can we help?', 'betterdocs' ),
290 294 'reaction_feedback_text' => __( 'Thanks for your feedback', 'betterdocs' ),
@@ -343,9 +347,21 @@
343 347 'singular_estimated_reading_time_text' => __( 'min read', 'betterdocs' ),
344 348 'betterdocs_access_control_repeater' => array(),
345 349 'internal_knowledge_base_type' => 'basic',
346 350 'betterdocs_access_control_repeater_kb' => array(),
347 - 'enable_git_integration' => false
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' => ''
348 364 );
349 365
350 366 $_default = apply_filters( 'betterdocs_default_settings', $_default );
351 367 // $_default = apply_filters_deprecated(
@@ -717,21 +733,38 @@
717 733 betterdocs()->kbmigration->migrate();
718 734 }
719 735 $_settings = wp_parse_args( $_normalized_settings, $_old_settings );
720 736
721 - // Check if there are actual changes before saving.
722 - // update_option returns false when values serialize identically, which can happen
723 - // due to object caching or type normalization even when user made changes.
724 - $_has_changes = $_settings != $_old_settings;
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;
725 759
726 760 $_saved = $this->database->save( $this->base_key, $_settings );
727 761
728 762 do_action_ref_array( 'betterdocs::settings::saved', array( $_saved, $_settings, $_old_settings, &$this ) );
729 763
730 - // Return true if save succeeded OR if there were changes to attempt saving.
731 - // This handles cases where update_option returns false due to identical serialization
732 - // (e.g., object caching, type coercion during serialization).
733 - return $_saved || $_has_changes;
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;
734 767 }
735 768
736 769 public function views( $hook ) {
737 770 return betterdocs()->views->get( 'admin/settings' );
@@ -1384,8 +1417,44 @@
1384 1417 'enable_disable_text_active' => true,
1385 1418 'default' => 1,
1386 1419 'priority' => 3
1387 1420 ),
1421 + 'print_enable_logo' => array(
1422 + 'name' => 'print_enable_logo',
1423 + 'type' => 'toggle',
1424 + 'label' => __( 'Logo on Printed Doc', 'betterdocs' ),
1425 + 'label_subtitle' => __( 'Show a logo at the top of the printed / PDF page', 'betterdocs' ),
1426 + 'enable_disable_text_active' => true,
1427 + 'default' => 0,
1428 + 'priority' => 4
1429 + ),
1430 + 'print_logo' => array(
1431 + 'name' => 'print_logo',
1432 + 'type' => 'media',
1433 + 'value' => '',
1434 + 'label' => __( 'Print Logo', 'betterdocs' ),
1435 + 'label_subtitle' => __( 'Leave empty to use your site logo, or the site icon when no site logo is set', 'betterdocs' ),
1436 + 'priority' => 5,
1437 + 'rules' => Rules::is( 'print_enable_logo', true )
1438 + ),
1439 + 'print_enable_footer' => array(
1440 + 'name' => 'print_enable_footer',
1441 + 'type' => 'toggle',
1442 + 'label' => __( 'Footer on Printed Doc', 'betterdocs' ),
1443 + 'label_subtitle' => __( 'Show a footer on every page of the printed / PDF document', 'betterdocs' ),
1444 + 'enable_disable_text_active' => true,
1445 + 'default' => 0,
1446 + 'priority' => 6
1447 + ),
1448 + 'print_footer_text' => array(
1449 + 'name' => 'print_footer_text',
1450 + 'type' => 'textarea',
1451 + 'label' => __( 'Print Footer Text', 'betterdocs' ),
1452 + 'label_subtitle' => __( 'Leave empty to use the site name and current year', 'betterdocs' ),
1453 + 'default' => '',
1454 + 'priority' => 7,
1455 + 'rules' => Rules::is( 'print_enable_footer', true )
1456 + ),
1388 1457 'enable_tags' => array(
1389 1458 'name' => 'enable_tags',
1390 1459 'type' => 'toggle',
1391 1460 'label' => __( 'Tags', 'betterdocs' ),
@@ -1390,9 +1459,9 @@
1390 1459 'type' => 'toggle',
1391 1460 'label' => __( 'Tags', 'betterdocs' ),
1392 1461 'enable_disable_text_active' => true,
1393 1462 'default' => 1,
1394 - 'priority' => 4
1463 + 'priority' => 8
1395 1464 ),
1396 1465 'show_last_update_time' => array(
1397 1466 'name' => 'show_last_update_time',
1398 1467 'type' => 'toggle',
@@ -1398,9 +1467,9 @@
1398 1467 'type' => 'toggle',
1399 1468 'label' => __( 'Last Update Time', 'betterdocs' ),
1400 1469 'enable_disable_text_active' => true,
1401 1470 'default' => 1,
1402 - 'priority' => 5
1471 + 'priority' => 9
1403 1472 ),
1404 1473 'enable_navigation' => array(
1405 1474 'name' => 'enable_navigation',
1406 1475 'type' => 'toggle',
@@ -1406,9 +1475,9 @@
1406 1475 'type' => 'toggle',
1407 1476 'label' => __( 'Navigation', 'betterdocs' ),
1408 1477 'enable_disable_text_active' => true,
1409 1478 'default' => 1,
1410 - 'priority' => 6
1479 + 'priority' => 10
1411 1480 ),
1412 1481 'enable_comment' => array(
1413 1482 'name' => 'enable_comment',
1414 1483 'type' => 'toggle',
@@ -1414,9 +1483,9 @@
1414 1483 'type' => 'toggle',
1415 1484 'label' => __( 'Comment', 'betterdocs' ),
1416 1485 'enable_disable_text_active' => true,
1417 1486 'default' => '',
1418 - 'priority' => 7
1487 + 'priority' => 11
1419 1488 ),
1420 1489 'enable_credit' => array(
1421 1490 'name' => 'enable_credit',
1422 1491 'type' => 'toggle',
@@ -1422,9 +1491,9 @@
1422 1491 'type' => 'toggle',
1423 1492 'label' => __( 'Show Powered by BetterDocs', 'betterdocs' ),
1424 1493 'enable_disable_text_active' => true,
1425 1494 'default' => '',
1426 - 'priority' => 8
1495 + 'priority' => 12
1427 1496 ),
1428 1497 'reaction_feedback_text' => array(
1429 1498 'name' => 'reaction_feedback_text',
1430 1499 'type' => 'text',
@@ -1429,9 +1498,9 @@
1429 1498 'name' => 'reaction_feedback_text',
1430 1499 'type' => 'text',
1431 1500 'label' => __( 'Reaction Feedback Text', 'betterdocs' ),
1432 1501 'default' => __( 'Thanks for your feedback.', 'betterdocs' ),
1433 - 'priority' => 9
1502 + 'priority' => 13
1434 1503 ),
1435 1504 'enable_estimated_reading_time' => array(
1436 1505 'name' => 'enable_estimated_reading_time',
1437 1506 'type' => 'toggle',
@@ -1437,9 +1506,9 @@
1437 1506 'type' => 'toggle',
1438 1507 'label' => __( 'Estimated Reading Time', 'betterdocs' ),
1439 1508 'enable_disable_text_active' => true,
1440 1509 'default' => 0,
1441 - 'priority' => 10
1510 + 'priority' => 14
1442 1511 ),
1443 1512 'estimated_reading_time_title' => array(
1444 1513 'name' => 'estimated_reading_time_title',
1445 1514 'type' => 'text',
@@ -1444,9 +1513,9 @@
1444 1513 'name' => 'estimated_reading_time_title',
1445 1514 'type' => 'text',
1446 1515 'label' => __( 'Estimated Reading Time Title', 'betterdocs' ),
1447 1516 'default' => '',
1448 - 'priority' => 11,
1517 + 'priority' => 15,
1449 1518 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1450 1519 ),
1451 1520 'estimated_reading_time_text' => array(
1452 1521 'name' => 'estimated_reading_time_text',
@@ -1452,9 +1521,9 @@
1452 1521 'name' => 'estimated_reading_time_text',
1453 1522 'type' => 'text',
1454 1523 'label' => __( 'Estimated Reading Time Text', 'betterdocs' ),
1455 1524 'default' => __( 'min read', 'betterdocs' ),
1456 - 'priority' => 12,
1525 + 'priority' => 16,
1457 1526 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1458 1527 ),
1459 1528 'singular_estimated_reading_time_text' => array(
1460 1529 'name' => 'singular_estimated_reading_time_text',
@@ -1460,9 +1529,9 @@
1460 1529 'name' => 'singular_estimated_reading_time_text',
1461 1530 'type' => 'text',
1462 1531 'label' => __( 'Estimated Reading Time Text Singular', 'betterdocs' ),
1463 1532 'default' => __( 'min read', 'betterdocs' ),
1464 - 'priority' => 13,
1533 + 'priority' => 17,
1465 1534 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1466 1535 )
1467 1536 )
1468 1537 ),