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
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/** api#347: общий редактор, копирование и старое приватное состояние. */
|
||||
declare(strict_types=1);
|
||||
require dirname(__DIR__).'/bootstrap.php';
|
||||
use PrelandAdmin\{Config,Copy,LinkBuilder,Notes,Store,Problem};
|
||||
function partCheck(bool $ok,string $message): void {if(!$ok)throw new RuntimeException($message);echo "PASS $message\n";}
|
||||
$valid=Config::decode('{"host":"keep.example","metadata":{"keep":true},"utm":{"part":{"default":"2","weights":{"1":0,"2":100}},"unknown":{"keep":true}}}');
|
||||
Config::validate($valid,static fn()=>true);
|
||||
foreach (['{"default":"3","weights":{}}','{"default":"1","weights":{"9":1}}','{"default":"1","weights":{"2":-1}}'] as $group) {
|
||||
$invalid=Config::decode('{"utm":{"part":'.$group.'}}');$rejected=false;
|
||||
try {Config::validate($invalid,static fn()=>true);}catch(Problem){$rejected=true;}
|
||||
partCheck($rejected,'invalid part enum/weights rejected');
|
||||
}
|
||||
$project=new ReflectionMethod(Copy::class,'project');$changes=$project->invoke(null,$valid);
|
||||
$target=Config::decode('{"host":"before.example","notes":"keep","utm":{"part":{"default":"1","weights":{"1":1},"metadata":"keep"},"unknown":{"keep":true}}}');
|
||||
$patched=Config::patch($target,$changes);
|
||||
partCheck($patched->utm->part->default==='2'&&$patched->utm->part->weights->{'2'}===100,'copy includes part default and weights');
|
||||
partCheck($patched->notes==='keep'&&$patched->utm->part->metadata==='keep'&&$patched->utm->unknown->keep===true,'copy preserves metadata and unknown groups');
|
||||
$root=sys_get_temp_dir().'/part347-'.bin2hex(random_bytes(6));$store=new Store($root);
|
||||
$notes=new Notes($store);$old=$notes->all();unset($old['part']);$store->write('utm-notes.json',$old);
|
||||
$loaded=$notes->all();partCheck(isset($loaded['part'])&&array_diff_key($loaded,['part'=>true])===$old,'old notes gain empty part without losing notes/versions');
|
||||
$notes->save(['marker'=>'part','text'=>'Видимость ссылки на сайте','version'=>$loaded['part']['version']]);
|
||||
partCheck($notes->all()['part']['text']==='Видимость ссылки на сайте','part note saves with CAS');
|
||||
$store->write('targets.json',['fixture'=>['id'=>'fixture','domain'=>'fixture.example']]);
|
||||
$oldSelection=['indpic'=>'1','theme'=>'1','degr'=>'1','reg'=>'2','banch'=>'2','tp'=>'1','cons'=>'2','focus'=>'1'];
|
||||
$params=[];foreach($oldSelection as $key=>$value)$params[$key]='abcd'.$value.'abcdefabcdef';
|
||||
$store->write('link-builder-fixture.json',['selection'=>$oldSelection,'url'=>'https://fixture.example/?'.http_build_query($params),'saved_at'=>'2026-10-28T01:00:00+00:00']);
|
||||
$builder=new LinkBuilder($store);$saved=$builder->get('fixture');
|
||||
partCheck($saved['selection']===$oldSelection+['part'=>'1'],'old saved builder choice gains default1');
|
||||
parse_str(parse_url($saved['url'],PHP_URL_QUERY),$newParams);
|
||||
partCheck(array_intersect_key($newParams,$params)===$params&&$newParams['part'][4]==='1','migration preserves old noise and adds masked part');
|
||||
partCheck($builder->get('fixture')===$saved,'migrated builder reload preserves exact noise');
|
||||
foreach(['1','2','rnd'] as $part)partCheck($builder->save('fixture',array_replace($saved['selection'],['part'=>$part]))['selection']['part']===$part,'builder supports part '.$part);
|
||||
try{$builder->save('fixture',array_replace($saved['selection'],['part'=>'3']));throw new RuntimeException('invalid builder part accepted');}catch(Problem){}
|
||||
echo "Part admin contract complete\n";
|
||||
|
||||
Reference in new issue
Block a user