fix: make project template inheritance granular and safe
linter / quality (pull_request) Successful in 2m52s
tests / ci (8.4) (pull_request) Successful in 3m15s

This commit is contained in:
Nico Schröder
2026-09-08 12:03:07 +02:00
parent 0f125f17a3
commit 3122e00ed8
50 changed files with 1504 additions and 624 deletions
@@ -10,23 +10,39 @@ class UpdateProjectTemplateLink
{
public function __construct(
private readonly DuplicateProjectConfiguration $duplicateProjectConfiguration,
private readonly ProjectTemplateOverrideManager $projectTemplateOverrideManager,
) {}
public function switch(Project $project, ProjectTemplate $template): void
{
DB::transaction(function () use ($project, $template): void {
$project = Project::query()->whereKey($project->id)->lockForUpdate()->firstOrFail();
$configuration = $this->duplicateProjectConfiguration->normalizeConfiguration(
$template->configuration_snapshot ?? [],
);
$localAreas = array_values(array_diff(
DuplicateProjectConfiguration::copyableAreas(),
array_keys($configuration),
));
$project->forceFill([
'project_template_id' => $template->id,
])->save();
'template_overrides' => $localAreas,
])->saveQuietly();
$this->duplicateProjectConfiguration->apply(
$blockedAreas = $this->duplicateProjectConfiguration->apply($project, $configuration);
$this->projectTemplateOverrideManager->clear(
$project->fresh(),
$template->configuration_snapshot ?? [],
array_values(array_diff(array_keys($configuration), $blockedAreas)),
);
});
}
public function reset(Project $project): void
/**
* @param list<string> $areas
* @param array<int|string, int|string> $statusReplacements
*/
public function reset(Project $project, array $areas, array $statusReplacements = []): void
{
$template = $project->projectTemplate;
@@ -34,10 +50,19 @@ class UpdateProjectTemplateLink
return;
}
DB::transaction(function () use ($project, $template): void {
$this->duplicateProjectConfiguration->apply(
$project->fresh(),
DB::transaction(function () use ($project, $template, $areas, $statusReplacements): void {
$project = Project::query()->whereKey($project->id)->lockForUpdate()->firstOrFail();
$configuration = collect($this->duplicateProjectConfiguration->normalizeConfiguration(
$template->configuration_snapshot ?? [],
))->only($areas)->all();
$blockedAreas = $this->duplicateProjectConfiguration->apply(
$project,
$configuration,
$statusReplacements,
);
$this->projectTemplateOverrideManager->clear(
$project->fresh(),
array_values(array_diff(array_keys($configuration), $blockedAreas)),
);
});
}