Initial
8
web/src/app/Models/DnsDomain.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\Models;
|
||||
|
||||
class DnsDomain extends Model {
|
||||
}
|
||||
8
web/src/app/Models/MailDomain.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\Models;
|
||||
|
||||
class MailDomain extends Model {
|
||||
}
|
||||
30
web/src/app/Models/Model.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\Models;
|
||||
|
||||
class Model {
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public static function all() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal list of models required
|
||||
*
|
||||
* User
|
||||
*
|
||||
* WebDomain
|
||||
*
|
||||
* MailDomain
|
||||
* `-MailAccount
|
||||
*
|
||||
* DNSDomain
|
||||
* `-DNSRecord
|
||||
*
|
||||
* Database
|
||||
*
|
||||
*/
|
||||
8
web/src/app/Models/User.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\Models;
|
||||
|
||||
class User extends Model {
|
||||
}
|
||||
8
web/src/app/Models/WebDomain.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\Models;
|
||||
|
||||
class WebDomain extends Model {
|
||||
}
|
||||
353
web/src/app/System/HestiaApp.php
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\System;
|
||||
use function Hestiacp\quoteshellarg\quoteshellarg;
|
||||
|
||||
class HestiaApp {
|
||||
/** @var string[] */
|
||||
public $errors;
|
||||
protected const TMPDIR_DOWNLOADS = "/tmp/hestia-webapp";
|
||||
protected $phpsupport = false;
|
||||
|
||||
public function __construct() {
|
||||
@mkdir(self::TMPDIR_DOWNLOADS);
|
||||
}
|
||||
|
||||
public function run(string $cmd, $args, &$cmd_result = null): bool {
|
||||
$cli_script = realpath(HESTIA_DIR_BIN . $cmd);
|
||||
if (!str_starts_with((string) $cli_script, HESTIA_DIR_BIN)) {
|
||||
$errstr = "$cmd is trying to traverse outside of " . HESTIA_DIR_BIN;
|
||||
trigger_error($errstr);
|
||||
throw new \Exception($errstr);
|
||||
}
|
||||
$cli_script = "/usr/bin/sudo " . quoteshellarg($cli_script);
|
||||
|
||||
$cli_arguments = "";
|
||||
if (!empty($args) && is_array($args)) {
|
||||
foreach ($args as $arg) {
|
||||
$cli_arguments .= quoteshellarg((string) $arg) . " ";
|
||||
}
|
||||
} else {
|
||||
$cli_arguments = quoteshellarg($args);
|
||||
}
|
||||
|
||||
exec($cli_script . " " . $cli_arguments . " 2>&1", $output, $exit_code);
|
||||
|
||||
$result["code"] = $exit_code;
|
||||
$result["args"] = $cli_arguments;
|
||||
$result["raw"] = $output;
|
||||
$result["text"] = implode(PHP_EOL, $output);
|
||||
$result["json"] = json_decode($result["text"], true);
|
||||
$cmd_result = (object) $result;
|
||||
if ($exit_code > 0) {
|
||||
//log error message in nginx-error.log
|
||||
trigger_error($result["text"]);
|
||||
//throw exception if command fails
|
||||
throw new \Exception($result["text"]);
|
||||
}
|
||||
return $exit_code === 0;
|
||||
}
|
||||
|
||||
public function runUser(string $cmd, $args, &$cmd_result = null): bool {
|
||||
if (!empty($args) && is_array($args)) {
|
||||
array_unshift($args, $this->user());
|
||||
} else {
|
||||
$args = [$this->user(), $args];
|
||||
}
|
||||
return $this->run($cmd, $args, $cmd_result);
|
||||
}
|
||||
|
||||
public function installComposer($version) {
|
||||
exec("curl https://composer.github.io/installer.sig", $output);
|
||||
|
||||
$signature = implode(PHP_EOL, $output);
|
||||
if (empty($signature)) {
|
||||
throw new \Exception("Error reading composer signature");
|
||||
}
|
||||
|
||||
$composer_setup =
|
||||
self::TMPDIR_DOWNLOADS . DIRECTORY_SEPARATOR . "composer-setup-" . $signature . ".php";
|
||||
|
||||
exec(
|
||||
"wget https://getcomposer.org/installer --quiet -O " . quoteshellarg($composer_setup),
|
||||
$output,
|
||||
$return_code,
|
||||
);
|
||||
if ($return_code !== 0) {
|
||||
throw new \Exception("Error downloading composer");
|
||||
}
|
||||
|
||||
if ($signature !== hash_file("sha384", $composer_setup)) {
|
||||
unlink($composer_setup);
|
||||
throw new \Exception("Invalid composer signature");
|
||||
}
|
||||
|
||||
$install_folder = $this->getUserHomeDir() . DIRECTORY_SEPARATOR . ".composer";
|
||||
|
||||
if (!file_exists($install_folder)) {
|
||||
exec(HESTIA_CMD . "v-rebuild-user " . $this->user(), $output, $return_code);
|
||||
if ($return_code !== 0) {
|
||||
throw new \Exception("Unable to rebuild user");
|
||||
}
|
||||
}
|
||||
|
||||
$this->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php",
|
||||
$composer_setup,
|
||||
"--quiet",
|
||||
"--install-dir=" . $install_folder,
|
||||
"--filename=composer",
|
||||
"--$version",
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
unlink($composer_setup);
|
||||
|
||||
if ($status->code !== 0) {
|
||||
throw new \Exception("Error installing composer");
|
||||
}
|
||||
}
|
||||
|
||||
public function updateComposer($version) {
|
||||
$this->runUser("v-run-cli-cmd", ["composer", "selfupdate", "--$version"]);
|
||||
}
|
||||
|
||||
public function runComposer($args, &$cmd_result = null, $data = []): bool {
|
||||
$composer =
|
||||
$this->getUserHomeDir() .
|
||||
DIRECTORY_SEPARATOR .
|
||||
".composer" .
|
||||
DIRECTORY_SEPARATOR .
|
||||
"composer";
|
||||
if (!is_file($composer)) {
|
||||
$this->installComposer($data["version"]);
|
||||
} else {
|
||||
$this->updateComposer($data["version"]);
|
||||
}
|
||||
if (empty($data["php_version"])) {
|
||||
$data["php_version"] = "";
|
||||
}
|
||||
if (!empty($args) && is_array($args)) {
|
||||
array_unshift($args, "php" . $data["php_version"], $composer);
|
||||
} else {
|
||||
$args = ["php" . $data["php_version"], $composer, $args];
|
||||
}
|
||||
|
||||
return $this->runUser("v-run-cli-cmd", $args, $cmd_result);
|
||||
}
|
||||
|
||||
public function runWp($args, &$cmd_result = null): bool {
|
||||
$wp =
|
||||
$this->getUserHomeDir() . DIRECTORY_SEPARATOR . ".wp-cli" . DIRECTORY_SEPARATOR . "wp";
|
||||
if (!is_file($wp)) {
|
||||
$this->runUser("v-add-user-wp-cli", []);
|
||||
} else {
|
||||
$this->runUser("v-run-cli-cmd", [$wp, "cli", "update"]);
|
||||
}
|
||||
array_unshift($args, $wp);
|
||||
|
||||
return $this->runUser("v-run-cli-cmd", $args, $cmd_result);
|
||||
}
|
||||
|
||||
// Logged in user
|
||||
public function realuser(): string {
|
||||
return $_SESSION["user"];
|
||||
}
|
||||
|
||||
// Effective user
|
||||
public function user(): string {
|
||||
$user = $this->realuser();
|
||||
if ($_SESSION["userContext"] === "admin" && !empty($_SESSION["look"])) {
|
||||
$user = $_SESSION["look"];
|
||||
}
|
||||
|
||||
if (strpos($user, DIRECTORY_SEPARATOR) !== false) {
|
||||
throw new \Exception("illegal characters in username");
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function getUserHomeDir() {
|
||||
$info = posix_getpwnam($this->user());
|
||||
return $info["dir"];
|
||||
}
|
||||
|
||||
public function userOwnsDomain(string $domain): bool {
|
||||
return $this->runUser("v-list-web-domain", [$domain, "json"]);
|
||||
}
|
||||
|
||||
public function checkDatabaseLimit() {
|
||||
$status = $this->runUser("v-list-user", ["json"], $result);
|
||||
$result->json[$this->user()];
|
||||
if ($result->json[$this->user()]["DATABASES"] != "unlimited") {
|
||||
if (
|
||||
$result->json[$this->user()]["DATABASES"] -
|
||||
$result->json[$this->user()]["U_DATABASES"] <
|
||||
1
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function databaseAdd(
|
||||
string $dbname,
|
||||
string $dbuser,
|
||||
string $dbpass,
|
||||
string $dbtype = "mysql",
|
||||
string $charset = "utf8mb4",
|
||||
) {
|
||||
$v_password = tempnam("/tmp", "hst");
|
||||
$fp = fopen($v_password, "w");
|
||||
fwrite($fp, $dbpass . "\n");
|
||||
fclose($fp);
|
||||
$status = $this->runUser("v-add-database", [
|
||||
$dbname,
|
||||
$dbuser,
|
||||
$v_password,
|
||||
$dbtype,
|
||||
"localhost",
|
||||
$charset,
|
||||
]);
|
||||
if (!$status) {
|
||||
$this->errors[] = _("Unable to add database!");
|
||||
}
|
||||
unlink($v_password);
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function getCurrentBackendTemplate(string $domain) {
|
||||
$status = $this->runUser("v-list-web-domain", [$domain, "json"], $return_message);
|
||||
$version = $return_message->json[$domain]["BACKEND"];
|
||||
if (!empty($version)) {
|
||||
if ($version != "default") {
|
||||
$test = preg_match("/^.*PHP-([0-9])\_([0-9])/", $version, $match);
|
||||
return $match[1] . "." . $match[2];
|
||||
} else {
|
||||
$supported = $this->run("v-list-sys-php", "json", $result);
|
||||
return $result->json[0];
|
||||
}
|
||||
} else {
|
||||
$supported = $this->run("v-list-sys-php", "json", $result);
|
||||
return $result->json[0];
|
||||
}
|
||||
}
|
||||
|
||||
public function changeWebTemplate(string $domain, string $template) {
|
||||
$status = $this->runUser("v-change-web-domain-tpl", [$domain, $template]);
|
||||
}
|
||||
public function changeBackendTemplate(string $domain, string $template) {
|
||||
$status = $this->runUser("v-change-web-domain-backend-tpl", [$domain, $template]);
|
||||
}
|
||||
|
||||
public function listSuportedPHP() {
|
||||
if (!$this->phpsupport) {
|
||||
$status = $this->run("v-list-sys-php", "json", $result);
|
||||
$this->phpsupport = $result->json;
|
||||
}
|
||||
return $this->phpsupport;
|
||||
}
|
||||
|
||||
/*
|
||||
Return highest available supported php version
|
||||
Eg: Package requires: 7.3 or 7.4 and system has 8.0 and 7.4 it will return 7.4
|
||||
Package requires: 8.0 or 8.1 and system has 8.0 and 7.4 it will return 8.0
|
||||
Package requires: 7.4 or 8.0 and system has 8.0 and 7.4 it will return 8.0
|
||||
If package isn't supported by the available php version false will returned
|
||||
*/
|
||||
public function getSupportedPHP($support) {
|
||||
$versions = $this->listSuportedPHP();
|
||||
$supported = false;
|
||||
$supported_versions = [];
|
||||
|
||||
foreach ($versions as $version) {
|
||||
if (in_array($version, $support)) {
|
||||
$supported = true;
|
||||
$supported_versions[] = $version;
|
||||
}
|
||||
}
|
||||
if ($supported) {
|
||||
return $supported_versions;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getWebDomainIp(string $domain) {
|
||||
$this->runUser("v-list-web-domain", [$domain, "json"], $result);
|
||||
$ip = $result->json[$domain]["IP"];
|
||||
return filter_var($ip, FILTER_VALIDATE_IP);
|
||||
}
|
||||
|
||||
public function getWebDomainPath(string $domain) {
|
||||
return Util::join_paths($this->getUserHomeDir(), "web", $domain);
|
||||
}
|
||||
|
||||
public function downloadUrl(string $src, $path = null, &$result = null) {
|
||||
if (strpos($src, "http://") !== 0 && strpos($src, "https://") !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
exec(
|
||||
"/usr/bin/wget --tries 3 --timeout=30 --no-dns-cache -nv " .
|
||||
quoteshellarg($src) .
|
||||
" -P " .
|
||||
quoteshellarg(self::TMPDIR_DOWNLOADS) .
|
||||
" 2>&1",
|
||||
$output,
|
||||
$return_var,
|
||||
);
|
||||
if ($return_var !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!preg_match(
|
||||
'/URL:\s*(.+?)\s*\[(.+?)\]\s*->\s*"(.+?)"/',
|
||||
implode(PHP_EOL, $output),
|
||||
$matches,
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($matches) || count($matches) != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status["url"] = $matches[1];
|
||||
$status["file"] = $matches[3];
|
||||
$result = (object) $status;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function archiveExtract(string $src, string $path, $skip_components = null) {
|
||||
if (empty($path)) {
|
||||
throw new \Exception("Error extracting archive: missing target folder");
|
||||
}
|
||||
|
||||
if (realpath($src)) {
|
||||
$archive_file = $src;
|
||||
} else {
|
||||
if (!$this->downloadUrl($src, null, $download_result)) {
|
||||
throw new \Exception("Error downloading archive");
|
||||
}
|
||||
$archive_file = $download_result->file;
|
||||
}
|
||||
|
||||
$result = $this->runUser("v-extract-fs-archive", [
|
||||
$archive_file,
|
||||
$path,
|
||||
null,
|
||||
$skip_components,
|
||||
]);
|
||||
unlink($archive_file);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
8
web/src/app/System/HestiaCli.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\System;
|
||||
|
||||
class HestiaCLI {
|
||||
}
|
||||
33
web/src/app/System/Util.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\System;
|
||||
|
||||
class Util {
|
||||
/*
|
||||
* Method from: https://stackoverflow.com/a/15575293
|
||||
* https://stackoverflow.com/questions/1091107/how-to-join-filesystem-path-strings-in-php
|
||||
*/
|
||||
public static function join_paths() {
|
||||
$paths = [];
|
||||
foreach (func_get_args() as $arg) {
|
||||
if ($arg !== "") {
|
||||
$paths[] = $arg;
|
||||
}
|
||||
}
|
||||
return preg_replace("#/+#", "/", join("/", $paths));
|
||||
}
|
||||
|
||||
public static function generate_string(int $length = 16, $full = true) {
|
||||
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
if ($full) {
|
||||
$chars .= '~`!@|#[]$%^&*() _-=+{}:;<>?,./';
|
||||
}
|
||||
$random_string = "";
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$random_string .= $chars[random_int(0, strlen($chars) - 1)];
|
||||
}
|
||||
return $random_string;
|
||||
}
|
||||
}
|
||||
133
web/src/app/WebApp/AppWizard.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\WebApp;
|
||||
|
||||
use Hestia\System\HestiaApp;
|
||||
|
||||
class AppWizard {
|
||||
private $domain;
|
||||
private $appsetup;
|
||||
private $appcontext;
|
||||
private $formNamespace = "webapp";
|
||||
private $errors;
|
||||
|
||||
private $database_config = [
|
||||
"database_create" => ["type" => "boolean", "value" => true],
|
||||
"database_name" => ["type" => "text", "placeholder" => "auto"],
|
||||
"database_user" => ["type" => "text", "placeholder" => "auto"],
|
||||
"database_password" => ["type" => "password", "placeholder" => "auto"],
|
||||
];
|
||||
|
||||
public function __construct(InstallerInterface $app, string $domain, HestiaApp $context) {
|
||||
$this->domain = $domain;
|
||||
$this->appcontext = $context;
|
||||
|
||||
if (!$this->appcontext->userOwnsDomain($domain)) {
|
||||
throw new \Exception("User does not have access to domain [$domain]");
|
||||
}
|
||||
|
||||
$this->appsetup = $app;
|
||||
}
|
||||
|
||||
public function getStatus() {
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
public function isDomainRootClean() {
|
||||
$this->appcontext->runUser("v-run-cli-cmd", ["ls", $this->appsetup->getDocRoot()], $status);
|
||||
if ($status->code !== 0) {
|
||||
throw new \Exception("Cannot list domain files");
|
||||
}
|
||||
|
||||
$files = $status->raw;
|
||||
if (count($files) > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (!in_array($file, ["index.html", "robots.txt"])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function formNs() {
|
||||
return $this->formNamespace;
|
||||
}
|
||||
|
||||
public function getOptions() {
|
||||
$options = $this->appsetup->getOptions();
|
||||
|
||||
$config = $this->appsetup->getConfig();
|
||||
$options = array_merge($options, [
|
||||
"php_version" => [
|
||||
"type" => "select",
|
||||
"value" => $this->appcontext->getCurrentBackendTemplate($this->domain),
|
||||
"options" => $this->appcontext->getSupportedPHP(
|
||||
$config["server"]["php"]["supported"],
|
||||
),
|
||||
],
|
||||
]);
|
||||
|
||||
if ($this->appsetup->withDatabase()) {
|
||||
$options = array_merge($options, $this->database_config);
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function info() {
|
||||
return $this->appsetup->info();
|
||||
}
|
||||
|
||||
public function filterOptions(array $options) {
|
||||
$filteredoptions = [];
|
||||
array_walk($options, function ($value, $key) use (&$filteredoptions) {
|
||||
if (strpos($key, $this->formNs() . "_") === 0) {
|
||||
$option = str_replace($this->formNs() . "_", "", $key);
|
||||
$filteredoptions[$option] = $value;
|
||||
}
|
||||
});
|
||||
return $filteredoptions;
|
||||
}
|
||||
|
||||
public function execute(array $options) {
|
||||
$options = $this->filterOptions($options);
|
||||
|
||||
$random_num = (string) random_int(10000, 99999);
|
||||
if ($this->appsetup->withDatabase() && !empty($options["database_create"])) {
|
||||
if (empty($options["database_name"])) {
|
||||
$options["database_name"] = $random_num;
|
||||
}
|
||||
|
||||
if (empty($options["database_user"])) {
|
||||
$options["database_user"] = $random_num;
|
||||
}
|
||||
|
||||
if (empty($options["database_password"])) {
|
||||
$options["database_password"] = bin2hex(random_bytes(10));
|
||||
}
|
||||
|
||||
if (!$this->appcontext->checkDatabaseLimit()) {
|
||||
$this->errors[] = _("Unable to add database! Limit reached!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!$this->appcontext->databaseAdd(
|
||||
$options["database_name"],
|
||||
$options["database_user"],
|
||||
$options["database_password"],
|
||||
)
|
||||
) {
|
||||
$this->errors[] = "Error adding database";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->errors)) {
|
||||
return $this->appsetup->install($options);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
web/src/app/WebApp/InstallerInterface.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Hestia\WebApp;
|
||||
|
||||
interface InstallerInterface {
|
||||
public function install(array $options = null);
|
||||
public function getDocRoot(string $append_relative_path = null): string;
|
||||
public function withDatabase(): bool;
|
||||
}
|
||||
201
web/src/app/WebApp/Installers/BaseSetup.php
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers;
|
||||
|
||||
use Hestia\System\Util;
|
||||
use Hestia\System\HestiaApp;
|
||||
use Hestia\WebApp\InstallerInterface;
|
||||
use Hestia\Models\WebDomain;
|
||||
|
||||
use Hestia\WebApp\Installers\Resources\ComposerResource;
|
||||
use Hestia\WebApp\Installers\Resources\WpResource;
|
||||
|
||||
abstract class BaseSetup implements InstallerInterface {
|
||||
protected $appInfo;
|
||||
protected $config;
|
||||
protected $domain;
|
||||
protected $extractsubdir;
|
||||
protected $AppDirInstall;
|
||||
protected $appcontext;
|
||||
|
||||
public function setAppDirInstall(string $appDir) {
|
||||
if (!empty($appDir)) {
|
||||
if (strpos(".", $appDir) !== false) {
|
||||
throw new \Exception("Invalid install folder");
|
||||
}
|
||||
if (!is_dir($this->getDocRoot($appDir))) {
|
||||
$this->appcontext->runUser(
|
||||
"v-add-fs-directory",
|
||||
[$this->getDocRoot($appDir)],
|
||||
$result,
|
||||
);
|
||||
}
|
||||
$this->AppDirInstall = $appDir;
|
||||
}
|
||||
}
|
||||
public function getAppDirInstall() {
|
||||
return $this->AppDirInstall;
|
||||
}
|
||||
|
||||
public function info() {
|
||||
$this->appInfo["enabled"] = true;
|
||||
if (isset($this->config["server"]["php"]["supported"])) {
|
||||
$this->appInfo["php_support"] = $this->config["server"]["php"]["supported"];
|
||||
} else {
|
||||
$this->appInfo["php_support"] = [
|
||||
"5.6",
|
||||
"7.0",
|
||||
"7.1",
|
||||
"7.2",
|
||||
"7.3",
|
||||
"7.4",
|
||||
"8.0",
|
||||
"8.1",
|
||||
"8.2",
|
||||
];
|
||||
}
|
||||
return $this->appInfo;
|
||||
}
|
||||
public function __construct($domain, HestiaApp $appcontext) {
|
||||
if (filter_var($domain, FILTER_VALIDATE_DOMAIN) === false) {
|
||||
throw new \Exception("Invalid domain name");
|
||||
}
|
||||
|
||||
$this->domain = $domain;
|
||||
$this->appcontext = $appcontext;
|
||||
}
|
||||
|
||||
public function getConfig($section = null) {
|
||||
return !empty($section) ? $this->config[$section] : $this->config;
|
||||
}
|
||||
|
||||
public function getOptions() {
|
||||
return $this->getConfig("form");
|
||||
}
|
||||
|
||||
public function withDatabase(): bool {
|
||||
return $this->getConfig("database") === true;
|
||||
}
|
||||
|
||||
public function getDocRoot($append_relative_path = null): string {
|
||||
$domain_path = $this->appcontext->getWebDomainPath($this->domain);
|
||||
|
||||
if (empty($domain_path) || !is_dir($domain_path)) {
|
||||
throw new \Exception("Error finding domain folder ($domain_path)");
|
||||
}
|
||||
if (!$this->AppDirInstall) {
|
||||
return Util::join_paths($domain_path, "public_html", $append_relative_path);
|
||||
} else {
|
||||
return Util::join_paths(
|
||||
$domain_path,
|
||||
"public_html",
|
||||
$this->AppDirInstall,
|
||||
$append_relative_path,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function retrieveResources($options) {
|
||||
foreach ($this->getConfig("resources") as $res_type => $res_data) {
|
||||
if (!empty($res_data["dst"]) && is_string($res_data["dst"])) {
|
||||
$resource_destination = $this->getDocRoot($res_data["dst"]);
|
||||
} else {
|
||||
$resource_destination = $this->getDocRoot($this->extractsubdir);
|
||||
}
|
||||
|
||||
if ($res_type === "composer") {
|
||||
$res_data["php_version"] = $options["php_version"];
|
||||
new ComposerResource(
|
||||
$this->appcontext,
|
||||
$res_data,
|
||||
$resource_destination,
|
||||
$options["php_version"],
|
||||
);
|
||||
} elseif ($res_type === "wp") {
|
||||
new WpResource(
|
||||
$this->appcontext,
|
||||
$res_data,
|
||||
$resource_destination,
|
||||
$options,
|
||||
$this->info(),
|
||||
);
|
||||
} else {
|
||||
$this->appcontext->archiveExtract($res_data["src"], $resource_destination, 1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function setup(array $options = null) {
|
||||
if ($_SESSION["WEB_SYSTEM"] == "nginx") {
|
||||
if (isset($this->config["server"]["nginx"]["template"])) {
|
||||
$this->appcontext->changeWebTemplate(
|
||||
$this->domain,
|
||||
$this->config["server"]["nginx"]["template"],
|
||||
);
|
||||
} else {
|
||||
$this->appcontext->changeWebTemplate($this->domain, "default");
|
||||
}
|
||||
} else {
|
||||
if (isset($this->config["server"]["apache2"]["template"])) {
|
||||
$this->appcontext->changeWebTemplate(
|
||||
$this->domain,
|
||||
$this->config["server"]["apache2"]["template"],
|
||||
);
|
||||
} else {
|
||||
$this->appcontext->changeWebTemplate($this->domain, "default");
|
||||
}
|
||||
}
|
||||
if ($_SESSION["WEB_BACKEND"] == "php-fpm") {
|
||||
if (isset($this->config["server"]["php"]["supported"])) {
|
||||
$php_version = $this->appcontext->getSupportedPHP(
|
||||
$this->config["server"]["php"]["supported"],
|
||||
);
|
||||
if (!$php_version) {
|
||||
throw new \Exception("Required PHP version is not supported");
|
||||
}
|
||||
//convert from x.x to PHP-x_x to accepted..
|
||||
$this->appcontext->changeBackendTemplate(
|
||||
$this->domain,
|
||||
"PHP-" . str_replace(".", "_", $options["php_version"]),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function install(array $options = null) {
|
||||
$this->appcontext->runUser("v-delete-fs-file", [$this->getDocRoot("robots.txt")]);
|
||||
$this->appcontext->runUser("v-delete-fs-file", [$this->getDocRoot("index.html")]);
|
||||
return $this->retrieveResources($options);
|
||||
}
|
||||
|
||||
public function cleanup() {
|
||||
// Remove temporary folder
|
||||
if (!empty($this->extractsubdir)) {
|
||||
$this->appcontext->runUser(
|
||||
"v-delete-fs-directory",
|
||||
[$this->getDocRoot($this->extractsubdir)],
|
||||
$result,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function saveTempFile(string $data) {
|
||||
$tmp_file = tempnam("/tmp", "hst.");
|
||||
if (empty($tmp_file)) {
|
||||
throw new \Exception("Error creating temp file");
|
||||
}
|
||||
|
||||
if (file_put_contents($tmp_file, $data) > 0) {
|
||||
chmod($tmp_file, 0644);
|
||||
$user_tmp_file = Util::join_paths($this->appcontext->getUserHomeDir(), $tmp_file);
|
||||
$this->appcontext->runUser("v-copy-fs-file", [$tmp_file, $user_tmp_file], $result);
|
||||
unlink($tmp_file);
|
||||
return $user_tmp_file;
|
||||
}
|
||||
|
||||
if (file_exists($tmp_file)) {
|
||||
unlink($tmp_file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
140
web/src/app/WebApp/Installers/DokuWiki/DokuWikiSetup.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\DokuWiki;
|
||||
|
||||
use Hestia\System\Util;
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class DokuWikiSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "DokuWiki",
|
||||
"group" => "wiki",
|
||||
"enabled" => true,
|
||||
"version" => "2023-04-04a",
|
||||
"thumbnail" => "dokuwiki-logo.svg",
|
||||
];
|
||||
|
||||
protected $appname = "dokuwiki";
|
||||
protected $extractsubdir = "/tmp-dokuwiki";
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"wiki_name" => "text",
|
||||
"superuser" => "text",
|
||||
"real_name" => "text",
|
||||
"email" => "text",
|
||||
"password" => "password",
|
||||
"initial_ACL_policy" => [
|
||||
"type" => "select",
|
||||
"options" => [
|
||||
"0: Open Wiki (read, write, upload for everyone)", // 0
|
||||
"1: Public Wiki (read for everyone, write and upload for registered users)", // 1
|
||||
"2: Closed Wiki (read, write, upload for registered users only)", // 3
|
||||
],
|
||||
],
|
||||
"content_license" => [
|
||||
"type" => "select",
|
||||
"options" => [
|
||||
"cc-zero: CC0 1.0 Universal",
|
||||
"publicdomain: Public Domain",
|
||||
"cc-by: CC Attribution 4.0 International",
|
||||
"cc-by-sa: CC Attribution-Share Alike 4.0 International",
|
||||
"gnufdl: GNU Free Documentation License 1.3",
|
||||
"cc-by-nc: CC Attribution-Noncommercial 4.0 International",
|
||||
"cc-by-nc-sa: CC Attribution-Noncommercial-Share Alike 4.0 International",
|
||||
"0: Do not show any license information",
|
||||
],
|
||||
],
|
||||
],
|
||||
"resources" => [
|
||||
"archive" => [
|
||||
"src" =>
|
||||
"https://github.com/dokuwiki/dokuwiki/releases/download/release-2023-04-04a/dokuwiki-2023-04-04a.zip",
|
||||
],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "default",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["7.3", "7.4", "8.0", "8.1"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null, &$status = null) {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
|
||||
//check if ssl is enabled
|
||||
$this->appcontext->run(
|
||||
"v-list-web-domain",
|
||||
[$this->appcontext->user(), $this->domain, "json"],
|
||||
$status,
|
||||
);
|
||||
$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
|
||||
|
||||
$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain . "/";
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-copy-fs-directory",
|
||||
[
|
||||
$this->getDocRoot($this->extractsubdir . "/dokuwiki-2023-04-04/."),
|
||||
$this->getDocRoot(),
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
// enable htaccess
|
||||
$this->appcontext->runUser(
|
||||
"v-move-fs-file",
|
||||
[$this->getDocRoot(".htaccess.dist"), $this->getDocRoot(".htaccess")],
|
||||
$status,
|
||||
);
|
||||
|
||||
$installUrl = $webDomain . "install.php";
|
||||
|
||||
$cmd =
|
||||
"curl --request POST " .
|
||||
($sslEnabled ? "" : "--insecure ") .
|
||||
"--url $installUrl " .
|
||||
"--header 'Content-Type: application/x-www-form-urlencoded' " .
|
||||
"--data l=en " .
|
||||
"--data 'd[title]=" .
|
||||
rawurlencode($options["wiki_name"]) .
|
||||
"' " .
|
||||
"--data 'd[acl]=on' " .
|
||||
"--data 'd[superuser]=" .
|
||||
rawurlencode($options["superuser"]) .
|
||||
"' " .
|
||||
"--data 'd[fullname]=" .
|
||||
rawurlencode($options["real_name"]) .
|
||||
"' " .
|
||||
"--data 'd[email]=" .
|
||||
rawurlencode($options["email"]) .
|
||||
"' " .
|
||||
"--data 'd[password]=" .
|
||||
rawurlencode($options["password"]) .
|
||||
"' " .
|
||||
"--data 'd[confirm]=" .
|
||||
rawurlencode($options["password"]) .
|
||||
"' " .
|
||||
"--data 'd[policy]=" .
|
||||
substr(rawurlencode($options["initial_ACL_policy"]), 0, 1) .
|
||||
"' " .
|
||||
"--data 'd[license]=" .
|
||||
explode(":", rawurlencode($options["content_license"])[0]) .
|
||||
"' " .
|
||||
"--data submit=";
|
||||
|
||||
exec($cmd, $output, $return_var);
|
||||
if ($return_var > 0) {
|
||||
throw new \Exception(implode(PHP_EOL, $output));
|
||||
}
|
||||
// remove temp folder
|
||||
$this->appcontext->runUser("v-delete-fs-file", [$this->getDocRoot("install.php")], $status);
|
||||
$this->cleanup();
|
||||
|
||||
return $status->code === 0;
|
||||
}
|
||||
}
|
||||
586
web/src/app/WebApp/Installers/DokuWiki/dokuwiki-logo.svg
Normal file
@@ -0,0 +1,586 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="128.17094"
|
||||
height="128.03864"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.1 "
|
||||
sodipodi:docname="dokuwiki-logo.svg"
|
||||
version="1.1">
|
||||
<title
|
||||
id="title3181">DokuWiki Logo</title>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient2624">
|
||||
<stop
|
||||
style="stop-color:#3a9030;stop-opacity:0.83673471;"
|
||||
offset="0"
|
||||
id="stop2626" />
|
||||
<stop
|
||||
style="stop-color:#3d9c32;stop-opacity:0.79591835;"
|
||||
offset="1"
|
||||
id="stop2628" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2612">
|
||||
<stop
|
||||
style="stop-color:#25901b;stop-opacity:0.83673471;"
|
||||
offset="0"
|
||||
id="stop2614" />
|
||||
<stop
|
||||
style="stop-color:#25901b;stop-opacity:0.37755102;"
|
||||
offset="1"
|
||||
id="stop2616" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2600">
|
||||
<stop
|
||||
style="stop-color:#e32525;stop-opacity:0.81632656;"
|
||||
offset="0"
|
||||
id="stop2602" />
|
||||
<stop
|
||||
style="stop-color:#e32525;stop-opacity:0.5714286;"
|
||||
offset="1"
|
||||
id="stop2604" />
|
||||
</linearGradient>
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutL"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="TriangleOutL"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path2488"
|
||||
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||
transform="scale(0.8,0.8)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path2571"
|
||||
style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(1.1,0,0,1.1,-5.5,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<linearGradient
|
||||
id="linearGradient2408">
|
||||
<stop
|
||||
id="stop2410"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:0.17346939;" />
|
||||
<stop
|
||||
id="stop2412"
|
||||
offset="1"
|
||||
style="stop-color:#c7cec2;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2389">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.17346939;"
|
||||
offset="0"
|
||||
id="stop2391" />
|
||||
<stop
|
||||
style="stop-color:#c7cec2;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2393" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2370">
|
||||
<stop
|
||||
style="stop-color:#fbfaf9;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2372" />
|
||||
<stop
|
||||
style="stop-color:#e9dac7;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2374" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2364">
|
||||
<stop
|
||||
id="stop2366"
|
||||
offset="0"
|
||||
style="stop-color:#fbf6f0;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2368"
|
||||
offset="1"
|
||||
style="stop-color:#e9dac7;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2348">
|
||||
<stop
|
||||
style="stop-color:#fbf6f0;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2350" />
|
||||
<stop
|
||||
style="stop-color:#e9dac7;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2352" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2332">
|
||||
<stop
|
||||
style="stop-color:#ede1ae;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2334" />
|
||||
<stop
|
||||
style="stop-color:#fefdfa;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2336" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2249">
|
||||
<stop
|
||||
style="stop-color:#00a423;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2251" />
|
||||
<stop
|
||||
style="stop-color:#00b427;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2253" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2229">
|
||||
<stop
|
||||
id="stop2231"
|
||||
offset="0"
|
||||
style="stop-color:#00b62b;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2233"
|
||||
offset="1"
|
||||
style="stop-color:#a1d784;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2213">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2215" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2217" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2360">
|
||||
<stop
|
||||
style="stop-color:#d69c00;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2362" />
|
||||
<stop
|
||||
style="stop-color:#ffe658;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2364" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2352">
|
||||
<stop
|
||||
id="stop2354"
|
||||
offset="0"
|
||||
style="stop-color:#ce411e;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2356"
|
||||
offset="1"
|
||||
style="stop-color:#ecad8d;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2336">
|
||||
<stop
|
||||
style="stop-color:#8f2a15;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2338" />
|
||||
<stop
|
||||
style="stop-color:#c8381b;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2340" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2336"
|
||||
id="linearGradient2342"
|
||||
x1="219.21262"
|
||||
y1="189.01556"
|
||||
x2="286.22665"
|
||||
y2="189.01556"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2352"
|
||||
id="linearGradient2350"
|
||||
x1="219.66267"
|
||||
y1="192.73286"
|
||||
x2="277.8761"
|
||||
y2="192.73286"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2360"
|
||||
id="radialGradient2366"
|
||||
cx="224.41418"
|
||||
cy="212.80016"
|
||||
fx="224.41418"
|
||||
fy="212.80016"
|
||||
r="8.6813803"
|
||||
gradientTransform="matrix(1,0,0,0.984179,0,3.366635)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2249"
|
||||
id="linearGradient2227"
|
||||
x1="192.03938"
|
||||
y1="262.25757"
|
||||
x2="263.67093"
|
||||
y2="262.25757"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2229"
|
||||
id="linearGradient2247"
|
||||
x1="191.75092"
|
||||
y1="258.91571"
|
||||
x2="255.6561"
|
||||
y2="258.91571"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2360"
|
||||
id="radialGradient2317"
|
||||
cx="257.41144"
|
||||
cy="274.64203"
|
||||
fx="257.41144"
|
||||
fy="274.64203"
|
||||
r="7.1440549"
|
||||
gradientTransform="matrix(1,0,0,1.631384,0,-173.4045)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2360"
|
||||
id="linearGradient2325"
|
||||
x1="184.07063"
|
||||
y1="246.35907"
|
||||
x2="201.40646"
|
||||
y2="246.35907"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2332"
|
||||
id="linearGradient2346"
|
||||
x1="162.76369"
|
||||
y1="184.99277"
|
||||
x2="240.84924"
|
||||
y2="289.50323"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2348"
|
||||
id="linearGradient2354"
|
||||
x1="140.15784"
|
||||
y1="303.78967"
|
||||
x2="136.14151"
|
||||
y2="195.87151"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2370"
|
||||
id="linearGradient2362"
|
||||
x1="286.15598"
|
||||
y1="262.28729"
|
||||
x2="185.81258"
|
||||
y2="172.32423"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2389"
|
||||
id="linearGradient2395"
|
||||
x1="213.96568"
|
||||
y1="220.07191"
|
||||
x2="244.79126"
|
||||
y2="265.40363"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2408"
|
||||
id="linearGradient2406"
|
||||
x1="184.30582"
|
||||
y1="241.52789"
|
||||
x2="224.67441"
|
||||
y2="307.52844"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2600"
|
||||
id="linearGradient2606"
|
||||
x1="202.41772"
|
||||
y1="222.05145"
|
||||
x2="206.06017"
|
||||
y2="210.3558"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2612"
|
||||
id="linearGradient2618"
|
||||
x1="248.62152"
|
||||
y1="234.52202"
|
||||
x2="251.64362"
|
||||
y2="213.12164"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2624"
|
||||
id="linearGradient2630"
|
||||
x1="275.71765"
|
||||
y1="251.56442"
|
||||
x2="255.68353"
|
||||
y2="217.94008"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2352"
|
||||
id="linearGradient2640"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="219.66267"
|
||||
y1="192.73286"
|
||||
x2="277.8761"
|
||||
y2="192.73286" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2336"
|
||||
id="linearGradient2643"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="219.21262"
|
||||
y1="189.01556"
|
||||
x2="286.22665"
|
||||
y2="189.01556" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2360"
|
||||
id="radialGradient2647"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.984179,0,3.366635)"
|
||||
cx="224.41418"
|
||||
cy="212.80016"
|
||||
fx="224.41418"
|
||||
fy="212.80016"
|
||||
r="8.6813803" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.03"
|
||||
inkscape:cx="35.144424"
|
||||
inkscape:cy="83.160427"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer3"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="716"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:showpageshadow="false"
|
||||
showborder="true"
|
||||
borderlayer="false" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>DokuWiki Logo</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Esther Brunner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<cc:license
|
||||
rdf:resource="http://www.gnu.org/licenses/gpl-2.0.html" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="paper"
|
||||
style="display:inline"
|
||||
transform="translate(-158.10602,-158.67323)">
|
||||
<g
|
||||
id="g1419"
|
||||
transform="matrix(0.99993322,0,0,0.9959778,0.01483419,0.8957919)">
|
||||
<g
|
||||
id="g2376">
|
||||
<path
|
||||
transform="matrix(0.989976,-0.141236,0.201069,0.979577,0,0)"
|
||||
style="fill:url(#linearGradient2354);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.7216621px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m 120.21543,196.43769 70.90655,-0.79226 -2.40261,109.05308 -71.71761,0.37344 3.21367,-108.63426 z"
|
||||
id="rect1422"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2362);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m 179.20033,182.08731 79.84173,-19.51687 26.61391,101.72428 -82.50312,21.58684 -23.95252,-103.79425 z"
|
||||
id="rect1425"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
transform="matrix(0.995676,-0.09289891,0.08102261,0.996712,0,0)"
|
||||
style="fill:url(#linearGradient2346);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00418305px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m 159.01353,181.74387 85.58587,0.53396 0,110.47429 -84.53387,-2.5127 -1.052,-108.49555 z"
|
||||
id="rect1419"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
id="text2382"
|
||||
d="m 167.55116,214.00773 0,-20.1846 5.34962,0 0,2.37403 -2.48145,0 0,15.43654 2.48145,0 0,2.37403 -5.34962,0 m 7.34767,0 0,-20.1846 5.34961,0 0,2.37403 -2.48144,0 0,15.43654 2.48144,0 0,2.37403 -5.34961,0 m 7.36915,-20.1846 5.81153,0 c 1.31054,2e-5 2.30956,0.10028 2.99707,0.30078 0.92382,0.27216 1.71516,0.75555 2.37403,1.4502 0.65884,0.69468 1.16014,1.54689 1.50391,2.55664 0.34373,1.00262 0.51561,2.24155 0.51562,3.71681 -10e-6,1.29623 -0.16115,2.41342 -0.4834,3.35156 -0.39389,1.14584 -0.95607,2.07325 -1.68652,2.78223 -0.55145,0.53711 -1.29624,0.95606 -2.23438,1.25684 -0.70183,0.222 -1.63999,0.33301 -2.81446,0.33301 l -5.9834,0 0,-15.74807 m 3.17969,2.66407 0,10.43067 2.37402,0 c 0.88802,1e-5 1.52897,-0.0501 1.92286,-0.15039 0.51561,-0.1289 0.94172,-0.34732 1.27832,-0.65527 0.34374,-0.30794 0.62304,-0.81282 0.83789,-1.51465 0.21483,-0.70898 0.32226,-1.6722 0.32227,-2.88965 -1e-5,-1.21744 -0.10744,-2.15201 -0.32227,-2.80372 -0.21485,-0.65168 -0.51563,-1.16014 -0.90234,-1.52539 -0.38673,-0.36522 -0.87729,-0.61229 -1.47168,-0.74121 -0.44402,-0.10025 -1.31414,-0.15038 -2.61036,-0.15039 l -1.42871,0 m 14.96388,13.084 -3.75977,-15.74807 3.25489,0 2.37403,10.8174 2.87891,-10.8174 3.78125,0 2.76074,11.00002 2.417,-11.00002 3.20118,0 -3.82423,15.74807 -3.37305,0 -3.13672,-11.77345 -3.12598,11.77345 -3.44825,0 m 22.76272,-15.74807 0,20.1846 -5.34961,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34961,0 m 7.34767,0 0,20.1846 -5.34962,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34962,0"
|
||||
style="font-size:12.0000124px;font-style:normal;font-weight:normal;line-height:125%;fill:#6184a3;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans"
|
||||
transform="matrix(0.995433,-0.09546066,0.09546066,0.995433,0,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g2632"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:url(#linearGradient2606);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker-end:none"
|
||||
d="m 174.75585,201.60224 c -6.04576,2.46667 -10.16789,4.4194 -12.88454,6.35064 -2.71665,1.93124 -3.19257,4.60007 -3.24631,6.26587 -0.0269,0.8329 0.0809,1.77774 0.63189,2.44014 0.55103,0.6624 1.80769,1.87421 2.75794,2.38558 1.90049,1.02274 7.5417,2.42901 10.51899,3.07308 11.90917,2.57627 26.80568,1.68117 26.80568,1.68117 1.69307,1.2452 2.83283,2.82434 3.269,4.26902 4.5766,-1.88674 11.81084,-6.58439 13.15657,-8.57706 -5.45142,-4.19955 -10.79692,-6.33346 -16.51317,-8.30847 -1.59867,-0.71918 -2.87956,-1.22649 -0.71773,2.55635 0.98506,2.47275 0.85786,5.05143 0.57176,7.41825 0,0 -16.52749,0.40678 -28.23838,-2.1266 -2.92772,-0.63334 -5.46627,-0.95523 -7.21875,-1.89832 -0.87624,-0.47154 -1.48296,-0.8208 -1.91578,-1.3411 -0.43282,-0.5203 -0.2196,-1.29055 -0.20128,-1.85858 0.0366,-1.13607 0.25336,-1.67063 2.86177,-3.52492 2.60841,-1.85429 5.65407,-3.36195 11.65936,-5.81211 -0.0877,-1.29125 -0.29025,-2.5059 -1.29702,-2.99294 z"
|
||||
id="path2414"
|
||||
sodipodi:nodetypes="csssssccccccssssscc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2618);fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 269.62539,220.7482 c -1.43576,-0.13963 -2.58044,0.30288 -2.56084,1.50218 0.94391,0.85652 1.34942,2.43518 1.48562,3.14008 0.1362,0.7049 0.0359,1.21914 -0.48562,1.89004 -1.043,1.3418 -3.12498,1.56875 -6.5006,2.72063 -6.75124,2.30377 -16.89306,2.52561 -27.90689,3.84639 -22.02767,2.64157 -39.03164,3.76107 -39.03164,3.76107 1.98346,-4.64758 6.32828,-4.41197 6.34903,-8.20969 0.27376,-0.89755 -3.14597,-1.31638 -5.09943,-0.10731 -4.26694,3.70137 -7.59152,6.75353 -10.69418,10.51311 l 1.88795,3.08438 c 0,0 26.13006,-2.88973 48.19776,-5.5361 11.03385,-1.32318 20.95601,-1.99856 27.80968,-4.33728 3.42683,-1.16936 5.95975,-1.49022 7.6409,-3.51958 0.63172,-0.76256 1.35238,-3.04699 1.06804,-4.73369 -0.21951,-1.30213 -1.14979,-3.09774 -2.15978,-4.01423 z"
|
||||
id="path2608"
|
||||
sodipodi:nodetypes="ccsssscccccssssc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2630);fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 254.36185,220.33948 c -6.84997,3.24198 -7.15311,8.60912 -5.95953,12.79884 1.19358,4.18972 5.26293,8.75677 9.32121,12.40608 8.11656,7.29861 12.06046,9.33163 12.06046,9.33163 -3.71515,-0.10342 -7.89887,-1.41174 -8.13315,0.49304 -0.9483,2.97582 11.49137,3.47486 17.43787,2.70205 -1.39456,-7.57836 -3.79323,-13.21546 -7.73151,-14.90312 -1.68464,-0.14804 0.31242,4.72441 0.76985,9.39604 0,0 -3.62454,-1.73122 -11.60519,-8.90762 -3.99032,-3.5882 -7.37386,-7.3421 -8.47319,-11.20099 -1.09933,-3.85889 0.0776,-6.1205 4.95082,-9.53176 0.92816,-0.99528 -1.28985,-2.45913 -2.63764,-2.58419 z"
|
||||
id="path2620"
|
||||
sodipodi:nodetypes="csscccccsscc"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
id="rect2386"
|
||||
d="m 213.96569,234.57806 2.18756,-14.42897 15.21982,6.08793 21.49387,29.94828 -20.40591,9.21832 -18.49534,-30.82556 z"
|
||||
style="fill:url(#linearGradient2395);fill-opacity:1;stroke:none;display:inline"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g2649"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:url(#radialGradient2647);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 232.55816,219.5295 -15.92827,0.32199 3.08809,-15.15716 12.84018,14.83517 z"
|
||||
id="path1443"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#812310;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 221.60041,219.29315 -4.41205,0.0782 0.85429,-3.98263 3.55776,3.90445 z"
|
||||
id="path1452"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2643);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 269.44172,159.27421 0.098,8.91471 8.0581,8.72344 7.75906,0.7992 -52.80669,41.84092 -6.66532,-3.30696 -5.08243,-5.618 -1.08987,-5.91194 49.72911,-45.44137 z"
|
||||
id="rect1437"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2640);fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 268.94766,168.32844 8.3426,8.82719 -51.1007,38.68262 -4.9197,-5.4436 47.6778,-42.06621 z"
|
||||
id="rect1446"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffe965;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;display:inline"
|
||||
d="m 285.33776,177.73216 -8.16219,-0.86619 -7.7518,-8.67862 0.0132,-9.14293 8.36213,0.75209 7.18862,9.57682 0.35007,8.35883 z"
|
||||
id="path1440"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#cb391c;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 280.72049,168.46367 0.1644,4.05654 -3.81335,-0.71676 -2.87504,-3.18901 -0.28089,-3.53393 3.85447,-0.16637 2.95041,3.54953 z"
|
||||
id="path1449"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g2657"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:url(#linearGradient2406);fill-opacity:1;stroke:none"
|
||||
d="m 183.88617,256.82796 0.99991,-16.30721 17.2878,8.44012 26.05488,38.00946 -29.28095,-1.13363 -15.06164,-29.00874 z"
|
||||
id="rect2397"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2325);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline"
|
||||
d="m 200.90647,238.44836 -8.04601,15.77386 -7.05577,-13.57337 15.10178,-2.20049 z"
|
||||
id="rect2207"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2227);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 201.05389,238.55401 62.11704,24.91912 -7.88689,3.21429 -4.35152,9.30976 1.1716,9.96396 -59.31453,-31.72759 -0.49402,-7.36382 3.09592,-5.82826 5.6624,-2.48746 z"
|
||||
id="rect1328"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#radialGradient2317);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline"
|
||||
d="m 255.27801,266.53504 7.9241,-3.04772 0.85337,10.24037 -3.9011,8.28983 -8.04601,3.77919 -1.341,-9.63083 4.51064,-9.63084 z"
|
||||
id="rect2204"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#linearGradient2247);fill-opacity:1;stroke:none;display:inline"
|
||||
d="m 195.7549,241.421 59.13059,24.7962 -4.5917,9.76614 -57.48995,-29.00967 2.95106,-5.55267 z"
|
||||
id="rect2210"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#00b527;fill-opacity:1;stroke:none"
|
||||
d="m 255.02263,275.21029 2.08411,-4.1069 2.96459,-1.06995 0.69433,3.37197 -1.76759,3.85723 -3.15516,1.38315 -0.82028,-3.4355 z"
|
||||
id="rect2308"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#258209;fill-opacity:1;stroke:none;display:inline"
|
||||
d="m 186.56849,241.00362 3.54963,-0.47312 -2.02297,3.53926 -1.52666,-3.06614 z"
|
||||
id="rect2327"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 24 KiB |
89
web/src/app/WebApp/Installers/Drupal/DrupalSetup.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Drupal;
|
||||
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class DrupalSetup extends BaseSetup {
|
||||
protected $appname = "drupal";
|
||||
|
||||
protected $appInfo = [
|
||||
"name" => "Drupal",
|
||||
"group" => "cms",
|
||||
"enabled" => "yes",
|
||||
"version" => "latest",
|
||||
"thumbnail" => "drupal-thumb.png",
|
||||
];
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"username" => ["type" => "text", "value" => "admin"],
|
||||
"password" => "password",
|
||||
"email" => "text",
|
||||
],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"composer" => ["src" => "drupal/recommended-project", "dst" => "/"],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "drupal-composer",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["8.1", "8.2"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null): bool {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
$this->appcontext->runComposer(
|
||||
["require", "-d " . $this->getDocRoot(), "drush/drush"],
|
||||
$status2,
|
||||
["version" => 2, "php_version" => $options["php_version"]],
|
||||
);
|
||||
|
||||
$htaccess_rewrite = '
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteRule ^(.*)$ web/$1 [L]
|
||||
</IfModule>';
|
||||
|
||||
$tmp_configpath = $this->saveTempFile($htaccess_rewrite);
|
||||
$this->appcontext->runUser(
|
||||
"v-move-fs-file",
|
||||
[$tmp_configpath, $this->getDocRoot(".htaccess")],
|
||||
$result,
|
||||
);
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("/vendor/drush/drush/drush"),
|
||||
"site-install",
|
||||
"standard",
|
||||
"--db-url=mysql://" .
|
||||
$this->appcontext->user() .
|
||||
"_" .
|
||||
$options["database_user"] .
|
||||
":" .
|
||||
$options["database_password"] .
|
||||
"@localhost:3306/" .
|
||||
$this->appcontext->user() .
|
||||
"_" .
|
||||
$options["database_name"] .
|
||||
"",
|
||||
"--account-name=" .
|
||||
$options["username"] .
|
||||
" --account-pass=" .
|
||||
$options["password"],
|
||||
"--site-name=Drupal",
|
||||
"--site-mail=" . $options["email"],
|
||||
],
|
||||
$status,
|
||||
);
|
||||
return $status->code === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/Drupal/drupal-thumb.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
214
web/src/app/WebApp/Installers/Flarum/FlarumSetup.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
namespace Hestia\WebApp\Installers\Flarum;
|
||||
|
||||
use Hestia\System\Util;
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class FlarumSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "Flarum",
|
||||
"group" => "forum",
|
||||
"enabled" => true,
|
||||
"version" => "latest",
|
||||
"thumbnail" => "fl-thumb.png",
|
||||
];
|
||||
|
||||
protected $appname = "flarum";
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"forum_title" => ["type" => "text", "value" => "Flarum Forum"],
|
||||
"admin_username" => ["value" => "fladmin"],
|
||||
"admin_email" => "text",
|
||||
"admin_password" => "password",
|
||||
"install_directory" => ["type" => "text", "value" => "", "placeholder" => "/"],
|
||||
],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"composer" => ["src" => "flarum/flarum"],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "flarum",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["8.0", "8.1", "8.2"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Our updateFile routine done the 'Hestia way'
|
||||
public function updateFile($file, $search, $replace) {
|
||||
$result = null;
|
||||
$this->appcontext->runUser("v-open-fs-file", [$file], $result);
|
||||
foreach ($result->raw as $line_num => $line) {
|
||||
if (strpos($line, $search) !== false) {
|
||||
$result->raw[$line_num] = str_replace($search, $replace, $line);
|
||||
}
|
||||
}
|
||||
$tmp = $this->saveTempFile(implode("\r\n", $result->raw));
|
||||
if (!$this->appcontext->runUser("v-move-fs-file", [$tmp, $file], $result)) {
|
||||
throw new \Exception("Error updating file in: " . $tmp . " " . $result->text);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function install(array $options = null): bool {
|
||||
parent::setAppDirInstall($options["install_directory"]);
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
$result = null;
|
||||
|
||||
// Move public folder content (https://docs.flarum.org/install/#customizing-paths)
|
||||
if (
|
||||
!$this->appcontext->runUser(
|
||||
"v-list-fs-directory",
|
||||
[$this->getDocRoot("public")],
|
||||
$result,
|
||||
)
|
||||
) {
|
||||
throw new \Exception(
|
||||
"Error listing folder at: " . $this->getDocRoot("public") . $result->text,
|
||||
);
|
||||
}
|
||||
foreach ($result->raw as $line_num => $line) {
|
||||
$detail = explode("|", $line);
|
||||
$type = $detail[0];
|
||||
$name = end($detail);
|
||||
if ($name != "") {
|
||||
if ($type == "d") {
|
||||
// Directory
|
||||
if (
|
||||
!$this->appcontext->runUser(
|
||||
"v-move-fs-directory",
|
||||
[
|
||||
$this->getDocRoot("public") . "/" . $name,
|
||||
$this->getDocRoot() . "/" . $name,
|
||||
],
|
||||
$result,
|
||||
)
|
||||
) {
|
||||
throw new \Exception(
|
||||
"Error moving folder at: " .
|
||||
$this->getDocRoot("public") .
|
||||
"/" .
|
||||
$name .
|
||||
$result->text,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
!$this->appcontext->runUser(
|
||||
"v-move-fs-file",
|
||||
[
|
||||
$this->getDocRoot("public") . "/" . $name,
|
||||
$this->getDocRoot() . "/" . $name,
|
||||
],
|
||||
$result,
|
||||
)
|
||||
) {
|
||||
throw new \Exception(
|
||||
"Error moving file at: " .
|
||||
$this->getDocRoot("public") .
|
||||
"/" .
|
||||
$name .
|
||||
$result->text,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
!$this->appcontext->runUser(
|
||||
"v-delete-fs-directory",
|
||||
[$this->getDocRoot("public")],
|
||||
$result,
|
||||
)
|
||||
) {
|
||||
throw new \Exception(
|
||||
"Error deleting folder at: " . $this->getDocRoot("public") . $result->text,
|
||||
);
|
||||
}
|
||||
|
||||
// Not using 'public'; enable protection rewrite rules and update paths
|
||||
$result = $this->updateFile(
|
||||
$this->getDocRoot(".htaccess"),
|
||||
"# RewriteRule ",
|
||||
"RewriteRule ",
|
||||
);
|
||||
$result = $this->updateFile(
|
||||
$this->getDocRoot("index.php"),
|
||||
'$site = require \'../site.php\';',
|
||||
'$site = require \'./site.php\';',
|
||||
);
|
||||
$result = $this->updateFile(
|
||||
$this->getDocRoot("site.php"),
|
||||
"'public' => __DIR__.'/public',",
|
||||
"'public' => __DIR__,",
|
||||
);
|
||||
|
||||
// POST install
|
||||
$this->appcontext->run(
|
||||
"v-list-web-domain",
|
||||
[$this->appcontext->user(), $this->domain, "json"],
|
||||
$status,
|
||||
);
|
||||
$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
|
||||
$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain;
|
||||
$webPort = $sslEnabled ? "443" : "80";
|
||||
|
||||
$mysql_host = "localhost";
|
||||
$mysql_database = addcslashes(
|
||||
$this->appcontext->user() . "_" . $options["database_name"],
|
||||
"\\'",
|
||||
);
|
||||
$mysql_username = addcslashes(
|
||||
$this->appcontext->user() . "_" . $options["database_user"],
|
||||
"\\'",
|
||||
);
|
||||
$mysql_password = addcslashes($options["database_password"], "\\'");
|
||||
$table_prefix = addcslashes(Util::generate_string(5, false) . "_", "\\'");
|
||||
$subfolder = $options["install_directory"];
|
||||
if (substr($subfolder, 0, 1) != "/") {
|
||||
$subfolder = "/" . $subfolder;
|
||||
}
|
||||
|
||||
$cmd =
|
||||
"/usr/bin/curl --location --post301 --insecure --resolve " .
|
||||
$this->domain .
|
||||
":$webPort:" .
|
||||
$this->appcontext->getWebDomainIp($this->domain) .
|
||||
" " .
|
||||
escapeshellarg($webDomain . $subfolder . "/index.php") .
|
||||
" -d " .
|
||||
escapeshellarg(
|
||||
"forumTitle=" .
|
||||
rawurlencode($options["forum_title"]) .
|
||||
"&mysqlHost=" .
|
||||
rawurlencode($mysql_host) .
|
||||
"&mysqlDatabase=" .
|
||||
rawurlencode($mysql_database) .
|
||||
"&mysqlUsername=" .
|
||||
rawurlencode($mysql_username) .
|
||||
"&mysqlPassword=" .
|
||||
rawurlencode($mysql_password) .
|
||||
"&tablePrefix=" .
|
||||
rawurlencode($table_prefix) .
|
||||
"&adminUsername=" .
|
||||
rawurlencode($options["admin_username"]) .
|
||||
"&adminEmail=" .
|
||||
rawurlencode($options["admin_email"]) .
|
||||
"&adminPassword=" .
|
||||
rawurlencode($options["admin_password"]) .
|
||||
"&adminPasswordConfirmation=" .
|
||||
rawurlencode($options["admin_password"]),
|
||||
);
|
||||
exec($cmd, $output, $return_var);
|
||||
|
||||
// Report any errors
|
||||
if ($return_var > 0) {
|
||||
throw new \Exception(implode(PHP_EOL, $output));
|
||||
}
|
||||
return $result->code === 0 && $return_var === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/Flarum/fl-thumb.png
Executable file
|
After Width: | Height: | Size: 9.8 KiB |
76
web/src/app/WebApp/Installers/Grav/GravSetup.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Grav;
|
||||
|
||||
use Hestia\System\Util;
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class GravSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "Grav",
|
||||
"group" => "cms",
|
||||
"enabled" => true,
|
||||
"version" => "latest",
|
||||
"thumbnail" => "grav-symbol.svg",
|
||||
];
|
||||
|
||||
protected $appname = "grav";
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"admin" => ["type" => "boolean", "value" => false, "label" => "Create admin account"],
|
||||
"username" => ["text" => "admin"],
|
||||
"password" => "password",
|
||||
"email" => "text",
|
||||
],
|
||||
"database" => false,
|
||||
"resources" => [
|
||||
"composer" => ["src" => "getgrav/grav", "dst" => "/"],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "grav",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["7.4", "8.0", "8.1"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null) {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
|
||||
if ($options["admin"] == true) {
|
||||
chdir($this->getDocRoot());
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("/bin/gpm"),
|
||||
"install admin",
|
||||
],
|
||||
$status,
|
||||
);
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("/bin/plugin"),
|
||||
"login new-user",
|
||||
"-u " . $options["username"],
|
||||
"-p " . $options["password"],
|
||||
"-e " . $options["email"],
|
||||
"-P a",
|
||||
"-N " . $options["username"],
|
||||
"-l en",
|
||||
],
|
||||
$status,
|
||||
);
|
||||
return $status->code === 0;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
web/src/app/WebApp/Installers/Grav/grav-symbol.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg id="Grav-logo.fw-Page%201" viewBox="0 0 186 186" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" x="0px" y="0px" width="186px" height="186px">
|
||||
<g id="Layer_1_1">
|
||||
<g>
|
||||
<path d="M 98.4134 69.506 C 99.4991 68.4215 99.4991 66.6638 98.4134 65.5802 C 97.3273 64.4957 95.5692 64.4957 94.4835 65.5802 C 93.3973 66.6638 93.3973 68.4215 94.4835 69.506 C 95.5692 70.5895 97.3273 70.5895 98.4134 69.506 Z" fill="#221e1f"/>
|
||||
<path d="M 88.6113 71.4462 C 87.5251 72.5297 87.5251 74.2875 88.6113 75.372 C 89.6955 76.4555 91.4551 76.4555 92.5412 75.372 C 93.6254 74.2875 93.6254 72.5297 92.5412 71.4462 C 91.4551 70.3617 89.6955 70.3617 88.6113 71.4462 Z" fill="#221e1f"/>
|
||||
<path d="M 105.6614 72.8903 C 103.9628 71.193 101.2094 71.1945 99.5118 72.8903 L 95.8949 76.5033 C 94.1958 78.2006 94.1958 80.9511 95.8949 82.6464 L 99.8659 86.6146 C 101.5644 88.3119 104.3179 88.3104 106.0155 86.6146 L 109.6324 83.0016 C 111.331 81.3043 111.331 78.5538 109.6324 76.857 L 105.6614 72.8903 Z" fill="#221e1f"/>
|
||||
<path d="M 140.0328 59.4342 C 144.622 50.7036 138.1301 45.604 133.6678 41.4182 C 126.5199 34.7063 119.3906 31.8046 111.2479 41.0982 C 103.1106 50.3923 108.2806 61.171 115.7239 66.4911 C 123.1706 71.8111 135.4371 68.1624 140.0328 59.4342 ZM 127.7032 55.8539 C 124.8355 52.4203 130.1964 46.1865 133.5598 49.9089 C 139.7549 56.7671 130.5759 59.2874 127.7032 55.8539 Z" fill="#221e1f"/>
|
||||
<path d="M 92.7791 0.6418 C 41.5387 0.6418 0 42.1363 0 93.3177 C 0 144.503 41.5387 186 92.7791 186 C 144.0164 186 185.5547 144.503 185.5547 93.3177 C 185.5547 42.1363 144.0164 0.6418 92.7791 0.6418 ZM 142.9489 108.5071 C 133.2741 102.1201 127.7457 96.7234 122.9299 87.0473 C 119.6367 93.6768 111.9473 103.5349 98.9765 111.2898 C 92.5012 131.4129 61.6979 169.9242 51.7287 164.4651 C 48.7769 162.8503 48.2163 160.7232 48.8829 158.5289 C 49.5979 153.0278 60.9897 140.3846 60.9897 140.3846 C 60.9897 140.3846 61.2305 143.0375 64.8748 148.6264 C 60.0613 133.699 72.828 115.2805 76.21 109.0106 C 81.5244 107.3187 81.9093 100.5024 81.9093 100.5024 C 82.2492 89.9662 77.5378 82.3381 72.972 77.7761 C 76.2524 81.7756 77.3142 87.8196 77.47 93.3548 C 77.47 93.3631 77.47 93.3743 77.47 93.3856 C 77.4866 94.011 77.4866 94.6247 77.4841 95.2365 C 77.3283 99.8184 75.9409 106.1478 72.972 106.1478 L 72.9808 106.1878 C 69.9285 106.0571 66.1602 106.7079 62.7933 107.7597 L 55.35 109.5365 C 55.35 109.5365 59.3195 109.355 61.463 111.205 C 59.0758 115.0883 53.7701 119.9073 47.8524 122.6451 C 39.2424 126.6339 36.7678 118.6974 41.1393 113.5359 C 42.2127 112.2743 43.2969 111.2108 44.322 110.3395 C 43.6622 109.6575 43.2461 108.7442 43.1367 107.5851 C 43.1357 107.5792 43.1313 107.5734 43.1299 107.5675 C 42.5297 104.9341 42.8608 101.5152 46.591 96.0814 C 47.3275 94.9311 48.2104 93.7519 49.2682 92.5542 C 49.302 92.5132 49.3303 92.4752 49.3645 92.4352 C 49.4099 92.3801 49.4607 92.3279 49.5076 92.2742 C 49.5344 92.2444 49.5598 92.2147 49.5881 92.1835 C 49.8543 91.881 50.1376 91.5854 50.4404 91.3 C 54.8855 86.7517 61.9074 82.0215 72.972 77.7761 C 85.8759 58.8293 90.6014 55.2753 90.6014 55.2753 C 92.0299 53.8161 94.5269 52.0018 95.4446 51.5393 C 88.706 39.8425 87.3454 23.3534 89.1109 18.91 C 88.9678 19.1506 88.8364 19.3964 88.727 19.6511 C 89.3814 18.1295 89.82 17.6402 90.4998 16.8396 C 92.34 14.6647 98.5775 13.5251 100.8172 18.1324 C 102.0103 20.5887 102.2355 23.7705 102.1959 26.1562 C 97.2565 25.899 92.7761 31.5328 92.7761 31.5328 C 92.7761 31.5328 96.8672 29.6043 101.9498 29.5702 C 101.9498 29.5702 103.3045 30.7469 104.9948 32.9569 C 102.7126 37.2378 98.9609 46.3065 101.6777 55.827 C 102.128 57.7033 102.8088 59.3157 103.6542 60.6875 C 103.6864 60.7466 103.7133 60.8061 103.746 60.8671 C 103.8139 60.9559 103.8749 61.0295 103.9384 61.1115 C 108.4305 67.8673 116.664 68.6576 116.664 68.6576 C 112.7878 66.7257 109.6309 63.6488 107.5753 59.9182 C 106.5068 57.9229 105.8524 56.2383 105.4504 54.9094 C 103.2703 46.4978 106.4799 41.5875 108.3172 38.2955 C 112.5446 31.745 120.2458 27.7797 128.5232 28.7242 C 140.1402 30.0483 148.4841 40.5298 147.1562 52.1315 C 146.3465 59.2196 142.1137 65.0826 136.2982 68.2732 C 137.6969 72.0546 136.202 76.6394 136.202 76.6394 C 139.7241 81.0652 139.8794 83.6167 139.7578 85.9867 C 135.2814 85.2345 130.9324 88.2523 130.9324 88.2523 C 130.9324 88.2523 139.5683 86.1931 144.5854 90.6633 C 147.8482 94.169 150.0244 97.3372 151.3211 99.6769 C 153.1784 103.0139 161.8026 103.2519 160.8204 109.2535 C 159.8378 115.2463 153.2604 115.3029 142.9489 108.5071 Z" fill="#221e1f"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
55
web/src/app/WebApp/Installers/Laravel/LaravelSetup.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Laravel;
|
||||
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class LaravelSetup extends BaseSetup {
|
||||
protected $appname = "laravel";
|
||||
|
||||
protected $appInfo = [
|
||||
"name" => "Laravel",
|
||||
"group" => "framework",
|
||||
"enabled" => true,
|
||||
"version" => "10.x",
|
||||
"thumbnail" => "laravel-thumb.png",
|
||||
];
|
||||
|
||||
protected $config = [
|
||||
"form" => [],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"composer" => ["src" => "laravel/laravel", "dst" => "/"],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "laravel",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["8.1", "8.2"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null): bool {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
|
||||
$result = null;
|
||||
|
||||
$htaccess_rewrite = '
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteRule ^(.*)$ public/$1 [L]
|
||||
</IfModule>';
|
||||
|
||||
$tmp_configpath = $this->saveTempFile($htaccess_rewrite);
|
||||
$this->appcontext->runUser(
|
||||
"v-move-fs-file",
|
||||
[$tmp_configpath, $this->getDocRoot(".htaccess")],
|
||||
$result,
|
||||
);
|
||||
|
||||
return $result->code === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/Laravel/laravel-thumb.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,53 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="270" height="300" viewBox="0 0 270 300">
|
||||
<defs>
|
||||
<linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="24" x2="246" y1="238" y2="16">
|
||||
<stop offset="0%" stop-color="#0a00b2"/>
|
||||
<stop offset="50%" stop-color="#ff0000"/>
|
||||
<stop offset="100%" stop-color="#fffc00"/>
|
||||
</linearGradient>
|
||||
<style>
|
||||
.wordmark {
|
||||
fill: #000000;
|
||||
}
|
||||
.petal {
|
||||
opacity: 0.65;
|
||||
}
|
||||
.petals {
|
||||
fill: url(#gradient);
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path id="wordmark" class="wordmark" d="M51.242,283.882l-0.046-35.7H46.274L33.716,271.845,20.928,248.178H16.006v35.7h5.7v-23.36L32.289,279.8h2.668l10.58-19.585,0.046,23.666h5.658Zm30.313-13.465a16.339,16.339,0,0,0-1.587-7.371,11.726,11.726,0,0,0-10.833-6.707A12.1,12.1,0,0,0,58.072,263.1a15.488,15.488,0,0,0-1.633,7.166,15.245,15.245,0,0,0,1.679,7.218,12.194,12.194,0,0,0,4.761,4.973,15.1,15.1,0,0,0,12.834.663A10.484,10.484,0,0,0,79.9,279.8l-3.082-3.927a8.521,8.521,0,0,1-6.67,2.958,8.086,8.086,0,0,1-5.313-1.759,7.558,7.558,0,0,1-2.645-4.769H81.463q0.092-1.224.092-1.887h0Zm-12.42-8.977a6.462,6.462,0,0,1,4.692,1.836,7.809,7.809,0,0,1,2.254,4.794H62.143a7.89,7.89,0,0,1,2.323-4.82,6.534,6.534,0,0,1,4.669-1.81h0Zm35.328-15.4v13.976a9.068,9.068,0,0,0-3.45-2.755,10.682,10.682,0,0,0-4.462-.918,11.775,11.775,0,0,0-10.81,6.631,17.384,17.384,0,0,0,0,14.613,11.74,11.74,0,0,0,10.81,6.656,10.891,10.891,0,0,0,4.623-.969,9.033,9.033,0,0,0,3.519-2.908v3.52h5.52V246.036h-5.75Zm-7.222,32.745a6.833,6.833,0,0,1-3.726-1.045,7.251,7.251,0,0,1-2.622-2.984,10.911,10.911,0,0,1,0-8.977,7.264,7.264,0,0,1,2.622-2.984,7.166,7.166,0,0,1,7.452,0,7.264,7.264,0,0,1,2.622,2.984,10.911,10.911,0,0,1,0,8.977,7.251,7.251,0,0,1-2.622,2.984,6.835,6.835,0,0,1-3.726,1.045h0Zm19.6,5.1h5.75V256.645h-5.75v27.237Zm21.758-27.543a18.782,18.782,0,0,0-5.75.867,13.457,13.457,0,0,0-4.646,2.5l2.254,4.641a9.726,9.726,0,0,1,3.381-1.989,12.032,12.032,0,0,1,4.071-.714,6.239,6.239,0,0,1,4.577,1.53,5.912,5.912,0,0,1,1.541,4.386v0.408h-6.348q-5.291,0-7.751,2.219a7.545,7.545,0,0,0-2.461,5.891,7.959,7.959,0,0,0,1.127,4.208,7.678,7.678,0,0,0,3.2,2.907,10.581,10.581,0,0,0,4.83,1.046,10.77,10.77,0,0,0,4.715-.944,6.892,6.892,0,0,0,3.013-2.729v3.316h5.428V267.917q0-5.814-2.875-8.7t-8.3-2.882h0ZM137.812,279.6a5.281,5.281,0,0,1-3.45-1.02,3.378,3.378,0,0,1-1.242-2.754q0-3.621,4.968-3.621h5.934v3.162a5.86,5.86,0,0,1-2.369,3.137,6.869,6.869,0,0,1-3.841,1.1h0Zm60.306-31.419-8.234,27.288-8.142-27.288h-5.52L167.9,275.313l-8-27.135h-6.21l10.672,35.7h6.394l8.1-26.421,7.958,26.421h6.348l10.672-35.7h-5.7Zm9.338,35.7h5.75V256.645h-5.75v27.237Zm30.911,0h6.992L234.135,268.07l10.258-11.425h-6.9l-11.914,12.241v-22.85h-5.75v37.846h5.75V276.69l4.278-4.488Zm9.568,0h5.75V256.645h-5.75v27.237Zm-128.2-30.857a3.567,3.567,0,0,0,2.645-1.043,3.513,3.513,0,0,0,1.035-2.574,3.073,3.073,0,0,0-1.058-2.388,3.781,3.781,0,0,0-2.622-.95,3.677,3.677,0,0,0-2.622,1,3.437,3.437,0,0,0,0,4.961,3.677,3.677,0,0,0,2.622,1h0Zm90.62,0A3.569,3.569,0,0,0,213,251.982a3.513,3.513,0,0,0,1.035-2.574,3.077,3.077,0,0,0-1.058-2.388,3.784,3.784,0,0,0-2.622-.95,3.674,3.674,0,0,0-2.622,1,3.437,3.437,0,0,0,0,4.961,3.674,3.674,0,0,0,2.622,1h0Zm40.479,0a3.569,3.569,0,0,0,2.645-1.043,3.513,3.513,0,0,0,1.035-2.574,3.077,3.077,0,0,0-1.058-2.388,3.784,3.784,0,0,0-2.622-.95,3.674,3.674,0,0,0-2.622,1,3.437,3.437,0,0,0,0,4.961,3.674,3.674,0,0,0,2.622,1h0Z"/>
|
||||
<g id="petals" class="petals">
|
||||
<path class="petal" d="M103.283,45.02c-0.647,8.246.645,16.05,5.16,23.1a23.041,23.041,0,0,0,13.04,9.63,5.672,5.672,0,0,0,4.719-1.153c6.093-5.8,9.031-12.89,8-21.625-1.829-15.522-11.06-26.108-22.808-36.2C106.826,27.538,104,35.917,103.283,45.02Z"/>
|
||||
<path class="petal" d="M86.913,53.254c1.081,8.2,3.968,15.565,9.849,21.519a23.04,23.04,0,0,0,14.757,6.709,5.673,5.673,0,0,0,4.376-2.109c4.754-6.944,6.154-14.486,3.331-22.816-5.016-14.8-16.246-23.238-29.836-30.668C86.743,35.417,85.719,44.2,86.913,53.254Z"/>
|
||||
<path class="petal" d="M72.611,64.711c2.762,7.8,7.117,14.4,14.108,19a23.04,23.04,0,0,0,15.83,3.494,5.673,5.673,0,0,0,3.842-2.973c3.206-7.78,3.007-15.449-1.486-23.01C96.921,47.786,84.183,41.87,69.345,37.429,68.737,47.3,69.561,56.1,72.611,64.711Z"/>
|
||||
<path class="petal" d="M61,78.891c4.323,7.052,9.955,12.605,17.75,15.653a23.04,23.04,0,0,0,16.21.126A5.671,5.671,0,0,0,98.1,90.963c1.519-8.277-.27-15.737-6.237-22.2-10.6-11.483-24.293-14.621-39.73-15.881C53.595,62.666,56.232,71.107,61,78.891Z"/>
|
||||
<path class="petal" d="M52.6,95.174c5.694,6,12.358,10.26,20.617,11.62A23.038,23.038,0,0,0,89.1,103.548a5.673,5.673,0,0,0,2.3-4.279c-0.235-8.412-3.536-15.337-10.716-20.416-12.759-9.028-26.8-9.251-42.164-7.274C41.979,80.844,46.313,88.552,52.6,95.174Z"/>
|
||||
<path class="petal" d="M47.764,112.849c6.817,4.684,14.222,7.467,22.582,7.08a23.035,23.035,0,0,0,14.86-6.478,5.671,5.671,0,0,0,1.36-4.663c-1.979-8.179-6.647-14.266-14.727-17.742C57.483,84.868,43.7,87.57,29.086,92.7,34.4,101.041,40.238,107.679,47.764,112.849Z"/>
|
||||
<path class="petal" d="M46.709,131.144c7.642,3.164,15.463,4.346,23.561,2.23a23.043,23.043,0,0,0,13.189-9.426,5.671,5.671,0,0,0,.361-4.844c-3.636-7.589-9.468-12.573-18.094-14.293-15.328-3.058-28.248,2.45-41.477,10.5C31.178,122.373,38.273,127.651,46.709,131.144Z"/>
|
||||
<path class="petal" d="M49.481,149.257c8.133,1.506,16.029,1.037,23.509-2.717a23.041,23.041,0,0,0,10.941-11.962,5.67,5.67,0,0,0-.654-4.813c-5.135-6.667-11.876-10.33-20.67-10.219-15.629.2-27.121,8.27-38.386,18.9C32.465,143.907,40.5,147.6,49.481,149.257Z"/>
|
||||
<path class="petal" d="M55.958,166.4c8.268-.218,15.894-2.319,22.431-7.546A23.037,23.037,0,0,0,86.6,144.878a5.67,5.67,0,0,0-1.64-4.572c-6.409-5.454-13.764-7.635-22.343-5.7C47.374,138.049,37.811,148.336,29,161.075,38.2,164.7,46.83,166.64,55.958,166.4Z"/>
|
||||
<path class="petal" d="M65.857,181.82c8.042-1.933,15.065-5.573,20.372-12.045A23.039,23.039,0,0,0,91.358,154.4a5.672,5.672,0,0,0-2.555-4.131c-7.4-4-15.05-4.606-23.039-.928-14.2,6.536-21.413,18.586-27.381,32.878C48.137,183.853,56.979,183.953,65.857,181.82Z"/>
|
||||
<path class="petal" d="M78.747,194.845c7.465-3.562,13.577-8.583,17.422-16.017a23.039,23.039,0,0,0,1.82-16.108,5.671,5.671,0,0,0-3.358-3.51c-8.073-2.375-15.679-1.376-22.728,3.883-12.529,9.344-17.08,22.631-19.947,37.852C61.836,200.518,70.506,198.778,78.747,194.845Z"/>
|
||||
<path class="petal" d="M94.062,204.906c6.561-5.036,11.5-11.219,13.712-19.289a23.042,23.042,0,0,0-1.569-16.135,5.67,5.67,0,0,0-4.014-2.735c-8.391-.645-15.623,1.914-21.425,8.523-10.312,11.746-12,25.689-11.641,41.173C78.7,213.971,86.82,210.466,94.062,204.906Z"/>
|
||||
<path class="petal" d="M111.135,211.562c5.371-6.29,8.912-13.363,9.4-21.718a23.035,23.035,0,0,0-4.89-15.456,5.666,5.666,0,0,0-4.5-1.84c-8.341,1.113-14.883,5.119-19.184,12.791-7.644,13.633-6.4,27.622-2.826,42.693C97.994,223.623,105.207,218.507,111.135,211.562Z"/>
|
||||
<path class="petal" d="M129.219,214.524c3.945-7.27,5.939-14.924,4.68-23.2a23.038,23.038,0,0,0-8-14.1,5.674,5.674,0,0,0-4.78-.866c-7.927,2.823-13.494,8.1-16.106,16.5-4.643,14.924-.516,28.349,6.112,42.348C118.872,229.053,124.864,222.549,129.219,214.524Z"/>
|
||||
<path class="petal" d="M147.523,213.661c2.348-7.931,2.706-15.833-.245-23.665a23.042,23.042,0,0,0-10.753-12.131,5.671,5.671,0,0,0-4.855.147c-7.167,4.41-11.514,10.731-12.323,19.489-1.439,15.563,5.389,27.837,14.783,40.152C140.424,230.024,144.932,222.416,147.523,213.661Z"/>
|
||||
<path class="petal" d="M165.248,209.011c0.648-8.246-.645-16.049-5.16-23.1a23.038,23.038,0,0,0-13.04-9.631,5.67,5.67,0,0,0-4.719,1.154c-6.093,5.8-9.031,12.89-8,21.624,1.829,15.523,11.06,26.108,22.808,36.2C161.706,226.493,164.534,218.114,165.248,209.011Z"/>
|
||||
<path class="petal" d="M181.619,200.778c-1.081-8.2-3.968-15.565-9.849-21.519a23.043,23.043,0,0,0-14.758-6.709,5.669,5.669,0,0,0-4.375,2.109c-4.754,6.944-6.155,14.486-3.331,22.816,5.015,14.8,16.245,23.238,29.835,30.668C181.789,218.614,182.813,209.83,181.619,200.778Z"/>
|
||||
<path class="petal" d="M195.92,189.321c-2.762-7.8-7.117-14.4-14.108-19a23.04,23.04,0,0,0-15.83-3.494,5.668,5.668,0,0,0-3.841,2.972c-3.207,7.781-3.008,15.45,1.485,23.01,7.984,13.437,20.723,19.353,35.56,23.8C199.794,206.732,198.97,197.927,195.92,189.321Z"/>
|
||||
<path class="petal" d="M207.527,175.14c-4.323-7.051-9.956-12.6-17.751-15.652a23.039,23.039,0,0,0-16.21-.127,5.672,5.672,0,0,0-3.139,3.707c-1.519,8.277.27,15.737,6.237,22.2,10.6,11.483,24.293,14.622,39.73,15.881C214.936,191.366,212.3,182.925,207.527,175.14Z"/>
|
||||
<path class="petal" d="M215.931,158.857c-5.694-6-12.358-10.26-20.616-11.62a23.04,23.04,0,0,0-15.883,3.247,5.669,5.669,0,0,0-2.3,4.278c0.236,8.412,3.536,15.337,10.716,20.416,12.759,9.028,26.8,9.251,42.164,7.274C226.553,173.187,222.218,165.479,215.931,158.857Z"/>
|
||||
<path class="petal" d="M220.767,141.182c-6.817-4.684-14.222-7.467-22.582-7.08a23.039,23.039,0,0,0-14.86,6.478,5.671,5.671,0,0,0-1.361,4.663c1.979,8.179,6.648,14.267,14.727,17.742,14.357,6.178,28.14,3.477,42.755-1.651C234.135,152.99,228.293,146.352,220.767,141.182Z"/>
|
||||
<path class="petal" d="M221.822,122.888c-7.642-3.164-15.463-4.347-23.561-2.23a23.031,23.031,0,0,0-13.188,9.426,5.668,5.668,0,0,0-.361,4.844c3.636,7.588,9.468,12.573,18.093,14.292,15.328,3.058,28.248-2.45,41.477-10.5C237.354,131.659,230.259,126.38,221.822,122.888Z"/>
|
||||
<path class="petal" d="M219.05,104.774c-8.132-1.506-16.028-1.037-23.509,2.717A23.042,23.042,0,0,0,184.6,119.453a5.673,5.673,0,0,0,.654,4.814c5.135,6.666,11.876,10.329,20.67,10.218,15.629-.2,27.121-8.27,38.387-18.9C236.066,110.124,228.029,106.436,219.05,104.774Z"/>
|
||||
<path class="petal" d="M212.573,87.632c-8.268.218-15.894,2.319-22.43,7.546a23.038,23.038,0,0,0-8.215,13.975,5.672,5.672,0,0,0,1.64,4.572c6.409,5.454,13.764,7.635,22.343,5.7,15.246-3.441,24.809-13.728,33.619-26.467C230.33,89.328,221.7,87.391,212.573,87.632Z"/>
|
||||
<path class="petal" d="M202.674,72.212c-8.042,1.932-15.065,5.573-20.372,12.045a23.036,23.036,0,0,0-5.129,15.378,5.67,5.67,0,0,0,2.555,4.131c7.4,4,15.05,4.606,23.039.928,14.2-6.536,21.413-18.586,27.381-32.878C220.4,70.178,211.552,70.078,202.674,72.212Z"/>
|
||||
<path class="petal" d="M189.785,59.186c-7.465,3.562-13.577,8.583-17.423,16.017a23.039,23.039,0,0,0-1.82,16.108,5.672,5.672,0,0,0,3.358,3.51c8.073,2.376,15.679,1.376,22.729-3.883,12.528-9.345,17.08-22.632,19.947-37.853C206.7,53.513,198.025,55.254,189.785,59.186Z"/>
|
||||
<path class="petal" d="M174.469,49.126c-6.561,5.036-11.5,11.218-13.712,19.289a23.046,23.046,0,0,0,1.569,16.135,5.673,5.673,0,0,0,4.015,2.735c8.39,0.645,15.622-1.913,21.424-8.523,10.312-11.745,12-25.688,11.641-41.173C189.831,40.06,181.712,43.565,174.469,49.126Z"/>
|
||||
<path class="petal" d="M157.4,42.469c-5.371,6.29-8.912,13.363-9.4,21.718a23.041,23.041,0,0,0,4.889,15.456,5.671,5.671,0,0,0,4.5,1.84c8.341-1.113,14.883-5.12,19.185-12.791,7.644-13.633,6.4-27.622,2.826-42.693C170.537,30.408,163.325,35.524,157.4,42.469Z"/>
|
||||
<path class="petal" d="M139.312,39.507c-3.945,7.27-5.939,14.924-4.68,23.2a23.035,23.035,0,0,0,8,14.1,5.67,5.67,0,0,0,4.779.865c7.928-2.823,13.494-8.1,16.106-16.5,4.643-14.924.516-28.349-6.112-42.348C149.659,24.978,143.667,31.482,139.312,39.507Z"/>
|
||||
<path class="petal" d="M121.008,40.37c-2.348,7.931-2.706,15.833.245,23.665a23.042,23.042,0,0,0,10.753,12.131,5.671,5.671,0,0,0,4.855-.147c7.167-4.41,11.515-10.731,12.323-19.489,1.439-15.563-5.389-27.837-14.782-40.152C128.108,24.007,123.6,31.615,121.008,40.37Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
92
web/src/app/WebApp/Installers/MediaWiki/MediaWikiSetup.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\MediaWiki;
|
||||
|
||||
use Hestia\System\Util;
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class MediaWikiSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "MediaWiki",
|
||||
"group" => "cms",
|
||||
"enabled" => true,
|
||||
"version" => "1.40.0",
|
||||
"thumbnail" => "MediaWiki-2020-logo.svg", //Max size is 300px by 300px
|
||||
];
|
||||
|
||||
protected $appname = "mediawiki";
|
||||
protected $extractsubdir = "/tmp-mediawiki";
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"admin_username" => ["type" => "text", "value" => "admin"],
|
||||
"admin_password" => "password",
|
||||
"language" => ["type" => "text", "value" => "en"],
|
||||
],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"archive" => [
|
||||
"src" => "https://releases.wikimedia.org/mediawiki/1.40/mediawiki-1.40.0.zip",
|
||||
],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "default",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["7.4", "8.0"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null) {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
|
||||
//check if ssl is enabled
|
||||
$this->appcontext->run(
|
||||
"v-list-web-domain",
|
||||
[$this->appcontext->user(), $this->domain, "json"],
|
||||
$status,
|
||||
);
|
||||
|
||||
if ($status->code !== 0) {
|
||||
throw new \Exception("Cannot list domain");
|
||||
}
|
||||
|
||||
$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
|
||||
|
||||
$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain;
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-copy-fs-directory",
|
||||
[$this->getDocRoot($this->extractsubdir . "/mediawiki-1.39.2/."), $this->getDocRoot()],
|
||||
$result,
|
||||
);
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("maintenance/install.php"),
|
||||
"--dbserver=localhost",
|
||||
"--dbname=" . $this->appcontext->user() . "_" . $options["database_name"],
|
||||
"--installdbuser=" . $this->appcontext->user() . "_" . $options["database_user"],
|
||||
"--installdbpass=" . $options["database_password"],
|
||||
"--dbuser=" . $this->appcontext->user() . "_" . $options["database_user"],
|
||||
"--dbpass=" . $options["database_password"],
|
||||
"--server=" . $webDomain,
|
||||
"--scriptpath=", // must NOT be /
|
||||
"--lang=" . $options["language"],
|
||||
"--pass=" . $options["admin_password"],
|
||||
"MediaWiki", // A Space here would trigger the next argument and preemptively set the admin username
|
||||
$options["admin_username"],
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
$this->cleanup();
|
||||
|
||||
return $status->code === 0;
|
||||
}
|
||||
}
|
||||
85
web/src/app/WebApp/Installers/Nextcloud/NextcloudSetup.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Nextcloud;
|
||||
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class NextcloudSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "Nextcloud",
|
||||
"group" => "cloud",
|
||||
"enabled" => true,
|
||||
"version" => "latest",
|
||||
"thumbnail" => "nextcloud-thumb.png",
|
||||
];
|
||||
|
||||
protected $appname = "nextcloud";
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"username" => ["value" => "admin"],
|
||||
"password" => "password",
|
||||
],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"archive" => ["src" => "https://download.nextcloud.com/server/releases/latest.tar.bz2"],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "owncloud",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["8.0", "8.1", "8.2"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null): bool {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
|
||||
// install nextcloud
|
||||
$php_version = $this->appcontext->getSupportedPHP(
|
||||
$this->config["server"]["php"]["supported"],
|
||||
);
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("occ"),
|
||||
"maintenance:install",
|
||||
"--database mysql",
|
||||
"--database-name " . $this->appcontext->user() . "_" . $options["database_name"],
|
||||
"--database-user " . $this->appcontext->user() . "_" . $options["database_user"],
|
||||
"--database-pass " . $options["database_password"],
|
||||
"--admin-user " . $options["username"],
|
||||
"--admin-pass " . $options["password"],
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("occ"),
|
||||
"config:system:set",
|
||||
"trusted_domains 2 --value=" . $this->domain,
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
// Bump minimum memory limit to 512M
|
||||
$result = null;
|
||||
$file = $this->getDocRoot(".user.ini");
|
||||
$this->appcontext->runUser("v-open-fs-file", [$file], $result);
|
||||
array_push($result->raw, "memory_limit=512M");
|
||||
$tmp = $this->saveTempFile(implode("\r\n", $result->raw));
|
||||
if (!$this->appcontext->runUser("v-move-fs-file", [$tmp, $file], $result)) {
|
||||
throw new \Exception("Error updating file in: " . $tmp . " " . $result->text);
|
||||
}
|
||||
|
||||
return $status->code === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/Nextcloud/nextcloud-thumb.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
134
web/src/app/WebApp/Installers/Opencart/OpencartSetup.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Opencart;
|
||||
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class OpencartSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "Opencart",
|
||||
"group" => "ecommerce",
|
||||
"enabled" => true,
|
||||
"version" => "4.0.2.2",
|
||||
"thumbnail" => "opencart-thumb.png",
|
||||
];
|
||||
|
||||
protected $appname = "opencart";
|
||||
protected $extractsubdir = "/tmp-opencart";
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"opencart_account_username" => ["value" => "ocadmin"],
|
||||
"opencart_account_email" => "text",
|
||||
"opencart_account_password" => "password",
|
||||
],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"archive" => [
|
||||
"src" =>
|
||||
"https://github.com/opencart/opencart/releases/download/4.0.2.2/opencart-4.0.2.2.zip",
|
||||
],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "opencart",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["7.4", "8.0", "8.1", "8.2"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null): bool {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-copy-fs-directory",
|
||||
[$this->getDocRoot($this->extractsubdir . "/upload/."), $this->getDocRoot()],
|
||||
$result,
|
||||
);
|
||||
|
||||
$this->appcontext->runUser("v-copy-fs-file", [
|
||||
$this->getDocRoot("config-dist.php"),
|
||||
$this->getDocRoot("config.php"),
|
||||
]);
|
||||
$this->appcontext->runUser("v-copy-fs-file", [
|
||||
$this->getDocRoot("admin/config-dist.php"),
|
||||
$this->getDocRoot("admin/config.php"),
|
||||
]);
|
||||
$this->appcontext->runUser("v-copy-fs-file", [
|
||||
$this->getDocRoot(".htaccess.txt"),
|
||||
$this->getDocRoot(".htaccess"),
|
||||
]);
|
||||
#Check if SSL is enabled
|
||||
$this->appcontext->run(
|
||||
"v-list-web-domain",
|
||||
[$this->appcontext->user(), $this->domain, "json"],
|
||||
$status,
|
||||
);
|
||||
if ($status->code !== 0) {
|
||||
throw new \Exception("Cannot list domain");
|
||||
}
|
||||
if ($status->json[$this->domain]["SSL"] == "no") {
|
||||
$protocol = "http://";
|
||||
} else {
|
||||
$protocol = "https://";
|
||||
}
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("/install/cli_install.php"),
|
||||
"install",
|
||||
"--db_username " . $this->appcontext->user() . "_" . $options["database_user"],
|
||||
"--db_password " . $options["database_password"],
|
||||
"--db_database " . $this->appcontext->user() . "_" . $options["database_name"],
|
||||
"--username " . $options["opencart_account_username"],
|
||||
"--password " . $options["opencart_account_password"],
|
||||
"--email " . $options["opencart_account_email"],
|
||||
"--http_server " . $protocol . $this->domain . "/",
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
// After install, 'storage' folder must be moved to a location where the web server is not allowed to serve file
|
||||
// - Opencart Nginx template and Apache ".htaccess" forbids acces to /storage folder
|
||||
$this->appcontext->runUser(
|
||||
"v-move-fs-directory",
|
||||
[$this->getDocRoot("system/storage"), $this->getDocRoot()],
|
||||
$result,
|
||||
);
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
["sed", "-i", "s/'storage\//'..\/storage\// ", $this->getDocRoot("config.php")],
|
||||
$status,
|
||||
);
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
["sed", "-i", "s/'storage\//'..\/storage\// ", $this->getDocRoot("admin/config.php")],
|
||||
$status,
|
||||
);
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
["sed", "-i", "s/\^system\/storage\//^\/storage\// ", $this->getDocRoot(".htaccess")],
|
||||
$status,
|
||||
);
|
||||
|
||||
$this->appcontext->runUser("v-change-fs-file-permission", [
|
||||
$this->getDocRoot("config.php"),
|
||||
"640",
|
||||
]);
|
||||
$this->appcontext->runUser("v-change-fs-file-permission", [
|
||||
$this->getDocRoot("admin/config.php"),
|
||||
"640",
|
||||
]);
|
||||
|
||||
// remove install folder
|
||||
$this->appcontext->runUser("v-delete-fs-directory", [$this->getDocRoot("/install")]);
|
||||
$this->cleanup();
|
||||
|
||||
return $status->code === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/Opencart/opencart-thumb.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
93
web/src/app/WebApp/Installers/Prestashop/PrestashopSetup.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Prestashop;
|
||||
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class PrestashopSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "Prestashop",
|
||||
"group" => "ecommerce",
|
||||
"enabled" => true,
|
||||
"version" => "8.1.0",
|
||||
"thumbnail" => "prestashop-thumb.png",
|
||||
];
|
||||
|
||||
protected $appname = "prestashop";
|
||||
protected $extractsubdir = "/tmp-prestashop";
|
||||
|
||||
protected $config = [
|
||||
"form" => [
|
||||
"prestashop_account_first_name" => ["value" => "John"],
|
||||
"prestashop_account_last_name" => ["value" => "Doe"],
|
||||
"prestashop_account_email" => "text",
|
||||
"prestashop_account_password" => "password",
|
||||
],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"archive" => [
|
||||
"src" =>
|
||||
"https://github.com/PrestaShop/PrestaShop/releases/download/8.1.0/prestashop_8.1.0.zip",
|
||||
],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "prestashop",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["8.0", "8.1"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null): bool {
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
$this->appcontext->archiveExtract(
|
||||
$this->getDocRoot($this->extractsubdir . "/prestashop.zip"),
|
||||
$this->getDocRoot(),
|
||||
);
|
||||
//check if ssl is enabled
|
||||
$this->appcontext->run(
|
||||
"v-list-web-domain",
|
||||
[$this->appcontext->user(), $this->domain, "json"],
|
||||
$status,
|
||||
);
|
||||
if ($status->code !== 0) {
|
||||
throw new \Exception("Cannot list domain");
|
||||
}
|
||||
|
||||
if ($status->json[$this->domain]["SSL"] == "no") {
|
||||
$ssl_enabled = 0;
|
||||
} else {
|
||||
$ssl_enabled = 1;
|
||||
}
|
||||
|
||||
$php_version = $this->appcontext->getSupportedPHP(
|
||||
$this->config["server"]["php"]["supported"],
|
||||
);
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-run-cli-cmd",
|
||||
[
|
||||
"/usr/bin/php" . $options["php_version"],
|
||||
$this->getDocRoot("/install/index_cli.php"),
|
||||
"--db_user=" . $this->appcontext->user() . "_" . $options["database_user"],
|
||||
"--db_password=" . $options["database_password"],
|
||||
"--db_name=" . $this->appcontext->user() . "_" . $options["database_name"],
|
||||
"--firstname=" . $options["prestashop_account_first_name"],
|
||||
"--lastname=" . $options["prestashop_account_last_name"],
|
||||
"--password=" . $options["prestashop_account_password"],
|
||||
"--email=" . $options["prestashop_account_email"],
|
||||
"--domain=" . $this->domain,
|
||||
"--ssl=" . $ssl_enabled,
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
// remove install folder
|
||||
$this->appcontext->runUser("v-delete-fs-directory", [$this->getDocRoot("/install")]);
|
||||
$this->cleanup();
|
||||
return $status->code === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/Prestashop/prestashop-thumb.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
37
web/src/app/WebApp/Installers/Resources/ComposerResource.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Resources;
|
||||
|
||||
use Hestia\System\HestiaApp;
|
||||
|
||||
class ComposerResource {
|
||||
private $project;
|
||||
private $folder;
|
||||
private $appcontext;
|
||||
|
||||
public function __construct(HestiaApp $appcontext, $data, $destination) {
|
||||
$this->folder = dirname($destination);
|
||||
$this->project = basename($destination);
|
||||
$this->appcontext = $appcontext;
|
||||
if (empty($data["version"])) {
|
||||
$data["version"] = 2;
|
||||
}
|
||||
|
||||
$this->appcontext->runComposer(
|
||||
[
|
||||
"create-project",
|
||||
"--no-progress",
|
||||
"--prefer-dist",
|
||||
$data["src"],
|
||||
"-d " . $this->folder,
|
||||
$this->project,
|
||||
],
|
||||
$status,
|
||||
$data,
|
||||
);
|
||||
|
||||
if ($status->code !== 0) {
|
||||
throw new \Exception("Error fetching Composer resource: " . $status->text);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
web/src/app/WebApp/Installers/Resources/WpResource.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Resources;
|
||||
|
||||
use Hestia\System\HestiaApp;
|
||||
|
||||
class WpResource {
|
||||
private $appcontext;
|
||||
private $options;
|
||||
|
||||
public function __construct(HestiaApp $appcontext, $data, $destination, $options, $appinfo) {
|
||||
$this->appcontext = $appcontext;
|
||||
$this->appcontext->runWp(
|
||||
[
|
||||
"core",
|
||||
"download",
|
||||
"--locale=" . $options["language"],
|
||||
"--version=" . $appinfo["version"],
|
||||
"--path=" . $destination,
|
||||
],
|
||||
$status,
|
||||
);
|
||||
|
||||
if ($status->code !== 0) {
|
||||
throw new \Exception("Error fetching WP resource: " . $status->text);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
web/src/app/WebApp/Installers/Symfony/SymfonySetup.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Symfony;
|
||||
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
|
||||
class SymfonySetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "Symfony",
|
||||
"group" => "framework",
|
||||
"enabled" => true,
|
||||
"version" => "latest",
|
||||
"thumbnail" => "symfony-thumb.png",
|
||||
];
|
||||
|
||||
protected $appname = "symfony";
|
||||
|
||||
protected $config = [
|
||||
"form" => [],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"composer" => ["src" => "symfony/website-skeleton", "dst" => "/"],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "symfony4-5",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["8.1", "8.2"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null): bool {
|
||||
parent::install($options);
|
||||
$result = null;
|
||||
|
||||
$htaccess_rewrite = '
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteRule ^(.*)$ public/$1 [L]
|
||||
</IfModule>';
|
||||
|
||||
$this->appcontext->runComposer(
|
||||
["config", "-d " . $this->getDocRoot(), "extra.symfony.allow-contrib", "true"],
|
||||
$result,
|
||||
);
|
||||
$this->appcontext->runComposer(
|
||||
["require", "-d " . $this->getDocRoot(), "symfony/apache-pack"],
|
||||
$result,
|
||||
);
|
||||
|
||||
$tmp_configpath = $this->saveTempFile($htaccess_rewrite);
|
||||
$this->appcontext->runUser(
|
||||
"v-move-fs-file",
|
||||
[$tmp_configpath, $this->getDocRoot(".htaccess")],
|
||||
$result,
|
||||
);
|
||||
|
||||
return $result->code === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/Symfony/symfony-thumb.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
272
web/src/app/WebApp/Installers/WordPress/WordPressSetup.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace Hestia\WebApp\Installers\Wordpress;
|
||||
|
||||
use Hestia\System\Util;
|
||||
use Hestia\WebApp\Installers\BaseSetup as BaseSetup;
|
||||
use function Hestiacp\quoteshellarg\quoteshellarg;
|
||||
|
||||
class WordpressSetup extends BaseSetup {
|
||||
protected $appInfo = [
|
||||
"name" => "WordPress",
|
||||
"group" => "cms",
|
||||
"enabled" => true,
|
||||
"version" => "latest",
|
||||
"thumbnail" => "wp-thumb.png",
|
||||
];
|
||||
|
||||
protected $appname = "wordpress";
|
||||
protected $config = [
|
||||
"form" => [
|
||||
//'protocol' => [
|
||||
// 'type' => 'select',
|
||||
// 'options' => ['http','https'],
|
||||
//],
|
||||
|
||||
"site_name" => ["type" => "text", "value" => "WordPress Blog"],
|
||||
"wordpress_account_username" => ["value" => "wpadmin"],
|
||||
"wordpress_account_email" => "text",
|
||||
"wordpress_account_password" => "password",
|
||||
"install_directory" => ["type" => "text", "value" => "", "placeholder" => "/"],
|
||||
"language" => [
|
||||
"type" => "select",
|
||||
"value" => "en_US",
|
||||
"options" => [
|
||||
"cs_CZ" => "Czech",
|
||||
"de_DE" => "German",
|
||||
"es_ES" => "Spanish",
|
||||
"en_US" => "English",
|
||||
"fr_FR" => "French",
|
||||
"hu_HU" => "Hungarian",
|
||||
"it_IT" => "Italian",
|
||||
"nl_NL" => "Dutch",
|
||||
"pt_PT" => "Portuguese",
|
||||
"pt_BR" => "Portuguese (Brazil)",
|
||||
"sk_SK" => "Slovak",
|
||||
"sr_RS" => "Serbian",
|
||||
"tr_TR" => "Turkish",
|
||||
"ru_RU" => "Russian",
|
||||
"uk" => "Ukrainian",
|
||||
"zh-CN" => "Simplified Chinese (China)",
|
||||
"zh_TW" => "Traditional Chinese",
|
||||
],
|
||||
],
|
||||
],
|
||||
"database" => true,
|
||||
"resources" => [
|
||||
"wp" => ["src" => "https://wordpress.org/latest.tar.gz"],
|
||||
],
|
||||
"server" => [
|
||||
"nginx" => [
|
||||
"template" => "wordpress",
|
||||
],
|
||||
"php" => [
|
||||
"supported" => ["7.4", "8.0", "8.1", "8.2"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
public function install(array $options = null) {
|
||||
parent::setAppDirInstall($options["install_directory"]);
|
||||
parent::install($options);
|
||||
parent::setup($options);
|
||||
|
||||
$this->appcontext->runUser(
|
||||
"v-open-fs-file",
|
||||
[$this->getDocRoot("wp-config-sample.php")],
|
||||
$result,
|
||||
);
|
||||
foreach ($result->raw as $line_num => $line) {
|
||||
if ('$table_prefix =' === substr($line, 0, 15)) {
|
||||
$result->raw[$line_num] =
|
||||
'$table_prefix = \'' .
|
||||
addcslashes(Util::generate_string(5, false) . "_", "\\'") .
|
||||
"';\r\n";
|
||||
continue;
|
||||
}
|
||||
if (!preg_match('/^define\(\s*\'([A-Z_]+)\',([ ]+)/', $line, $match)) {
|
||||
continue;
|
||||
}
|
||||
$constant = $match[1];
|
||||
$padding = $match[2];
|
||||
switch ($constant) {
|
||||
case "DB_NAME":
|
||||
$result->raw[$line_num] =
|
||||
"define( '" .
|
||||
$constant .
|
||||
"'," .
|
||||
$padding .
|
||||
"'" .
|
||||
addcslashes(
|
||||
$this->appcontext->user() . "_" . $options["database_name"],
|
||||
"\\'",
|
||||
) .
|
||||
"' );";
|
||||
break;
|
||||
case "DB_USER":
|
||||
$result->raw[$line_num] =
|
||||
"define( '" .
|
||||
$constant .
|
||||
"'," .
|
||||
$padding .
|
||||
"'" .
|
||||
addcslashes(
|
||||
$this->appcontext->user() . "_" . $options["database_user"],
|
||||
"\\'",
|
||||
) .
|
||||
"' );";
|
||||
break;
|
||||
case "DB_PASSWORD":
|
||||
$result->raw[$line_num] =
|
||||
"define( '" .
|
||||
$constant .
|
||||
"'," .
|
||||
$padding .
|
||||
"'" .
|
||||
addcslashes($options["database_password"], "\\'") .
|
||||
"' );";
|
||||
break;
|
||||
case "DB_HOST":
|
||||
$result->raw[$line_num] =
|
||||
"define( '" .
|
||||
$constant .
|
||||
"'," .
|
||||
$padding .
|
||||
"'" .
|
||||
addcslashes("localhost", "\\'") .
|
||||
"' );";
|
||||
break;
|
||||
case "DB_CHARSET":
|
||||
$result->raw[$line_num] =
|
||||
"define( '" .
|
||||
$constant .
|
||||
"'," .
|
||||
$padding .
|
||||
"'" .
|
||||
addcslashes("utf8mb4", "\\'") .
|
||||
"' );";
|
||||
break;
|
||||
case "AUTH_KEY":
|
||||
case "SECURE_AUTH_KEY":
|
||||
case "LOGGED_IN_KEY":
|
||||
case "NONCE_KEY":
|
||||
case "AUTH_SALT":
|
||||
case "SECURE_AUTH_SALT":
|
||||
case "LOGGED_IN_SALT":
|
||||
case "NONCE_SALT":
|
||||
$result->raw[$line_num] =
|
||||
"define( '" .
|
||||
$constant .
|
||||
"'," .
|
||||
$padding .
|
||||
"'" .
|
||||
Util::generate_string(64) .
|
||||
"' );";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$tmp_configpath = $this->saveTempFile(implode("\r\n", $result->raw));
|
||||
|
||||
if (
|
||||
!$this->appcontext->runUser(
|
||||
"v-move-fs-file",
|
||||
[$tmp_configpath, $this->getDocRoot("wp-config.php")],
|
||||
$result,
|
||||
)
|
||||
) {
|
||||
throw new \Exception(
|
||||
"Error installing config file in: " .
|
||||
$tmp_configpath .
|
||||
" to:" .
|
||||
$this->getDocRoot("wp-config.php") .
|
||||
$result->text,
|
||||
);
|
||||
}
|
||||
|
||||
$this->appcontext->downloadUrl(
|
||||
"https://raw.githubusercontent.com/roots/wp-password-bcrypt/master/wp-password-bcrypt.php",
|
||||
null,
|
||||
$plugin_output,
|
||||
);
|
||||
$this->appcontext->runUser(
|
||||
"v-add-fs-directory",
|
||||
[$this->getDocRoot("wp-content/mu-plugins/")],
|
||||
$result,
|
||||
);
|
||||
if (
|
||||
!$this->appcontext->runUser(
|
||||
"v-copy-fs-file",
|
||||
[
|
||||
$plugin_output->file,
|
||||
$this->getDocRoot("wp-content/mu-plugins/wp-password-bcrypt.php"),
|
||||
],
|
||||
$result,
|
||||
)
|
||||
) {
|
||||
throw new \Exception(
|
||||
"Error installing wp-password-bcrypt file in: " .
|
||||
$plugin_output->file .
|
||||
" to:" .
|
||||
$this->getDocRoot("wp-content/mu-plugins/wp-password-bcrypt.php") .
|
||||
$result->text,
|
||||
);
|
||||
}
|
||||
|
||||
$this->appcontext->run(
|
||||
"v-list-web-domain",
|
||||
[$this->appcontext->user(), $this->domain, "json"],
|
||||
$status,
|
||||
);
|
||||
$sslEnabled = $status->json[$this->domain]["SSL"] == "no" ? 0 : 1;
|
||||
$webDomain = ($sslEnabled ? "https://" : "http://") . $this->domain . "/";
|
||||
$webPort = $sslEnabled ? "443" : "80";
|
||||
|
||||
if (substr($options["install_directory"], 0, 1) == "/") {
|
||||
$options["install_directory"] = substr($options["install_directory"], 1);
|
||||
}
|
||||
if (substr($options["install_directory"], -1, 1) == "/") {
|
||||
$options["install_directory"] = substr(
|
||||
$options["install_directory"],
|
||||
0,
|
||||
strlen($options["install_directory"]) - 1,
|
||||
);
|
||||
}
|
||||
|
||||
exec(
|
||||
"/usr/bin/curl --location --post301 --insecure --resolve " .
|
||||
$this->domain .
|
||||
":$webPort:" .
|
||||
$this->appcontext->getWebDomainIp($this->domain) .
|
||||
" " .
|
||||
quoteshellarg(
|
||||
$webDomain . $options["install_directory"] . "/wp-admin/install.php?step=2",
|
||||
) .
|
||||
" -d " .
|
||||
quoteshellarg(
|
||||
"weblog_title=" .
|
||||
rawurlencode($options["site_name"]) .
|
||||
"&user_name=" .
|
||||
rawurlencode($options["wordpress_account_username"]) .
|
||||
"&admin_password=" .
|
||||
rawurlencode($options["wordpress_account_password"]) .
|
||||
"&admin_password2=" .
|
||||
rawurlencode($options["wordpress_account_password"]) .
|
||||
"&admin_email=" .
|
||||
rawurlencode($options["wordpress_account_email"]),
|
||||
),
|
||||
$output,
|
||||
$return_var,
|
||||
);
|
||||
|
||||
if (
|
||||
strpos(implode(PHP_EOL, $output), "Error establishing a database connection") !== false
|
||||
) {
|
||||
throw new \Exception("Error establishing a database connection");
|
||||
}
|
||||
if ($return_var > 0) {
|
||||
throw new \Exception(implode(PHP_EOL, $output));
|
||||
}
|
||||
return $return_var === 0;
|
||||
}
|
||||
}
|
||||
BIN
web/src/app/WebApp/Installers/WordPress/wp-thumb.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
10
web/src/composer.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hestia\\": "app/"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"filp/whoops": "2.15.3"
|
||||
}
|
||||
}
|
||||
140
web/src/composer.lock
generated
Normal file
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "6a75f12aba408723434633776955d2a1",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.15.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/c83e88a30524f9360b11f585f71e6b17313b7187",
|
||||
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9 || ^7.0 || ^8.0",
|
||||
"psr/log": "^1.0.1 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^0.9 || ^1.0",
|
||||
"phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3",
|
||||
"symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
|
||||
"whoops/soap": "Formats errors as SOAP responses"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Whoops\\": "src/Whoops/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Filipe Dobreira",
|
||||
"homepage": "https://github.com/filp",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "php error handling for cool kids",
|
||||
"homepage": "https://filp.github.io/whoops/",
|
||||
"keywords": [
|
||||
"error",
|
||||
"exception",
|
||||
"handling",
|
||||
"library",
|
||||
"throwable",
|
||||
"whoops"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/filp/whoops/issues",
|
||||
"source": "https://github.com/filp/whoops/tree/2.15.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/denis-sokolov",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-13T12:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/3.0.0"
|
||||
},
|
||||
"time": "2021-07-14T16:46:02+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
19
web/src/init.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$loader = require_once __DIR__ .
|
||||
DIRECTORY_SEPARATOR .
|
||||
"vendor" .
|
||||
DIRECTORY_SEPARATOR .
|
||||
"autoload.php";
|
||||
|
||||
#
|
||||
# Dev-debugging: Html error handler
|
||||
# https://github.com/filp/whoops
|
||||
# install:
|
||||
# cd $HESTIA/web/src; composer require filp/whoops
|
||||
#
|
||||
# $whoops = new \Whoops\Run;
|
||||
# $whoops->prependHandler(new \Whoops\Handler\PrettyPageHandler);
|
||||
# $whoops->register();
|
||||