*/ declare(strict_types=1); namespace oat\taoQtiTest\scripts\install; use common_report_Report as Report; use oat\oatbox\extension\script\ScriptAction; use oat\taoQtiTest\models\test\Template\DefaultConfigurationRegistry; use qtism\data\NavigationMode; use qtism\data\SubmissionMode; use ReflectionMethod; class SetupDefaultTemplateConfiguration extends ScriptAction { public const PART_ID_PREFIX = 'partIdPrefix'; public const SECTION_ID_PREFIX = 'sectionIdPrefix'; public const SECTION_TITLE_PREFIX = 'sectionTitlePrefix'; public const CATEGORIES = 'categories'; public const NAVIGATION_MODE = 'navigationMode'; public const SUBMISSION_MODE = 'submissionMode'; public const MAX_ATTEMPTS = 'maxAttempts'; private const ARRAY_VALUE_DELIMITER = ','; private const OPTION_DEFAULT_VALUES = [ self::PART_ID_PREFIX => 'testPart', self::SECTION_ID_PREFIX => 'assessmentSection', self::SECTION_TITLE_PREFIX => 'Section', self::CATEGORIES => '', self::NAVIGATION_MODE => NavigationMode::LINEAR, self::SUBMISSION_MODE => SubmissionMode::INDIVIDUAL, self::MAX_ATTEMPTS => 0, ]; protected function provideUsage() { return [ 'prefix' => 'h', 'longPrefix' => 'help', 'description' => 'Displays this message', ]; } protected function provideOptions(): array { return [ self::PART_ID_PREFIX => [ 'prefix' => 'pi', 'longPrefix' => self::PART_ID_PREFIX, 'description' => sprintf( 'Test part ID prefix, "%s" by default', self::OPTION_DEFAULT_VALUES[self::PART_ID_PREFIX] ), ], self::SECTION_ID_PREFIX => [ 'prefix' => 'si', 'longPrefix' => self::SECTION_ID_PREFIX, 'description' => sprintf( 'Test section ID prefix, "%s" by default', self::OPTION_DEFAULT_VALUES[self::SECTION_ID_PREFIX] ), ], self::SECTION_TITLE_PREFIX => [ 'prefix' => 'st', 'longPrefix' => self::SECTION_TITLE_PREFIX, 'description' => sprintf( 'Test section title prefix, "%s" by default', self::OPTION_DEFAULT_VALUES[self::SECTION_TITLE_PREFIX] ), ], self::CATEGORIES => [ 'prefix' => 'c', 'longPrefix' => self::CATEGORIES, 'description' => sprintf( 'Test item categories separated by "%s", "%s" by default', self::ARRAY_VALUE_DELIMITER, self::OPTION_DEFAULT_VALUES[self::CATEGORIES] ), ], self::NAVIGATION_MODE => [ 'prefix' => 'nm', 'longPrefix' => self::NAVIGATION_MODE, 'description' => sprintf( 'Test part navigation mode, %s, %d by default', $this->createEnumerableOptionDescription(NavigationMode::asArray()), self::OPTION_DEFAULT_VALUES[self::NAVIGATION_MODE] ), ], self::SUBMISSION_MODE => [ 'prefix' => 'sm', 'longPrefix' => self::SUBMISSION_MODE, 'description' => sprintf( 'Test part submission mode, %s, %d by default', $this->createEnumerableOptionDescription(SubmissionMode::asArray()), self::OPTION_DEFAULT_VALUES[self::SUBMISSION_MODE] ), ], self::MAX_ATTEMPTS => [ 'prefix' => 'm', 'longPrefix' => self::MAX_ATTEMPTS, 'description' => sprintf( 'Test element max attempts, %d by default', self::OPTION_DEFAULT_VALUES[self::MAX_ATTEMPTS] ), ], ]; } protected function provideDescription(): string { return sprintf('Sets `%s` values.', DefaultConfigurationRegistry::class); } protected function run(): Report { $registry = $this->propagate(new DefaultConfigurationRegistry()); $setValues = []; foreach (self::OPTION_DEFAULT_VALUES as $optionName => $defaultValue) { $value = $this->getOption($optionName) ?? $defaultValue; $method = [$registry, 'set' . ucfirst($optionName)]; $setValues[$optionName] = $this->setRegistryValue($method, $value); } return $this->createReport($setValues); } private function createReport(array $setValues): Report { $setValues = array_filter( $setValues, static function ($value): bool { return null !== $value; } ); return $setValues ? Report::createSuccess( sprintf( "Applied the following configuration to `%s`\n%s", DefaultConfigurationRegistry::class, json_encode($setValues, JSON_PRETTY_PRINT) ) ) : Report::createFailure( sprintf('No values set to `%s`', DefaultConfigurationRegistry::class) ); } private function setRegistryValue(array $method, $value) { if (!is_callable($method)) { return null; } $type = $this->getArgumentType($method); if ('array' === $type) { $value = $value ? explode(',', $value) : []; } else { settype($value, $type); } $method($value); return $value; } private function getArgumentType(array $method): string { /** @noinspection PhpUnhandledExceptionInspection */ $reflection = new ReflectionMethod(...$method); $arguments = $reflection->getParameters(); $firstArgument = reset($arguments); if (!$firstArgument) { return 'null'; } return (string)$firstArgument->getType(); } private function createEnumerableOptionDescription(array $values): string { return implode( ', ', array_map( static function (int $value, string $label): string { return "$value – $label"; }, $values, array_keys($values) ) ); } }