PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.2
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 3.5.1 All 200 releases
← All changes | includes/Core/FAQBuilder.php +47 -16 4.7.04.9.2 View file →
@@ -492,9 +492,9 @@
492 492 if ( ! check_ajax_referer( 'faq_cat_order_nonce', 'nonce', false ) ) {
493 493 wp_send_json_error( __( 'Nonce Failed', 'betterdocs' ) );
494 494 }
495 495
496 - if ( ! current_user_can( 'edit_others_posts' ) ) {
496 + if ( ! $this->can_manage_faqs() ) {
497 497 wp_send_json_error( __( 'You don\'t have permission to manage FAQ groups.', 'betterdocs' ) );
498 498 }
499 499
500 500 $base_index = isset( $_POST['base_index'] ) ? intval( $_POST['base_index'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
@@ -567,8 +567,39 @@
567 567
568 568 return $pieces;
569 569 }
570 570
571 + /**
572 + * Whether the current user may manage FAQ groups and FAQs.
573 + *
574 + * Two capabilities, either of which is enough. Nothing that could reach
575 + * these routes before can be turned away now — the gate only widens.
576 + *
577 + * - `edit_others_posts` is the original gate, kept verbatim for backward
578 + * compatibility: every site that granted FAQ Builder access by granting a
579 + * core editor-level role keeps working exactly as it did.
580 + * - `edit_others_docs` is the BetterDocs-side answer, added in 4.9.0. The
581 + * `betterdocs_faq` post type is registered with
582 + * `capability_type => [ 'doc', 'docs' ]` and `map_meta_cap => true`, so
583 + * WordPress already governs individual FAQ posts with the docs capability
584 + * family — the routes were the one place that asked for a *core* post
585 + * capability instead. A documentation-only role (BetterDocs' own `editor`
586 + * bucket, or anything Pro's `article_roles` grants) could edit every FAQ
587 + * post through `wp/v2/betterdocs_faq` and still get a 403 from the FAQ
588 + * Builder's own API.
589 + *
590 + * It is also what lines the REST routes up with the MCP FAQ abilities, which
591 + * are gated on `edit_others_docs`: an agent that may create an FAQ through
592 + * `bd-create-faq` reaches these same routes underneath.
593 + *
594 + * @since 4.9.0
595 + *
596 + * @return bool
597 + */
598 + private function can_manage_faqs() {
599 + return current_user_can( 'edit_others_posts' ) || current_user_can( 'edit_others_docs' );
600 + }
601 +
571 602 public function register_api_endpoint() {
572 603 register_rest_route(
573 604 $this->namespace,
574 605 '/faq/sample_data',
@@ -575,9 +606,9 @@
575 606 [
576 607 'methods' => [ 'POST' ],
577 608 'callback' => [ $this, 'create_faq_sample' ],
578 609 'permission_callback' => function () {
579 - return current_user_can( 'edit_others_posts' );
610 + return $this->can_manage_faqs();
580 611 }
581 612 ]
582 613 );
583 614
@@ -587,9 +618,9 @@
587 618 [
588 619 'methods' => [ 'GET' ],
589 620 'callback' => [ $this, 'fetch_faq_posts' ],
590 621 'permission_callback' => function () {
591 - return current_user_can( 'edit_others_posts' );
622 + return $this->can_manage_faqs();
592 623 }
593 624 ]
594 625 );
595 626
@@ -599,9 +630,9 @@
599 630 [
600 631 'methods' => [ 'POST' ],
601 632 'callback' => [ $this, 'create_faq_category' ],
602 633 'permission_callback' => function () {
603 - return current_user_can( 'edit_others_posts' );
634 + return $this->can_manage_faqs();
604 635 }
605 636 ]
606 637 );
607 638
@@ -611,9 +642,9 @@
611 642 [
612 643 'methods' => [ 'POST' ],
613 644 'callback' => [ $this, 'update_faq_category' ],
614 645 'permission_callback' => function () {
615 - return current_user_can( 'edit_others_posts' );
646 + return $this->can_manage_faqs();
616 647 }
617 648 ]
618 649 );
619 650
@@ -623,9 +654,9 @@
623 654 [
624 655 'methods' => [ 'POST' ],
625 656 'callback' => [ $this, 'delete_faq_category' ],
626 657 'permission_callback' => function () {
627 - return current_user_can( 'edit_others_posts' );
658 + return $this->can_manage_faqs();
628 659 }
629 660 ]
630 661 );
631 662
@@ -635,9 +666,9 @@
635 666 [
636 667 'methods' => [ 'POST' ],
637 668 'callback' => [ $this, 'create_betterdocs_faq' ],
638 669 'permission_callback' => function () {
639 - return current_user_can( 'edit_others_posts' );
670 + return $this->can_manage_faqs();
640 671 }
641 672 ]
642 673 );
643 674
@@ -647,9 +678,9 @@
647 678 [
648 679 'methods' => [ 'POST' ],
649 680 'callback' => [ $this, 'update_betterdocs_faq' ],
650 681 'permission_callback' => function () {
651 - return current_user_can( 'edit_others_posts' );
682 + return $this->can_manage_faqs();
652 683 }
653 684 ]
654 685 );
655 686
@@ -659,9 +690,9 @@
659 690 [
660 691 'methods' => [ 'POST' ],
661 692 'callback' => [ $this, 'delete_betterdocs_faq' ],
662 693 'permission_callback' => function () {
663 - return current_user_can( 'edit_others_posts' );
694 + return $this->can_manage_faqs();
664 695 }
665 696 ]
666 697 );
667 698
@@ -671,9 +702,9 @@
671 702 [
672 703 'methods' => [ 'POST' ],
673 704 'callback' => [ $this, 'update_category_status' ],
674 705 'permission_callback' => function () {
675 - return current_user_can( 'edit_others_posts' );
706 + return $this->can_manage_faqs();
676 707 }
677 708 ]
678 709 );
679 710
@@ -683,9 +714,9 @@
683 714 [
684 715 'methods' => [ 'POST' ],
685 716 'callback' => [ $this, 'update_faq_category_order' ],
686 717 'permission_callback' => function () {
687 - return current_user_can( 'edit_others_posts' );
718 + return $this->can_manage_faqs();
688 719 }
689 720 ]
690 721 );
691 722
@@ -695,9 +726,9 @@
695 726 [
696 727 'methods' => [ 'POST' ],
697 728 'callback' => [ $this, 'update_faq_order_by_category' ],
698 729 'permission_callback' => function () {
699 - return current_user_can( 'edit_others_posts' );
730 + return $this->can_manage_faqs();
700 731 }
701 732 ]
702 733 );
703 734
@@ -707,9 +738,9 @@
707 738 [
708 739 'methods' => [ 'POST' ],
709 740 'callback' => [ $this, 'update_faq_order_preference' ],
710 741 'permission_callback' => function () {
711 - return current_user_can( 'edit_others_posts' );
742 + return $this->can_manage_faqs();
712 743 }
713 744 ]
714 745 );
715 746
@@ -719,9 +750,9 @@
719 750 [
720 751 'methods' => [ 'GET' ],
721 752 'callback' => [ $this, 'get_uncategorised_faq' ],
722 753 'permission_callback' => function () {
723 - return current_user_can( 'edit_others_posts' );
754 + return $this->can_manage_faqs();
724 755 }
725 756 ]
726 757 );
727 758
@@ -731,9 +762,9 @@
731 762 [
732 763 'methods' => [ 'GET' ],
733 764 'callback' => [ $this, 'category_search' ],
734 765 'permission_callback' => function () {
735 - return current_user_can( 'edit_others_posts' );
766 + return $this->can_manage_faqs();
736 767 },
737 768 'args' => [
738 769 'title' => [
739 770 'type' => 'string',
@@ -1325,9 +1356,9 @@
1325 1356 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query, WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- intentional NOT-IN scan to find FAQs without any group.
1326 1357 $posts = get_posts(
1327 1358 [
1328 1359 'post_type' => 'betterdocs_faq',
1329 - 'post_status' => current_user_can( 'edit_others_posts' ) ? [ 'publish', 'draft' ] : 'publish',
1360 + 'post_status' => $this->can_manage_faqs() ? [ 'publish', 'draft' ] : 'publish',
1330 1361 'posts_per_page' => -1,
1331 1362 'tax_query' => $tax_query,
1332 1363 'meta_query' => $meta_query,
1333 1364 ]