Files
preland/components/utm-codec.php
Panfilov Konstantin 965eb2e6a5
deploy-preland / deploy zoomstage.online (push) Successful in 42s
fix(utm): заменить публичную chob на banch (#327)
2026-10-25 05:09:55 +03:00

89 lines
4.4 KiB
PHP

<?php
/** api#326: внешняя граница UTM; semantic-контекст шаблонов остаётся прежним. */
declare(strict_types=1);
function prelandUtmEnums(): array
{
return ['theme'=>['1'=>'dark','2'=>'light'], 'reg'=>['1'=>'before','2'=>'after'], 'banch'=>['1'=>'b','2'=>'a'], 'focus'=>['1'=>'face','2'=>'center']];
}
/** Совместимость host-config при доставке кода до точечной миграции. */
function prelandNumericUtmConfig(array $config): array
{
$settings = is_array($config['utm'] ?? null) ? $config['utm'] : [];
foreach (['registration'=>'reg','chob'=>'banch','bchoice'=>'banch'] as $old=>$new) {
if (!isset($settings[$new]) && isset($settings[$old])) $settings[$new] = $settings[$old];
unset($settings[$old]);
}
unset($settings['chb']);
foreach (prelandUtmEnums() as $key=>$map) {
if (!is_array($settings[$key] ?? null)) continue;
$weights=[];
foreach ((array)($settings[$key]['weights'] ?? []) as $variant=>$weight) {
$digit=array_search((string)$variant,$map,true);
$weights[$digit === false ? $variant : $digit]=$weight;
}
$settings[$key]['weights']=$weights;
$default=$settings[$key]['default'] ?? null;
$digit=array_search($default,$map,true);
if ($digit !== false) $settings[$key]['default']=(string)$digit;
}
$config['utm']=$settings;
return $config;
}
/** Выбирает random один раз, до рендера/сохранения загрузки. */
function prelandResolveUtm(array $query, array $config): array
{
$config=prelandNumericUtmConfig($config);
$defaults=['indpic'=>'1','theme'=>'2','degr'=>'1','reg'=>'2','banch'=>'2','tp'=>'1','cons'=>'2','focus'=>'1'];
$enums=prelandUtmEnums(); $digits=[]; $context=$query;
foreach (['registration','bchoice','chob','chb'] as $old) unset($context[$old]);
foreach ($defaults as $key=>$fallback) {
unset($context[$key]);
$settings=$config['utm'][$key] ?? [];
$valid=static fn($digit): bool => preg_match('/^[1-9]$/D',(string)$digit)===1
&& (!isset($enums[$key]) || isset($enums[$key][$digit]))
&& (in_array($key,['cons','theme','reg','banch','focus'],true) || isset($settings['weights'][$digit]));
$default=(string)($settings['default'] ?? $fallback);
if (!$valid($default)) $default=$fallback;
$value=$query[$key] ?? null;
$digit=is_string($value) && preg_match('/\A.{4}([0-9])/us',$value,$match) ? $match[1] : null;
if ($digit==='0') {
// Generic resolver исторически выбирает первый ключ при sum<=0;
// cons имеет отдельный контракт: только положительные веса и default.
if ($key !== 'cons') {
$weights=(array)($settings['weights'] ?? []);
$total=array_sum($weights);
$digit=$weights ? (string)array_key_first($weights) : $default;
if ($total>0 && is_finite((float)$total)) {
$point=mt_rand()/mt_getrandmax()*$total; $current=0.0;
foreach ($weights as $variant=>$weight) {
$current+=(float)$weight;
$digit=(string)$variant;
if ($point<=$current) break;
}
}
} else {
$weights=[];
foreach ((array)($settings['weights'] ?? []) as $variant=>$weight) {
if ($valid($variant) && is_numeric($weight) && is_finite((float)$weight) && (float)$weight>0) $weights[$variant]=(float)$weight;
}
$total=array_sum($weights); $digit=$default;
if ($total>0 && is_finite($total)) {
$point=mt_rand()/(mt_getrandmax()+1.0)*$total;
foreach ($weights as $variant=>$weight) {
if ($point<$weight) { $digit=(string)$variant; break; }
$point-=$weight;
}
}
}
}
if (!$valid($digit ?? '')) $digit=$default;
$digits[$key]=$digit;
$internal=['reg'=>'registration','banch'=>'bchoice'][$key] ?? $key;
$context[$internal]=$enums[$key][$digit] ?? $digit;
}
return ['digits'=>$digits,'context'=>$context];
}