From 722bb31815dd2fdb939e0e98a9fe427735305f80 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Wed, 6 Aug 2025 20:35:52 +0800 Subject: [PATCH] Introduce AttributeMapper for managing extensions and doctor attributes --- src/SPC/builder/BuilderBase.php | 31 +---- src/SPC/builder/linux/library/imap.php | 3 - src/SPC/command/BaseCommand.php | 82 ++++++++++--- src/SPC/command/DoctorCommand.php | 120 ++++++++++--------- src/SPC/doctor/AsFixItem.php | 2 +- src/SPC/doctor/CheckListHandler.php | 111 ------------------ src/SPC/doctor/DoctorHandler.php | 63 ++++++++++ src/SPC/util/AttributeMapper.php | 133 ++++++++++++++++++++++ src/SPC/util/CustomExt.php | 37 +----- tests/SPC/builder/BuilderTest.php | 6 +- tests/SPC/builder/ExtensionTest.php | 5 +- tests/SPC/doctor/CheckListHandlerTest.php | 6 +- tests/SPC/store/FileSystemTest.php | 2 - tests/bootstrap.php | 2 + 14 files changed, 338 insertions(+), 265 deletions(-) delete mode 100644 src/SPC/doctor/CheckListHandler.php create mode 100644 src/SPC/doctor/DoctorHandler.php create mode 100644 src/SPC/util/AttributeMapper.php diff --git a/src/SPC/builder/BuilderBase.php b/src/SPC/builder/BuilderBase.php index 5dec6ad8..2dd3362b 100644 --- a/src/SPC/builder/BuilderBase.php +++ b/src/SPC/builder/BuilderBase.php @@ -46,20 +46,14 @@ abstract class BuilderBase /** * Convert libraries to class * - * @param array $sorted_libraries Libraries to build (if not empty, must sort first) - * @throws FileSystemException - * @throws RuntimeException - * @throws WrongUsageException + * @param array $sorted_libraries Libraries to build (if not empty, must sort first) + * * @internal */ abstract public function proveLibs(array $sorted_libraries); /** * Set-Up libraries - * - * @throws FileSystemException - * @throws RuntimeException - * @throws WrongUsageException */ public function setupLibs(): void { @@ -139,9 +133,6 @@ abstract class BuilderBase /** * Check if there is a cpp extensions or libraries. - * - * @throws FileSystemException - * @throws WrongUsageException */ public function hasCpp(): bool { @@ -174,15 +165,10 @@ abstract class BuilderBase /** * Verify the list of "ext" extensions for validity and declare an Extension object to check the dependencies of the extensions. * - * @throws FileSystemException - * @throws RuntimeException - * @throws \ReflectionException - * @throws \Throwable|WrongUsageException * @internal */ public function proveExts(array $static_extensions, array $shared_extensions = [], bool $skip_check_deps = false, bool $skip_extract = false): void { - CustomExt::loadCustomExt(); // judge ext foreach ($static_extensions as $ext) { // if extension does not support static build, throw exception @@ -213,7 +199,7 @@ abstract class BuilderBase } foreach ([...$static_extensions, ...$shared_extensions] as $extension) { - $class = CustomExt::getExtClass($extension); + $class = AttributeMapper::getExtensionClassByName($extension) ?? Extension::class; /** @var Extension $ext */ $ext = new $class($extension, $this); if (in_array($extension, $static_extensions)) { @@ -247,11 +233,6 @@ abstract class BuilderBase */ abstract public function testPHP(int $build_target = BUILD_TARGET_NONE); - /** - * @throws WrongUsageException - * @throws RuntimeException - * @throws FileSystemException - */ public function buildSharedExts(): void { $lines = file(BUILD_BIN_PATH . '/php-config'); @@ -284,9 +265,6 @@ abstract class BuilderBase /** * Generate extension enable arguments for configure. * e.g. --enable-mbstring - * - * @throws FileSystemException - * @throws WrongUsageException */ public function makeStaticExtensionArgs(): string { @@ -321,9 +299,6 @@ abstract class BuilderBase /** * Get PHP Version ID from php-src/main/php_version.h - * - * @throws RuntimeException - * @throws WrongUsageException */ public function getPHPVersionID(): int { diff --git a/src/SPC/builder/linux/library/imap.php b/src/SPC/builder/linux/library/imap.php index a6500252..0407156e 100644 --- a/src/SPC/builder/linux/library/imap.php +++ b/src/SPC/builder/linux/library/imap.php @@ -39,9 +39,6 @@ class imap extends LinuxLibraryBase return false; } - /** - * @throws RuntimeException - */ protected function build(): void { if ($this->builder->getLib('openssl')) { diff --git a/src/SPC/command/BaseCommand.php b/src/SPC/command/BaseCommand.php index 9c07b074..09927ad9 100644 --- a/src/SPC/command/BaseCommand.php +++ b/src/SPC/command/BaseCommand.php @@ -69,9 +69,6 @@ abstract class BaseCommand extends Command } } - /** - * @throws WrongUsageException - */ abstract public function handle(): int; protected function execute(InputInterface $input, OutputInterface $output): int @@ -79,22 +76,17 @@ abstract class BaseCommand extends Command $this->input = $input; $this->output = $output; - global $ob_logger; - if ($input->getOption('debug') || $output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { - $ob_logger = new ConsoleLogger(LogLevel::DEBUG, decorated: !$input->getOption('no-ansi')); - define('DEBUG_MODE', true); - } else { - $ob_logger = new ConsoleLogger(decorated: !$input->getOption('no-ansi')); - } + // init log + $this->initLogFiles(); - // windows fallback - Prompt::fallbackWhen(PHP_OS_FAMILY === 'Windows'); - ConfirmPrompt::fallbackUsing(function (ConfirmPrompt $prompt) use ($input, $output) { - $helper = new QuestionHelper(); - $case = $prompt->default ? ' [Y/n] ' : ' [y/N] '; - $question = new ConfirmationQuestion($prompt->label . $case, $prompt->default); - return $helper->ask($input, $output, $question); - }); + // init logger + $this->initConsoleLogger(); + + // load attribute maps + AttributeMapper::init(); + + // init windows fallback + $this->initWindowsPromptFallback($input, $output); // init GlobalEnv if (!$this instanceof BuildCommand) { @@ -178,4 +170,58 @@ abstract class BaseCommand extends Command return true; })); } + + /** + * Initialize spc log files. + */ + private function initLogFiles(): void + { + $log_dir = SPC_LOGS_DIR; + if (!file_exists($log_dir)) { + mkdir($log_dir, 0755, true); + } elseif (!$this->getOption('preserve-log')) { + // Clean up old log files + $files = glob($log_dir . '/*.log'); + foreach ($files as $file) { + if (is_file($file)) { + unlink($file); + } + } + } + } + + /** + * Initialize console logger. + */ + private function initConsoleLogger(): void + { + global $ob_logger; + if ($this->input->getOption('debug') || $this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { + $ob_logger = new ConsoleLogger(LogLevel::DEBUG, decorated: !$this->input->getOption('no-ansi')); + define('DEBUG_MODE', true); + } else { + $ob_logger = new ConsoleLogger(decorated: !$this->input->getOption('no-ansi')); + } + $log_file_fd = fopen(SPC_OUTPUT_LOG, 'a'); + $ob_logger->addLogCallback(function ($level, $output) use ($log_file_fd) { + if ($log_file_fd) { + fwrite($log_file_fd, strip_ansi_colors($output) . "\n"); + } + return true; + }); + } + + /** + * Initialize Windows prompt fallback for laravel-prompts. + */ + private function initWindowsPromptFallback(InputInterface $input, OutputInterface $output): void + { + Prompt::fallbackWhen(PHP_OS_FAMILY === 'Windows'); + ConfirmPrompt::fallbackUsing(function (ConfirmPrompt $prompt) use ($input, $output) { + $helper = new QuestionHelper(); + $case = $prompt->default ? ' [Y/n] ' : ' [y/N] '; + $question = new ConfirmationQuestion($prompt->label . $case, $prompt->default); + return $helper->ask($input, $output, $question); + }); + } } diff --git a/src/SPC/command/DoctorCommand.php b/src/SPC/command/DoctorCommand.php index 1b5b8d14..77580b40 100644 --- a/src/SPC/command/DoctorCommand.php +++ b/src/SPC/command/DoctorCommand.php @@ -4,10 +4,12 @@ declare(strict_types=1); namespace SPC\command; -use SPC\doctor\CheckListHandler; use SPC\doctor\CheckResult; -use SPC\exception\RuntimeException; +use SPC\doctor\DoctorHandler; +use SPC\util\AttributeMapper; use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Input\InputOption; +use ZM\Logger\ConsoleColor; use function Laravel\Prompts\confirm; @@ -16,72 +18,78 @@ class DoctorCommand extends BaseCommand { public function configure(): void { - $this->addOption('auto-fix', null, null, 'Automatically fix failed items (if possible)'); + $this->addOption('auto-fix', null, InputOption::VALUE_OPTIONAL, 'Automatically fix failed items (if possible)', false); } public function handle(): int { - try { - $checker = new CheckListHandler(); - // skipped items - $skip_items = array_filter(explode(',', getenv('SPC_SKIP_DOCTOR_CHECK_ITEMS') ?: '')); + $fix_policy = match ($this->input->getOption('auto-fix')) { + 'never' => FIX_POLICY_DIE, + true, null => FIX_POLICY_AUTOFIX, + default => FIX_POLICY_PROMPT, + }; + $fix_map = AttributeMapper::getDoctorFixMap(); - $fix_policy = $this->input->getOption('auto-fix') ? FIX_POLICY_AUTOFIX : FIX_POLICY_PROMPT; - foreach ($checker->runChecks() as $check) { - if ($check->limit_os !== null && $check->limit_os !== PHP_OS_FAMILY) { - continue; + foreach (DoctorHandler::getValidCheckList() as $check) { + // output + $this->output->write("Checking {$check->item_name} ... "); + + // null => skipped + if (($result = call_user_func($check->callback)) === null) { + $this->output->writeln('skipped'); + continue; + } + // invalid return value => skipped + if (!$result instanceof CheckResult) { + $this->output->writeln('Skipped due to invalid return value'); + continue; + } + // true => OK + if ($result->isOK()) { + /* @phpstan-ignore-next-line */ + $this->output->writeln($result->getMessage() ?? (string) ConsoleColor::green('✓')); + continue; + } + + // Failed => output error message + $this->output->writeln('' . $result->getMessage() . ''); + // If the result is not fixable, fail immediately + if ($result->getFixItem() === '') { + $this->output->writeln('This check item can not be fixed !'); + return static::FAILURE; + } + if (!isset($fix_map[$result->getFixItem()])) { + $this->output->writeln("Internal error: Unknown fix item: {$result->getFixItem()}"); + return static::FAILURE; + } + + // prompt for fix + if ($fix_policy === FIX_POLICY_PROMPT) { + if (!confirm('Do you want to fix it?')) { + $this->output->writeln('You canceled fix.'); + return static::FAILURE; } - - $this->output->write('Checking ' . $check->item_name . ' ... '); - - // check if this item is skipped - if (in_array($check->item_name, $skip_items) || ($result = call_user_func($check->callback)) === null) { - $this->output->writeln('skipped'); - } elseif ($result instanceof CheckResult) { - if ($result->isOK()) { - $this->output->writeln($result->getMessage() ?? 'ok'); - continue; - } - - // Failed - $this->output->writeln('' . $result->getMessage() . ''); - switch ($fix_policy) { - case FIX_POLICY_DIE: - throw new RuntimeException('Some check items can not be fixed !'); - case FIX_POLICY_PROMPT: - if ($result->getFixItem() !== '') { - $question = confirm('Do you want to fix it?'); - if ($question) { - $checker->emitFix($this->output, $result); - } else { - throw new RuntimeException('You cancelled fix'); - } - } else { - throw new RuntimeException('Some check items can not be fixed !'); - } - break; - case FIX_POLICY_AUTOFIX: - if ($result->getFixItem() !== '') { - $this->output->writeln('Automatically fixing ' . $result->getFixItem() . ' ...'); - $checker->emitFix($this->output, $result); - } else { - throw new RuntimeException('Some check items can not be fixed !'); - } - break; - } + if (DoctorHandler::emitFix($this->output, $result)) { + $this->output->writeln('Fix applied successfully!'); + } else { + $this->output->writeln('Failed to apply fix!'); + return static::FAILURE; } } - $this->output->writeln('Doctor check complete !'); - } catch (\Throwable $e) { - $this->output->writeln('' . $e->getMessage() . ''); - - if (extension_loaded('pcntl')) { - pcntl_signal(SIGINT, SIG_IGN); + // auto fix + if ($fix_policy === FIX_POLICY_AUTOFIX) { + $this->output->writeln('Automatically fixing ' . $result->getFixItem() . ' ...'); + if (DoctorHandler::emitFix($this->output, $result)) { + $this->output->writeln('Fix applied successfully!'); + } else { + $this->output->writeln('Failed to apply fix!'); + return static::FAILURE; + } } - return static::FAILURE; } + $this->output->writeln('Doctor check complete !'); return static::SUCCESS; } } diff --git a/src/SPC/doctor/AsFixItem.php b/src/SPC/doctor/AsFixItem.php index 200bd1f7..2050f765 100644 --- a/src/SPC/doctor/AsFixItem.php +++ b/src/SPC/doctor/AsFixItem.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace SPC\doctor; -#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] +#[\Attribute(\Attribute::TARGET_METHOD)] class AsFixItem { public function __construct(public string $name) {} diff --git a/src/SPC/doctor/CheckListHandler.php b/src/SPC/doctor/CheckListHandler.php deleted file mode 100644 index cac17ce3..00000000 --- a/src/SPC/doctor/CheckListHandler.php +++ /dev/null @@ -1,111 +0,0 @@ - - * @throws \ReflectionException - * @throws RuntimeException - * @throws FileSystemException - */ - public function runChecks(bool $include_manual = false): array - { - return $this->loadCheckList($include_manual); - } - - /** - * @throws RuntimeException - */ - public function emitFix(OutputInterface $output, CheckResult $result): void - { - if (PHP_OS_FAMILY === 'Windows') { - sapi_windows_set_ctrl_handler(function () use ($output) { - $output->writeln('You cancelled fix'); - }); - } elseif (extension_loaded('pcntl')) { - pcntl_signal(SIGINT, function () use ($output) { - $output->writeln('You cancelled fix'); - }); - } - - $fix_result = call_user_func($this->fix_map[$result->getFixItem()], ...$result->getFixParams()); - - if (PHP_OS_FAMILY === 'Windows') { - sapi_windows_set_ctrl_handler(null); - } elseif (extension_loaded('pcntl')) { - pcntl_signal(SIGINT, SIG_IGN); - } - - if ($fix_result) { - $output->writeln('Fix done'); - } else { - $output->writeln('Fix failed'); - throw new RuntimeException('Some check item are not fixed'); - } - } - - /** - * Load Doctor check item list - * - * @return array - * @throws \ReflectionException - * @throws RuntimeException - * @throws FileSystemException - */ - private function loadCheckList(bool $include_manual = false): array - { - foreach (FileSystem::getClassesPsr4(__DIR__ . '/item', 'SPC\doctor\item') as $class) { - $ref = new \ReflectionClass($class); - $optional = $ref->getAttributes(OptionalCheck::class)[0] ?? null; - if ($optional !== null) { - /** @var OptionalCheck $instance */ - $instance = $optional->newInstance(); - if (is_callable($instance->check) && !call_user_func($instance->check)) { - continue; // skip this class if optional check is false - } - } - foreach ($ref->getMethods() as $method) { - foreach ($method->getAttributes() as $a) { - if (is_a($a->getName(), AsCheckItem::class, true)) { - /** @var AsCheckItem $instance */ - $instance = $a->newInstance(); - if (!$include_manual && $instance->manual) { - continue; - } - $instance->callback = [new $class(), $method->getName()]; - $this->check_list[] = $instance; - } elseif (is_a($a->getName(), AsFixItem::class, true)) { - /** @var AsFixItem $instance */ - $instance = $a->newInstance(); - // Redundant fix item - if (isset($this->fix_map[$instance->name])) { - throw new RuntimeException('Redundant doctor fix item: ' . $instance->name); - } - $this->fix_map[$instance->name] = [new $class(), $method->getName()]; - } - } - } - } - - // sort check list by level - usort($this->check_list, fn (AsCheckItem $a, AsCheckItem $b) => $a->level > $b->level ? -1 : ($a->level == $b->level ? 0 : 1)); - - return $this->check_list; - } -} diff --git a/src/SPC/doctor/DoctorHandler.php b/src/SPC/doctor/DoctorHandler.php new file mode 100644 index 00000000..4ae8d2fe --- /dev/null +++ b/src/SPC/doctor/DoctorHandler.php @@ -0,0 +1,63 @@ + + */ + public static function getValidCheckList(): iterable + { + foreach (AttributeMapper::getDoctorCheckMap() as [$item, $optional]) { + /* @var AsCheckItem $item */ + // optional check + if ($optional !== null && !call_user_func($optional)) { + continue; // skip this when the optional check is false + } + // limit_os check + if ($item->limit_os !== null && $item->limit_os !== PHP_OS_FAMILY) { + continue; + } + // skipped items by env + $skip_items = array_filter(explode(',', getenv('SPC_SKIP_DOCTOR_CHECK_ITEMS') ?: '')); + if (in_array($item->item_name, $skip_items)) { + continue; // skip this item + } + yield $item; + } + } + + /** + * Emit the fix for a given CheckResult. + * + * @param OutputInterface $output the output interface to write messages to + * @param CheckResult $result the result of the check that needs fixing + * @return bool returns true if the fix was successful, false otherwise + */ + public static function emitFix(OutputInterface $output, CheckResult $result): bool + { + keyboard_interrupt_register(function () use ($output) { + $output->writeln('You cancelled fix'); + }); + try { + $fix_result = call_user_func(AttributeMapper::getDoctorFixMap()[$result->getFixItem()], ...$result->getFixParams()); + } catch (SPCException $e) { + $output->writeln('Fix failed: ' . $e->getMessage() . ''); + return false; + } catch (\Throwable $e) { + $output->writeln('Fix failed with an unexpected error: ' . $e->getMessage() . ''); + return false; + } + keyboard_interrupt_unregister(); + return $fix_result; + } +} diff --git a/src/SPC/util/AttributeMapper.php b/src/SPC/util/AttributeMapper.php new file mode 100644 index 00000000..4eafc6dd --- /dev/null +++ b/src/SPC/util/AttributeMapper.php @@ -0,0 +1,133 @@ + $extensions The mapping of extension names to their classes */ + private static array $ext_attr_map = []; + + /** @var array> $doctor_map The mapping of doctor modules */ + private static array $doctor_map = [ + 'check' => [], + 'fix' => [], + ]; + + public static function init(): void + { + // Load CustomExt attributes from extension classes + self::loadExtensionAttributes(); + + // Load doctor check items + self::loadDoctorAttributes(); + + // TODO: 3.0, refactor library loader and vendor loader here + } + + /** + * Get the class name of an extension by its attributed name. + * + * @param string $name The name of the extension (attributed name) + * @return null|string Returns the class name of the extension if it exists, otherwise null + */ + public static function getExtensionClassByName(string $name): ?string + { + return self::$ext_attr_map[$name] ?? null; + } + + /** + * @internal + */ + public static function getDoctorCheckMap(): array + { + return self::$doctor_map['check']; + } + + /** + * @internal + */ + public static function getDoctorFixMap(): array + { + return self::$doctor_map['fix']; + } + + private static function loadExtensionAttributes(): void + { + $classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/builder/extension', 'SPC\builder\extension'); + foreach ($classes as $class) { + $reflection = new \ReflectionClass($class); + foreach ($reflection->getAttributes(CustomExt::class) as $attribute) { + /** @var CustomExt $instance */ + $instance = $attribute->newInstance(); + self::$ext_attr_map[$instance->ext_name] = $class; + } + } + } + + private static function loadDoctorAttributes(): void + { + $classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/doctor/item', 'SPC\doctor\item'); + foreach ($classes as $class) { + $optional_passthrough = null; + $ref = new \ReflectionClass($class); + // #[OptionalCheck] + $optional = $ref->getAttributes(OptionalCheck::class)[0] ?? null; + if ($optional !== null) { + /** @var OptionalCheck $instance */ + $instance = $optional->newInstance(); + if (is_callable($instance->check)) { + $optional_passthrough = $instance->check; + } + } + $check_items = []; + $fix_items = []; + // load check items and fix items + foreach ($ref->getMethods() as $method) { + $optional_passthrough_single = $optional_passthrough ?? null; + // #[OptionalCheck] + foreach ($method->getAttributes(OptionalCheck::class) as $method_attr) { + $optional_check = $method_attr->newInstance(); + if (is_callable($optional_check->check)) { + $optional_passthrough_single = $optional_check->check; + } + } + // #[AsCheckItem] + foreach ($method->getAttributes(AsCheckItem::class) as $method_attr) { + // [{AsCheckItem object}, {OptionalCheck callable or null}] + $obj = $method_attr->newInstance(); + $obj->callback = [new $class(), $method->getName()]; + $check_items[] = [$obj, $optional_passthrough_single]; + } + // #[AsFixItem] + $fix_item = $method->getAttributes(AsFixItem::class)[0] ?? null; + if ($fix_item !== null) { + // [{AsFixItem object}, {OptionalCheck callable or null}] + $obj = $fix_item->newInstance(); + $fix_items[$obj->name] = [new $class(), $method->getName()]; + } + } + + // add to doctor map + self::$doctor_map['check'] = array_merge(self::$doctor_map['check'], $check_items); + self::$doctor_map['fix'] = array_merge(self::$doctor_map['fix'], $fix_items); + } + + // sort check items by level + usort(self::$doctor_map['check'], fn (array $a, array $b) => $a[0]->level > $b[0]->level ? -1 : ($a[0]->level == $b[0]->level ? 0 : 1)); + } +} diff --git a/src/SPC/util/CustomExt.php b/src/SPC/util/CustomExt.php index 8bdf287d..04cc645f 100644 --- a/src/SPC/util/CustomExt.php +++ b/src/SPC/util/CustomExt.php @@ -5,8 +5,6 @@ declare(strict_types=1); namespace SPC\util; use SPC\builder\Extension; -use SPC\exception\FileSystemException; -use SPC\store\FileSystem; /** * Custom extension attribute and manager @@ -17,43 +15,10 @@ use SPC\store\FileSystem; #[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)] class CustomExt { - private static array $custom_ext_class = []; - /** * Constructor for custom extension attribute * * @param string $ext_name The extension name */ - public function __construct(protected string $ext_name) {} - - /** - * Load all custom extension classes - * - * This method scans the extension directory and registers all classes - * that have the CustomExt attribute. - * - * @throws \ReflectionException - * @throws FileSystemException - */ - public static function loadCustomExt(): void - { - $classes = FileSystem::getClassesPsr4(ROOT_DIR . '/src/SPC/builder/extension', 'SPC\builder\extension'); - foreach ($classes as $class) { - $reflection = new \ReflectionClass($class); - foreach ($reflection->getAttributes(CustomExt::class) as $attribute) { - self::$custom_ext_class[$attribute->getArguments()[0]] = $class; - } - } - } - - /** - * Get the class name for a custom extension - * - * @param string $ext_name The extension name - * @return string The class name for the extension - */ - public static function getExtClass(string $ext_name): string - { - return self::$custom_ext_class[$ext_name] ?? Extension::class; - } + public function __construct(public string $ext_name) {} } diff --git a/tests/SPC/builder/BuilderTest.php b/tests/SPC/builder/BuilderTest.php index ac55375c..483d8bbb 100644 --- a/tests/SPC/builder/BuilderTest.php +++ b/tests/SPC/builder/BuilderTest.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace SPC\Tests\builder; -use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use SPC\builder\BuilderBase; use SPC\builder\BuilderProvider; @@ -14,7 +13,7 @@ use SPC\exception\RuntimeException; use SPC\exception\WrongUsageException; use SPC\store\FileSystem; use SPC\store\LockFile; -use SPC\util\CustomExt; +use SPC\util\AttributeMapper; use SPC\util\DependencyUtil; use Symfony\Component\Console\Input\ArgvInput; @@ -36,9 +35,8 @@ class BuilderTest extends TestCase $this->builder = BuilderProvider::makeBuilderByInput(new ArgvInput()); [$extensions, $libs] = DependencyUtil::getExtsAndLibs(['mbregex']); $this->builder->proveLibs($libs); - CustomExt::loadCustomExt(); foreach ($extensions as $extension) { - $class = CustomExt::getExtClass($extension); + $class = AttributeMapper::getExtensionClassByName($extension) ?? Extension::class; $ext = new $class($extension, $this->builder); $this->builder->addExt($ext); } diff --git a/tests/SPC/builder/ExtensionTest.php b/tests/SPC/builder/ExtensionTest.php index c387dc99..89462065 100644 --- a/tests/SPC/builder/ExtensionTest.php +++ b/tests/SPC/builder/ExtensionTest.php @@ -7,7 +7,7 @@ namespace SPC\Tests\builder; use PHPUnit\Framework\TestCase; use SPC\builder\BuilderProvider; use SPC\builder\Extension; -use SPC\util\CustomExt; +use SPC\util\AttributeMapper; use SPC\util\DependencyUtil; use Symfony\Component\Console\Input\ArgvInput; @@ -23,9 +23,8 @@ class ExtensionTest extends TestCase $builder = BuilderProvider::makeBuilderByInput(new ArgvInput()); [$extensions, $libs] = DependencyUtil::getExtsAndLibs(['mbregex']); $builder->proveLibs($libs); - CustomExt::loadCustomExt(); foreach ($extensions as $extension) { - $class = CustomExt::getExtClass($extension); + $class = AttributeMapper::getExtensionClassByName($extension) ?? Extension::class; $ext = new $class($extension, $builder); $builder->addExt($ext); } diff --git a/tests/SPC/doctor/CheckListHandlerTest.php b/tests/SPC/doctor/CheckListHandlerTest.php index 364d78ce..c6191e30 100644 --- a/tests/SPC/doctor/CheckListHandlerTest.php +++ b/tests/SPC/doctor/CheckListHandlerTest.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace SPC\Tests\doctor; use PHPUnit\Framework\TestCase; -use SPC\doctor\CheckListHandler; +use SPC\doctor\DoctorHandler; /** * @internal @@ -14,9 +14,9 @@ final class CheckListHandlerTest extends TestCase { public function testRunChecksReturnsListOfCheck(): void { - $list = new CheckListHandler(); + $list = new DoctorHandler(); - $id = $list->runChecks(); + $id = $list->getValidCheckList(); foreach ($id as $item) { $this->assertInstanceOf('SPC\doctor\AsCheckItem', $item); } diff --git a/tests/SPC/store/FileSystemTest.php b/tests/SPC/store/FileSystemTest.php index b7f766fd..13d2893f 100644 --- a/tests/SPC/store/FileSystemTest.php +++ b/tests/SPC/store/FileSystemTest.php @@ -5,8 +5,6 @@ declare(strict_types=1); namespace SPC\Tests\store; use PHPUnit\Framework\TestCase; -use SPC\exception\FileSystemException; -use SPC\exception\RuntimeException; use SPC\store\FileSystem; /** diff --git a/tests/bootstrap.php b/tests/bootstrap.php index d573204b..d4fa46c7 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -4,3 +4,5 @@ declare(strict_types=1); require_once __DIR__ . '/../src/globals/internal-env.php'; require_once __DIR__ . '/mock/SPC_store.php'; + +\SPC\util\AttributeMapper::init();