diff --git a/cli/Commands/Config/ConfigList.php b/cli/Commands/Config/ConfigList.php new file mode 100644 index 0000000000000000000000000000000000000000..e818ac0d731041494f655ed13c652d9f6263cdeb --- /dev/null +++ b/cli/Commands/Config/ConfigList.php @@ -0,0 +1,53 @@ +<?php + +namespace Studip\Cli\Commands\Config; + +use ConfigurationModel; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ConfigList extends Command +{ + protected static $defaultName = 'config:list'; + + protected function configure() + { + $this->setDescription('List all Stud.IP configuration.'); + $this->setHelp('This command shows a list of available configurations.'); + $this->addArgument('config-section', InputArgument::OPTIONAL, 'Section of the configuration.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $section = $input->getArgument('config-section'); + $sections = ConfigurationModel::getConfig($section); + + foreach ($sections as $section => $configs) { + $data = []; + foreach ($configs as $config) { + $data[] = [ + $config['field'], + $config['type'], + mila(kill_format((string)$config['value']),40), + $config['range'], + mila(kill_format((string)$config['description']),40), + ]; + } + $table = new Table($output); + $table->setColumnMaxWidth(1, 10); + $table->setColumnMaxWidth(2, 50); + $table->setColumnMaxWidth(3, 10); + $table->setColumnMaxWidth(4, 50); + $table->setHeaderTitle($section ?? _('Ohne Kategorie')); + $table->setHeaders(['Field', 'Type', 'Value', 'Range', 'Description']); + $table->setRows($data); + $table->setStyle('box'); + $table->render(); + } + + return Command::SUCCESS; + } +} diff --git a/cli/Commands/Config/GetConfigValue.php b/cli/Commands/Config/GetConfigValue.php new file mode 100644 index 0000000000000000000000000000000000000000..46fe903b6a29da14f40ed193675145cac9018a36 --- /dev/null +++ b/cli/Commands/Config/GetConfigValue.php @@ -0,0 +1,107 @@ +<?php + +namespace Studip\Cli\Commands\Config; + +use Course; +use Institute; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use User; +use RangeFactory; + +class GetConfigValue extends Command +{ + protected static $defaultName = 'config:get'; + + protected function configure(): void + { + $this->setDescription('Get value of a Stud.IP configuration key.'); + $this->setHelp('This command will return the value of a Stud.IP configuration key.'); + $this->addArgument('config-key', InputArgument::REQUIRED, 'Key of the configuration.'); + $this->addOption( + 'user', + 'u', + InputOption::VALUE_OPTIONAL, + 'Read configuration for a user' + ); + $this->addOption( + 'course', + 'c', + InputOption::VALUE_OPTIONAL, + 'Read configuration for a course' + ); + $this->addOption( + 'inst', + 'i', + InputOption::VALUE_OPTIONAL, + 'Read configuration for a institute' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $configKey = $input->getArgument('config-key'); + $userId = $input->getOption('user'); + $courseId = $input->getOption('course'); + $instituteId = $input->getOption('inst'); + + $range = null; + if ($userId && $courseId && $instituteId) { + $output->writeln('<error>Please select one specific range</error>'); + return Command::FAILURE; + } + if ($userId) { + $range = User::find($userId); + if (empty($range)) { + $output->writeln('<error>Could not find user</error>'); + return Command::FAILURE; + } + + } else if ($courseId) { + $range = Course::find($courseId); + if (empty($range)) { + $output->writeln('<error>Could not find course</error>'); + return Command::FAILURE; + } + } else if ($instituteId) { + $range = Institute::find($instituteId); + if (empty($range)) { + $output->writeln('<error>Could not find institute</error>'); + return Command::FAILURE; + } + } + + if ($range) { + $config = $range->getConfiguration(); + } else { + $config = \Config::get(); + } + + if (empty($config)) { + $output->writeln('<error>Could not find config</error>'); + return Command::FAILURE; + } + + $metadata = $config->getMetadata($configKey) ?: [ + 'field' => $configKey, + 'type' => 'string', + 'description' => 'missing in table `config`', + ]; + if (isset($metadata['is_default'])) { + $metadata['is_default'] = $metadata['is_default'] ? 'true' : 'false'; + } + $metadata['value'] = $config->$configKey; + $pairs = array_map(null, array_keys($metadata), array_values($metadata)); + + $table = new Table($output); + $table->setHeaders(['Field', 'Value'])->setRows($pairs); + $table->setStyle('box'); + $table->render(); + + return Command::SUCCESS; + } +} diff --git a/cli/Commands/Config/SectionList.php b/cli/Commands/Config/SectionList.php new file mode 100644 index 0000000000000000000000000000000000000000..28a0ed79ff85a715053c38b7b3c873bb23b8e19d --- /dev/null +++ b/cli/Commands/Config/SectionList.php @@ -0,0 +1,36 @@ +<?php + +namespace Studip\Cli\Commands\Config; + +use ConfigurationModel; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class SectionList extends Command +{ + protected static $defaultName = 'config:section-list'; + + protected function configure(): void + { + $this->setDescription('List all configuration sections'); + $this->setHelp('This command shows a list of available configuration sections.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $ranges = ConfigurationModel::getConfig(); + $data = []; + foreach (array_keys($ranges) as $range) { + $data[] = [$range ?? _('Ohne Kategorie')]; + } + $table = new Table($output); + $table->setHeaders(['Range']) + ->setRows($data) + ->setStyle('box') + ->render(); + + return Command::SUCCESS; + } +} diff --git a/cli/Commands/Config/SetConfigValue.php b/cli/Commands/Config/SetConfigValue.php new file mode 100644 index 0000000000000000000000000000000000000000..9444dc954a1c28ae18366fb107c5731289e24505 --- /dev/null +++ b/cli/Commands/Config/SetConfigValue.php @@ -0,0 +1,36 @@ +<?php + +namespace Studip\Cli\Commands\Config; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Helper\Table; + +class SetConfigValue extends Command +{ + protected static $defaultName = 'config:set'; + + protected function configure(): void + { + $this->setDescription('Set value of a Stud.IP configuration key.'); + $this->setHelp('This command will set the value of a Stud.IP configuration key.'); + $this->addArgument('config-key', InputArgument::REQUIRED, 'Key of the configuration.'); + $this->addArgument('config-value', InputArgument::REQUIRED, 'Value of the configuration.'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $configKey = $input->getArgument('config-key'); + $configValue = $input->getArgument('config-value'); + $metadata = \Config::get()->getMetadata($configKey); + if (!$metadata) { + throw new \RuntimeException("Unknown config key '{$configKey}"); + } + + \Config::get()->store($configKey, $configValue); + + return Command::SUCCESS; + } +} diff --git a/cli/Commands/Course/GetCourse.php b/cli/Commands/Course/GetCourse.php new file mode 100644 index 0000000000000000000000000000000000000000..97a777234336f0c07d64918220d2cf8c995cc213 --- /dev/null +++ b/cli/Commands/Course/GetCourse.php @@ -0,0 +1,69 @@ +<?php + +namespace Studip\Cli\Commands\Course; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableSeparator; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Course; + +class GetCourse extends Command +{ + protected static $defaultName = 'course:get'; + + protected function configure(): void + { + $this->setDescription('Get data of Stud.IP courses.'); + $this->setHelp('This command will return the course data.'); + $this->addOption( + 'field', + 'f', + InputOption::VALUE_OPTIONAL, + 'In which database field should be searched', + 'name' + ); + $this->addArgument('needle', InputArgument::REQUIRED, 'Value to search for a course.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $needle = $input->getArgument('needle'); + $field = $input->getOption('field'); + + if ($field === 'id') { + $courses = array_filter([Course::find($needle)]); + } else { + $courses = Course::findBySQL($field . " LIKE :needle ORDER BY $field", [':needle' => "%$needle%"]); + } + + if (empty($courses)) { + $output->writeln('<error>Could not find courses</error>'); + return Command::FAILURE; + } + $data = []; + + foreach ($courses as $i => $course) { + $data[] = [ + $course->id, + $course->veranstaltungsnummer, + $course->getFullName(), + $course->getTextualSemester() + ]; + if ($i + 1 < count($courses)) { + $data[] = [new TableSeparator(), new TableSeparator()]; + } + } + + $table = new Table($output); + $table->setHeaders(['Id', 'Course-number', 'Name', 'Semester']) + ->setRows($data) + ->setStyle('box') + ->render(); + + return Command::SUCCESS; + } +} diff --git a/cli/Commands/User/GetUser.php b/cli/Commands/User/GetUser.php new file mode 100644 index 0000000000000000000000000000000000000000..402356c94c2bab398d5a47e1f7d92ca84401e364 --- /dev/null +++ b/cli/Commands/User/GetUser.php @@ -0,0 +1,66 @@ +<?php + +namespace Studip\Cli\Commands\User; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Helper\Table; +use User; + +class GetUser extends Command +{ + protected static $defaultName = 'user:get'; + + protected function configure(): void + { + $this->setDescription('Get data of Stud.IP users.'); + $this->setHelp('This command will return the user data.'); + $this->addOption( + 'field', + 'f', + InputOption::VALUE_OPTIONAL, + 'In which database field should be searched', + 'username' + ); + $this->addArgument('needle', InputArgument::REQUIRED, 'Value to search for a user.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $needle = $input->getArgument('needle'); + $field = $input->getOption('field'); + + if ($field === 'id') { + $field = 'user_id'; + } + + $users = User::findBySQL($field . ' = ?', [$needle]); + + if (empty($users)) { + $output->writeln('<error>Could not find users</error>'); + return Command::FAILURE; + } + $data = []; + foreach ($users as $user) { + $data[] = [ + $user->id, + $user->username, + $user->vorname, + $user->nachname, + $user->email, + $user->auth_plugin, + ]; + } + + $table = new Table($output); + $table->setHeaders(['Id', 'Username', 'Firstname', 'Lastname', 'Email', 'Auth-Plugin']) + ->setRows($data) + ->setStyle('box') + ->render(); + + return Command::SUCCESS; + } +} diff --git a/cli/Commands/Users/UserDelete.php b/cli/Commands/User/UsersDelete.php similarity index 97% rename from cli/Commands/Users/UserDelete.php rename to cli/Commands/User/UsersDelete.php index 2ba854e60d8c0d61edb37e8928a424174306ff31..33b41c30c29498958d87a24e5391aa7fe4589d00 100644 --- a/cli/Commands/Users/UserDelete.php +++ b/cli/Commands/User/UsersDelete.php @@ -1,6 +1,6 @@ <?php -namespace Studip\Cli\Commands\Users; +namespace Studip\Cli\Commands\User; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -class UserDelete extends Command +class UsersDelete extends Command { protected static $defaultName = 'user:delete'; diff --git a/cli/studip b/cli/studip index 6ba02ce51be78456aecd657b168aac0636c9335e..d830e31f7600094c8f59c4b22b55cf8513c5982d 100755 --- a/cli/studip +++ b/cli/studip @@ -19,6 +19,11 @@ $commands = [ Commands\Checks\HelpTours::class, Commands\CleanupAdmissionRules::class, Commands\Composer\GenerateUpdateList::class, + Commands\Config\ConfigList::class, + Commands\Config\GetConfigValue::class, + Commands\Config\SectionList::class, + Commands\Config\SetConfigValue::class, + Commands\Course\GetCourse::class, Commands\Cronjobs\CronjobExecute::class, Commands\Cronjobs\CronjobExecute::class, Commands\Cronjobs\CronjobList::class, @@ -56,8 +61,8 @@ $commands = [ Commands\Resources\UpdateBookingIntervals::class, Commands\SORM\DescribeModels::class, Commands\Twillo\PrivateKeys::class, - Commands\Users\UserDelete::class, - Commands\Users\UserDelete::class, + Commands\User\UsersDelete::class, + Commands\User\GetUser::class, ]; $creator = function ($command) { return new $command();