This commit is contained in:
root
2025-11-13 19:04:05 +03:00
commit 240d0aba5f
75129 changed files with 11118122 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
abstract class BaseProvider implements FeaturePromoterProvider
{
public function __construct(protected readonly ProviderConfiguration $configuration)
{
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
class Code
{
private string $featureId;
public function __construct(string $featureId)
{
$this->featureId = $featureId;
}
public function get(): string
{
return "limit_{$this->getVersion()}_$this->featureId";
}
private function getVersion(): string
{
return 'v2';
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
interface FeaturePromoterProvider
{
public function getRendererParameters(): array;
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
use Bitrix\Main\Result;
use Bitrix\Main\Localization\Loc;
use Bitrix\UI\Helpdesk;
class Popup extends BaseProvider
{
private const HELPDESK_PATH = '/widget2/restrictive_popup.php';
public function getRendererParameters(): array
{
$resultLoadingConfigurationFromHelpdesk = $this->loadConfigurationFromHelpdesk();
if ($resultLoadingConfigurationFromHelpdesk->isSuccess())
{
$configuration = $resultLoadingConfigurationFromHelpdesk->getData()['popup'] ?? [];
$validator = new PopupConfigurationValidator($configuration);
return $validator->isValidConfiguration()
? $configuration
: $this->getDefaultConfiguration();
}
return $this->getDefaultConfiguration();
}
private function loadConfigurationFromHelpdesk(): Result
{
$helpdeskRequest = new Helpdesk\Request(self::HELPDESK_PATH, [
'url' => $this->configuration->currentUrl,
'code' => $this->configuration->code,
]);
return $helpdeskRequest->send();
}
private function getDefaultConfiguration(): array
{
return [
'header' => [
'top' => [
'title' => Loc::getMessage('UI_INFOHELPER_PROVIDER_POPUP_DEFAULT_TOP_TITLE'),
],
'info' => [
'title' => Loc::getMessage('UI_INFOHELPER_PROVIDER_POPUP_DEFAULT_DEESCRIPTION'),
'roundContent' => '--rocket',
'moreLabel' => Loc::getMessage('UI_INFOHELPER_PROVIDER_POPUP_MORE_BUTTON'),
'code' => 'limit_why_pay_tariff',
],
'button' => [
'label' => Loc::getMessage('UI_INFOHELPER_PROVIDER_POPUP_EXTRA_BUTTON'),
'url' => '/settings/license_all.php',
],
],
];
}
}

View File

@@ -0,0 +1,166 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
class PopupConfigurationValidator
{
public function __construct(private array $configuration)
{
}
public function isValidConfiguration(): bool
{
if (!is_array($this->configuration['header']) || !is_array($this->configuration['items']))
{
return false;
}
return $this->isValidHeaderConfiguration($this->configuration['header'])
&& $this->isValidItemsConfiguration($this->configuration['items']);
}
private function isValidHeaderConfiguration(array $headerConfiguration): bool
{
if (isset($headerConfiguration['iconClass']) && !is_string($headerConfiguration['iconClass']))
{
return false;
}
return is_array($headerConfiguration['top'])
&& $this->isValidHeaderTopConfiguration($headerConfiguration['top'])
&& is_array($headerConfiguration['info'])
&& $this->isValidHeaderInfoConfiguration($headerConfiguration['info']);
}
private function isValidHeaderTopConfiguration(array $headerTopConfiguration): bool
{
if (isset($headerTopConfiguration['subtitle']) && !is_string($headerTopConfiguration['subtitle']))
{
return false;
}
return is_string($headerTopConfiguration['title']);
}
private function isValidHeaderInfoConfiguration(array $headerInfoConfiguration): bool
{
if (
(isset($headerTopConfiguration['subtitle']) && !is_string($headerTopConfiguration['subtitle']))
|| (isset($headerTopConfiguration['subtitleDescription'])
&& !is_string($headerTopConfiguration['subtitleDescription']))
|| (isset($headerTopConfiguration['moreLabel']) && !is_string($headerTopConfiguration['moreLabel']))
|| (isset($headerTopConfiguration['moreUrl']) && !is_string($headerTopConfiguration['moreUrl']))
|| (isset($headerTopConfiguration['roundContent'])
&& (is_string($headerTopConfiguration['roundContent'])
|| is_array($headerTopConfiguration['roundContent']))
&& !$this->isValidRoundContentConfiguration($headerTopConfiguration['roundContent']))
)
{
return false;
}
return is_string($headerInfoConfiguration['title']);
}
private function isValidRoundContentConfiguration(array|string $roundContentConfiguration): bool
{
if (is_array($roundContentConfiguration))
{
return is_string($roundContentConfiguration['posterUrl'])
&& is_array($roundContentConfiguration['videos'])
&& $this->isValidVideosConfiguration($roundContentConfiguration['videos']);
}
return true;
}
private function isValidVideosConfiguration(array $videosConfiguration): bool
{
foreach ($videosConfiguration as $videoConfiguration)
{
if (!is_string($videoConfiguration['url']) && !is_string($videoConfiguration['type']))
{
return false;
}
}
return true;
}
private function isValidItemsConfiguration(array $itemsConfiguration): bool
{
foreach ($itemsConfiguration as $itemConfiguration)
{
if (!is_array($itemConfiguration) || !$this->isValidItemConfiguration($itemConfiguration))
{
return false;
}
}
return true;
}
private function isValidItemConfiguration(array $itemConfiguration): bool
{
if (
(isset($itemConfiguration['description']) && (!is_array($itemConfiguration['description'])
|| !$this->isValidTextConfiguration($itemConfiguration['description'])))
|| (isset($itemConfiguration['more']) && (!is_array($itemConfiguration['more'])
|| !$this->isValidMoreItemConfiguration($itemConfiguration['more'])))
|| (isset($itemConfiguration['icon']) && (!is_array($itemConfiguration['icon'])
|| !$this->isValidItemIconConfiguration($itemConfiguration['icon'])))
|| (isset($itemConfiguration['button']) && (!is_array($itemConfiguration['button'])
|| !$this->isValidItemButtonConfiguration($itemConfiguration['button'])))
)
{
return false;
}
return is_array($itemConfiguration['title']) && $this->isValidTextConfiguration($itemConfiguration['title']);
}
private function isValidTextConfiguration(array $textConfiguration): bool
{
if (isset($textConfiguration['color']) && !is_string($textConfiguration['color']))
{
return false;
}
return is_string($textConfiguration['text']);
}
private function isValidMoreItemConfiguration(array $itemMoreConfiguration): bool
{
return is_array($itemMoreConfiguration['text'])
&& $this->isValidTextConfiguration($itemMoreConfiguration['text']);
}
private function isValidItemIconConfiguration(array $itemIconConfiguration): bool
{
if (isset($itemIconConfiguration['color']) && !is_string($itemIconConfiguration['color']))
{
return false;
}
return is_string($itemIconConfiguration['name']);
}
private function isValidItemButtonConfiguration(array $itemButtonConfiguration): bool
{
if (
(isset($itemButtonConfiguration['description'])
&& !is_array($itemButtonConfiguration['description'])
&& !$this->isValidTextConfiguration($itemButtonConfiguration['description']))
|| (isset($itemButtonConfiguration['backgroundColor'])
&& !is_string($itemButtonConfiguration['backgroundColor']))
|| (isset($itemButtonConfiguration['onclick']) && !is_string($itemButtonConfiguration['onclick']))
|| (isset($itemButtonConfiguration['url']) && !is_string($itemButtonConfiguration['url']))
)
{
return false;
}
return is_string($itemButtonConfiguration['text']);
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Loader;
class PopupProviderAvailabilityChecker
{
private const MODULE_ID = 'ui';
private const ACCESS_OPTION_NAME = 'info-helper-popup-provider';
private const AVAILABLE_ZONES = ['ru', 'by'];
private const UNDEFINED_OPTION_STATUS = 'undefined';
private const DISABLED_OPTION_STATUS = 'N';
private const ENABLED_OPTION_STATUS = 'Y';
public function isAvailable(): bool
{
if (!Loader::includeModule('bitrix24'))
{
return false;
}
if ($this->isUnavailableByOption())
{
return false;
}
return $this->isAvailableByRegion() || $this->isAvailableByOption();
}
private function isAvailableByOption(): bool
{
return Option::get(self::MODULE_ID, self::ACCESS_OPTION_NAME, self::UNDEFINED_OPTION_STATUS)
=== self::ENABLED_OPTION_STATUS;
}
private function isUnavailableByOption(): bool
{
return Option::get(self::MODULE_ID, self::ACCESS_OPTION_NAME, self::UNDEFINED_OPTION_STATUS)
=== self::DISABLED_OPTION_STATUS;
}
private function isAvailableByRegion(): bool
{
return in_array(\CBitrix24::getPortalZone(), self::AVAILABLE_ZONES);
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
class ProviderConfiguration
{
public function __construct(
public readonly string $type,
public string $code,
public readonly string $currentUrl,
public readonly ?string $featureId
)
{
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
class ProviderFactory
{
public function createProvider(ProviderConfiguration $configuration): FeaturePromoterProvider
{
if ($configuration->featureId)
{
$configuration->code = (new Code($configuration->featureId))->get();
}
if ($configuration->type === ProviderType::POPUP)
{
return (new Popup($configuration));
}
return (new Slider($configuration));
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
class ProviderType
{
public const POPUP = 'popup';
public const SLIDER = 'slider';
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Bitrix\UI\FeaturePromoter;
use Bitrix\Main\Loader;
use Bitrix\UI\Helpdesk;
use Bitrix\Bitrix24;
class Slider extends BaseProvider
{
private const PATH_HELPDESK = '/widget2/show/code/';
public function getRendererParameters(): array
{
$requestHelpdesk = new Helpdesk\Request(self::PATH_HELPDESK, [
'url' => $this->configuration->currentUrl,
'featurePromoterVersion' => 2,
'isPromoEditionAvailable' => $this->isPromoEditionAvailable(),
]);
return [
'frameUrlTemplate' => $requestHelpdesk->getPreparedUrl(),
'code' => $this->configuration->code,
'trialableFeatureList' => $this->getTrialableFeatureList(),
'availableDomainList' => $requestHelpdesk->getUrl()->getDomain()->getList(),
];
}
private function getTrialableFeatureList(): array
{
if (Loader::includeModule('bitrix24'))
{
return Bitrix24\Feature::getTrialableFeatureList();
}
return [];
}
private function isPromoEditionAvailable(): bool
{
if (Loader::includeModule('bitrix24'))
{
if (Loader::includeModule('extranet') && !\CExtranet::isIntranetUser())
{
return false;
}
return Bitrix24\Feature::isPromoEditionAvailableByFeature($this->configuration->featureId ?? '');
}
return false;
}
}