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 +75 -18 4.9.0 → 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' ),
@@ -729,21 +733,38 @@
729 733 betterdocs()->kbmigration->migrate();
730 734 }
731 735 $_settings = wp_parse_args( $_normalized_settings, $_old_settings );
732 736
733 - // Check if there are actual changes before saving.
734 - // update_option returns false when values serialize identically, which can happen
735 - // due to object caching or type normalization even when user made changes.
736 - $_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;
737 759
738 760 $_saved = $this->database->save( $this->base_key, $_settings );
739 761
740 762 do_action_ref_array( 'betterdocs::settings::saved', array( $_saved, $_settings, $_old_settings, &$this ) );
741 763
742 - // Return true if save succeeded OR if there were changes to attempt saving.
743 - // This handles cases where update_option returns false due to identical serialization
744 - // (e.g., object caching, type coercion during serialization).
745 - 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;
746 767 }
747 768
748 769 public function views( $hook ) {
749 770 return betterdocs()->views->get( 'admin/settings' );
@@ -1396,8 +1417,44 @@
1396 1417 'enable_disable_text_active' => true,
1397 1418 'default' => 1,
1398 1419 'priority' => 3
1399 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 + ),
1400 1457 'enable_tags' => array(
1401 1458 'name' => 'enable_tags',
1402 1459 'type' => 'toggle',
1403 1460 'label' => __( 'Tags', 'betterdocs' ),
@@ -1402,9 +1459,9 @@
1402 1459 'type' => 'toggle',
1403 1460 'label' => __( 'Tags', 'betterdocs' ),
1404 1461 'enable_disable_text_active' => true,
1405 1462 'default' => 1,
1406 - 'priority' => 4
1463 + 'priority' => 8
1407 1464 ),
1408 1465 'show_last_update_time' => array(
1409 1466 'name' => 'show_last_update_time',
1410 1467 'type' => 'toggle',
@@ -1410,9 +1467,9 @@
1410 1467 'type' => 'toggle',
1411 1468 'label' => __( 'Last Update Time', 'betterdocs' ),
1412 1469 'enable_disable_text_active' => true,
1413 1470 'default' => 1,
1414 - 'priority' => 5
1471 + 'priority' => 9
1415 1472 ),
1416 1473 'enable_navigation' => array(
1417 1474 'name' => 'enable_navigation',
1418 1475 'type' => 'toggle',
@@ -1418,9 +1475,9 @@
1418 1475 'type' => 'toggle',
1419 1476 'label' => __( 'Navigation', 'betterdocs' ),
1420 1477 'enable_disable_text_active' => true,
1421 1478 'default' => 1,
1422 - 'priority' => 6
1479 + 'priority' => 10
1423 1480 ),
1424 1481 'enable_comment' => array(
1425 1482 'name' => 'enable_comment',
1426 1483 'type' => 'toggle',
@@ -1426,9 +1483,9 @@
1426 1483 'type' => 'toggle',
1427 1484 'label' => __( 'Comment', 'betterdocs' ),
1428 1485 'enable_disable_text_active' => true,
1429 1486 'default' => '',
1430 - 'priority' => 7
1487 + 'priority' => 11
1431 1488 ),
1432 1489 'enable_credit' => array(
1433 1490 'name' => 'enable_credit',
1434 1491 'type' => 'toggle',
@@ -1434,9 +1491,9 @@
1434 1491 'type' => 'toggle',
1435 1492 'label' => __( 'Show Powered by BetterDocs', 'betterdocs' ),
1436 1493 'enable_disable_text_active' => true,
1437 1494 'default' => '',
1438 - 'priority' => 8
1495 + 'priority' => 12
1439 1496 ),
1440 1497 'reaction_feedback_text' => array(
1441 1498 'name' => 'reaction_feedback_text',
1442 1499 'type' => 'text',
@@ -1441,9 +1498,9 @@
1441 1498 'name' => 'reaction_feedback_text',
1442 1499 'type' => 'text',
1443 1500 'label' => __( 'Reaction Feedback Text', 'betterdocs' ),
1444 1501 'default' => __( 'Thanks for your feedback.', 'betterdocs' ),
1445 - 'priority' => 9
1502 + 'priority' => 13
1446 1503 ),
1447 1504 'enable_estimated_reading_time' => array(
1448 1505 'name' => 'enable_estimated_reading_time',
1449 1506 'type' => 'toggle',
@@ -1449,9 +1506,9 @@
1449 1506 'type' => 'toggle',
1450 1507 'label' => __( 'Estimated Reading Time', 'betterdocs' ),
1451 1508 'enable_disable_text_active' => true,
1452 1509 'default' => 0,
1453 - 'priority' => 10
1510 + 'priority' => 14
1454 1511 ),
1455 1512 'estimated_reading_time_title' => array(
1456 1513 'name' => 'estimated_reading_time_title',
1457 1514 'type' => 'text',
@@ -1456,9 +1513,9 @@
1456 1513 'name' => 'estimated_reading_time_title',
1457 1514 'type' => 'text',
1458 1515 'label' => __( 'Estimated Reading Time Title', 'betterdocs' ),
1459 1516 'default' => '',
1460 - 'priority' => 11,
1517 + 'priority' => 15,
1461 1518 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1462 1519 ),
1463 1520 'estimated_reading_time_text' => array(
1464 1521 'name' => 'estimated_reading_time_text',
@@ -1464,9 +1521,9 @@
1464 1521 'name' => 'estimated_reading_time_text',
1465 1522 'type' => 'text',
1466 1523 'label' => __( 'Estimated Reading Time Text', 'betterdocs' ),
1467 1524 'default' => __( 'min read', 'betterdocs' ),
1468 - 'priority' => 12,
1525 + 'priority' => 16,
1469 1526 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1470 1527 ),
1471 1528 'singular_estimated_reading_time_text' => array(
1472 1529 'name' => 'singular_estimated_reading_time_text',
@@ -1472,9 +1529,9 @@
1472 1529 'name' => 'singular_estimated_reading_time_text',
1473 1530 'type' => 'text',
1474 1531 'label' => __( 'Estimated Reading Time Text Singular', 'betterdocs' ),
1475 1532 'default' => __( 'min read', 'betterdocs' ),
1476 - 'priority' => 13,
1533 + 'priority' => 17,
1477 1534 'rules' => Rules::is( 'enable_estimated_reading_time', true )
1478 1535 )
1479 1536 )
1480 1537 ),