setName('user:profile') ->setDescription('Read and modify user profile properties') ->addArgument( 'uid', InputArgument::REQUIRED, 'Account ID used to login' ) ->addArgument( 'key', InputArgument::OPTIONAL, 'Profile property to set, get or delete', '' ) // Get ->addOption( 'default-value', null, InputOption::VALUE_REQUIRED, '(Only applicable on get) If no default value is set and the property does not exist, the command will exit with 1' ) // Set ->addArgument( 'value', InputArgument::OPTIONAL, 'The new value of the property', null ) ->addOption( 'update-only', null, InputOption::VALUE_NONE, 'Only updates the value, if it is not set before, it is not being added' ) // Delete ->addOption( 'delete', null, InputOption::VALUE_NONE, 'Specify this option to delete the property value' ) ->addOption( 'error-if-not-exists', null, InputOption::VALUE_NONE, 'Checks whether the property exists before deleting it' ) ; } protected function checkInput(InputInterface $input): IUser { $uid = $input->getArgument('uid'); $user = $this->userManager->get($uid); if (!$user) { throw new \InvalidArgumentException('The user "' . $uid . '" does not exist.'); } // normalize uid $input->setArgument('uid', $user->getUID()); $key = $input->getArgument('key'); if ($key === '') { if ($input->hasParameterOption('--default-value')) { throw new \InvalidArgumentException('The "default-value" option can only be used when specifying a key.'); } if ($input->getArgument('value') !== null) { throw new \InvalidArgumentException('The value argument can only be used when specifying a key.'); } if ($input->getOption('delete')) { throw new \InvalidArgumentException('The "delete" option can only be used when specifying a key.'); } } if ($input->getArgument('value') !== null && $input->hasParameterOption('--default-value')) { throw new \InvalidArgumentException('The value argument can not be used together with "default-value".'); } if ($input->getOption('update-only') && $input->getArgument('value') === null) { throw new \InvalidArgumentException('The "update-only" option can only be used together with "value".'); } if ($input->getOption('delete') && $input->hasParameterOption('--default-value')) { throw new \InvalidArgumentException('The "delete" option can not be used together with "default-value".'); } if ($input->getOption('delete') && $input->getArgument('value') !== null) { throw new \InvalidArgumentException('The "delete" option can not be used together with "value".'); } if ($input->getOption('error-if-not-exists') && !$input->getOption('delete')) { throw new \InvalidArgumentException('The "error-if-not-exists" option can only be used together with "delete".'); } return $user; } protected function execute(InputInterface $input, OutputInterface $output): int { try { $user = $this->checkInput($input); } catch (\InvalidArgumentException $e) { $output->writeln('' . $e->getMessage() . ''); return self::FAILURE; } $uid = $input->getArgument('uid'); $key = $input->getArgument('key'); $userAccount = $this->accountManager->getAccount($user); if ($key === '') { $settings = $this->getAllProfileProperties($userAccount); $this->writeArrayInOutputFormat($input, $output, $settings); return self::SUCCESS; } $value = $this->getStoredValue($userAccount, $key); $inputValue = $input->getArgument('value'); if ($inputValue !== null) { if ($input->hasParameterOption('--update-only') && $value === null) { $output->writeln('The property does not exist for user "' . $uid . '".'); return self::FAILURE; } return $this->editProfileProperty($output, $userAccount, $key, $inputValue); } elseif ($input->hasParameterOption('--delete')) { if ($input->hasParameterOption('--error-if-not-exists') && $value === null) { $output->writeln('The property does not exist for user "' . $uid . '".'); return self::FAILURE; } return $this->deleteProfileProperty($output, $userAccount, $key); } elseif ($value !== null) { $output->writeln($value); } elseif ($input->hasParameterOption('--default-value')) { $output->writeln($input->getOption('default-value')); } else { $output->writeln('The property does not exist for user "' . $uid . '".'); return self::FAILURE; } return self::SUCCESS; } private function deleteProfileProperty(OutputInterface $output, IAccount $userAccount, string $key): int { return $this->editProfileProperty($output, $userAccount, $key, ''); } private function editProfileProperty(OutputInterface $output, IAccount $userAccount, string $key, string $value): int { try { $userAccount->getProperty($key)->setValue($value); } catch (PropertyDoesNotExistException $exception) { $output->writeln('' . $exception->getMessage() . ''); return self::FAILURE; } $this->accountManager->updateAccount($userAccount); return self::SUCCESS; } private function getStoredValue(IAccount $userAccount, string $key): ?string { try { $property = $userAccount->getProperty($key); } catch (PropertyDoesNotExistException) { return null; } return $property->getValue() === '' ? null : $property->getValue(); } private function getAllProfileProperties(IAccount $userAccount): array { $properties = []; foreach ($userAccount->getAllProperties() as $property) { if ($property->getValue() !== '') { $properties[$property->getName()] = $property->getValue(); } } return $properties; } /** * @param string $argumentName * @param CompletionContext $context * @return string[] */ public function completeArgumentValues($argumentName, CompletionContext $context): array { if ($argumentName === 'uid') { return array_map(static fn (IUser $user) => $user->getUID(), $this->userManager->search($context->getCurrentWord())); } if ($argumentName === 'key') { $userId = $context->getWordAtIndex($context->getWordIndex() - 1); $user = $this->userManager->get($userId); if (!($user instanceof IUser)) { return []; } $account = $this->accountManager->getAccount($user); $properties = $this->getAllProfileProperties($account); return array_keys($properties); } return []; } }