Make WordPress Core


Ignore:
Timestamp:
09/19/2022 08:47:22 PM (2 years ago)
Author:
davidbaumwald
Message:

Role/Capability: Add a new update_role function.

Until now, changing a user's role involved deleting a user's role then re-adding. This change creates a new update_role function and associated method in WP_Roles to consolidate this process.

This commit also introduces new unit tests around update_role and adds additional "unhappy path" tests for roles and capabilities in general.

Props maksimkuzmin, peterwilsoncc, NomNom99, costdev, SergeyBiryukov.
Fixes #54572.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/user/capabilities.php

    r54090 r54213  
    10001000
    10011001    /**
     1002     * @dataProvider data_update_role_unhappy_paths
     1003     *
     1004     * @ticket 54572
     1005     *
     1006     * @covers WP_Roles::update_role
     1007     * @covers ::update_role
     1008     *
     1009     * @param mixed $role         The role to update.
     1010     * @param mixed $display_name The display name for the role.
     1011     * @param mixed $capabilities The capabilities for the role.
     1012     */
     1013    public function test_update_role_unhappy_paths( $role, $display_name, $capabilities ) {
     1014        global $wp_roles;
     1015
     1016        // Create role if it does not exist.
     1017        $role_name     = 'janitor';
     1018        $expected_caps = array(
     1019            'edit_posts' => true,
     1020            'edit_pages' => true,
     1021            'level_0'    => true,
     1022            'level_1'    => true,
     1023            'level_2'    => true,
     1024        );
     1025        add_role( $role_name, 'Janitor', $expected_caps );
     1026        $this->flush_roles();
     1027
     1028        $this->assertTrue(
     1029            $wp_roles->is_role( $role_name ),
     1030            "The $role_name role was not created"
     1031        );
     1032
     1033        $this->assertNotInstanceOf(
     1034            'WP_Role',
     1035            update_role( $role, $display_name, $capabilities ),
     1036            "The $role_name role was updated"
     1037        );
     1038
     1039        // Clean up.
     1040        remove_role( $role_name );
     1041        $this->flush_roles();
     1042        $this->assertFalse(
     1043            $wp_roles->is_role( $role_name ),
     1044            "The $role_name role was not removed"
     1045        );
     1046    }
     1047
     1048    /**
     1049     * Data provider.
     1050     *
     1051     * @return array
     1052     */
     1053    public function data_update_role_unhappy_paths() {
     1054        return array(
     1055            'true as the role'                       => array(
     1056                'role'         => true,
     1057                'display_name' => 'Janitor',
     1058                'capabilities' => array(
     1059                    'level_1' => true,
     1060                ),
     1061            ),
     1062            'false as the role'                      => array(
     1063                'role'         => false,
     1064                'display_name' => 'Janitor',
     1065                'capabilities' => array(
     1066                    'level_1' => true,
     1067                ),
     1068            ),
     1069            'null as the role'                       => array(
     1070                'role'         => null,
     1071                'display_name' => 'Janitor',
     1072                'capabilities' => array(
     1073                    'level_1' => true,
     1074                ),
     1075            ),
     1076            '(int) 1 as the role'                    => array(
     1077                'role'         => 1,
     1078                'display_name' => 'Janitor',
     1079                'capabilities' => array(
     1080                    'level_1' => true,
     1081                ),
     1082            ),
     1083            '(float) 1.0 as the role'                => array(
     1084                'role'         => 1.0,
     1085                'display_name' => 'Janitor',
     1086                'capabilities' => array(
     1087                    'level_1' => true,
     1088                ),
     1089            ),
     1090            '(int) 0 as the role'                    => array(
     1091                'role'         => 0,
     1092                'display_name' => 'Janitor',
     1093                'capabilities' => array(
     1094                    'level_1' => true,
     1095                ),
     1096            ),
     1097            '(float) 0.0 as the role'                => array(
     1098                'role'         => 0.0,
     1099                'display_name' => 'Janitor',
     1100                'capabilities' => array(
     1101                    'level_1' => true,
     1102                ),
     1103            ),
     1104            'an empty string as the role'            => array(
     1105                'role'         => '',
     1106                'display_name' => 'Janitor',
     1107                'capabilities' => array(
     1108                    'level_1' => true,
     1109                ),
     1110            ),
     1111            'a string with only a space as the role' => array(
     1112                'role'         => ' ',
     1113                'display_name' => 'Janitor',
     1114                'capabilities' => array(
     1115                    'level_1' => true,
     1116                ),
     1117            ),
     1118            'an empty array as the role'             => array(
     1119                'role'         => array(),
     1120                'display_name' => 'Janitor',
     1121                'capabilities' => array(
     1122                    'level_1' => true,
     1123                ),
     1124            ),
     1125            'a non-empty array as the role'          => array(
     1126                'role'         => array( 'janitor' ),
     1127                'display_name' => 'Janitor',
     1128                'capabilities' => array(
     1129                    'level_1' => true,
     1130                ),
     1131            ),
     1132            'an object as the role'                  => array(
     1133                'role'         => (object) array( 'janitor' ),
     1134                'display_name' => 'Janitor',
     1135                'capabilities' => array(
     1136                    'level_1' => true,
     1137                ),
     1138            ),
     1139            'true as the display name'               => array(
     1140                'role'         => 'janitor',
     1141                'display_name' => true,
     1142                'capabilities' => array(
     1143                    'level_1' => true,
     1144                ),
     1145            ),
     1146            'false as the display name'              => array(
     1147                'role'         => 'janitor',
     1148                'display_name' => false,
     1149                'capabilities' => array(
     1150                    'level_1' => true,
     1151                ),
     1152            ),
     1153            '(int) 1 as the display name'            => array(
     1154                'role'         => 'janitor',
     1155                'display_name' => 1,
     1156                'capabilities' => array(
     1157                    'level_1' => true,
     1158                ),
     1159            ),
     1160            '(float) 1.0 as the display name'        => array(
     1161                'role'         => 'janitor',
     1162                'display_name' => 1.0,
     1163                'capabilities' => array(
     1164                    'level_1' => true,
     1165                ),
     1166            ),
     1167            '(int) 0 as the display name'            => array(
     1168                'role'         => 'janitor',
     1169                'display_name' => 0,
     1170                'capabilities' => array(
     1171                    'level_1' => true,
     1172                ),
     1173            ),
     1174            '(float) 0.0 as the display name'        => array(
     1175                'role'         => 'janitor',
     1176                'display_name' => 0.0,
     1177                'capabilities' => array(
     1178                    'level_1' => true,
     1179                ),
     1180            ),
     1181            'an empty string as the display name'    => array(
     1182                'role'         => 'janitor',
     1183                'display_name' => '',
     1184                'capabilities' => array(
     1185                    'level_1' => true,
     1186                ),
     1187            ),
     1188            'a string with only a space as the display name' => array(
     1189                'role'         => 'janitor',
     1190                'display_name' => ' ',
     1191                'capabilities' => array(
     1192                    'level_1' => true,
     1193                ),
     1194            ),
     1195            'an empty array as the display name'     => array(
     1196                'role'         => 'janitor',
     1197                'display_name' => array(),
     1198                'capabilities' => array(
     1199                    'level_1' => true,
     1200                ),
     1201            ),
     1202            'a non-empty array as the display name'  => array(
     1203                'role'         => 'janitor',
     1204                'display_name' => array( 'Janitor' ),
     1205                'capabilities' => array(
     1206                    'level_1' => true,
     1207                ),
     1208            ),
     1209            'an object as the display name'          => array(
     1210                'role'         => 'janitor',
     1211                'display_name' => (object) array( 'Janitor' ),
     1212                'capabilities' => array(
     1213                    'level_1' => true,
     1214                ),
     1215            ),
     1216            'true as the capabilities'               => array(
     1217                'role'         => 'janitor',
     1218                'display_name' => 'Janitor',
     1219                'capabilities' => true,
     1220            ),
     1221            'false as the capabilities'              => array(
     1222                'role'         => (object) array( 'janitor' ),
     1223                'display_name' => 'Janitor',
     1224                'capabilities' => false,
     1225            ),
     1226            '(int) 1 as the capabilities'            => array(
     1227                'role'         => 'janitor',
     1228                'display_name' => 'Janitor',
     1229                'capabilities' => 1,
     1230            ),
     1231            '(float) 1.0 as the capabilities'        => array(
     1232                'role'         => 'janitor',
     1233                'display_name' => 'Janitor',
     1234                'capabilities' => 1.0,
     1235            ),
     1236            '(int) 0 as the capabilities'            => array(
     1237                'role'         => 'janitor',
     1238                'display_name' => 'Janitor',
     1239                'capabilities' => 0,
     1240            ),
     1241            '(float) 0.0 as the capabilities'        => array(
     1242                'role'         => 'janitor',
     1243                'display_name' => 'Janitor',
     1244                'capabilities' => 0.0,
     1245            ),
     1246            'an empty string as the capabilities'    => array(
     1247                'role'         => 'janitor',
     1248                'display_name' => 'Janitor',
     1249                'capabilities' => '',
     1250            ),
     1251            'a string with only a space as the capabilities' => array(
     1252                'role'         => 'janitor',
     1253                'display_name' => 'Janitor',
     1254                'capabilities' => ' ',
     1255            ),
     1256            'an object as the capabilities'          => array(
     1257                'role'         => 'janitor',
     1258                'display_name' => 'Janitor',
     1259                'capabilities' => (object) array( 'level_1' => true ),
     1260            ),
     1261        );
     1262    }
     1263
     1264    /**
     1265     * @ticket 54572
     1266     *
     1267     * @covers WP_Roles::update_role
     1268     * @covers ::update_role
     1269     */
     1270    public function test_update_role_should_create_a_role_if_it_does_not_exist() {
     1271        global $wp_roles;
     1272
     1273        // Create role if it does not exist.
     1274        $role_name     = 'janitor';
     1275        $expected_caps = array(
     1276            'edit_posts' => true,
     1277            'edit_pages' => true,
     1278            'level_0'    => true,
     1279            'level_1'    => true,
     1280            'level_2'    => true,
     1281        );
     1282        update_role( $role_name, 'Janitor', $expected_caps );
     1283        $this->flush_roles();
     1284        $this->assertTrue( $wp_roles->is_role( $role_name ) );
     1285    }
     1286
     1287    /**
     1288     * @ticket 54572
     1289     *
     1290     * @covers WP_Roles::update_role
     1291     * @covers ::update_role
     1292     */
     1293    public function test_update_role_should_change_the_display_name_of_a_role() {
     1294        global $wp_roles;
     1295        $role_name = 'janitor';
     1296
     1297        add_role( $role_name, 'Janitor', array( 'level_1' => true ) );
     1298        $this->flush_roles();
     1299
     1300        $expected_display_name = 'Janitor Executive';
     1301        update_role( $role_name, $expected_display_name );
     1302        $this->flush_roles();
     1303
     1304        $this->assertSame(
     1305            $expected_display_name,
     1306            $wp_roles->roles[ $role_name ]['name'],
     1307            'The expected display name was not correct'
     1308        );
     1309        $this->assertSame(
     1310            array( 'level_1' => true ),
     1311            $wp_roles->roles[ $role_name ]['capabilities'],
     1312            'The expected capabilities were not correct'
     1313        );
     1314
     1315        // Clean up.
     1316        remove_role( $role_name );
     1317        $this->flush_roles();
     1318        $this->assertFalse(
     1319            $wp_roles->is_role( $role_name ),
     1320            "The $role_name role was not removed"
     1321        );
     1322    }
     1323
     1324    /**
     1325     * @dataProvider data_update_role_should_change_the_capabilities_of_a_role
     1326     *
     1327     * @ticket 54572
     1328     *
     1329     * @covers WP_Roles::update_role
     1330     * @covers ::update_role
     1331     *
     1332     * @param array $capabilities An array of capabilities.
     1333     */
     1334    public function test_update_role_should_change_the_capabilities_of_a_role( $capabilities ) {
     1335        global $wp_roles;
     1336        $role_name = 'janitor';
     1337
     1338        add_role( $role_name, 'Janitor', array( 'level_1' => true ) );
     1339        $this->flush_roles();
     1340
     1341        update_role( $role_name, null, $capabilities );
     1342        $this->flush_roles();
     1343
     1344        $this->assertSame(
     1345            'Janitor',
     1346            $wp_roles->roles[ $role_name ]['name'],
     1347            'The display name was changed'
     1348        );
     1349        $this->assertSame(
     1350            $capabilities,
     1351            $wp_roles->roles[ $role_name ]['capabilities'],
     1352            'The expected capabilities were not correct'
     1353        );
     1354
     1355        // Clean up.
     1356        remove_role( $role_name );
     1357        $this->flush_roles();
     1358        $this->assertFalse(
     1359            $wp_roles->is_role( $role_name ),
     1360            "The $role_name role was not removed"
     1361        );
     1362    }
     1363
     1364    /**
     1365     * Data provider.
     1366     *
     1367     * @return array
     1368     */
     1369    public function data_update_role_should_change_the_capabilities_of_a_role() {
     1370        return array(
     1371            'an empty array'           => array( 'capabilities' => array() ),
     1372            'an array of capabilities' => array( 'capabilities' => array( 'level_2' => true ) ),
     1373        );
     1374    }
     1375
     1376    /**
     1377     * @ticket 54572
     1378     *
     1379     * @covers WP_Roles::update_role
     1380     * @covers ::update_role
     1381     */
     1382    public function test_update_role_should_change_display_name_and_capabilities_of_role() {
     1383        global $wp_roles;
     1384        $role_name = 'janitor';
     1385
     1386        add_role( $role_name, 'Janitor', array( 'level_1' => true ) );
     1387        $this->flush_roles();
     1388
     1389        $expected_display_name = 'Janitor Manager';
     1390        $new_expected_caps     = array(
     1391            'level_3' => true,
     1392            'level_4' => true,
     1393        );
     1394        update_role( $role_name, $expected_display_name, $new_expected_caps );
     1395        $this->flush_roles();
     1396
     1397        $this->assertSame(
     1398            $expected_display_name,
     1399            $wp_roles->roles[ $role_name ]['name'],
     1400            'The expected display name was not correct'
     1401        );
     1402
     1403        $this->assertSame(
     1404            $new_expected_caps,
     1405            $wp_roles->roles[ $role_name ]['capabilities'],
     1406            'The expected capabilities were not correct'
     1407        );
     1408
     1409        // Clean up.
     1410        remove_role( $role_name );
     1411        $this->flush_roles();
     1412        $this->assertFalse(
     1413            $wp_roles->is_role( $role_name ),
     1414            "The $role_name role was not removed"
     1415        );
     1416    }
     1417
     1418    /**
     1419     * @ticket 54572
     1420     *
     1421     * @covers WP_Roles::update_role
     1422     * @covers ::update_role
     1423     */
     1424    public function test_update_role_should_change_capabilities_of_a_user() {
     1425        global $wp_roles;
     1426        $role_name = 'janitor';
     1427
     1428        add_role( $role_name, 'Janitor', array( 'level_1' => true ) );
     1429        $this->flush_roles();
     1430
     1431        // Assign a user to the role.
     1432        $id = self::factory()->user->create( array( 'role' => $role_name ) );
     1433
     1434        // Update empty capabilities.
     1435        update_role( $role_name, null, array( 'level_2' => true ) );
     1436        $this->flush_roles();
     1437
     1438        $this->assertTrue(
     1439            user_can( $id, 'level_2' ),
     1440            'The user does not have level_2 capabilities'
     1441        );
     1442        $this->assertFalse(
     1443            user_can( $id, 'level_1' ),
     1444            'The user has level_1 capabilities'
     1445        );
     1446
     1447        // Clean up.
     1448        remove_role( $role_name );
     1449        $this->flush_roles();
     1450        $this->assertFalse(
     1451            $wp_roles->is_role( $role_name ),
     1452            "The $role_name role was not removed"
     1453        );
     1454    }
     1455
     1456    /**
    10021457     * Change the capabilites associated with a role and make sure the change
    10031458     * is reflected in has_cap().
Note: See TracChangeset for help on using the changeset viewer.