api#347: передавать и настраивать UTM part без ссылки в Preland
This commit is contained in:
1 parent
94619432a3
commit
0d350ed14b
23 files changed
+126
-47
No files matched your search
@@ -17,7 +17,7 @@ foreach(['2','rnd','dark','abcdx','abc',[],null,'abcd0'] as $value) {
|
||||
if(prelandResolveUtm(["theme"=>"абвг2"],$config)["digits"]["theme"]!=="2")throw new RuntimeException("Unicode fifth symbol");
|
||||
for($i=0;$i<50;$i++) if(prelandResolveUtm(['indpic'=>'abcd0'],$config)['digits']['indpic']!=='2')throw new RuntimeException('0 нарушил веса');
|
||||
$settings=json_decode(file_get_contents(dirname(__DIR__).'/config.json'),true);
|
||||
$defaults=['indpic'=>'1','theme'=>'1','degr'=>'1','reg'=>'2','banch'=>'2','tp'=>'2','cons'=>'2','focus'=>'1'];
|
||||
$defaults=['indpic'=>'1','theme'=>'1','degr'=>'1','reg'=>'2','banch'=>'2','tp'=>'2','cons'=>'2','focus'=>'1','part'=>'1'];
|
||||
foreach(array_keys($defaults) as $key) foreach(['1','rnd','abcdx','abc',[],null,"\xffabcd2"] as $invalid) {
|
||||
$resolved=prelandResolveUtm([$key=>$invalid,'registration'=>'before','bchoice'=>'b','chb'=>'a'],$settings);
|
||||
if($resolved['digits'][$key]!==$defaults[$key])throw new RuntimeException('Открытый/invalid URL изменил '.$key);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/** api#347: part задаёт передаваемый вариант, но никогда не добавляет ссылку на Preland. */
|
||||
declare(strict_types=1);
|
||||
require dirname(__DIR__) . '/components/utm-codec.php';
|
||||
function partCheck(bool $ok, string $message): void { if (!$ok) throw new RuntimeException($message); }
|
||||
foreach (['abcd1'=>'1','abcd2'=>'2','абвг2'=>'2','abcd0'=>'1','abcd9'=>'1','2'=>'1','abcdx'=>'1','abc'=>'1'] as $raw=>$expected) {
|
||||
$value=prelandResolveUtm(['part'=>$raw,'utm_source'=>'keep'],[]);
|
||||
partCheck(($value['digits']['part']??null)===$expected && ($value['context']['part']??null)===$expected, 'part: fifth symbol / default1: '.$raw);
|
||||
partCheck($value['context']['utm_source']==='keep','foreign query preserved');
|
||||
}
|
||||
foreach ([[],null, false, "\xffabcd2"] as $invalid) partCheck((prelandResolveUtm(['part'=>$invalid],[])['digits']['part']??null)==='1','invalid fallback');
|
||||
$config=['utm'=>['part'=>['default'=>'2','weights'=>['1'=>0,'2'=>100]]]];
|
||||
for($i=0;$i<200;$i++) partCheck(prelandResolveUtm(['part'=>'abcd0'],$config)['digits']['part']==='2','random follows configured weights');
|
||||
partCheck(prelandResolveUtm(['part'=>'abcd1'],$config)['digits']['part']==='1','concrete independent of weights');
|
||||
partCheck(prelandResolveUtm([],['utm'=>['part'=>['default'=>'2']]])['digits']['part']==='2','configured default');
|
||||
partCheck(prelandResolveUtm(['part'=>'abcd0'],['utm'=>['part'=>['default'=>'1','weights'=>['2'=>0,'1'=>0]]]])['digits']['part']==='2','existing generic zero weights order');
|
||||
$_GET=['part'=>'abcd2','utm_source'=>'keep'];$_SERVER['HTTP_HOST']='zoomstage.online';
|
||||
ob_start();require dirname(__DIR__).'/index.php';$html=ob_get_clean();
|
||||
partCheck(!array_key_exists('part',$get_params),'part is not foreign query');
|
||||
partCheck($redirect_digits['part']==='2','handoff snapshot part');
|
||||
echo "OK: part numeric/default/random/context/foreign boundary\n";
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
$root = dirname(__DIR__);
|
||||
foreach (['light', 'dark'] as $theme) foreach ([
|
||||
foreach (['abcd1','abcd2','abcd0','invalid'] as $part) foreach (['ru','en'] as $lang) foreach (['light', 'dark'] as $theme) foreach ([
|
||||
'zoomstage.online' => 'zoomstage.online',
|
||||
'New-Preland.example:8080' => 'new-preland.example',
|
||||
'www.example.test.' => 'www.example.test',
|
||||
'<script>alert(1)</script>' => 'fixture.local',
|
||||
] as $host => $expected) {
|
||||
$html = shell_exec(PHP_BINARY . ' ' . escapeshellarg(__DIR__ . '/render-preland.php') . ' ' . escapeshellarg($host) . ' ' . escapeshellarg($theme));
|
||||
$html = shell_exec(PHP_BINARY . ' ' . escapeshellarg(__DIR__ . '/render-preland.php') . ' ' . escapeshellarg($host) . ' ' . escapeshellarg($theme) . ' ' . escapeshellarg($part) . ' ' . escapeshellarg($lang));
|
||||
if (!preg_match('~<footer\b.*?</footer>~s', $html, $match)) throw new RuntimeException('Подвал не найден');
|
||||
$footer = $match[0];
|
||||
foreach (['Наши реквизиты', 'payment.svg', 'ИНН:', 'ОГРНИП:', 'ИП Иванов', 'ИП Кардаполова'] as $forbidden) {
|
||||
foreach (['Наши реквизиты', 'payment.svg', 'ИНН:', 'ОГРНИП:', 'ИП Иванов', 'ИП Кардаполова', 'Для бизнеса', '/public/api-pricing'] as $forbidden) {
|
||||
if (str_contains($footer, $forbidden)) throw new RuntimeException('В подвале остался ' . $forbidden);
|
||||
}
|
||||
if (!str_contains($footer, date('Y') . '© ' . $expected)) throw new RuntimeException('Неправильный домен копирайта: ' . $host);
|
||||
|
||||
@@ -45,7 +45,7 @@ if ($params !== $expected) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ($redirect_digits !== ['indpic'=>'1','theme'=>'1','degr'=>'1','reg'=>'2','banch'=>'2','tp'=>'2','cons'=>'2','focus'=>'1']) {
|
||||
if ($redirect_digits !== ['indpic'=>'1','theme'=>'1','degr'=>'1','reg'=>'2','banch'=>'2','tp'=>'2','cons'=>'2','focus'=>'1','part'=>'1']) {
|
||||
throw new RuntimeException('Type-in обязан сохранить полный resolved numeric snapshot для handoff/recovery.');
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,15 @@ const source = fs.readFileSync('/app/components/utm-handoff.php','utf8').replace
|
||||
const context = {window:{},URLSearchParams,Uint8Array,crypto:require('node:crypto').webcrypto};
|
||||
vm.runInNewContext(source,context);
|
||||
const handoff=context.window.ZoomzillaUtmHandoff;
|
||||
const defaults={indpic:'1',theme:'1',degr:'1',reg:'2',banch:'2',tp:'1',cons:'2',focus:'1'};
|
||||
const selected={indpic:'2',theme:'2',degr:'2',reg:'1',banch:'1',tp:'2',cons:'3',focus:'2'};
|
||||
const defaults={indpic:'1',theme:'1',degr:'1',reg:'2',banch:'2',tp:'1',cons:'2',focus:'1',part:'1'};
|
||||
const selected={indpic:'2',theme:'2',degr:'2',reg:'1',banch:'1',tp:'2',cons:'3',focus:'2',part:'2'};
|
||||
const foreign='utm_source=abcd9same&subid=%D1%82%D0%B5%D1%81%D1%82+%2B+%26&id=42&stage=keep';
|
||||
for(const meta of [
|
||||
{redirectUtm:foreign,utmDigits:selected},
|
||||
{redirectUtm:foreign,utmDigits:{...selected,banch:undefined,chob:'1'}},
|
||||
{redirectUtm:foreign+'&indpic=abcd2&theme=абвг2°r=abcd2®=abcd1&chob=abcd1&tp=abcd2&cons=abcd3&focus=abcd2'},
|
||||
{redirectUtm:foreign+'&indpic=2&theme=light°r=2®istration=before&bchoice=b&tp=2&cons=3&focus=center&chb=a'},
|
||||
{redirectUtm:foreign+'&indpic=abcd2&theme=абвг2°r=abcd2®=abcd1&banch=abcd1&tp=abcd2&cons=abcd3&focus=abcd2'}
|
||||
{redirectUtm:foreign+'&indpic=abcd2&theme=абвг2°r=abcd2®=abcd1&chob=abcd1&tp=abcd2&cons=abcd3&focus=abcd2&part=abcd2'},
|
||||
{redirectUtm:foreign+'&indpic=2&theme=light°r=2®istration=before&bchoice=b&tp=2&cons=3&focus=center&part=2&chb=a'},
|
||||
{redirectUtm:foreign+'&indpic=abcd2&theme=абвг2°r=abcd2®=abcd1&banch=abcd1&tp=abcd2&cons=abcd3&focus=abcd2&part=abcd2'}
|
||||
]){
|
||||
const before=JSON.stringify(meta);
|
||||
const first=new URLSearchParams(handoff.query(meta,defaults));
|
||||
@@ -35,4 +35,9 @@ for(const meta of [
|
||||
}
|
||||
const typeIn=new URLSearchParams(handoff.query({redirectUtm:'',utmDigits:defaults},defaults));
|
||||
for(const [key,digit]of Object.entries(defaults))assert.equal(typeIn.get(key)[4],digit);
|
||||
console.log('OK: all8 fresh noise/repeated handoff, legacy recovery, type-in, foreign/technical values');
|
||||
console.log('OK: all9 fresh noise/repeated handoff, legacy recovery, type-in, foreign/technical values');
|
||||
for (const part of ['abcd9','abcd0','bad']) {
|
||||
const query = new URLSearchParams(handoff.query({redirectUtm:'part='+part},defaults));
|
||||
assert.equal(query.get('part')[4],'1');
|
||||
}
|
||||
assert.equal(new URLSearchParams(handoff.query({utmDigits:{...defaults,part:'9'}},defaults)).get('part')[4],'1');
|
||||
@@ -3,4 +3,6 @@ if (PHP_SAPI !== 'cli') { http_response_code(404); exit; }
|
||||
$_SERVER['HTTP_HOST'] = $argv[1] ?? 'zoomstage.online';
|
||||
$_SERVER['SERVER_NAME'] = 'fixture.local';
|
||||
$_GET = ['theme' => 'abcd' . (($argv[2] ?? 'light') === 'dark' ? '1' : '2'), 'indpic' => 'abcd1'];
|
||||
if (isset($argv[3])) $_GET['part'] = $argv[3];
|
||||
if (isset($argv[4])) $_GET['lang'] = $argv[4];
|
||||
require dirname(__DIR__) . '/index.php';
|
||||
Reference in new issue
Block a user