Files
kupshop/bundles/KupShop/ContentBundle/Util/BlocekSettings.php
2025-08-02 16:30:27 +02:00

236 lines
8.6 KiB
PHP

<?php
namespace KupShop\ContentBundle\Util;
use KupShop\ComponentsBundle\Utils\ComponentsLocator;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Context\DomainContext;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Util\Logging\SentryLogger;
use KupShop\LLMBundle\TextObjects\BlocekTextBlock;
use KupShop\LLMBundle\TextObjects\ProductBlocekTextBlock;
use KupShop\LLMBundle\Util\TextObjectUtil;
use Symfony\Contracts\Service\Attribute\Required;
class BlocekSettings
{
#[Required]
public DomainContext $domainContext;
#[Required]
public LanguageContext $languageContext;
public ?ComponentsLocator $componentsLocator;
public ?TextObjectUtil $textObjectUtil;
#[Required]
public SentryLogger $sentryLogger;
private bool $isDevelopment;
private bool $isWpjAdmin;
private bool $allowHtml;
private string $urlPrefix;
private string $adminPath;
private string $language;
private string $feLanguage;
private array $modules;
private array $components;
private array $llmPrompts;
public function fetchSettings(): void
{
$config = Config::get()->getContainer();
$settings = \Settings::getDefault();
$user = getAdminUser();
$isLocalDev = ($this->domainContext->getActiveId() == 'www.kupshop.local' || $this->domainContext->getActiveId() == 'kupshop.local');
$originalAddr = $config['Addr']['full_original'] ?? '/';
$adminPath = $config['Path']['admin'];
$this->isDevelopment = (isDevelopment() && $isLocalDev);
$this->urlPrefix = "{$originalAddr}{$adminPath}";
$this->adminPath = '/'.ltrim($adminPath, '/');
$this->isWpjAdmin = $user['superuser'] ?? false;
$this->allowHtml = $settings['blocek_allow_html'] == 'Y';
$this->language = $config['Lang']['language'] == 'en' ? 'en' : 'cs';
$this->feLanguage = $this->languageContext->getActiveId();
$this->modules = $this->loadModules();
if (findModule(\Modules::COMPONENTS)) {
$this->components = $this->loadComponents();
}
if (findModule(\Modules::LLM)) {
$this->llmPrompts = $this->loadLlmPrompts([BlocekTextBlock::getLabel(), ProductBlocekTextBlock::getLabel()]);
}
}
private function loadModules(): array
{
return [
\Modules::COMPONENTS => findModule(\Modules::COMPONENTS),
\Modules::VIDEOS => findModule(\Modules::CDN) && findModule(\Modules::VIDEOS),
];
}
private function loadComponents(): array
{
$loadedComponents = [];
try {
foreach ($this->componentsLocator->getComponents() as $component) {
$reflectionClass = new \ReflectionClass($component['class']);
if ($attributes = $reflectionClass->getAttributes('KupShop\ComponentsBundle\Attributes\Blocek', \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null) {
$loadedComponents[] = [
'name' => $component['name'],
'title' => $attributes->getArguments()['title'] ?? null,
'descr' => $attributes->getArguments()['descr'] ?? null,
'icon' => $attributes->getArguments()['icon'] ?? null,
'attributes' => $this->loadAttributes($reflectionClass),
'lazy_component' => $attributes->getArguments()['lazy'] ?? false,
];
}
}
} catch (\ReflectionException $e) {
$this->sentryLogger->captureException($e);
}
return $loadedComponents;
}
private function loadLlmPrompts(array $textObjects): array
{
$result = [];
foreach ($textObjects as $textObject) {
$result[$textObject] = array_values(array_map(fn ($prompt) => [
'id' => $prompt->getId(),
'title' => $prompt->getTitle(),
], $this->textObjectUtil->getObjectLabelPrompts($textObject)));
}
return $result;
}
/** @throws \Exception */
private function loadAttributes(\ReflectionClass $reflectionClass): array
{
$loadedAttributes = [];
foreach ($reflectionClass->getProperties() as $property) {
if ($attributes = $property->getAttributes('KupShop\ComponentsBundle\Attributes\BlocekAttribute', \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null) {
$loadedAttributes[$property->getName()] = [
'name' => $property->getName(),
'default' => !empty($attributes->getArguments()['default']) ? $attributes->getArguments()['default'] : $property->getDefaultValue(),
'type' => !empty($attributes->getArguments()['type']) ? $attributes->getArguments()['type'] : $this->processBlocekTypeConversion($property),
'title' => !empty($attributes->getArguments()['title']) ? $attributes->getArguments()['title'] : $property->getName(),
'options' => $this->getAttributeOptionValues($attributes, $reflectionClass),
];
if (!empty($attributes->getArguments()['autocompleteType'])) {
$loadedAttributes[$property->getName()]['autocompleteType'] = $attributes->getArguments()['autocompleteType'];
$loadedAttributes[$property->getName()]['autocompleteMulti'] = !empty($attributes->getArguments()['autocompleteMulti']) ? $attributes->getArguments()['autocompleteMulti'] : false;
$loadedAttributes[$property->getName()]['autocompletePreload'] = !empty($attributes->getArguments()['autocompletePreload']) ? $attributes->getArguments()['autocompletePreload'] : null;
$loadedAttributes[$property->getName()]['autocompleteInvert'] = isset($attributes->getArguments()['autocompleteInvert']) ? $attributes->getArguments()['autocompleteInvert'] : null;
$loadedAttributes[$property->getName()]['autocompleteSortable'] = isset($attributes->getArguments()['autocompleteSortable']) ? $attributes->getArguments()['autocompleteSortable'] : null;
}
}
}
return $loadedAttributes;
}
private function getAttributeOptionValues(\ReflectionAttribute $attributes, \ReflectionClass $class): array
{
if (!empty($attributes->getArguments()['options'])) {
$options = $attributes->getArguments()['options'];
if (is_string($options) && $class->hasMethod($options)) {
return $class->getMethod($options)->invoke(null);
}
return $attributes->getArguments()['options'];
}
return [];
}
private function processBlocekTypeConversion(\ReflectionProperty $property): BlocekTypes
{
return match ($property->getType()->getName()) {
'int' => BlocekTypes::NUMBER,
'string' => BlocekTypes::TEXT,
'bool' => BlocekTypes::TOGGLE,
default => throw new \Exception('Add new conversion type or specify trough parameter'),
};
}
public function isDevelopment(): bool
{
return $this->isDevelopment;
}
public function getUrlPrefix(): string
{
return $this->urlPrefix;
}
public function isWpjAdmin(): bool
{
return $this->isWpjAdmin;
}
public function isAllowHtml(): bool
{
return $this->allowHtml;
}
public function getLanguage(): string
{
return $this->language;
}
public function getFeLanguage(): string
{
return $this->feLanguage;
}
public function getModules(): array
{
return $this->modules;
}
public function getComponents(): array
{
return $this->components;
}
public function asArray(): array
{
$array = [
'isDevelopment' => $this->isDevelopment,
'isWpjAdmin' => $this->isWpjAdmin,
'allowHtml' => $this->allowHtml,
'urlPrefix' => $this->urlPrefix,
'adminPath' => $this->adminPath,
'language' => $this->language,
'feLanguage' => $this->feLanguage,
'modules' => $this->modules,
'llmPrompts' => $this->llmPrompts,
];
if (findModule(\Modules::COMPONENTS)) {
$array['components'] = $this->components;
}
return $array;
}
#[Required]
public function setComponentsLocator(?ComponentsLocator $componentsLocator = null): void
{
$this->componentsLocator = $componentsLocator;
}
#[Required]
public function setTextObjectUtil(?TextObjectUtil $textObjectUtil): void
{
$this->textObjectUtil = $textObjectUtil;
}
}