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,46 @@
<?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\Htmlizer;
/**
* @internal
*/
class CreateForUserParams
{
/**
* @var bool
*/
public $useUserTimezone = false;
/**
* @var bool
*/
public $applyAcl = false;
}

View File

@@ -0,0 +1,38 @@
<?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\Htmlizer;
use Espo\Core\Htmlizer\Helper\Data;
use Espo\Core\Htmlizer\Helper\Result;
interface Helper
{
public function render(Data $data): Result;
}

View File

@@ -0,0 +1,110 @@
<?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\Htmlizer\Helper;
use stdClass;
use Closure;
class Data
{
/**
* @param mixed[] $argumentList
* @param array<string, mixed> $rootContext
* @noinspection PhpPluralMixedCanBeReplacedWithArrayInspection
*/
public function __construct(
private string $name,
private array $argumentList,
private stdClass $options,
private mixed $context,
private array $rootContext,
private ?Closure $func,
private ?Closure $inverseFunc
) {}
public function getName(): string
{
return $this->name;
}
/**
* @return mixed A context.
*/
public function getContext(): mixed
{
return $this->context;
}
/**
* @return array<string, mixed>
*/
public function getRootContext(): array
{
return $this->rootContext;
}
public function getOptions(): stdClass
{
return $this->options;
}
/**
* @return mixed[]
* @noinspection PhpPluralMixedCanBeReplacedWithArrayInspection
*/
public function getArgumentList(): array
{
return $this->argumentList;
}
public function hasOption(string $name): bool
{
return property_exists($this->options, $name);
}
/**
* @return mixed
*/
public function getOption(string $name)
{
return $this->options->$name ?? null;
}
public function getFunction(): ?Closure
{
return $this->func;
}
/** @noinspection PhpUnused */
public function getInverseFunction(): ?Closure
{
return $this->inverseFunc;
}
}

View File

@@ -0,0 +1,76 @@
<?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\Htmlizer\Helper;
class Result
{
/**
* @var string|SafeString|null
*/
private $value = null;
private function __construct() {}
public static function createSafeString(string $value): self
{
$obj = new self();
$obj->value = new SafeString($value);
return $obj;
}
public static function createEmpty(): self
{
$obj = new self();
$obj->value = '';
return $obj;
}
public static function create(string $value): self
{
$obj = new self();
$obj->value = $value;
return $obj;
}
/**
* @return SafeString|string
*/
public function getValue()
{
if ($this->value instanceof SafeString) {
return $this->value;
}
return (string) $this->value;
}
}

View File

@@ -0,0 +1,57 @@
<?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\Htmlizer\Helper;
use LightnCandy\SafeString as LightnCandySafeString;
class SafeString
{
private $wrappee;
public function __construct(string $value)
{
$this->wrappee = new LightnCandySafeString($value);
}
public static function create(string $value): self
{
return new self($value);
}
public function getWrappee(): LightnCandySafeString
{
return $this->wrappee;
}
public function __toString()
{
return (string) $this->wrappee;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
<?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\Htmlizer;
use Espo\Core\InjectableFactory;
use Espo\Core\Utils\DateTime\DateTimeFactory;
use Espo\Core\AclManager;
use Espo\Entities\User;
/**
* Not for direct use. Use `TemplateRenderer`.
* @internal
*/
class HtmlizerFactory
{
public function __construct(
private InjectableFactory $injectableFactory,
private DateTimeFactory $dateTimeFactory,
private AclManager $aclManager
) {}
public function create(bool $skipAcl = false, ?string $timeZone = null): Htmlizer
{
$with = [];
if ($skipAcl) {
$with['acl'] = null;
}
if ($timeZone) {
$with['dateTime'] = $this->dateTimeFactory->createWithTimeZone($timeZone);
}
return $this->injectableFactory->createWith(Htmlizer::class, $with);
}
public function createNoAcl(): Htmlizer
{
return $this->create(true);
}
public function createForUser(User $user, ?CreateForUserParams $params = null): Htmlizer
{
if (!$params) {
$params = new CreateForUserParams();
$params->useUserTimezone = true;
$params->applyAcl = true;
}
$deps = [];
if ($params->useUserTimezone) {
$deps['dateTime'] = $this->dateTimeFactory->createWithUserTimeZone($user);
}
if ($params->applyAcl) {
$deps['acl'] = $this->aclManager->createUserAcl($user);
$deps['user'] = $user;
}
return $this->injectableFactory->createWith(Htmlizer::class, $deps);
}
}

View File

@@ -0,0 +1,181 @@
<?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\Htmlizer;
use Espo\Core\ApplicationState;
use Espo\ORM\Entity;
use Espo\Entities\User;
use stdClass;
use InvalidArgumentException;
use LogicException;
class TemplateRenderer
{
/** @var ?array<string, mixed> */
private $data = null;
private ?User $user = null;
private ?Entity $entity = null;
private bool $skipRelations = false;
private bool $skipInlineAttachmentHandling = false;
private bool $applyAcl = false;
private bool $useUserTimezone = false;
private HtmlizerFactory $htmlizerFactory;
private ApplicationState $applicationState;
private ?string $template = null;
public function __construct(HtmlizerFactory $htmlizerFactory, ApplicationState $applicationState)
{
$this->htmlizerFactory = $htmlizerFactory;
$this->applicationState = $applicationState;
}
public function setUser(User $user): self
{
$this->user = $user;
return $this;
}
public function setEntity(Entity $entity): self
{
$this->entity = $entity;
return $this;
}
/**
* @param stdClass|array<string, mixed> $data Additional data.
*/
public function setData($data): self
{
/** @var mixed $data */
if (!is_array($data) && !$data instanceof stdClass) {
throw new InvalidArgumentException();
}
if (is_object($data)) {
$data = get_object_vars($data);
}
$this->data = $data;
return $this;
}
public function setSkipRelations(bool $skipRelations = true): self
{
$this->skipRelations = $skipRelations;
return $this;
}
public function setSkipInlineAttachmentHandling(bool $skipInlineAttachmentHandling = true): self
{
$this->skipInlineAttachmentHandling = $skipInlineAttachmentHandling;
return $this;
}
public function setApplyAcl(bool $applyAcl = true): self
{
$this->applyAcl = $applyAcl;
return $this;
}
public function setUseUserTimezone(bool $useUserTimezone = true): self
{
$this->useUserTimezone = $useUserTimezone;
return $this;
}
public function setTemplate(string $template): self
{
$this->template = $template;
return $this;
}
public function render(): string
{
if (!$this->template) {
throw new LogicException("No template.");
}
return $this->renderTemplate($this->template);
}
public function renderTemplate(string $template): string
{
return $this->renderTemplateInternal($template, $this->createHtmlizer());
}
private function renderTemplateInternal(string $template, Htmlizer $htmlizer): string
{
return $htmlizer->render(
$this->entity,
$template,
null,
$this->data,
$this->skipRelations,
$this->skipInlineAttachmentHandling
);
}
/**
* @return string[]
*/
public function renderMultipleTemplates(string ...$templateList): array
{
$htmlizer = $this->createHtmlizer();
$resultList = [];
foreach ($templateList as $template) {
$resultList[] = $this->renderTemplateInternal($template, $htmlizer);
}
return $resultList;
}
private function createHtmlizer(): Htmlizer
{
$user = $this->user ?? $this->applicationState->getUser();
$params = new CreateForUserParams();
$params->applyAcl = $this->applyAcl;
$params->useUserTimezone = $this->useUserTimezone;
return $this->htmlizerFactory->createForUser($user, $params);
}
}

View File

@@ -0,0 +1,47 @@
<?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\Htmlizer;
use Espo\Core\InjectableFactory;
class TemplateRendererFactory
{
private $injectableFactory;
public function __construct(InjectableFactory $injectableFactory)
{
$this->injectableFactory = $injectableFactory;
}
public function create(): TemplateRenderer
{
return $this->injectableFactory->create(TemplateRenderer::class);
}
}