} $attributes */ public function handle(ProjectTemplate $projectTemplate, array $attributes): ProjectTemplate { $projectTemplate->loadMissing('sourceProject', 'linkedProjects.projectTemplate'); $sourceProject = $projectTemplate->sourceProject; abort_if($sourceProject === null, 422, 'This template cannot be edited because the source project is missing.'); $copyAreas = array_values(Arr::get($attributes, 'copy_areas', [])); $normalizedCopyAreas = $this->duplicateProjectConfiguration->normalizeCopyAreas($copyAreas); $previousConfiguration = $projectTemplate->configuration_snapshot ?? []; $nextConfiguration = $this->duplicateProjectConfiguration->export($sourceProject, $normalizedCopyAreas); $affectedAreas = array_values(array_unique([ ...array_keys($previousConfiguration), ...array_keys($nextConfiguration), ])); DB::transaction(function () use ($projectTemplate, $attributes, $normalizedCopyAreas, $nextConfiguration, $previousConfiguration, $affectedAreas): void { $projectTemplate->forceFill([ 'name' => $attributes['name'], 'copy_areas' => $normalizedCopyAreas, 'configuration_snapshot' => $nextConfiguration, ])->save(); foreach ($projectTemplate->linkedProjects as $linkedProject) { $currentConfiguration = $this->duplicateProjectConfiguration->export($linkedProject->fresh(), $affectedAreas); $replacementConfiguration = []; foreach ($nextConfiguration as $area => $configuration) { $isNewTemplateArea = ! array_key_exists($area, $previousConfiguration); $matchesPreviousTemplate = array_key_exists($area, $previousConfiguration) && array_key_exists($area, $currentConfiguration) && $currentConfiguration[$area] === $previousConfiguration[$area]; if ($isNewTemplateArea || $matchesPreviousTemplate) { $replacementConfiguration[$area] = $configuration; } } if ($replacementConfiguration === []) { continue; } $this->duplicateProjectConfiguration->apply($linkedProject->fresh(), $replacementConfiguration); } }); return $projectTemplate->fresh(['sourceProject'])->loadCount('linkedProjects'); } }