Files
SGF/scripts/sgf-install-single-workspace.php
T
2026-11-11 09:00:17 +02:00

25 lines
5.0 KiB
PHP

<?php
// Install approved SGF application code into the existing private8085 app.
// The native frozen Purchasing bundle, bootstrap/SGC routes and cached data are excluded.
use Symfony\Component\Process\Process;
$book='8085';require __DIR__.'/sgf-single-bootstrap.php';
$build=$run['root'].'/private/single-ui-build-20261110';if(!is_file($build.'/manifest.json'))throw new LogicException('Private build missing');
$pins=json_decode(file_get_contents($s['root'].'/single-binding-pins.json'),true);
$configuration=['enabled'=>true,'schema_sha256'=>$host->table('sgf_composition_schema')->value('source_hash'),'profiles_sha256'=>App\Shared\Installation\SyntheticProfiles::fingerprint(App\Shared\Installation\SyntheticProfiles::policy()),'bindings_sha256'=>$pins['single-bindings.json'],'material_perimeter_sha256'=>hash_file('sha256',$s['root'].'/single-material-perimeter.json'),'ledger_enabled'=>true,'finance_enabled'=>true];
$files=['app/Modules/Identity/Services/IdentityWorkflow.php','app/Modules/Purchasing/ReceiptRuntime.php','app/Modules/Purchasing/ComposedFinance.php','app/Modules/Purchasing/ComposedFinanceController.php','app/Modules/Inventory/StockOperationsController.php','app/Shared/Context/ModuleNavigation.php','app/Shared/Installation/PresentationEntry.php','app/Shared/Installation/SyntheticProfiles.php','routes/web.php','resources/views/sgf-presentation-entry.blade.php','resources/views/finance/composed-payables.blade.php','resources/views/accounting/composed-ledger.blade.php','resources/views/stock-operations-workspace.blade.php','public/stock-operations-workspace.mjs','public/sgf-finance-payables.mjs','public/sgf-composed-ledger.mjs'];
foreach(glob($repo.'/app/Modules/Accounting/*.php') as $file)$files[]=str_replace('\\','/',substr($file,strlen($repo)+1));
$iterator=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($repo.'/packages/general-ledger',FilesystemIterator::SKIP_DOTS));foreach($iterator as $file)if($file->isFile()&&in_array($file->getExtension(),['php','json'],true))$files[]=str_replace('\\','/',substr($file->getPathname(),strlen($repo)+1));
$files=array_values(array_unique($files));$backup=$work.'/application-before';mkdir($backup,0700,true);$source=[];$before=[];
foreach($files as $file){if(str_ends_with($file,'.php'))(new Process([PHP_BINARY,'-l',$repo.'/'.$file]))->mustRun();$source[$file]=hash_file('sha256',$repo.'/'.$file);$before[$file]=is_file($s['app'].'/'.$file)?hash_file('sha256',$s['app'].'/'.$file):null;}
$copy=function($from,$relative)use($s,$backup){$target=$s['app'].'/'.$relative;$save=$backup.'/'.$relative;if(is_file($target)){if(!is_dir(dirname($save)))mkdir(dirname($save),0700,true);copy($target,$save);}if(!is_dir(dirname($target)))mkdir(dirname($target),0700,true);if(!copy($from,$target))throw new RuntimeException('Copy failed: '.$relative);};
foreach($files as $file){if($before[$file]!==null&&!hash_equals($before[$file],hash_file('sha256',$s['app'].'/'.$file)))throw new LogicException('Concurrent application edit: '.$file);$copy($repo.'/'.$file,$file);}
foreach(glob($build.'/assets/*') as $asset)$copy($asset,'public/build/assets/'.basename($asset));$copy($build.'/manifest.json','public/build/manifest.json');
// Preserve the SELECT-only reader connection and all original bindings.
$readPath=$s['root'].'/stock-binding.json';$read=json_decode(file_get_contents($readPath),true);copy($readPath,$work.'/stock-binding-before.json');$template=$read['bindings'][implode(':',array_values($f['scope'])).':'.$f['validator']];$ledger=json_decode(file_get_contents($s['root'].'/single-native-ledger.json'),true);$people=json_decode(file_get_contents($s['root'].'/single-profiles.json'),true)['profiles'];
foreach([$f['validator'],$people['workshop_record']['user_id'],$people['workshop_verify']['user_id'],$people['read_only']['user_id']] as $user)$read['bindings'][implode(':',array_values($f['scope'])).':'.$user]=array_replace($template,['warehouse_ids'=>[$nf['warehouse'],$ledger['warehouse_id']]]);
file_put_contents($readPath,json_encode($read,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
$configs=['stock_operations'=>['enabled'=>true,'profile_sha256'=>$pins['stock-operations-binding.json']],'sales_ledger'=>['synthetic_enabled'=>true],'cost_ledger'=>['synthetic_enabled'=>true,'correction_enabled'=>true],'industrial_ledger'=>['synthetic_enabled'=>true,'correction_enabled'=>true],'sgf_single_installation'=>$configuration];
// Activate last, after all coherent code, immutable assets and bindings are in place.
foreach($configs as $name=>$value){$file=$work.'/'.$name.'.php';file_put_contents($file,"<?php\nreturn ".var_export($value,true).";\n");$copy($file,'config/'.$name.'.php');}
file_put_contents($work.'/workspace-installation.json',json_encode(['passed'=>true,'composition'=>$tag,'port'=>8085,'files'=>$source,'before'=>$before,'flags'=>$configs,'native_bundle_changed'=>false,'cache_cleared'=>false,'new_server'=>false,'new_database'=>false,'sgc_enabled'=>false,'visual_acceptance'=>false],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));echo json_encode(['passed'=>true,'files'=>count($files),'port'=>8085,'proof'=>$work.'/workspace-installation.json']).PHP_EOL;