CoreService.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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\Exception\ExceptionHandle;
  9. use SixShop\Core\Plugin;
  10. use SixShop\Core\Request;
  11. use think\event\HttpRun;
  12. use think\exception\Handle;
  13. use think\Service;
  14. use function SixShop\Core\extension_path;
  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. /* @deprecated */
  23. public static array $extensionNameList = [];
  24. private static array $normalExtensionNameList = [];
  25. public static function getExtensionComposerMap(): array
  26. {
  27. return self::$extensionComposerMap;
  28. }
  29. /**
  30. * @throws ParsingException
  31. */
  32. public function register(): void
  33. {
  34. $this->app->bind(Handle::class, ExceptionHandle::class);
  35. $this->app->bind('think\Request', Request::class);
  36. $this->app->bind(
  37. 'classLoader',
  38. require $this->app->getRootPath() . 'vendor/autoload.php'
  39. );
  40. self::$extensionPath = $this->app->getRootPath() . 'extension' . DIRECTORY_SEPARATOR;
  41. $this->initExtensionList();
  42. $this->compatibleExtensionNameList();
  43. }
  44. /**
  45. * @throws ParsingException
  46. */
  47. private function initExtensionList(): void
  48. {
  49. if (!empty(self::$extensionComposerMap)) {
  50. return;
  51. }
  52. $runtimePath = $this->app->getRootPath() . 'runtime/';
  53. $reference = Plugin::getInstalledSixShopExtensions()['root']['reference'];
  54. $extensionComposerFile = $runtimePath . 'extension_' . $reference . '.php';
  55. if (file_exists($extensionComposerFile)) {
  56. self::$extensionComposerMap = require $extensionComposerFile;
  57. return;
  58. }
  59. $files = array_diff(scandir($runtimePath), ['.', '..']);
  60. foreach ($files as $file) {
  61. if (str_starts_with($file, 'extension_') && str_ends_with($file, '.php')) {
  62. unlink($runtimePath . $file);
  63. }
  64. }
  65. foreach (InstalledVersions::getInstalledPackagesByType(Plugin::EXTENSION_TYPE) as $item) {
  66. $installPath = InstalledVersions::getInstallPath($item);
  67. $composerJson = new JsonFile($installPath . '/composer.json');
  68. $composer = $composerJson->read();
  69. $extensionID = $composer['extra']['sixshop']['id'] ?? $composer['name'];
  70. self::$extensionComposerMap[$extensionID] = $composer;
  71. }
  72. $header = '// This file is automatically generated at:' . date('Y-m-d H:i:s') . PHP_EOL . 'declare (strict_types = 1);' . PHP_EOL;
  73. $content = '<?php ' . PHP_EOL . $header . "return " . var_export(self::$extensionComposerMap, true) . ';';
  74. file_put_contents($extensionComposerFile, $content);
  75. }
  76. /* @deprecated */
  77. private function compatibleExtensionNameList(): void
  78. {
  79. if (empty(self::$extensionNameList)) {
  80. self::$extensionNameList = array_keys(self::$extensionComposerMap);
  81. $normalFile = $this->app->getRootPath() . 'runtime/module_name_list_normal.php';
  82. if (file_exists($normalFile)) {
  83. $normalExtensionList = require $normalFile;
  84. foreach ($normalExtensionList as $item) {
  85. if (array_key_exists($item, self::$extensionComposerMap)) {
  86. continue;
  87. }
  88. if (is_dir(extension_path($item) . 'src')) {
  89. self::$extensionNameList[] = $item;
  90. self::$normalExtensionNameList[] = $item;
  91. }
  92. }
  93. }
  94. }
  95. }
  96. /**
  97. * @throws ReflectionException
  98. */
  99. public function boot(): void
  100. {
  101. $autoloadService = $this->app->make(AutoloadService::class);
  102. $invalidExtensionIDs = $autoloadService->load(self::$extensionComposerMap, self::$normalExtensionNameList);
  103. self::$extensionNameList = array_diff(self::$extensionNameList, $invalidExtensionIDs);
  104. $this->app->get('extension.system')->boot();
  105. foreach (self::$extensionComposerMap + self::$normalExtensionNameList as $moduleName => $_) {
  106. if (in_array($moduleName, $invalidExtensionIDs)) {
  107. continue;
  108. }
  109. $extension = $autoloadService->getExtension($moduleName);
  110. if (!$extension->available()) {
  111. continue;
  112. }
  113. $extension->boot();
  114. $this->app->event->trigger('extension.boot', $extension);
  115. }
  116. $this->app->make(HookAttributeService::class)->init();
  117. $this->app->event->trigger('hook_init', $this->app);
  118. $this->app->event->listen(HttpRun::class, function () {
  119. $this->registerRoutes($this->app->make(RegisterRouteService::class)->init());
  120. });
  121. $this->app->make(CommandService::class)->init(function ($commands) {
  122. $this->commands($commands);
  123. });
  124. }
  125. }