VvebOIDC/system/sites.php

317 lines
8.9 KiB
PHP

<?php
/**
* Vvveb
*
* Copyright (C) 2022 Ziadin Givan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Vvveb\System;
use function Vvveb\__;
class Sites {
private static $sites = null;
private static $host_matches = [];
const HOST_REGEX = '@(?<prefix>https://|http://|//|^)(?<subdomain>.*?)?\.?(?<domain>[^\.]+)\.(?<tld>[^\.]+|[^\.]{2,3}\.[^\.]{2,3})((?<path>/.*)|$)@';
private static $states;
/*
private static $states = [
'live' => ['name' => 'Live', 'template' => 'index.html', 'icon' => 'la-broadcast-tower'],
'maintenance' => ['name' => 'Maintenance', 'template' => 'index.maintenance.html', 'icon' => 'la-wrench'],
'coming-soon' => ['name' => 'Coming soon', 'template' => 'index.coming-soon.html', 'icon' => 'la-clock'],
];
*/
public static function getStates() {
static :: $states = [
'live' => ['name' => __('Live'), 'template' => 'index.html', 'icon' => 'la-broadcast-tower'],
'maintenance' => ['name' => __('Maintenance'), 'template' => 'index.maintenance.html', 'icon' => 'la-wrench'],
'coming-soon' => ['name' => __('Coming soon'), 'template' => 'index.coming-soon.html', 'icon' => 'la-clock'],
];
return static :: $states;
}
public static function getDefault() {
$sites = self :: getSites();
return current($sites);
}
public static function getSites() {
if (! self :: $sites) {
self :: $sites = \Vvveb\config('sites');
foreach (self::$sites as &$site) {
$site['url'] = self :: url($site['host']) . (V_SUBDIR_INSTALL ? V_SUBDIR_INSTALL : '') . ($site['path'] ?? '' ? '/' . $site['path'] : '');
}
return self :: $sites;
}
return self :: $sites;
}
public static function getSiteByKey($site_key) {
$sites = self :: getSites();
$site_key = self :: siteKey($site_key);
if (isset($sites[$site_key])) {
$site = $sites[$site_key];
$site['key'] = $site_key;
return $site;
}
return false;
}
public static function getSiteById($site_id) {
$sites = self :: getSites();
foreach ($sites as $site_key => $site) {
if ($site['id'] == $site_id) {
$site['key'] = $site_key;
return $site;
}
}
}
public static function getTheme($site = false) {
$data = self :: getSiteData($site);
if ($data) {
return $data['theme'];
}
return 'default';
}
public static function setTheme($site, $theme, $template = '') {
if ($template) {
self :: setSiteData($site, 'template', $template);
}
return self :: setSiteData($site, 'theme', $theme);
}
public static function urlSplit($url = null) {
$url = $url ?? $_SERVER['HTTP_HOST'] ?? '';
$host = $host ?? self :: getHost();
$host_matches = self :: $host_matches[$host] ?? [];
if (preg_match(self :: HOST_REGEX, $url, $matches)) {
if (($host_matches || preg_match(self :: HOST_REGEX, $host, $host_matches))//check is not ip
&& ! is_numeric($host_matches['domain'] ?? null)) {
self :: $host_matches[$host] = $host_matches;
$has_subdomain = ! empty($host_matches['subdomain']) || ($matches['subdomain'] != '*');
$has_tld = ! empty($host_matches['tld']) || ($matches['tld'] != '*');
return $matches;
}
//if host is ip number, localhost or does not have tld remove tld and subdomain
if (is_numeric($host_matches['domain'] ?? null) || $host == 'localhost' || (strpos($host, '.') === false)) {
$matches['domain'] = $host;
$matches['subdomain'] = $matches['tld'] = $matches['prefix'] = '';
}
if ($host == 'localhost') {
$matches['domain'] = 'localhost';
$matches['subdomain'] = $matches['tld'] = $matches['prefix'] = '';
}
return $matches;
}
return [];
}
public static function url($url, $host = null) {
$host = $host ?? self :: getHost();
$hasPort = strpos($host, ':') ?: null;
$hostWp = substr($host, 0, strpos($host, ':') ?: null);
$host_matches = self :: $host_matches[$host] ?? [];
if (preg_match(self :: HOST_REGEX, $url, $matches)) {
if (($host_matches || preg_match(self :: HOST_REGEX, $host, $host_matches))//check is not ip
&& ! is_numeric($host_matches['domain'] ?? null)) {
self :: $host_matches[$host] = $host_matches;
$subdomain = str_replace('*', $host_matches['subdomain'], $matches['subdomain']);
$domain = str_replace('*', $host_matches['domain'], $matches['domain']);
$tld = str_replace('*', $host_matches['tld'], $matches['tld']);
return $matches['prefix'] .
$subdomain . ($subdomain ? '.' : '') .
$domain . ($tld ? '.' : '') . $tld .
($matches['path'] ?? '');
}
//if host is ip number, localhost or does not have tld remove tld and subdomain
if (! ($matches['prefix'] || ($matches['tld'] && $matches['tld'] !== '*')) &&
(is_numeric($host_matches['domain'] ?? null) || $hostWp == 'localhost' || (strpos($hostWp, '.') === false))) {
$matches['domain'] = $host;
$matches['subdomain'] = $matches['tld'] = $matches['prefix'] = '';
}
$url = ($matches['prefix'] ? $matches['prefix'] : '') .
(! empty($matches['subdomain']) ? $matches['subdomain'] . '.' : '') .
($matches['domain'] ?? '') .
(! empty($matches['tld']) ? '.' . $matches['tld'] : '') .
($matches['path'] ?? '');
}
return $url;
}
public static function siteKey($site_url = false) {
return str_replace('.', ' ',$site_url);
}
public static function setSiteDataById($site_id, $name, $value) {
$site = self :: getSiteById($site_id);
if ($site && ($site['id'] == $site_id)) {
$key = "sites.{$site['key']}";
//key has changed replace site
if (isset($value['key']) && ($value['key'] != $site['key'])) {
$config = \Vvveb\getConfig($key);
if ($config) {
$value += $config;
$config = \Vvveb\unsetConfig($key);
$key = "sites.{$value['key']}";
}
}
if ($name) {
$key .= ".$name";
}
return \Vvveb\setConfig($key, $value);
}
return false;
}
public static function setSiteDataByKey($site_key, $name, $value) {
$site = self :: getSiteByKey($site_key);
$site_key = self :: siteKey($site_key);
if ($site && ($site['key'] == $site_key)) {
$key = "sites.{$site['key']}";
if ($name) {
$key .= ".$name";
}
return \Vvveb\setConfig($key, $value);
}
return false;
}
public static function setSiteData($site, $name, $value) {
if (is_int($site)) {
return self :: setSiteDataById($site, $name, $value);
} else {
return self :: setSiteDataByKey($site, $name, $value);
}
}
public static function getHost() {
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
return $host;
}
public static function getSiteData($site_url = false) {
if (is_int($site_url)) {
return self :: getSiteById($site_url);
}
if (! $site_url) {
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
}
$cacheDriver = Cache :: getInstance();
$cacheKey = $host;
if ($result = $cacheDriver->get('site', $cacheKey)) {
return $result;
} else {
$host = self :: siteKey($host);
$first = strpos($host, ' ');
$last = strrpos($host, ' ');
$subdomain_wildcard = '* ' . substr($host, $first);
$tld_wildcard = substr($host, 0, $last) . ' *';
$domain_wildcard = substr($host, 0, $first) . ' * *';
$full_wildcard = '* ' . trim(substr($host, $first, $last - $first)) . ' *';
$result = \Vvveb\config("sites.$host", null) ??
\Vvveb\config("sites.$subdomain_wildcard", null) ??
\Vvveb\config("sites.$domain_wildcard", null) ??
\Vvveb\config("sites.$full_wildcard", null) ??
\Vvveb\config("sites.$tld_wildcard", null) ??
\Vvveb\config('sites.* * *', null);
if ($result) {
$result['host'] = self :: url($result['host']);
} else {
if (APP !== 'app') {
//if site does not exist use fallback for admin, cli etc
$result = [
'host' => 'localhost',
'theme' => 'landing',
'template' => '',
'id' => 1,
'state' => 'live',
];
}
}
$cacheDriver->set('site', $cacheKey, $result);
}
return $result;
}
public static function saveSite($site) {
$key = self :: siteKey(trim($site['key'] ?? $site['host']));
unset($site['key']);
$return = \Vvveb\setConfig("sites.$key", $site);
}
public static function deleteSite($site) {
$key = self :: siteKey(trim($site['key'] ?? $site['host']));
$return = \Vvveb\unsetConfig("sites.$key", $site);
}
}