Initial commit

This commit is contained in:
root
2026-01-19 17:44:46 +01:00
commit 823af8b11d
8721 changed files with 1130846 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* 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/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Portal\Utils;
use Espo\Core\Utils\Config as BaseConfig;
use RuntimeException;
use stdClass;
class Config extends BaseConfig
{
private bool $portalParamsSet = false;
/**
* @var array<string, mixed>
*/
private $portalData = [];
/**
* @var string[]
*/
private $portalParamList = [
'applicationName',
'companyLogoId',
'tabList',
'quickCreateList',
'dashboardLayout',
'dashletsOptions',
'theme',
'themeParams',
'language',
'timeZone',
'dateFormat',
'timeFormat',
'weekStart',
'defaultCurrency',
];
/**
* @param mixed $default
* @return mixed
*/
public function get(string $name, $default = null)
{
if (array_key_exists($name, $this->portalData)) {
return $this->portalData[$name];
}
return parent::get($name, $default);
}
public function has(string $name): bool
{
if (array_key_exists($name, $this->portalData)) {
return true;
}
return parent::has($name);
}
public function getAllNonInternalData(): stdClass
{
$data = parent::getAllNonInternalData();
foreach ($this->portalData as $k => $v) {
$data->$k = $v;
}
return $data;
}
/**
* Override parameters for a portal. Can be called only once.
*
* @param array<string, mixed> $data
*/
public function setPortalParameters(array $data = []): void
{
if ($this->portalParamsSet) {
throw new RuntimeException("Can't set portal params second time.");
}
$this->portalParamsSet = true;
if (empty($data['applicationName'])) {
unset($data['applicationName']);
}
if (empty($data['language'])) {
unset($data['language']);
}
if (empty($data['theme'])) {
unset($data['theme']);
}
if (empty($data['timeZone'])) {
unset($data['timeZone']);
}
if (empty($data['dateFormat'])) {
unset($data['dateFormat']);
}
if (empty($data['timeFormat'])) {
unset($data['timeFormat']);
}
if (empty($data['defaultCurrency'])) {
unset($data['defaultCurrency']);
}
if (isset($data['weekStart']) && $data['weekStart'] === -1) {
unset($data['weekStart']);
}
if (array_key_exists('weekStart', $data) && is_null($data['weekStart'])) {
unset($data['weekStart']);
}
if ($this->get('webSocketInPortalDisabled')) {
$this->portalData['useWebSocket'] = false;
}
foreach ($data as $attribute => $value) {
if (!in_array($attribute, $this->portalParamList)) {
continue;
}
$this->portalData[$attribute] = $value;
}
}
}

View File

@@ -0,0 +1,32 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* 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/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Portal\Utils;
class Language extends \Espo\Core\Utils\Language {}

View File

@@ -0,0 +1,66 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* 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/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Portal\Utils;
use Espo\Core\Api\Route as RouteItem;
use Espo\Core\Utils\Route as BaseRoute;
class Route extends BaseRoute
{
public function getFullList(): array
{
$originalRouteList = parent::getFullList();
$newRouteList = [];
foreach ($originalRouteList as $route) {
$path = $route->getAdjustedRoute();
if ($path[0] !== '/') {
$path = '/' . $path;
}
$path = '/{portalId}' . $path;
$newRoute = new RouteItem(
$route->getMethod(),
$route->getRoute(),
$path,
$route->getParams(),
$route->noAuth(),
$route->getActionClassName()
);
$newRouteList[] = $newRoute;
}
return $newRouteList;
}
}

View File

@@ -0,0 +1,63 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* 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/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Portal\Utils;
use Espo\Core\Utils\Config;
use Espo\Core\Utils\Metadata;
use Espo\Core\Utils\Theme\MetadataProvider;
use Espo\Entities\Portal;
use Espo\Core\Utils\ThemeManager as BaseThemeManager;
class ThemeManager extends BaseThemeManager
{
private Portal $portal;
public function __construct(
Config $config,
Metadata $metadata,
MetadataProvider $metadataProvider,
Portal $portal,
) {
parent::__construct($config, $metadata, $metadataProvider);
$this->portal = $portal;
}
public function getName(): string
{
$theme = $this->portal->get('theme');
if ($theme) {
return $theme;
}
return parent::getName();
}
}

View File

@@ -0,0 +1,160 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* 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/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Portal\Utils;
class Url
{
public static function detectPortalIdForApi(): ?string
{
$portalId = filter_input(INPUT_GET, 'portalId');
if ($portalId) {
return $portalId;
}
$url = $_SERVER['REQUEST_URI'] ?? null;
$scriptName = $_SERVER['SCRIPT_NAME'];
if (!$url) {
return null;
}
$scriptNameModified = str_replace('public/api/', 'api/', $scriptName);
return explode('/', $url)[count(explode('/', $scriptNameModified)) - 1] ?? null;
}
public static function getPortalIdFromEnv(): ?string
{
return $_SERVER['ESPO_PORTAL_ID'] ?? null;
}
public static function detectPortalId(): ?string
{
$portalId = self::getPortalIdFromEnv();
if ($portalId) {
return $portalId;
}
$url = $_SERVER['REQUEST_URI'] ?? null;
$scriptName = $_SERVER['SCRIPT_NAME'];
$scriptNameModified = str_replace('public/api/', 'api/', $scriptName);
$idIndex = count(explode('/', $scriptNameModified)) - 1;
if ($url) {
$portalId = explode('/', $url)[$idIndex] ?? null;
if (str_contains($url, '=')) {
$portalId = null;
}
}
if ($portalId) {
return $portalId;
}
$url = $_SERVER['REDIRECT_URL'] ?? null;
if (!$url) {
return null;
}
$portalId = explode('/', $url)[$idIndex] ?? null;
if ($portalId === '') {
$portalId = null;
}
return $portalId;
}
protected static function detectIsCustomUrl(): bool
{
return (bool) ($_SERVER['ESPO_PORTAL_IS_CUSTOM_URL'] ?? false);
}
public static function detectIsInPortalDir(): bool
{
$isCustomUrl = self::detectIsCustomUrl();
if ($isCustomUrl) {
return false;
}
$a = explode('?', $_SERVER['REQUEST_URI']);
$url = rtrim($a[0], '/');
return str_contains($url, '/portal');
}
public static function detectIsInPortalWithId(): bool
{
if (!self::detectIsInPortalDir()) {
return false;
}
$url = $_SERVER['REQUEST_URI'];
$a = explode('?', $url);
$url = rtrim($a[0], '/');
$folders = explode('/', $url);
if (count($folders) > 1 && $folders[count($folders) - 2] === 'portal') {
return true;
}
return false;
}
public static function getRedirectUrlWithTrailingSlash(): ?string
{
$uri = $_SERVER['REQUEST_URI'];
if ($uri === '' || $uri === '/' || str_ends_with($uri, '/')) {
return null;
}
$output = $uri . '/';
$queryString = $_SERVER['QUERY_STRING'] ?? null;
if ($queryString !== null && $queryString !== '') {
$output .= '?' . $_SERVER['QUERY_STRING'];
}
return $output;
}
}