2023-08-30 22:37:21 +00:00
< ? php
namespace Misuzu ;
use stdClass ;
// All permissions should be defined in this class
// To avoid future conflicts, unused/deprecated permissions should remain defined for any given category
final class Perm {
// GLOBAL ALLOCATION:
// 0bXXXXX_XXXXXXXX_CCCCCCCC_FFFFFFFF_NNNNNNNN_LLLLLLLL_GGGGGGGG
// G -> General global permissions
// L -> Changelog permissions
// N -> News permissions
// F -> Global Forum perms
// C -> Global Comments perms
// X -> unallocated
public const G_IS_JANITOR = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000001 ;
public const G_LOGS_VIEW = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000010 ;
public const G_EMOTES_MANAGE = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000100 ;
public const G_CONFIG_MANAGE = 0 b00000_00000000_00000000_00000000_00000000_00000000_00001000 ;
//public const G_IS_TESTER = 0b00000_00000000_00000000_00000000_00000000_00000000_00010000; // deprecated: tester status went unused
public const G_BLACKLIST_MANAGE = 0 b00000_00000000_00000000_00000000_00000000_00000000_00100000 ; // unused: blacklist is currently removed to reduce overhead and it seemed like it was broken
//public const G_TWITTER_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000000_01000000; // deprecated: twitter integration has been removed
2023-08-31 00:37:09 +00:00
public const G_TIMINGS_VIEW = 0 b00000_00000000_00000000_00000000_00000000_00000000_10000000 ;
2023-08-30 22:37:21 +00:00
public const G_CL_CHANGES_MANAGE = 0 b00000_00000000_00000000_00000000_00000000_00000001_00000000 ;
public const G_CL_TAGS_MANAGE = 0 b00000_00000000_00000000_00000000_00000000_00000010_00000000 ;
//public const G_CL_ACTIONS_MANAGE = 0b00000_00000000_00000000_00000000_00000000_00000100_00000000; // deprecated: actions are hardcoded now
public const G_NEWS_POSTS_MANAGE = 0 b00000_00000000_00000000_00000000_00000001_00000000_00000000 ;
public const G_NEWS_CATEGORIES_MANAGE = 0 b00000_00000000_00000000_00000000_00000010_00000000_00000000 ;
public const G_FORUM_CATEGORIES_MANAGE = 0 b00000_00000000_00000000_00000001_00000000_00000000_00000000 ;
public const G_FORUM_LEADERBOARD_VIEW = 0 b00000_00000000_00000000_00000010_00000000_00000000_00000000 ;
public const G_FORUM_TOPIC_REDIRS_MANAGE = 0 b00000_00000000_00000000_00000100_00000000_00000000_00000000 ;
public const G_COMMENTS_CREATE = 0 b00000_00000000_00000001_00000000_00000000_00000000_00000000 ;
public const G_COMMENTS_EDIT_OWN = 0 b00000_00000000_00000010_00000000_00000000_00000000_00000000 ; // unused: editing not implemented
public const G_COMMENTS_EDIT_ANY = 0 b00000_00000000_00000100_00000000_00000000_00000000_00000000 ; // unused: editing not implemented
public const G_COMMENTS_DELETE_OWN = 0 b00000_00000000_00001000_00000000_00000000_00000000_00000000 ;
public const G_COMMENTS_DELETE_ANY = 0 b00000_00000000_00010000_00000000_00000000_00000000_00000000 ;
public const G_COMMENTS_PIN = 0 b00000_00000000_00100000_00000000_00000000_00000000_00000000 ;
public const G_COMMENTS_LOCK = 0 b00000_00000000_01000000_00000000_00000000_00000000_00000000 ;
public const G_COMMENTS_VOTE = 0 b00000_00000000_10000000_00000000_00000000_00000000_00000000 ;
// USER ALLOCATION:
// There's no rules here, manage perms started abouts halfway through the 31-bit integer
// Maybe formally define the octets regardless later?
public const U_PROFILE_EDIT = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000001 ;
public const U_AVATAR_CHANGE = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000010 ;
public const U_PROFILE_BACKGROUND_CHANGE = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000100 ;
public const U_PROFILE_ABOUT_EDIT = 0 b00000_00000000_00000000_00000000_00000000_00000000_00001000 ;
public const U_PROFILE_BIRTHDATE_EDIT = 0 b00000_00000000_00000000_00000000_00000000_00000000_00010000 ;
public const U_FORUM_SIGNATURE_EDIT = 0 b00000_00000000_00000000_00000000_00000000_00000000_00100000 ;
public const U_USERS_MANAGE = 0 b00000_00000000_00000000_00000000_00010000_00000000_00000000 ;
public const U_ROLES_MANAGE = 0 b00000_00000000_00000000_00000000_00100000_00000000_00000000 ;
public const U_PERMS_MANAGE = 0 b00000_00000000_00000000_00000000_01000000_00000000_00000000 ;
public const U_REPORTS_MANAGE = 0 b00000_00000000_00000000_00000000_10000000_00000000_00000000 ; // unused: reports are not implemented
public const U_WARNINGS_MANAGE = 0 b00000_00000000_00000000_00000001_00000000_00000000_00000000 ;
//public const U_BLACKLISTS_MANAGE = 0b00000_00000000_00000000_00000010_00000000_00000000_00000000; // deprecated: replaced with GLOBAL_BLACKLIST_MANAGE
public const U_NOTES_MANAGE = 0 b00000_00000000_00000000_00000100_00000000_00000000_00000000 ;
public const U_BANS_MANAGE = 0 b00000_00000000_00000000_00001000_00000000_00000000_00000000 ;
public const U_CAN_IMPERSONATE = 0 b00000_00000000_00000000_00010000_00000000_00000000_00000000 ;
// FORUM ALLOCATION:
// 0bXXXXX_XXXXXXXX_XXXXXXXX_PPPPPPPP_PPPPTTTT_TTTTTTTT_CCCCCCCC
// C -> Category related
// T -> Topic related
// N -> Post related
// X -> unallocated
public const F_CATEGORY_LIST = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000001 ;
public const F_CATEGORY_VIEW = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000010 ;
public const F_TOPIC_CREATE = 0 b00000_00000000_00000000_00000000_00000000_00000100_00000000 ;
//public const F_TOPIC_DELETE = 0b00000_00000000_00000000_00000000_00000000_00001000_00000000; // deprecated: use F_POST_DELETE_ANY instead
public const F_TOPIC_MOVE = 0 b00000_00000000_00000000_00000000_00000000_00010000_00000000 ; // unused: topic moving not implemented
public const F_TOPIC_LOCK = 0 b00000_00000000_00000000_00000000_00000000_00100000_00000000 ;
public const F_TOPIC_STICKY = 0 b00000_00000000_00000000_00000000_00000000_01000000_00000000 ;
public const F_TOPIC_ANNOUNCE_LOCAL = 0 b00000_00000000_00000000_00000000_00000000_10000000_00000000 ;
public const F_TOPIC_ANNOUNCE_GLOBAL = 0 b00000_00000000_00000000_00000000_00000001_00000000_00000000 ;
public const F_TOPIC_BUMP = 0 b00000_00000000_00000000_00000000_00000010_00000000_00000000 ;
public const F_TOPIC_PRIORITY_VOTE = 0 b00000_00000000_00000000_00000000_00000100_00000000_00000000 ; // unused: feature postponed, reuse if it makes sense otherwise deprecate
public const F_POST_CREATE = 0 b00000_00000000_00000000_00000000_00010000_00000000_00000000 ;
public const F_POST_EDIT_OWN = 0 b00000_00000000_00000000_00000000_00100000_00000000_00000000 ;
public const F_POST_EDIT_ANY = 0 b00000_00000000_00000000_00000000_01000000_00000000_00000000 ;
public const F_POST_DELETE_OWN = 0 b00000_00000000_00000000_00000000_10000000_00000000_00000000 ;
public const F_POST_DELETE_ANY = 0 b00000_00000000_00000000_00000001_00000000_00000000_00000000 ;
2023-09-06 20:44:28 +00:00
// CHAT ALLOCATION:
// 0bXXXXX_XXXXXXXX_XXXXXXXX_XXXXXXXX_XXXXXXMA_MMUMUUMT_ATATAMMM
// U -> Normal user permissions
// T -> Tenshi permissions
// M -> Moderator permissions
// A -> Administrator permissions
// no staircase here because it's a mess
public const C_USER_KICK = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000001 ;
public const C_USER_BAN = 0 b00000_00000000_00000000_00000000_00000000_00000000_00000010 ;
//public const C_USER_SILENCE = 0b00000_00000000_00000000_00000000_00000000_00000000_00000100; // deprecated: silencing is no longer a thing
public const C_MESSAGE_BROADCAST = 0 b00000_00000000_00000000_00000000_00000000_00000000_00001000 ;
public const C_NICK_SET_OWN = 0 b00000_00000000_00000000_00000000_00000000_00000000_00010000 ;
public const C_NICK_SET_ANY = 0 b00000_00000000_00000000_00000000_00000000_00000000_00100000 ;
public const C_CHANNEL_CREATE = 0 b00000_00000000_00000000_00000000_00000000_00000000_01000000 ;
public const C_CHANNEL_SET_PERSIST = 0 b00000_00000000_00000000_00000000_00000000_00000000_10000000 ;
public const C_CHANNEL_SET_PASSWORD = 0 b00000_00000000_00000000_00000000_00000000_00000001_00000000 ;
public const C_CHANNEL_SET_MIN_RANK = 0 b00000_00000000_00000000_00000000_00000000_00000010_00000000 ;
public const C_MESSAGE_SEND = 0 b00000_00000000_00000000_00000000_00000000_00000100_00000000 ;
public const C_MESSAGE_DELETE_OWN = 0 b00000_00000000_00000000_00000000_00000000_00001000_00000000 ;
public const C_MESSAGE_DELETE_ANY = 0 b00000_00000000_00000000_00000000_00000000_00010000_00000000 ;
public const C_MESSAGE_EDIT_OWN = 0 b00000_00000000_00000000_00000000_00000000_00100000_00000000 ;
public const C_MESSAGE_EDIT_ANY = 0 b00000_00000000_00000000_00000000_00000000_01000000_00000000 ;
public const C_USER_VIEW_ADDR = 0 b00000_00000000_00000000_00000000_00000000_10000000_00000000 ;
public const C_CHANNEL_DELETE = 0 b00000_00000000_00000000_00000000_00000001_00000000_00000000 ;
public const C_CHANNEL_JOIN_ANY = 0 b00000_00000000_00000000_00000000_00000010_00000000_00000000 ;
public const INFO_FOR_USER = [ 'global' , 'user' , 'chat' ];
2023-08-30 22:37:21 +00:00
public const INFO_FOR_ROLE = self :: INFO_FOR_USER ; // just alias for now, no clue if this will ever desync
public const INFO_FOR_FORUM_CATEGORY = [ 'forum' ];
2023-09-06 20:44:28 +00:00
public const LISTS_FOR_USER = [ 'global:general' , 'global:changelog' , 'global:news' , 'global:forum' , 'global:comments' , 'user:personal' , 'user:manage' , 'chat:general' ];
2023-08-30 22:37:21 +00:00
public const LISTS_FOR_ROLE = self :: LISTS_FOR_USER ; // idem
public const LISTS_FOR_FORUM_CATEGORY = [ 'forum:category' , 'forum:topic' , 'forum:post' ];
public const LISTS = [
'global:general' => [
'title' => 'Global Permissions' ,
'perms' => [
'global' ,
self :: G_IS_JANITOR ,
self :: G_LOGS_VIEW ,
self :: G_EMOTES_MANAGE ,
self :: G_CONFIG_MANAGE ,
self :: G_BLACKLIST_MANAGE ,
2023-08-31 00:37:09 +00:00
self :: G_TIMINGS_VIEW ,
2023-08-30 22:37:21 +00:00
],
],
'global:changelog' => [
'title' => 'Changelog Permissions' ,
'perms' => [
'global' ,
self :: G_CL_CHANGES_MANAGE ,
self :: G_CL_TAGS_MANAGE ,
],
],
'global:news' => [
'title' => 'News Permissions' ,
'perms' => [
'global' ,
self :: G_NEWS_POSTS_MANAGE ,
self :: G_NEWS_CATEGORIES_MANAGE ,
],
],
'global:forum' => [
'title' => 'Global Forum Permissions' ,
'perms' => [
'global' ,
self :: G_FORUM_CATEGORIES_MANAGE ,
self :: G_FORUM_LEADERBOARD_VIEW ,
self :: G_FORUM_TOPIC_REDIRS_MANAGE ,
],
],
'global:comments' => [
'title' => 'Comments Permissions' ,
'perms' => [
'global' ,
self :: G_COMMENTS_CREATE ,
self :: G_COMMENTS_EDIT_OWN ,
self :: G_COMMENTS_EDIT_ANY ,
self :: G_COMMENTS_DELETE_OWN ,
self :: G_COMMENTS_DELETE_ANY ,
self :: G_COMMENTS_PIN ,
self :: G_COMMENTS_LOCK ,
self :: G_COMMENTS_VOTE ,
],
],
'user:personal' => [
'title' => 'User Permissions' ,
'perms' => [
'user' ,
self :: U_PROFILE_EDIT ,
self :: U_AVATAR_CHANGE ,
self :: U_PROFILE_BACKGROUND_CHANGE ,
self :: U_PROFILE_ABOUT_EDIT ,
self :: U_FORUM_SIGNATURE_EDIT ,
self :: U_PROFILE_BIRTHDATE_EDIT ,
],
],
'user:manage' => [
'title' => 'User Management Permissions' ,
'perms' => [
'user' ,
self :: U_REPORTS_MANAGE ,
self :: U_NOTES_MANAGE ,
self :: U_WARNINGS_MANAGE ,
self :: U_BANS_MANAGE ,
self :: U_USERS_MANAGE ,
self :: U_ROLES_MANAGE ,
self :: U_PERMS_MANAGE ,
self :: U_CAN_IMPERSONATE ,
],
],
'forum:category' => [
'title' => 'Forum Category Permissions' ,
'perms' => [
'forum' ,
self :: F_CATEGORY_LIST ,
self :: F_CATEGORY_VIEW ,
],
],
'forum:topic' => [
'title' => 'Forum Topic Permissions' ,
'perms' => [
'forum' ,
self :: F_TOPIC_CREATE ,
self :: F_TOPIC_MOVE ,
self :: F_TOPIC_LOCK ,
self :: F_TOPIC_STICKY ,
self :: F_TOPIC_ANNOUNCE_LOCAL ,
self :: F_TOPIC_ANNOUNCE_GLOBAL ,
self :: F_TOPIC_BUMP ,
self :: F_TOPIC_PRIORITY_VOTE ,
],
],
'forum:post' => [
'title' => 'Forum Topic Permissions' ,
'perms' => [
'forum' ,
self :: F_POST_CREATE ,
self :: F_POST_EDIT_OWN ,
self :: F_POST_EDIT_ANY ,
self :: F_POST_DELETE_OWN ,
self :: F_POST_DELETE_ANY ,
],
],
2023-09-06 20:44:28 +00:00
'chat:general' => [
'title' => 'Chat Permissions' ,
'perms' => [
'chat' ,
self :: C_MESSAGE_SEND ,
self :: C_MESSAGE_BROADCAST ,
self :: C_MESSAGE_EDIT_OWN ,
self :: C_MESSAGE_EDIT_ANY ,
self :: C_MESSAGE_DELETE_OWN ,
self :: C_MESSAGE_DELETE_ANY ,
self :: C_NICK_SET_OWN ,
self :: C_NICK_SET_ANY ,
self :: C_USER_KICK ,
self :: C_USER_BAN ,
self :: C_USER_VIEW_ADDR ,
self :: C_CHANNEL_CREATE ,
self :: C_CHANNEL_SET_PERSIST ,
self :: C_CHANNEL_SET_PASSWORD ,
self :: C_CHANNEL_SET_MIN_RANK ,
self :: C_CHANNEL_JOIN_ANY ,
self :: C_CHANNEL_DELETE ,
],
],
2023-08-30 22:37:21 +00:00
];
public const LABELS = [
'global' => [
self :: G_IS_JANITOR => 'Can access the Broom closet.' ,
self :: G_LOGS_VIEW => 'Can view global audit logs.' ,
self :: G_EMOTES_MANAGE => 'Can manage emoticons.' ,
self :: G_CONFIG_MANAGE => 'Can manage global configuration.' ,
//self::G_IS_TESTER => 'Can test experimental features.',
self :: G_BLACKLIST_MANAGE => 'Can manage registration IP address blacklist.' ,
//self::G_TWITTER_MANAGE => 'Can manage Twitter integration settings.',
2023-08-31 00:37:09 +00:00
self :: G_TIMINGS_VIEW => 'Can view page load timings.' ,
2023-08-30 22:37:21 +00:00
self :: G_CL_CHANGES_MANAGE => 'Can manage changelog entries.' ,
self :: G_CL_TAGS_MANAGE => 'Can manage changelog tags.' ,
//self::G_CL_ACTIONS_MANAGE => 'Can manage changelog action types.',
self :: G_NEWS_POSTS_MANAGE => 'Can manage news posts.' ,
self :: G_NEWS_CATEGORIES_MANAGE => 'Can manage news categories.' ,
self :: G_FORUM_CATEGORIES_MANAGE => 'Can manage forum categories.' ,
self :: G_FORUM_LEADERBOARD_VIEW => 'Can view forum leaderboard.' ,
self :: G_FORUM_TOPIC_REDIRS_MANAGE => 'Can create redirects for deleted forum topics.' ,
self :: G_COMMENTS_CREATE => 'Can post comments.' ,
self :: G_COMMENTS_EDIT_OWN => 'Can edit own comments.' ,
self :: G_COMMENTS_EDIT_ANY => 'Can edit ANY comment.' ,
self :: G_COMMENTS_DELETE_OWN => 'Can delete own comments.' ,
self :: G_COMMENTS_DELETE_ANY => 'Can delete ANY comment.' ,
self :: G_COMMENTS_PIN => 'Can pin commments.' ,
self :: G_COMMENTS_LOCK => 'Can lock comment categories.' ,
self :: G_COMMENTS_VOTE => 'Can vote (like or dislike) on comments.' ,
],
'user' => [
self :: U_PROFILE_EDIT => 'Can edit own profile.' ,
self :: U_AVATAR_CHANGE => 'Can change own avatar.' ,
self :: U_PROFILE_BACKGROUND_CHANGE => 'Can change own profile background.' ,
self :: U_PROFILE_ABOUT_EDIT => 'Can edit own profile about section.' ,
self :: U_PROFILE_BIRTHDATE_EDIT => 'Can edit own profile birthdate.' ,
self :: U_FORUM_SIGNATURE_EDIT => 'Can edit own forum signature.' ,
self :: U_USERS_MANAGE => 'Can manage other users.' ,
self :: U_ROLES_MANAGE => 'Can manage user roles.' ,
self :: U_PERMS_MANAGE => 'Can manage permissions.' ,
self :: U_REPORTS_MANAGE => 'Can handle reports.' ,
self :: U_WARNINGS_MANAGE => 'Can manage user warnings.' ,
//self::U_BLACKLISTS_MANAGE => 'Can manage registration IP address blacklist.',
self :: U_NOTES_MANAGE => 'Can manage user notes.' ,
self :: U_BANS_MANAGE => 'Can manage user bans.' ,
self :: U_CAN_IMPERSONATE => 'Can impersonate select other users. Requires whitelisting in the configuration or super user status.' ,
],
'forum' => [
self :: F_CATEGORY_LIST => 'Can see the forum category listed but cannot access it.' ,
self :: F_CATEGORY_VIEW => 'Can access the forum category.' ,
self :: F_TOPIC_CREATE => 'Can create forum topics.' ,
//self::F_TOPIC_DELETE => 'Can delete forum topics.',
self :: F_TOPIC_MOVE => 'Can move forum topics to other categories.' ,
self :: F_TOPIC_LOCK => 'Can lock forum topics.' ,
self :: F_TOPIC_STICKY => 'Can make sticky topics.' ,
self :: F_TOPIC_ANNOUNCE_LOCAL => 'Can make local announcement topics.' ,
self :: F_TOPIC_ANNOUNCE_GLOBAL => 'Can make global announcement topics.' ,
self :: F_TOPIC_BUMP => 'Can bump topics without posting a reply.' ,
self :: F_TOPIC_PRIORITY_VOTE => 'Can use the priority voting system.' ,
self :: F_POST_CREATE => 'Can create forum posts (replies only, if not allowed to create topics).' ,
self :: F_POST_EDIT_OWN => 'Can edit own forum posts.' ,
self :: F_POST_EDIT_ANY => 'Can edit ANY forum post.' ,
self :: F_POST_DELETE_OWN => 'Can delete own forum posts.' ,
self :: F_POST_DELETE_ANY => 'Can delete ANY forum post.' ,
],
2023-09-06 20:44:28 +00:00
'chat' => [
self :: C_USER_KICK => 'Can kick other users.' ,
self :: C_USER_BAN => 'Can ban other users.' ,
//self::C_USER_SILENCE => 'Can silence other users.',
self :: C_MESSAGE_BROADCAST => 'Can broadcast messages across all channels.' ,
self :: C_NICK_SET_OWN => 'Can change own nickname.' ,
self :: C_NICK_SET_ANY => 'Can change ANYONE\'s nickname.' ,
self :: C_CHANNEL_CREATE => 'Can create channels.' ,
self :: C_CHANNEL_SET_PERSIST => 'Can set channels to persist after all users leave it.' ,
self :: C_CHANNEL_SET_PASSWORD => 'Can set passwords for own channel.' ,
self :: C_CHANNEL_SET_MIN_RANK => 'Can set minimum requires rank to join channel.' ,
self :: C_MESSAGE_SEND => 'Can send messages.' ,
self :: C_MESSAGE_DELETE_OWN => 'Can delete own messages.' ,
self :: C_MESSAGE_DELETE_ANY => 'Can delete ANY message.' ,
self :: C_MESSAGE_EDIT_OWN => 'Can edit own messages.' ,
self :: C_MESSAGE_EDIT_ANY => 'Can edit ANY message.' ,
self :: C_USER_VIEW_ADDR => 'Can view IP addresses of other users.' ,
self :: C_CHANNEL_DELETE => 'Can delete own channels.' ,
self :: C_CHANNEL_JOIN_ANY => 'Can join any channel regardless of join requirements.' ,
],
2023-08-30 22:37:21 +00:00
];
public static function label ( string $category , int $permission ) : string {
return array_key_exists ( $category , self :: LABELS )
&& array_key_exists ( $permission , self :: LABELS [ $category ])
? self :: LABELS [ $category ][ $permission ] : '' ;
}
public static function createList ( array $sections ) : array {
$list = [];
foreach ( $sections as $sectionName ) {
if ( ! array_key_exists ( $sectionName , self :: LISTS ))
continue ;
$currentCategoryName = '' ;
$sectionInfo = self :: LISTS [ $sectionName ];
$list [] = $item = new stdClass ;
$item -> name = $sectionName ;
$item -> title = $sectionInfo [ 'title' ];
$item -> perms = [];
foreach ( $sectionInfo [ 'perms' ] as $permInfo ) {
if ( is_string ( $permInfo )) {
$currentCategoryName = $permInfo ;
continue ;
}
$categoryName = $currentCategoryName ;
$perm = 0 ;
2023-08-31 17:14:41 +00:00
// if(is_array($permInfo))
// [$categoryName, $perm] = $permInfo;
// else
if ( is_int ( $permInfo ))
2023-08-30 22:37:21 +00:00
$perm = $permInfo ;
$item -> perms [] = $permItem = new stdClass ;
$permItem -> category = $categoryName ;
$permItem -> name = sprintf ( 'perms[%s:%d]' , $categoryName , $perm );
$permItem -> title = self :: label ( $categoryName , $perm );
$permItem -> value = $perm ;
}
}
return $list ;
}
public static function convertSubmission ( array $raw , array $categories ) : array {
$apply = [];
foreach ( $raw as $name => $mode ) {
$nameParts = explode ( ':' , $name , 2 );
if ( count ( $nameParts ) !== 2 || ! ctype_alpha ( $nameParts [ 0 ]) || ! ctype_digit ( $nameParts [ 1 ]))
continue ;
[ $category , $value ] = $nameParts ;
if ( ! in_array ( $category , $categories ))
continue ;
if ( $mode === 'yes' || $mode === 'never' ) {
if ( ! array_key_exists ( $category , $apply ))
$apply [ $category ] = [ 'allow' => 0 , 'deny' => 0 ];
$apply [ $category ][ $mode === 'yes' ? 'allow' : 'deny' ] |= ( int ) $value ;
}
}
return $apply ;
}
}