diff --git a/CategoryLockdown.php b/CategoryLockdown.php index 1e17ec7..caa13c1 100644 --- a/CategoryLockdown.php +++ b/CategoryLockdown.php @@ -16,6 +16,8 @@ class CategoryLockdown { */ public static function onGetUserPermissionsErrors( $title, $user, $action, &$result ) { global $wgCategoryLockdown; + global $wgCategoryGroupLockdown; + global $wgCategoryLockdownWhitelist; $explicitGroups = MediaWikiServices::getInstance()->getUserGroupManager()->getUserGroups( $user ); $implicitGroups = MediaWikiServices::getInstance()->getUserGroupManager()->getUserImplicitGroups( $user ); @@ -26,6 +28,11 @@ class CategoryLockdown { return; } + // Rules doesn’t apply to the whitelist + if ( in_array( $title, $wgCategoryLockdownWhitelist ) ) { + return; + } + $categories = array_keys( $title->getParentCategories() ); // Apply rules to the category page itself @@ -33,16 +40,11 @@ class CategoryLockdown { $categories[] = $title->getFullText(); } + // Support "Category:Top_secret", "Category:Top secret", "Top_secret" and "Top secret" + $categories = array_map( fn($c) => str_replace( '_', ' ', substr( $c, strpos( $c, ':' ) + 1 ) ), $categories ); $combinedGroups = []; foreach ( $categories as $category ) { - // Support "Category:Top_secret", "Category:Top secret", "Top_secret" and "Top secret" - $category = substr( $category, strpos( $category, ':' ) + 1 ); - $category = str_replace( '_', ' ', $category ); $permissions = $wgCategoryLockdown[ $category ] ?? null; - if ( !$permissions ) { - $category = str_replace( ' ', '_', $category ); - $permissions = $wgCategoryLockdown[ $category ] ?? null; - } if ( !$permissions ) { continue; } @@ -57,15 +59,40 @@ class CategoryLockdown { $combinedGroups[] = $allowedGroup; } } - if ( $combinedGroups ) { - foreach ( $userGroups as $userGroup ) { - if ( in_array( $userGroup, $combinedGroups ) ) { - return; - } + + $allow = false; + foreach ( $userGroups as $userGroup ) { + if ( in_array( $userGroup, $combinedGroups ) ) { + $allow = true; + break; } + } + if ( $combinedGroups && !$allow ) { $result = [ 'categorylockdown-error', implode( ', ', $combinedGroups ) ]; return false; } + + $allow = true; + foreach ( $wgCategoryGroupLockdown as $group => $groupCategories ) { + if ( str_starts_with( $group, "!") ? + in_array( substr($group, 1), $userGroups ) : + !in_array( $group, $userGroups ) ) { + continue; # Skip if this group rule doesn’t match the user + } + + $requiredCat = $groupCategories[$action] ?? []; + $groupLocked = true; + foreach ( $requiredCat as $c ) { + if ( in_array( $c, $categories ) ) { + $groupLocked = false; + break; # One of the category is present, we can grant this action. + } + } + if ( $groupLocked ) { + $result = [ 'categorylockdown-error', implode( ', ', $requiredCat ) ]; + return false; # This group of users need a category from groupCategories on this page to perform $action + } + } } /**