← All changes
|
includes/abilities/class-mainwp-abilities-sites.php
+259
-56
6.2.3
→
6.3
View file →
| @@ -766,8 +766,22 @@ | ||
| 766 | 766 | public static function execute_list_sites( $input ) { |
| 767 | 767 | $input = is_array( $input ) ? $input : array(); |
| 768 | 768 | $db = MainWP_DB::instance(); |
| 769 | 769 | |
| 770 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 771 | + $allowed_groups = MainWP_Abilities_Util::get_scoped_group_ids_or_all(); | |
| 772 | + if ( isset( $input['tag_id'] ) && 'all' !== $allowed_groups && ! in_array( (int) $input['tag_id'], $allowed_groups, true ) ) { | |
| 773 | + $allowed = array(); | |
| 774 | + } | |
| 775 | + if ( array() === $allowed ) { | |
| 776 | + return array( | |
| 777 | + 'items' => array(), | |
| 778 | + 'page' => (int) ( $input['page'] ?? 1 ), | |
| 779 | + 'per_page' => (int) ( $input['per_page'] ?? 20 ), | |
| 780 | + 'total' => 0, | |
| 781 | + ); | |
| 782 | + } | |
| 783 | + | |
| 770 | 784 | // Map ability input to DB method parameters. |
| 771 | 785 | $db_params = array( |
| 772 | 786 | 'paged' => $input['page'] ?? 1, |
| 773 | 787 | 'items_per_page' => $input['per_page'] ?? 20, |
| @@ -805,9 +819,13 @@ | ||
| 805 | 819 | 'tags' => isset( $input['tag_id'] ) ? array( (int) $input['tag_id'] ) : array(), |
| 806 | 820 | 'client_id' => isset( $input['client_id'] ) ? (int) $input['client_id'] : 0, |
| 807 | 821 | 's' => $input['search'] ?? '', |
| 808 | 822 | ); |
| 809 | - $total = $db->get_websites_count_for_current_user( $count_filters ); | |
| 823 | + if ( 'all' !== $allowed ) { | |
| 824 | + $db_params['include'] = $allowed; | |
| 825 | + $count_filters['include'] = $allowed; | |
| 826 | + } | |
| 827 | + $total = $db->get_websites_count_for_current_user( $count_filters ); | |
| 810 | 828 | |
| 811 | 829 | // Now get the paginated subset. |
| 812 | 830 | $websites = $db->get_websites_for_current_user( $db_params ); |
| 813 | 831 | |
| @@ -848,9 +866,9 @@ | ||
| 848 | 866 | // This shouldn't happen if permission_callback passed, but handle gracefully. |
| 849 | 867 | return $site; |
| 850 | 868 | } |
| 851 | 869 | |
| 852 | - $include_stats = $input['include_stats'] ?? false; | |
| 870 | + $include_stats = MainWP_Abilities_Util::get_boolean_input( $input, 'include_stats' ); | |
| 853 | 871 | |
| 854 | 872 | return MainWP_Abilities_Util::format_site_for_output( $site, true, $include_stats ); |
| 855 | 873 | } |
| 856 | 874 | |
| @@ -910,8 +928,14 @@ | ||
| 910 | 928 | if ( is_wp_error( $all_sites ) ) { |
| 911 | 929 | return $all_sites; |
| 912 | 930 | } |
| 913 | 931 | |
| 932 | + // API-key authentication bypasses DB site scoping. | |
| 933 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 934 | + if ( 'all' !== $allowed ) { | |
| 935 | + $all_sites = array_intersect_key( $all_sites ? $all_sites : array(), array_flip( $allowed ) ); | |
| 936 | + } | |
| 937 | + | |
| 914 | 938 | $site_ids_or_domains = array(); |
| 915 | 939 | if ( ! empty( $all_sites ) ) { |
| 916 | 940 | foreach ( $all_sites as $s ) { |
| 917 | 941 | $id = (int) $s->id; |
| @@ -1068,9 +1092,9 @@ | ||
| 1068 | 1092 | $plugin_updates = array(); |
| 1069 | 1093 | } |
| 1070 | 1094 | |
| 1071 | 1095 | $status_filter = $input['status'] ?? 'all'; |
| 1072 | - $has_update_filter = $input['has_update'] ?? null; | |
| 1096 | + $has_update_filter = MainWP_Abilities_Util::get_boolean_input( $input, 'has_update' ); | |
| 1073 | 1097 | |
| 1074 | 1098 | $plugins = array(); |
| 1075 | 1099 | foreach ( $plugins_data as $key => $plugin ) { |
| 1076 | 1100 | // Support both formats: |
| @@ -1095,9 +1119,9 @@ | ||
| 1095 | 1119 | |
| 1096 | 1120 | $has_update = isset( $plugin_updates[ $slug ] ); |
| 1097 | 1121 | |
| 1098 | 1122 | // Apply has_update filter if specified. |
| 1099 | - if ( null !== $has_update_filter && $has_update_filter && ! $has_update ) { | |
| 1123 | + if ( $has_update_filter && ! $has_update ) { | |
| 1100 | 1124 | continue; |
| 1101 | 1125 | } |
| 1102 | 1126 | |
| 1103 | 1127 | // Extract update version from plugin_upgrades structure. |
| @@ -1177,9 +1201,9 @@ | ||
| 1177 | 1201 | } |
| 1178 | 1202 | } |
| 1179 | 1203 | |
| 1180 | 1204 | $status_filter = $input['status'] ?? 'all'; |
| 1181 | - $has_update_filter = $input['has_update'] ?? null; | |
| 1205 | + $has_update_filter = MainWP_Abilities_Util::get_boolean_input( $input, 'has_update' ); | |
| 1182 | 1206 | |
| 1183 | 1207 | $themes = array(); |
| 1184 | 1208 | foreach ( $themes_data as $key => $theme ) { |
| 1185 | 1209 | // Support both formats: |
| @@ -1204,9 +1228,9 @@ | ||
| 1204 | 1228 | |
| 1205 | 1229 | $has_update = isset( $theme_updates[ $slug ] ); |
| 1206 | 1230 | |
| 1207 | 1231 | // Apply has_update filter if specified. |
| 1208 | - if ( null !== $has_update_filter && $has_update_filter && ! $has_update ) { | |
| 1232 | + if ( $has_update_filter && ! $has_update ) { | |
| 1209 | 1233 | continue; |
| 1210 | 1234 | } |
| 1211 | 1235 | |
| 1212 | 1236 | // Extract update version from theme_upgrades structure. |
| @@ -1253,9 +1277,9 @@ | ||
| 1253 | 1277 | 'category' => 'mainwp-sites', |
| 1254 | 1278 | 'input_schema' => self::get_add_site_input_schema(), |
| 1255 | 1279 | 'output_schema' => self::get_site_output_schema(), |
| 1256 | 1280 | 'execute_callback' => array( self::class, 'execute_add_site' ), |
| 1257 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 1281 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/add-site-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 1258 | 1282 | 'meta' => array( |
| 1259 | 1283 | 'show_in_rest' => true, |
| 1260 | 1284 | 'annotations' => array( |
| 1261 | 1285 | 'instructions' => '', |
| @@ -1363,8 +1387,37 @@ | ||
| 1363 | 1387 | array( 'status' => 400 ) |
| 1364 | 1388 | ); |
| 1365 | 1389 | } |
| 1366 | 1390 | |
| 1391 | + // Reject inaccessible relations before connecting the site, so a | |
| 1392 | + // denied tag or client assignment cannot leave a new site behind. | |
| 1393 | + $validated_tag_ids = array(); | |
| 1394 | + if ( ! empty( $input['tag_ids'] ) && is_array( $input['tag_ids'] ) ) { | |
| 1395 | + foreach ( array_values( array_unique( array_map( 'intval', $input['tag_ids'] ) ) ) as $tag_id ) { | |
| 1396 | + $tag = MainWP_Abilities_Util::resolve_tag( $tag_id ); | |
| 1397 | + if ( is_wp_error( $tag ) ) { | |
| 1398 | + return $tag; | |
| 1399 | + } | |
| 1400 | + $tag_access = MainWP_Abilities_Util::check_tag_access( $tag, $input ); | |
| 1401 | + if ( is_wp_error( $tag_access ) ) { | |
| 1402 | + return $tag_access; | |
| 1403 | + } | |
| 1404 | + $validated_tag_ids[] = $tag_id; | |
| 1405 | + } | |
| 1406 | + } | |
| 1407 | + | |
| 1408 | + $client_id = ! empty( $input['client_id'] ) ? (int) $input['client_id'] : 0; | |
| 1409 | + if ( $client_id > 0 ) { | |
| 1410 | + $client = MainWP_Abilities_Util::resolve_client( $client_id ); | |
| 1411 | + if ( is_wp_error( $client ) ) { | |
| 1412 | + return $client; | |
| 1413 | + } | |
| 1414 | + $client_access = MainWP_Abilities_Util::check_client_access( $client, $input ); | |
| 1415 | + if ( is_wp_error( $client_access ) ) { | |
| 1416 | + return $client_access; | |
| 1417 | + } | |
| 1418 | + } | |
| 1419 | + | |
| 1367 | 1420 | // Normalize URL for consistent storage and duplicate detection. |
| 1368 | 1421 | // This lowercases the host (per RFC 4343) and ensures trailing slash. |
| 1369 | 1422 | $url = MainWP_Abilities_Util::normalize_site_url( $url ); |
| 1370 | 1423 | |
| @@ -1436,18 +1489,14 @@ | ||
| 1436 | 1489 | array( 'status' => 500 ) |
| 1437 | 1490 | ); |
| 1438 | 1491 | } |
| 1439 | 1492 | |
| 1440 | - // Assign tags if provided. | |
| 1441 | - if ( ! empty( $input['tag_ids'] ) && is_array( $input['tag_ids'] ) ) { | |
| 1442 | - foreach ( $input['tag_ids'] as $tag_id ) { | |
| 1443 | - MainWP_DB_Common::instance()->update_group_site( (int) $tag_id, $site_id ); | |
| 1444 | - } | |
| 1493 | + foreach ( $validated_tag_ids as $tag_id ) { | |
| 1494 | + MainWP_DB_Common::instance()->update_group_site( $tag_id, $site_id ); | |
| 1445 | 1495 | } |
| 1446 | 1496 | |
| 1447 | - // Assign client if provided. | |
| 1448 | - if ( ! empty( $input['client_id'] ) ) { | |
| 1449 | - MainWP_DB::instance()->update_website_values( $site_id, array( 'client_id' => (int) $input['client_id'] ) ); | |
| 1497 | + if ( $client_id > 0 ) { | |
| 1498 | + MainWP_DB::instance()->update_website_values( $site_id, array( 'client_id' => $client_id ) ); | |
| 1450 | 1499 | } |
| 1451 | 1500 | |
| 1452 | 1501 | // Re-fetch site to get updated data. |
| 1453 | 1502 | $site = MainWP_DB::instance()->get_website_by_id( $site_id ); |
| @@ -1469,9 +1518,9 @@ | ||
| 1469 | 1518 | 'category' => 'mainwp-sites', |
| 1470 | 1519 | 'input_schema' => self::get_update_site_input_schema(), |
| 1471 | 1520 | 'output_schema' => self::get_site_output_schema(), |
| 1472 | 1521 | 'execute_callback' => array( self::class, 'execute_update_site' ), |
| 1473 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 1522 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/update-site-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 1474 | 1523 | 'meta' => array( |
| 1475 | 1524 | 'show_in_rest' => true, |
| 1476 | 1525 | 'annotations' => array( |
| 1477 | 1526 | 'instructions' => '', |
| @@ -1561,13 +1610,53 @@ | ||
| 1561 | 1610 | if ( is_wp_error( $site ) ) { |
| 1562 | 1611 | return $site; |
| 1563 | 1612 | } |
| 1564 | 1613 | |
| 1565 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 1614 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 1566 | 1615 | if ( is_wp_error( $access_check ) ) { |
| 1567 | 1616 | return $access_check; |
| 1568 | 1617 | } |
| 1569 | 1618 | |
| 1619 | + // Check relations before any write: attaching a site to an inaccessible | |
| 1620 | + // client would itself create the overlap used to grant client access. | |
| 1621 | + $validated_tag_ids = null; | |
| 1622 | + if ( isset( $input['tag_ids'] ) && is_array( $input['tag_ids'] ) ) { | |
| 1623 | + $validated_tag_ids = array(); | |
| 1624 | + foreach ( array_values( array_unique( array_map( 'intval', $input['tag_ids'] ) ) ) as $tag_id ) { | |
| 1625 | + $tag = MainWP_Abilities_Util::resolve_tag( $tag_id ); | |
| 1626 | + if ( is_wp_error( $tag ) ) { | |
| 1627 | + return $tag; | |
| 1628 | + } | |
| 1629 | + $tag_access = MainWP_Abilities_Util::check_tag_access( $tag, $input ); | |
| 1630 | + if ( is_wp_error( $tag_access ) ) { | |
| 1631 | + return $tag_access; | |
| 1632 | + } | |
| 1633 | + $validated_tag_ids[] = $tag_id; | |
| 1634 | + } | |
| 1635 | + } | |
| 1636 | + | |
| 1637 | + $new_client_id = null; | |
| 1638 | + if ( isset( $input['client_id'] ) ) { | |
| 1639 | + $new_client_id = (int) $input['client_id']; | |
| 1640 | + if ( $new_client_id < 0 ) { | |
| 1641 | + return new \WP_Error( | |
| 1642 | + 'mainwp_invalid_input', | |
| 1643 | + __( 'client_id must be 0 to unassign or a positive client ID.', 'mainwp' ), | |
| 1644 | + array( 'status' => 400 ) | |
| 1645 | + ); | |
| 1646 | + } | |
| 1647 | + if ( $new_client_id > 0 ) { | |
| 1648 | + $client = MainWP_Abilities_Util::resolve_client( $new_client_id ); | |
| 1649 | + if ( is_wp_error( $client ) ) { | |
| 1650 | + return $client; | |
| 1651 | + } | |
| 1652 | + $client_access = MainWP_Abilities_Util::check_client_access( $client, $input ); | |
| 1653 | + if ( is_wp_error( $client_access ) ) { | |
| 1654 | + return $client_access; | |
| 1655 | + } | |
| 1656 | + } | |
| 1657 | + } | |
| 1658 | + | |
| 1570 | 1659 | $update_data = array(); |
| 1571 | 1660 | |
| 1572 | 1661 | if ( isset( $input['name'] ) ) { |
| 1573 | 1662 | $update_data['name'] = sanitize_text_field( $input['name'] ); |
| @@ -1601,9 +1690,24 @@ | ||
| 1601 | 1690 | MainWP_Site_Url_Corrector::after_user_set_url( $site, $update_data['url'] ); |
| 1602 | 1691 | } |
| 1603 | 1692 | } |
| 1604 | 1693 | |
| 1605 | - if ( isset( $input['tag_ids'] ) && is_array( $input['tag_ids'] ) ) { | |
| 1694 | + if ( null !== $validated_tag_ids ) { | |
| 1695 | + // A groups-restricted caller only manages their slice of the tag | |
| 1696 | + // set: associations outside the allowed groups are invisible to | |
| 1697 | + // them and must survive the replace. | |
| 1698 | + $allowed_groups = MainWP_Abilities_Util::get_allowed_group_ids(); | |
| 1699 | + $preserved = array(); | |
| 1700 | + if ( 'all' !== $allowed_groups ) { | |
| 1701 | + $existing_groups = MainWP_DB_Common::instance()->get_groups_by_website_id( $site->id ); | |
| 1702 | + foreach ( (array) $existing_groups as $existing_group ) { | |
| 1703 | + $existing_id = (int) $existing_group->id; | |
| 1704 | + if ( ! in_array( $existing_id, $allowed_groups, true ) ) { | |
| 1705 | + $preserved[] = $existing_id; | |
| 1706 | + } | |
| 1707 | + } | |
| 1708 | + } | |
| 1709 | + | |
| 1606 | 1710 | global $wpdb; |
| 1607 | 1711 | // Clear existing tag associations for this site. |
| 1608 | 1712 | //phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery -- for testing results. |
| 1609 | 1713 | $wpdb->query( |
| @@ -1612,15 +1716,15 @@ | ||
| 1612 | 1716 | $site->id |
| 1613 | 1717 | ) |
| 1614 | 1718 | ); |
| 1615 | 1719 | // Add new tag associations. |
| 1616 | - foreach ( $input['tag_ids'] as $tag_id ) { | |
| 1720 | + foreach ( array_unique( array_merge( $preserved, $validated_tag_ids ) ) as $tag_id ) { | |
| 1617 | 1721 | MainWP_DB_Common::instance()->update_group_site( (int) $tag_id, $site->id ); |
| 1618 | 1722 | } |
| 1619 | 1723 | } |
| 1620 | 1724 | |
| 1621 | - if ( isset( $input['client_id'] ) ) { | |
| 1622 | - MainWP_DB::instance()->update_website_values( $site->id, array( 'client_id' => (int) $input['client_id'] ) ); | |
| 1725 | + if ( null !== $new_client_id ) { | |
| 1726 | + MainWP_DB::instance()->update_website_values( $site->id, array( 'client_id' => $new_client_id ) ); | |
| 1623 | 1727 | } |
| 1624 | 1728 | |
| 1625 | 1729 | $site = MainWP_DB::instance()->get_website_by_id( $site->id ); |
| 1626 | 1730 | |
| @@ -1641,9 +1745,9 @@ | ||
| 1641 | 1745 | 'category' => 'mainwp-sites', |
| 1642 | 1746 | 'input_schema' => self::get_delete_site_input_schema(), |
| 1643 | 1747 | 'output_schema' => self::get_delete_site_output_schema(), |
| 1644 | 1748 | 'execute_callback' => array( self::class, 'execute_delete_site' ), |
| 1645 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 1749 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/delete-site-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 1646 | 1750 | 'meta' => array( |
| 1647 | 1751 | 'show_in_rest' => true, |
| 1648 | 1752 | 'annotations' => array( |
| 1649 | 1753 | 'instructions' => 'Destructive operation - requires confirm:true or dry_run:true. Only call when user explicitly requests deletion.', |
| @@ -1726,10 +1830,10 @@ | ||
| 1726 | 1830 | */ |
| 1727 | 1831 | public static function execute_delete_site( $input ) { |
| 1728 | 1832 | $input = MainWP_Abilities_Util::normalize_input( $input ); |
| 1729 | 1833 | |
| 1730 | - $dry_run = ! empty( $input['dry_run'] ); | |
| 1731 | - $confirm = ! empty( $input['confirm'] ); | |
| 1834 | + $dry_run = MainWP_Abilities_Util::get_boolean_input( $input, 'dry_run' ); | |
| 1835 | + $confirm = MainWP_Abilities_Util::get_boolean_input( $input, 'confirm' ); | |
| 1732 | 1836 | |
| 1733 | 1837 | if ( $dry_run && $confirm ) { |
| 1734 | 1838 | return new \WP_Error( |
| 1735 | 1839 | 'mainwp_invalid_input', |
| @@ -1742,9 +1846,9 @@ | ||
| 1742 | 1846 | if ( is_wp_error( $site ) ) { |
| 1743 | 1847 | return $site; |
| 1744 | 1848 | } |
| 1745 | 1849 | |
| 1746 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 1850 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 1747 | 1851 | if ( is_wp_error( $access_check ) ) { |
| 1748 | 1852 | return $access_check; |
| 1749 | 1853 | } |
| 1750 | 1854 | |
| @@ -1780,8 +1884,15 @@ | ||
| 1780 | 1884 | 'url' => $site->url, |
| 1781 | 1885 | 'name' => MainWP_Utility::remove_http_prefix( (string) $site->name, true ), |
| 1782 | 1886 | ); |
| 1783 | 1887 | |
| 1888 | + // Same favicon cleanup, and the same point relative to the DB delete, | |
| 1889 | + // as MainWP_Manage_Sites_Handler::remove_website(). The file name is the | |
| 1890 | + // stored favi_icon option. A missing file or a cleanup failure must not | |
| 1891 | + // change this response. remove_website() itself is not called: it | |
| 1892 | + // deactivates the child plugin over the network. | |
| 1893 | + MainWP_Manage_Sites_Handler::delete_website_favicon( $site ); | |
| 1894 | + | |
| 1784 | 1895 | $result = MainWP_DB::instance()->remove_website( $site->id ); |
| 1785 | 1896 | |
| 1786 | 1897 | if ( false === $result ) { |
| 1787 | 1898 | return new \WP_Error( |
| @@ -1790,8 +1901,40 @@ | ||
| 1790 | 1901 | array( 'status' => 500 ) |
| 1791 | 1902 | ); |
| 1792 | 1903 | } |
| 1793 | 1904 | |
| 1905 | + // Same hooks, argument, and order as MainWP_Manage_Sites_Handler::remove_website(). | |
| 1906 | + // That handler is not called here: it deactivates the child plugin over the network | |
| 1907 | + // and applies can_edit_website(), which would change this ability's contract. | |
| 1908 | + // Demo sites fire the same hooks (still with no remote deactivate) so extension | |
| 1909 | + // rows are removed. Hooks run only after a successful delete so a failed removal | |
| 1910 | + // does not tell extensions to drop their per-site rows. | |
| 1911 | + /** | |
| 1912 | + * Fires after a child site has been removed from the MainWP Dashboard. | |
| 1913 | + * | |
| 1914 | + * @param object $website Object containing child site data. | |
| 1915 | + * | |
| 1916 | + * @since 3.4 | |
| 1917 | + */ | |
| 1918 | + try { | |
| 1919 | + do_action( 'mainwp_delete_site', $site ); | |
| 1920 | + } catch ( \Throwable $e ) { | |
| 1921 | + MainWP_Logger::instance()->debug( 'mainwp_delete_site listener failed: ' . $e->getMessage() ); | |
| 1922 | + } | |
| 1923 | + | |
| 1924 | + /** | |
| 1925 | + * Fires immediately after a website is deleted. | |
| 1926 | + * | |
| 1927 | + * @since 4.5.1.1 | |
| 1928 | + * | |
| 1929 | + * @param object $website Website data. | |
| 1930 | + */ | |
| 1931 | + try { | |
| 1932 | + do_action( 'mainwp_site_deleted', $site ); | |
| 1933 | + } catch ( \Throwable $e ) { | |
| 1934 | + MainWP_Logger::instance()->debug( 'mainwp_site_deleted listener failed: ' . $e->getMessage() ); | |
| 1935 | + } | |
| 1936 | + | |
| 1794 | 1937 | return array( |
| 1795 | 1938 | 'dry_run' => false, |
| 1796 | 1939 | 'deleted' => true, |
| 1797 | 1940 | 'site' => $site_info, |
| @@ -1814,9 +1957,9 @@ | ||
| 1814 | 1957 | 'category' => 'mainwp-sites', |
| 1815 | 1958 | 'input_schema' => self::get_single_site_input_schema(), |
| 1816 | 1959 | 'output_schema' => self::get_reconnect_site_output_schema(), |
| 1817 | 1960 | 'execute_callback' => array( self::class, 'execute_reconnect_site' ), |
| 1818 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 1961 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/reconnect-site-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 1819 | 1962 | 'meta' => array( |
| 1820 | 1963 | 'show_in_rest' => true, |
| 1821 | 1964 | 'annotations' => array( |
| 1822 | 1965 | 'instructions' => '', |
| @@ -1881,9 +2024,9 @@ | ||
| 1881 | 2024 | if ( is_wp_error( $site ) ) { |
| 1882 | 2025 | return $site; |
| 1883 | 2026 | } |
| 1884 | 2027 | |
| 1885 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2028 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 1886 | 2029 | if ( is_wp_error( $access_check ) ) { |
| 1887 | 2030 | return $access_check; |
| 1888 | 2031 | } |
| 1889 | 2032 | |
| @@ -1928,9 +2071,9 @@ | ||
| 1928 | 2071 | 'category' => 'mainwp-sites', |
| 1929 | 2072 | 'input_schema' => self::get_single_site_input_schema(), |
| 1930 | 2073 | 'output_schema' => self::get_disconnect_site_output_schema(), |
| 1931 | 2074 | 'execute_callback' => array( self::class, 'execute_disconnect_site' ), |
| 1932 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 2075 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/disconnect-site-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 1933 | 2076 | 'meta' => array( |
| 1934 | 2077 | 'show_in_rest' => true, |
| 1935 | 2078 | 'annotations' => array( |
| 1936 | 2079 | 'instructions' => '', |
| @@ -1977,9 +2120,9 @@ | ||
| 1977 | 2120 | if ( is_wp_error( $site ) ) { |
| 1978 | 2121 | return $site; |
| 1979 | 2122 | } |
| 1980 | 2123 | |
| 1981 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2124 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 1982 | 2125 | if ( is_wp_error( $access_check ) ) { |
| 1983 | 2126 | return $access_check; |
| 1984 | 2127 | } |
| 1985 | 2128 | |
| @@ -2007,9 +2150,9 @@ | ||
| 2007 | 2150 | 'category' => 'mainwp-sites', |
| 2008 | 2151 | 'input_schema' => self::get_single_site_input_schema(), |
| 2009 | 2152 | 'output_schema' => self::get_suspend_site_output_schema(), |
| 2010 | 2153 | 'execute_callback' => array( self::class, 'execute_suspend_site' ), |
| 2011 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 2154 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/suspend-site-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 2012 | 2155 | 'meta' => array( |
| 2013 | 2156 | 'show_in_rest' => true, |
| 2014 | 2157 | 'annotations' => array( |
| 2015 | 2158 | 'instructions' => '', |
| @@ -2056,9 +2199,9 @@ | ||
| 2056 | 2199 | if ( is_wp_error( $site ) ) { |
| 2057 | 2200 | return $site; |
| 2058 | 2201 | } |
| 2059 | 2202 | |
| 2060 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2203 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 2061 | 2204 | if ( is_wp_error( $access_check ) ) { |
| 2062 | 2205 | return $access_check; |
| 2063 | 2206 | } |
| 2064 | 2207 | |
| @@ -2088,9 +2231,9 @@ | ||
| 2088 | 2231 | 'category' => 'mainwp-sites', |
| 2089 | 2232 | 'input_schema' => self::get_single_site_input_schema(), |
| 2090 | 2233 | 'output_schema' => self::get_unsuspend_site_output_schema(), |
| 2091 | 2234 | 'execute_callback' => array( self::class, 'execute_unsuspend_site' ), |
| 2092 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 2235 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/unsuspend-site-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 2093 | 2236 | 'meta' => array( |
| 2094 | 2237 | 'show_in_rest' => true, |
| 2095 | 2238 | 'annotations' => array( |
| 2096 | 2239 | 'instructions' => '', |
| @@ -2137,9 +2280,9 @@ | ||
| 2137 | 2280 | if ( is_wp_error( $site ) ) { |
| 2138 | 2281 | return $site; |
| 2139 | 2282 | } |
| 2140 | 2283 | |
| 2141 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2284 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 2142 | 2285 | if ( is_wp_error( $access_check ) ) { |
| 2143 | 2286 | return $access_check; |
| 2144 | 2287 | } |
| 2145 | 2288 | |
| @@ -2169,9 +2312,9 @@ | ||
| 2169 | 2312 | 'category' => 'mainwp-sites', |
| 2170 | 2313 | 'input_schema' => self::get_single_site_input_schema(), |
| 2171 | 2314 | 'output_schema' => self::get_check_site_output_schema(), |
| 2172 | 2315 | 'execute_callback' => array( self::class, 'execute_check_site' ), |
| 2173 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_rest_api_permission' ), | |
| 2316 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/check-site-v1', array( MainWP_Abilities_Util::class, 'check_rest_api_permission' ) ), | |
| 2174 | 2317 | 'meta' => array( |
| 2175 | 2318 | 'show_in_rest' => true, |
| 2176 | 2319 | 'annotations' => array( |
| 2177 | 2320 | 'instructions' => '', |
| @@ -2235,9 +2378,9 @@ | ||
| 2235 | 2378 | if ( is_wp_error( $site ) ) { |
| 2236 | 2379 | return $site; |
| 2237 | 2380 | } |
| 2238 | 2381 | |
| 2239 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2382 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 2240 | 2383 | if ( is_wp_error( $access_check ) ) { |
| 2241 | 2384 | return $access_check; |
| 2242 | 2385 | } |
| 2243 | 2386 | |
| @@ -2309,9 +2452,9 @@ | ||
| 2309 | 2452 | 'category' => 'mainwp-sites', |
| 2310 | 2453 | 'input_schema' => self::get_activate_site_plugins_input_schema(), |
| 2311 | 2454 | 'output_schema' => self::get_activate_plugins_output_schema(), |
| 2312 | 2455 | 'execute_callback' => array( self::class, 'execute_activate_site_plugins' ), |
| 2313 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 2456 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/activate-site-plugins-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 2314 | 2457 | 'meta' => array( |
| 2315 | 2458 | 'show_in_rest' => true, |
| 2316 | 2459 | 'annotations' => array( |
| 2317 | 2460 | 'instructions' => '', |
| @@ -2421,9 +2564,9 @@ | ||
| 2421 | 2564 | if ( is_wp_error( $site ) ) { |
| 2422 | 2565 | return $site; |
| 2423 | 2566 | } |
| 2424 | 2567 | |
| 2425 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2568 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 2426 | 2569 | if ( is_wp_error( $access_check ) ) { |
| 2427 | 2570 | return $access_check; |
| 2428 | 2571 | } |
| 2429 | 2572 | |
| @@ -2493,9 +2636,9 @@ | ||
| 2493 | 2636 | 'category' => 'mainwp-sites', |
| 2494 | 2637 | 'input_schema' => self::get_deactivate_site_plugins_input_schema(), |
| 2495 | 2638 | 'output_schema' => self::get_deactivate_plugins_output_schema(), |
| 2496 | 2639 | 'execute_callback' => array( self::class, 'execute_deactivate_site_plugins' ), |
| 2497 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 2640 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/deactivate-site-plugins-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 2498 | 2641 | 'meta' => array( |
| 2499 | 2642 | 'show_in_rest' => true, |
| 2500 | 2643 | 'annotations' => array( |
| 2501 | 2644 | 'instructions' => '', |
| @@ -2545,9 +2688,9 @@ | ||
| 2545 | 2688 | if ( is_wp_error( $site ) ) { |
| 2546 | 2689 | return $site; |
| 2547 | 2690 | } |
| 2548 | 2691 | |
| 2549 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2692 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 2550 | 2693 | if ( is_wp_error( $access_check ) ) { |
| 2551 | 2694 | return $access_check; |
| 2552 | 2695 | } |
| 2553 | 2696 | |
| @@ -2617,9 +2760,9 @@ | ||
| 2617 | 2760 | 'category' => 'mainwp-sites', |
| 2618 | 2761 | 'input_schema' => self::get_delete_site_plugins_input_schema(), |
| 2619 | 2762 | 'output_schema' => self::get_delete_plugins_output_schema(), |
| 2620 | 2763 | 'execute_callback' => array( self::class, 'execute_delete_site_plugins' ), |
| 2621 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 2764 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/delete-site-plugins-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 2622 | 2765 | 'meta' => array( |
| 2623 | 2766 | 'show_in_rest' => true, |
| 2624 | 2767 | 'annotations' => array( |
| 2625 | 2768 | 'instructions' => 'Destructive operation - requires confirm:true or dry_run:true. Only call when user explicitly requests deletion. Permanently removes plugins from the child site.', |
| @@ -2721,10 +2864,10 @@ | ||
| 2721 | 2864 | */ |
| 2722 | 2865 | private static function execute_delete_remote_items( array $input, array $adapter ) { |
| 2723 | 2866 | $input = MainWP_Abilities_Util::normalize_input( $input ); |
| 2724 | 2867 | |
| 2725 | - $dry_run = ! empty( $input['dry_run'] ); | |
| 2726 | - $confirm = ! empty( $input['confirm'] ); | |
| 2868 | + $dry_run = MainWP_Abilities_Util::get_boolean_input( $input, 'dry_run' ); | |
| 2869 | + $confirm = MainWP_Abilities_Util::get_boolean_input( $input, 'confirm' ); | |
| 2727 | 2870 | |
| 2728 | 2871 | if ( $dry_run && $confirm ) { |
| 2729 | 2872 | return new \WP_Error( |
| 2730 | 2873 | 'mainwp_invalid_input', |
| @@ -2737,9 +2880,9 @@ | ||
| 2737 | 2880 | if ( is_wp_error( $site ) ) { |
| 2738 | 2881 | return $site; |
| 2739 | 2882 | } |
| 2740 | 2883 | |
| 2741 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 2884 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 2742 | 2885 | if ( is_wp_error( $access_check ) ) { |
| 2743 | 2886 | return $access_check; |
| 2744 | 2887 | } |
| 2745 | 2888 | |
| @@ -2989,9 +3132,9 @@ | ||
| 2989 | 3132 | if ( is_wp_error( $site ) ) { |
| 2990 | 3133 | return $site; |
| 2991 | 3134 | } |
| 2992 | 3135 | |
| 2993 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 3136 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 2994 | 3137 | if ( is_wp_error( $access_check ) ) { |
| 2995 | 3138 | return $access_check; |
| 2996 | 3139 | } |
| 2997 | 3140 | |
| @@ -3049,9 +3192,9 @@ | ||
| 3049 | 3192 | 'category' => 'mainwp-sites', |
| 3050 | 3193 | 'input_schema' => self::get_activate_site_theme_input_schema(), |
| 3051 | 3194 | 'output_schema' => self::get_activate_theme_output_schema(), |
| 3052 | 3195 | 'execute_callback' => array( self::class, 'execute_activate_site_theme' ), |
| 3053 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 3196 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/activate-site-theme-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 3054 | 3197 | 'meta' => array( |
| 3055 | 3198 | 'show_in_rest' => true, |
| 3056 | 3199 | 'annotations' => array( |
| 3057 | 3200 | 'instructions' => '', |
| @@ -3114,9 +3257,9 @@ | ||
| 3114 | 3257 | if ( is_wp_error( $site ) ) { |
| 3115 | 3258 | return $site; |
| 3116 | 3259 | } |
| 3117 | 3260 | |
| 3118 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 3261 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 3119 | 3262 | if ( is_wp_error( $access_check ) ) { |
| 3120 | 3263 | return $access_check; |
| 3121 | 3264 | } |
| 3122 | 3265 | |
| @@ -3174,9 +3317,9 @@ | ||
| 3174 | 3317 | 'category' => 'mainwp-sites', |
| 3175 | 3318 | 'input_schema' => self::get_delete_site_themes_input_schema(), |
| 3176 | 3319 | 'output_schema' => self::get_delete_themes_output_schema(), |
| 3177 | 3320 | 'execute_callback' => array( self::class, 'execute_delete_site_themes' ), |
| 3178 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 3321 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/delete-site-themes-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 3179 | 3322 | 'meta' => array( |
| 3180 | 3323 | 'show_in_rest' => true, |
| 3181 | 3324 | 'annotations' => array( |
| 3182 | 3325 | 'instructions' => 'Destructive operation - requires confirm:true or dry_run:true. Only call when user explicitly requests deletion. Permanently removes themes from the child site.', |
| @@ -3346,9 +3489,9 @@ | ||
| 3346 | 3489 | if ( is_wp_error( $site ) ) { |
| 3347 | 3490 | return $site; |
| 3348 | 3491 | } |
| 3349 | 3492 | |
| 3350 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 3493 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 3351 | 3494 | if ( is_wp_error( $access_check ) ) { |
| 3352 | 3495 | return $access_check; |
| 3353 | 3496 | } |
| 3354 | 3497 | |
| @@ -3450,9 +3593,9 @@ | ||
| 3450 | 3593 | if ( is_wp_error( $site ) ) { |
| 3451 | 3594 | return $site; |
| 3452 | 3595 | } |
| 3453 | 3596 | |
| 3454 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 3597 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 3455 | 3598 | if ( is_wp_error( $access_check ) ) { |
| 3456 | 3599 | return $access_check; |
| 3457 | 3600 | } |
| 3458 | 3601 | |
| @@ -3580,9 +3723,9 @@ | ||
| 3580 | 3723 | if ( is_wp_error( $site ) ) { |
| 3581 | 3724 | return $site; |
| 3582 | 3725 | } |
| 3583 | 3726 | |
| 3584 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 3727 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 3585 | 3728 | if ( is_wp_error( $access_check ) ) { |
| 3586 | 3729 | return $access_check; |
| 3587 | 3730 | } |
| 3588 | 3731 | |
| @@ -3714,9 +3857,9 @@ | ||
| 3714 | 3857 | if ( is_wp_error( $site ) ) { |
| 3715 | 3858 | return $site; |
| 3716 | 3859 | } |
| 3717 | 3860 | |
| 3718 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 3861 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 3719 | 3862 | if ( is_wp_error( $access_check ) ) { |
| 3720 | 3863 | return $access_check; |
| 3721 | 3864 | } |
| 3722 | 3865 | |
| @@ -3821,9 +3964,9 @@ | ||
| 3821 | 3964 | if ( is_wp_error( $site ) ) { |
| 3822 | 3965 | return $site; |
| 3823 | 3966 | } |
| 3824 | 3967 | |
| 3825 | - $access_check = MainWP_Abilities_Util::check_site_access( $site ); | |
| 3968 | + $access_check = MainWP_Abilities_Util::check_site_access( $site, $input ); | |
| 3826 | 3969 | if ( is_wp_error( $access_check ) ) { |
| 3827 | 3970 | return $access_check; |
| 3828 | 3971 | } |
| 3829 | 3972 | |
| @@ -3924,9 +4067,26 @@ | ||
| 3924 | 4067 | */ |
| 3925 | 4068 | public static function execute_count_sites( $input ) { |
| 3926 | 4069 | $input = MainWP_Abilities_Util::normalize_input( $input ); |
| 3927 | 4070 | |
| 4071 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 4072 | + if ( ! empty( $input['tag_ids'] ) && is_array( $input['tag_ids'] ) ) { | |
| 4073 | + $allowed_groups = MainWP_Abilities_Util::get_scoped_group_ids_or_all(); | |
| 4074 | + if ( 'all' !== $allowed_groups ) { | |
| 4075 | + $input['tag_ids'] = array_values( array_intersect( array_map( 'intval', $input['tag_ids'] ), $allowed_groups ) ); | |
| 4076 | + if ( empty( $input['tag_ids'] ) ) { | |
| 4077 | + $allowed = array(); | |
| 4078 | + } | |
| 4079 | + } | |
| 4080 | + } | |
| 4081 | + if ( array() === $allowed ) { | |
| 4082 | + return array( 'total' => 0 ); | |
| 4083 | + } | |
| 4084 | + | |
| 3928 | 4085 | $filters = array(); |
| 4086 | + if ( 'all' !== $allowed ) { | |
| 4087 | + $filters['include'] = $allowed; | |
| 4088 | + } | |
| 3929 | 4089 | |
| 3930 | 4090 | if ( ! empty( $input['status'] ) ) { |
| 3931 | 4091 | $filters['status'] = $input['status']; |
| 3932 | 4092 | } |
| @@ -4054,8 +4214,27 @@ | ||
| 4054 | 4214 | |
| 4055 | 4215 | $page = max( 1, (int) $input['page'] ); |
| 4056 | 4216 | $per_page = max( 1, min( 100, (int) $input['per_page'] ) ); |
| 4057 | 4217 | |
| 4218 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 4219 | + if ( ! empty( $input['tag_ids'] ) && is_array( $input['tag_ids'] ) ) { | |
| 4220 | + $allowed_groups = MainWP_Abilities_Util::get_scoped_group_ids_or_all(); | |
| 4221 | + if ( 'all' !== $allowed_groups ) { | |
| 4222 | + $input['tag_ids'] = array_values( array_intersect( array_map( 'intval', $input['tag_ids'] ), $allowed_groups ) ); | |
| 4223 | + if ( empty( $input['tag_ids'] ) ) { | |
| 4224 | + $allowed = array(); | |
| 4225 | + } | |
| 4226 | + } | |
| 4227 | + } | |
| 4228 | + if ( array() === $allowed ) { | |
| 4229 | + return array( | |
| 4230 | + 'items' => array(), | |
| 4231 | + 'page' => $page, | |
| 4232 | + 'per_page' => $per_page, | |
| 4233 | + 'total' => 0, | |
| 4234 | + ); | |
| 4235 | + } | |
| 4236 | + | |
| 4058 | 4237 | $filters = array( |
| 4059 | 4238 | 'offset' => ( $page - 1 ) * $per_page, |
| 4060 | 4239 | 'rowcount' => $per_page, |
| 4061 | 4240 | 'selectgroups' => false, |
| @@ -4060,8 +4239,12 @@ | ||
| 4060 | 4239 | 'rowcount' => $per_page, |
| 4061 | 4240 | 'selectgroups' => false, |
| 4062 | 4241 | ); |
| 4063 | 4242 | |
| 4243 | + if ( 'all' !== $allowed ) { | |
| 4244 | + $filters['include'] = $allowed; | |
| 4245 | + } | |
| 4246 | + | |
| 4064 | 4247 | if ( ! empty( $input['status'] ) ) { |
| 4065 | 4248 | $filters['status'] = $input['status']; |
| 4066 | 4249 | } |
| 4067 | 4250 | |
| @@ -4120,9 +4303,9 @@ | ||
| 4120 | 4303 | 'category' => 'mainwp-sites', |
| 4121 | 4304 | 'input_schema' => self::get_batch_sites_input_schema(), |
| 4122 | 4305 | 'output_schema' => self::get_batch_operation_output_schema(), |
| 4123 | 4306 | 'execute_callback' => array( self::class, 'execute_reconnect_sites' ), |
| 4124 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 4307 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/reconnect-sites-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 4125 | 4308 | 'meta' => array( |
| 4126 | 4309 | 'show_in_rest' => true, |
| 4127 | 4310 | 'annotations' => array( |
| 4128 | 4311 | 'instructions' => 'Pass site_ids_or_domains with specific IDs, or empty array for all applicable sites. Operations with >200 sites are automatically queued for background processing.', |
| @@ -4228,8 +4411,13 @@ | ||
| 4228 | 4411 | if ( is_wp_error( $all_sites ) ) { |
| 4229 | 4412 | return $all_sites; |
| 4230 | 4413 | } |
| 4231 | 4414 | |
| 4415 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 4416 | + if ( 'all' !== $allowed ) { | |
| 4417 | + $all_sites = array_intersect_key( $all_sites ? $all_sites : array(), array_flip( $allowed ) ); | |
| 4418 | + } | |
| 4419 | + | |
| 4232 | 4420 | $identifiers = array_map( |
| 4233 | 4421 | function ( $s ) { |
| 4234 | 4422 | return (int) $s->id; |
| 4235 | 4423 | }, |
| @@ -4317,9 +4505,9 @@ | ||
| 4317 | 4505 | 'category' => 'mainwp-sites', |
| 4318 | 4506 | 'input_schema' => self::get_batch_sites_input_schema(), |
| 4319 | 4507 | 'output_schema' => self::get_batch_operation_output_schema(), |
| 4320 | 4508 | 'execute_callback' => array( self::class, 'execute_disconnect_sites' ), |
| 4321 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 4509 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/disconnect-sites-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 4322 | 4510 | 'meta' => array( |
| 4323 | 4511 | 'show_in_rest' => true, |
| 4324 | 4512 | 'annotations' => array( |
| 4325 | 4513 | 'instructions' => 'Pass site_ids_or_domains with specific IDs, or empty array for all applicable sites. Operations with >200 sites are automatically queued for background processing.', |
| @@ -4362,8 +4550,13 @@ | ||
| 4362 | 4550 | if ( is_wp_error( $all_sites ) ) { |
| 4363 | 4551 | return $all_sites; |
| 4364 | 4552 | } |
| 4365 | 4553 | |
| 4554 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 4555 | + if ( 'all' !== $allowed ) { | |
| 4556 | + $all_sites = array_intersect_key( $all_sites ? $all_sites : array(), array_flip( $allowed ) ); | |
| 4557 | + } | |
| 4558 | + | |
| 4366 | 4559 | $identifiers = array_map( |
| 4367 | 4560 | function ( $s ) { |
| 4368 | 4561 | return (int) $s->id; |
| 4369 | 4562 | }, |
| @@ -4433,9 +4626,9 @@ | ||
| 4433 | 4626 | 'category' => 'mainwp-sites', |
| 4434 | 4627 | 'input_schema' => self::get_batch_sites_input_schema(), |
| 4435 | 4628 | 'output_schema' => self::get_batch_operation_output_schema(), |
| 4436 | 4629 | 'execute_callback' => array( self::class, 'execute_check_sites' ), |
| 4437 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_rest_api_permission' ), | |
| 4630 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/check-sites-v1', array( MainWP_Abilities_Util::class, 'check_rest_api_permission' ) ), | |
| 4438 | 4631 | 'meta' => array( |
| 4439 | 4632 | 'show_in_rest' => true, |
| 4440 | 4633 | 'annotations' => array( |
| 4441 | 4634 | 'instructions' => 'Pass site_ids_or_domains with specific IDs, or empty array for all applicable sites. Operations with >200 sites are automatically queued for background processing.', |
| @@ -4478,8 +4671,13 @@ | ||
| 4478 | 4671 | if ( is_wp_error( $all_sites ) ) { |
| 4479 | 4672 | return $all_sites; |
| 4480 | 4673 | } |
| 4481 | 4674 | |
| 4675 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 4676 | + if ( 'all' !== $allowed ) { | |
| 4677 | + $all_sites = array_intersect_key( $all_sites ? $all_sites : array(), array_flip( $allowed ) ); | |
| 4678 | + } | |
| 4679 | + | |
| 4482 | 4680 | $identifiers = array_map( |
| 4483 | 4681 | function ( $s ) { |
| 4484 | 4682 | return (int) $s->id; |
| 4485 | 4683 | }, |
| @@ -4575,9 +4773,9 @@ | ||
| 4575 | 4773 | 'category' => 'mainwp-sites', |
| 4576 | 4774 | 'input_schema' => self::get_batch_sites_input_schema(), |
| 4577 | 4775 | 'output_schema' => self::get_batch_operation_output_schema(), |
| 4578 | 4776 | 'execute_callback' => array( self::class, 'execute_suspend_sites' ), |
| 4579 | - 'permission_callback' => array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ), | |
| 4777 | + 'permission_callback' => MainWP_Abilities_Util::make_operation_permission_callback( 'mainwp/suspend-sites-v1', array( MainWP_Abilities_Util::class, 'check_manage_sites_permission' ) ), | |
| 4580 | 4778 | 'meta' => array( |
| 4581 | 4779 | 'show_in_rest' => true, |
| 4582 | 4780 | 'annotations' => array( |
| 4583 | 4781 | 'instructions' => 'Pass site_ids_or_domains with specific IDs, or empty array for all applicable sites. Operations with >200 sites are automatically queued for background processing.', |
| @@ -4618,8 +4816,13 @@ | ||
| 4618 | 4816 | |
| 4619 | 4817 | // Handle potential errors from DB query. |
| 4620 | 4818 | if ( is_wp_error( $all_sites ) ) { |
| 4621 | 4819 | return $all_sites; |
| 4820 | + } | |
| 4821 | + | |
| 4822 | + $allowed = MainWP_Abilities_Util::get_scoped_site_ids_or_all(); | |
| 4823 | + if ( 'all' !== $allowed ) { | |
| 4824 | + $all_sites = array_intersect_key( $all_sites ? $all_sites : array(), array_flip( $allowed ) ); | |
| 4622 | 4825 | } |
| 4623 | 4826 | |
| 4624 | 4827 | $identifiers = array_map( |
| 4625 | 4828 | function ( $s ) { |