137 lines
4.9 KiB
PHP
137 lines
4.9 KiB
PHP
<?php
|
|
|
|
namespace App\Actions\Projects;
|
|
|
|
use App\Models\Project;
|
|
use App\Models\ProjectTemplate;
|
|
|
|
class ResolveProjectTemplateState
|
|
{
|
|
public function __construct(
|
|
private readonly DuplicateProjectConfiguration $duplicateProjectConfiguration,
|
|
) {}
|
|
|
|
/**
|
|
* @param list<string>|null $areas
|
|
* @return array<string, mixed>|null
|
|
*/
|
|
public function handle(Project $project, ?array $areas = null): ?array
|
|
{
|
|
$project->loadMissing('projectTemplate');
|
|
|
|
/** @var ProjectTemplate|null $projectTemplate */
|
|
$projectTemplate = $project->projectTemplate;
|
|
|
|
if ($projectTemplate === null) {
|
|
return null;
|
|
}
|
|
|
|
$selectedAreas = $areas === null
|
|
? DuplicateProjectConfiguration::copyableAreas()
|
|
: $this->duplicateProjectConfiguration->normalizeCopyAreas($areas);
|
|
|
|
$normalizedTemplateConfiguration = $this->duplicateProjectConfiguration->normalizeConfiguration(
|
|
$projectTemplate->configuration_snapshot ?? [],
|
|
);
|
|
$templateConfiguration = collect($normalizedTemplateConfiguration)
|
|
->only($selectedAreas)
|
|
->all();
|
|
$currentConfiguration = $this->duplicateProjectConfiguration->export($project, $selectedAreas);
|
|
$persistedOverrides = $projectTemplate->is_published
|
|
? array_values(array_intersect($project->template_overrides ?? [], $selectedAreas))
|
|
: [];
|
|
|
|
$overriddenAreas = [];
|
|
$inheritedAreas = [];
|
|
|
|
foreach ($selectedAreas as $area) {
|
|
$label = $this->labelForArea($area);
|
|
$hasTemplateValue = array_key_exists($area, $templateConfiguration);
|
|
|
|
if (! $hasTemplateValue) {
|
|
continue;
|
|
}
|
|
|
|
if (! in_array($area, $persistedOverrides, true)) {
|
|
$inheritedAreas[] = [
|
|
'label' => $label,
|
|
'value' => $area,
|
|
];
|
|
|
|
continue;
|
|
}
|
|
|
|
$overriddenAreas[] = [
|
|
'label' => $label,
|
|
'value' => $area,
|
|
];
|
|
}
|
|
|
|
$overriddenAreaValues = array_flip(array_column($overriddenAreas, 'value'));
|
|
$inheritedAreaValues = array_flip(array_column($inheritedAreas, 'value'));
|
|
|
|
return [
|
|
'effectiveConfiguration' => array_replace($templateConfiguration, array_intersect_key($currentConfiguration, $overriddenAreaValues)),
|
|
'inheritedAreas' => $inheritedAreas,
|
|
'inheritedConfiguration' => array_intersect_key($templateConfiguration, $inheritedAreaValues),
|
|
'inheritsFromTemplate' => $projectTemplate->is_published,
|
|
'overriddenAreas' => $overriddenAreas,
|
|
'overriddenConfiguration' => array_intersect_key($currentConfiguration, $overriddenAreaValues),
|
|
'resetRequirements' => $this->resetRequirements($project, $templateConfiguration, $persistedOverrides),
|
|
'templateConfiguration' => $templateConfiguration,
|
|
'templateId' => $projectTemplate->id,
|
|
'templateName' => $projectTemplate->name,
|
|
'templateSlug' => $projectTemplate->slug,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $templateConfiguration
|
|
* @param list<string> $persistedOverrides
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function resetRequirements(Project $project, array $templateConfiguration, array $persistedOverrides): array
|
|
{
|
|
if (! in_array(DuplicateProjectConfiguration::COPY_TICKET_STATUSES, $persistedOverrides, true)) {
|
|
return [];
|
|
}
|
|
|
|
$templateStatuses = $templateConfiguration[DuplicateProjectConfiguration::COPY_TICKET_STATUSES] ?? [];
|
|
if (! is_array($templateStatuses)) {
|
|
return [];
|
|
}
|
|
|
|
$statuses = $project->ticketStatuses()->withCount('tickets')->get()->values();
|
|
$replacementOptions = $statuses->take(count($templateStatuses))->map(
|
|
static fn ($status): array => ['id' => $status->id, 'name' => $status->name],
|
|
)->all();
|
|
$removedStatuses = $statuses->slice(count($templateStatuses))
|
|
->filter(static fn ($status): bool => $status->tickets_count > 0)
|
|
->map(static fn ($status): array => [
|
|
'id' => $status->id,
|
|
'name' => $status->name,
|
|
'ticketCount' => $status->tickets_count,
|
|
])
|
|
->values()
|
|
->all();
|
|
|
|
return $removedStatuses === [] ? [] : [
|
|
DuplicateProjectConfiguration::COPY_TICKET_STATUSES => [
|
|
'removedStatuses' => $removedStatuses,
|
|
'replacementOptions' => $replacementOptions,
|
|
],
|
|
];
|
|
}
|
|
|
|
private function labelForArea(string $area): string
|
|
{
|
|
foreach (DuplicateProjectConfiguration::copyAreaOptions() as $option) {
|
|
if ($option['value'] === $area) {
|
|
return $option['label'];
|
|
}
|
|
}
|
|
|
|
return $area;
|
|
}
|
|
}
|