Files
KanbanGit/app/Actions/Projects/UpdateProjectTemplateLink.php
T
Twyco 1291a0fcad
CI/CD / preconditions (pull_request) Successful in 4s
CI/CD / test_and_check_app (pull_request) Failing after 2m14s
CI/CD / Publish immutable image (pull_request) Skipped
fix(KAN-14): preserve template inheritance and project data
2026-10-15 11:38:17 +02:00

82 lines
3.3 KiB
PHP

<?php
namespace App\Actions\Projects;
use App\Models\Project;
use App\Models\ProjectTemplate;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
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 {
$template = ProjectTemplate::query()->whereKey($template->id)->lockForUpdate()->firstOrFail();
$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,
'template_overrides' => $localAreas,
])->saveQuietly();
$blockedAreas = $this->duplicateProjectConfiguration->apply($project, $configuration);
$this->projectTemplateOverrideManager->clear(
$project->fresh(),
array_values(array_diff(array_keys($configuration), $blockedAreas)),
);
});
}
/**
* @param list<string> $areas
* @param array<int|string, int|string> $statusReplacements
*/
public function reset(Project $project, array $areas, array $statusReplacements = []): array
{
$template = $project->projectTemplate;
if ($template === null) {
return [];
}
return DB::transaction(function () use ($project, $template, $areas, $statusReplacements): array {
$template = ProjectTemplate::query()->whereKey($template->id)->lockForUpdate()->firstOrFail();
$project = Project::query()->whereKey($project->id)->lockForUpdate()->firstOrFail();
if ($project->project_template_id !== $template->id) {
throw ValidationException::withMessages(['areas' => 'The linked template changed. Reload this project before resetting.']);
}
$baseline = $this->duplicateProjectConfiguration->normalizeConfiguration($template->configuration_snapshot ?? []);
$configuration = collect($baseline)->only($areas)->all();
if (in_array('ticket_statuses', $areas, true)
&& ! in_array('status_transitions', $project->template_overrides ?? [], true)
&& isset($baseline['status_transitions'])) {
$configuration['status_transitions'] = $baseline['status_transitions'];
}
$blockedAreas = $this->duplicateProjectConfiguration->apply(
$project,
$configuration,
$statusReplacements,
);
$this->projectTemplateOverrideManager->clear(
$project->fresh(),
array_values(array_diff(array_keys($configuration), $blockedAreas)),
);
return $blockedAreas;
}, 3);
}
}