BaseSetup.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. declare(strict_types=1);
  3. namespace Hestia\WebApp;
  4. use Hestia\System\HestiaApp;
  5. use Hestia\WebApp\InstallationTarget\InstallationTarget;
  6. use Hestia\WebApp\InstallationTarget\TargetDatabase;
  7. use RuntimeException;
  8. use function basename;
  9. use function dirname;
  10. use function is_string;
  11. use function sprintf;
  12. use function str_replace;
  13. use function str_starts_with;
  14. abstract class BaseSetup implements InstallerInterface
  15. {
  16. protected array $info;
  17. protected array $config;
  18. public function __construct(protected HestiaApp $appcontext)
  19. {
  20. }
  21. public function getInfo(): InstallerInfo
  22. {
  23. $supportedPHPVersions = $this->appcontext->getSupportedPHPVersions(
  24. $this->config['server']['php']['supported'],
  25. );
  26. return InstallerInfo::fromArray([
  27. ...$this->info,
  28. 'supportedPHPVersions' => $supportedPHPVersions,
  29. ]);
  30. }
  31. public function getConfig(string $section = ''): mixed
  32. {
  33. return !empty($section) ? $this->config[$section] : $this->config;
  34. }
  35. public function install(InstallationTarget $target, array $options): void
  36. {
  37. $this->appcontext->deleteFile($target->getDocRoot('robots.txt'));
  38. $this->appcontext->deleteFile($target->getDocRoot('index.html'));
  39. $this->retrieveResources($target, $options);
  40. $this->setupDatabase($target->database);
  41. $this->setupWebServer($target->domain->domainName, $options['php_version']);
  42. $this->setupApplication($target, $options);
  43. }
  44. abstract protected function setupApplication(InstallationTarget $target, array $options): void;
  45. private function setupWebServer(string $domainName, string $phpVersion): void
  46. {
  47. if ($_SESSION['WEB_SYSTEM'] === 'nginx') {
  48. if (isset($this->config['server']['nginx']['template'])) {
  49. $this->appcontext->changeWebTemplate(
  50. $domainName,
  51. $this->config['server']['nginx']['template'],
  52. );
  53. } else {
  54. $this->appcontext->changeWebTemplate($domainName, 'default');
  55. }
  56. } else {
  57. if (isset($this->config['server']['apache2']['template'])) {
  58. $this->appcontext->changeWebTemplate(
  59. $domainName,
  60. $this->config['server']['apache2']['template'],
  61. );
  62. } else {
  63. $this->appcontext->changeWebTemplate($domainName, 'default');
  64. }
  65. }
  66. if ($_SESSION['WEB_BACKEND'] === 'php-fpm') {
  67. if (isset($this->config['server']['php']['supported'])) {
  68. $supportedPHPVersions = $this->appcontext->getSupportedPHPVersions(
  69. $this->config['server']['php']['supported'],
  70. );
  71. if (empty($supportedPHPVersions)) {
  72. throw new RuntimeException('Required PHP version is not supported');
  73. }
  74. //convert from x.x to PHP-x_x to accepted.
  75. $this->appcontext->changeBackendTemplate(
  76. $domainName,
  77. 'PHP-' . str_replace('.', '_', $phpVersion),
  78. );
  79. }
  80. }
  81. }
  82. private function setupDatabase(TargetDatabase $database): void
  83. {
  84. if ($database->createDatabase) {
  85. if (!$this->appcontext->checkDatabaseLimit()) {
  86. throw new RuntimeException('Unable to add database! Limit reached!');
  87. }
  88. $userPrefix = $this->appcontext->user() . '_';
  89. $databaseName = str_replace($userPrefix, '', $database->name);
  90. $databaseUser = str_replace($userPrefix, '', $database->user);
  91. $this->appcontext->databaseAdd(
  92. $databaseName,
  93. $databaseUser,
  94. $database->password,
  95. $database->host,
  96. );
  97. }
  98. }
  99. private function retrieveResources(InstallationTarget $target, array $options): void
  100. {
  101. foreach ($this->config['resources'] as $resourceType => $resourceData) {
  102. $resourceLocation = $resourceData['src'];
  103. if (!empty($resourceData['dst']) && is_string($resourceData['dst'])) {
  104. $destinationPath = $target->getDocRoot($resourceData['dst']);
  105. } else {
  106. $destinationPath = $target->getDocRoot();
  107. }
  108. if ($resourceType === 'composer') {
  109. $this->appcontext->runComposer($options['php_version'], [
  110. 'create-project',
  111. '--no-progress',
  112. '--no-interaction',
  113. '--prefer-dist',
  114. $resourceData['src'],
  115. '-d',
  116. dirname($destinationPath),
  117. basename($destinationPath),
  118. ]);
  119. return;
  120. }
  121. if ($resourceType === 'wp') {
  122. $this->appcontext->runWp($options['php_version'], [
  123. 'core',
  124. 'download',
  125. '--locale=' . $options['language'],
  126. '--version=' . $this->info['version'],
  127. '--path=' . $destinationPath,
  128. ]);
  129. return;
  130. }
  131. if ($resourceType === 'archive') {
  132. if (
  133. !str_starts_with($resourceLocation, 'http://') &&
  134. !str_starts_with($resourceLocation, 'https://')
  135. ) {
  136. // only unpack file archive
  137. $this->appcontext->archiveExtract($resourceLocation, $destinationPath);
  138. return;
  139. }
  140. // Download archive, unpack, delete download
  141. $resourceLocation = $this->appcontext->downloadUrl(
  142. $resourceLocation,
  143. $destinationPath,
  144. );
  145. $this->appcontext->archiveExtract($resourceLocation, $destinationPath);
  146. $this->appcontext->deleteFile($resourceLocation);
  147. return;
  148. }
  149. throw new RuntimeException(sprintf('Unknown resource type "%s"', $resourceType));
  150. }
  151. }
  152. }