135 lines
5.2 KiB
PHP
135 lines
5.2 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' => $currentConfiguration,
|
|
'localConfiguration' => array_diff_key($currentConfiguration, $templateConfiguration),
|
|
'localAreas' => collect(array_diff(array_keys($currentConfiguration), array_keys($templateConfiguration)))->map(fn (string $area): array => ['label' => $this->labelForArea($area), 'value' => $area])->values()->all(),
|
|
'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] ?? null;
|
|
if (! is_array($templateStatuses)) {
|
|
return [];
|
|
}
|
|
|
|
$statuses = $project->ticketStatuses()->withCount('tickets')->get();
|
|
$templateKeys = array_column($templateStatuses, 'configuration_key');
|
|
$replacementOptions = collect($templateStatuses)->map(
|
|
static fn (array $status): array => ['id' => $status['configuration_key'], 'name' => $status['name']],
|
|
)->all();
|
|
$removedStatuses = $statuses
|
|
->filter(static fn ($status): bool => ! in_array($status->configuration_key, $templateKeys, true) && $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;
|
|
}
|
|
}
|