[group1, group2, ...], ...] */ public function getUserStructure() { $config = $this->loadConfig(); ksort($config); return $config; } /** * Get the groups for a user * * @param string $user * @return string[] */ public function getUserGroups($user) { $config = $this->loadConfig(); return $config[$user] ?? []; } /** * Get all users in a group * * @param string $group * @return string[] */ public function getGroupUsers($group) { $config = $this->loadConfig(); $users = []; foreach ($config as $user => $groups) { if (in_array($group, $groups)) { $users[] = $user; } } return $users; } /** * Get the configuration by group * * @return array [group => [user1, user2, ...], ...] */ public function getGroupStructure() { $config = $this->loadConfig(); $groups = []; foreach ($config as $user => $usergroups) { foreach ($usergroups as $group) { if (!isset($groups[$group])) { $groups[$group] = []; } $groups[$group][] = $user; } } ksort($groups); return $groups; } // region individual user/group management /** * Remove a user from all groups * * @param string $user * @return void */ public function removeUser($user) { $config = $this->loadConfig(); if (isset($config[$user])) unset($config[$user]); $this->saveConfig($config); } /** * Add a user to one or more groups * * @param string $user * @param string[] $groups * @return void */ public function addGroupsToUser($user, $groups) { $config = $this->loadConfig(); if (!isset($config[$user])) { $config[$user] = []; } $config[$user] = array_filter(array_unique(array_merge($config[$user], $groups))); $this->saveConfig($config); } /** * Set the groups for a user * * @param string $user * @param string[] $groups * @return void */ public function setUserGroups($user, $groups) { $config = $this->loadConfig(); $config[$user] = array_filter($groups); if ($config[$user] === []) { unset($config[$user]); } $this->saveConfig($config); } /** * Remove a group from all users * * @param string $group * @return void */ public function removeGroup($group) { $config = $this->loadConfig(); foreach ($config as $user => $groups) { if (($key = array_search($group, $groups)) !== false) { unset($config[$user][$key]); } } $this->saveConfig($config); } /** * Add one or more users to a group * * @param string $group * @param string[] $users * @return void */ public function addUsersToGroup($group, $users) { $config = $this->loadConfig(); foreach ($users as $user) { if (!isset($config[$user])) { $config[$user] = []; } $config[$user][] = $group; $config[$user] = array_filter(array_unique($config[$user])); } $this->saveConfig($config); } public function setGroupUsers($group, $users) { $config = $this->loadConfig(); foreach ($users as $user) { if (!isset($config[$user])) { $config[$user] = []; } $config[$user][] = $group; $config[$user] = array_filter(array_unique($config[$user])); if ($config[$user] === []) { unset($config[$user]); } } $this->saveConfig($config); } // endregion // region file management /** * Load the configuration * * @return array [user => [group1, group2, ...], ...] */ protected function loadConfig() { if (!file_exists(self::CONFIG_FILE)) return $this->loadLegacyConfig(); $config = []; $raw = linesToHash(file(self::CONFIG_FILE)); foreach ($raw as $key => $value) { $user = rawurldecode($key); $groups = array_map(static fn($group) => rawurldecode(trim($group)), explode(',', $value)); $config[$user] = $groups; } return $config; } /** * Save the configuration * * @param array $config [user => [group1, group2, ...], ...] * @return boolean */ protected function saveConfig($config) { global $INPUT; $lines = [ '# This file is managed by the virtualgroup plugin', '# Last saved by ' . $INPUT->server->str('REMOTE_USER') . ' on ' . date('Y-m-d H:i:s'), '' ]; foreach ($config as $user => $groups) { $lines[] = auth_nameencode($user) . "\t" . implode(',', array_map(static fn($group) => auth_nameencode($group), $groups)); } $ok = file_put_contents(self::CONFIG_FILE, implode("\n", $lines)); if ($ok === false) { msg('Failed to save virtual group configuration', -1); } return (bool)$ok; } /** * Load the legacy configuration * * @return array [user => [group1, group2, ...], ...] * @deprecated */ protected function loadLegacyConfig() { global $conf; // determine the path to the data $userFile = $conf['savedir'] . '/virtualgrp.php'; // if there is no file we hava no data ;-) if (!is_file($userFile)) return []; // read the file $content = trim(file_get_contents($userFile)); // if its empty we have no data also if (empty($content)) return []; $users = unserialize($content); // check for invalid data if ($users === false) { Logger::error('Failed to parse virtualgrp.php configuration file. File will be deleted.'); @unlink($userFile); return []; } // save in new format $ok = $this->saveConfig($users); if ($ok) { @unlink($userFile); } return $users; } // endregion }