CoreService.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. <?php
  2. declare(strict_types=1);
  3. namespace SixShop\Core\Service;
  4. use Composer\InstalledVersions;
  5. use Composer\Json\JsonFile;
  6. use ReflectionException;
  7. use Seld\JsonLint\ParsingException;
  8. use SixShop\Core\Command\GenerateInstalledSixShopCommand;
  9. use SixShop\Core\Exception\ExceptionHandle;
  10. use SixShop\Core\Plugin;
  11. use SixShop\Core\Request;
  12. use think\event\HttpRun;
  13. use think\exception\Handle;
  14. use think\Service;
  15. class CoreService extends Service
  16. {
  17. public static string $extensionPath;
  18. /**
  19. * @var array<string, array{name:string,version:string}>
  20. */
  21. public static array $extensionComposerMap = [];
  22. private static array $invalidExtensionIDs = [];
  23. public static function getExtensionComposerMap(): array
  24. {
  25. return self::$extensionComposerMap;
  26. }
  27. public static function getExtensionNameList(): array
  28. {
  29. return array_diff(array_keys(self::$extensionComposerMap), self::$invalidExtensionIDs);
  30. }
  31. /**
  32. * @throws ParsingException
  33. */
  34. public function register(): void
  35. {
  36. $this->app->bind(Handle::class, ExceptionHandle::class);
  37. $this->app->bind('think\Request', Request::class);
  38. $this->app->bind(
  39. 'classLoader',
  40. require $this->app->getRootPath() . 'vendor/autoload.php'
  41. );
  42. self::$extensionPath = $this->app->getRootPath() . 'extension' . DIRECTORY_SEPARATOR;
  43. $this->initExtensionList();
  44. }
  45. /**
  46. * @throws ParsingException
  47. */
  48. private function initExtensionList(): void
  49. {
  50. if (!empty(self::$extensionComposerMap)) {
  51. return;
  52. }
  53. $runtimePath = $this->app->getRootPath() . 'runtime/';
  54. $reference = Plugin::getInstalledSixShopExtensions()['root']['reference'];
  55. $extensionComposerFile = $runtimePath . 'extension_' . $reference . '.php';
  56. if (file_exists($extensionComposerFile)) {
  57. self::$extensionComposerMap = require $extensionComposerFile;
  58. return;
  59. }
  60. $files = array_diff(scandir($runtimePath), ['.', '..']);
  61. foreach ($files as $file) {
  62. if (str_starts_with($file, 'extension_') && str_ends_with($file, '.php')) {
  63. unlink($runtimePath . $file);
  64. }
  65. }
  66. foreach (InstalledVersions::getInstalledPackagesByType(Plugin::EXTENSION_TYPE) as $item) {
  67. $installPath = InstalledVersions::getInstallPath($item);
  68. $composerJson = new JsonFile($installPath . '/composer.json');
  69. $composer = $composerJson->read();
  70. $extensionID = $composer['extra']['sixshop']['id'] ?? $composer['name'];
  71. self::$extensionComposerMap[$extensionID] = $composer;
  72. }
  73. $header = '// This file is automatically generated at:' . date('Y-m-d H:i:s') . PHP_EOL . 'declare (strict_types = 1);' . PHP_EOL;
  74. $content = '<?php ' . PHP_EOL . $header . "return " . var_export(self::$extensionComposerMap, true) . ';';
  75. file_put_contents($extensionComposerFile, $content);
  76. }
  77. /**
  78. * @throws ReflectionException
  79. */
  80. public function boot(): void
  81. {
  82. $autoloadService = $this->app->make(AutoloadService::class);
  83. self::$invalidExtensionIDs = $autoloadService->load(self::$extensionComposerMap);
  84. $this->app->get('extension.system')->boot();
  85. foreach (self::$extensionComposerMap as $moduleName => $_) {
  86. if (in_array($moduleName, self::$invalidExtensionIDs)) {
  87. continue;
  88. }
  89. $extension = $autoloadService->getExtension($moduleName);
  90. if (!$extension->available()) {
  91. continue;
  92. }
  93. $extension->boot();
  94. $this->app->event->trigger('extension.boot', $extension);
  95. }
  96. $this->app->make(HookAttributeService::class)->init();
  97. $this->app->event->trigger('hook_init', $this->app);
  98. $this->app->event->listen(HttpRun::class, function () {
  99. $this->registerRoutes($this->app->make(RegisterRouteService::class)->init());
  100. });
  101. $this->commands([
  102. GenerateInstalledSixShopCommand::class,
  103. ]);
  104. $this->app->make(CommandService::class)->init(function ($commands) {
  105. $this->commands($commands);
  106. });
  107. }
  108. }