The primary destination comes first. */ public function selectedS3Storages(): Collection { $storages = $this->relationLoaded('s3Storages') ? $this->s3Storages->sortBy('name') : $this->s3Storages()->orderBy('s3_storages.name')->get(); if ($storages->isEmpty()) { return $this->s3 ? collect([$this->s3]) : collect(); } return $storages ->sortBy(fn (S3Storage $storage): int => $storage->id === $this->s3_storage_id ? 0 : 1) ->values(); } /** * Schedules that send backups to the given storage. */ public function scopeUsingS3Storage(Builder $query, int $storageId): Builder { return $query->where(fn (Builder $query) => $query ->where('s3_storage_id', $storageId) ->orWhereHas('s3Storages', fn (Builder $query) => $query->whereKey($storageId))); } /** * Gives a cloned schedule the same destinations, limited to storages of the clone's team. */ public function copyS3StoragesTo(self $copy): void { $copy->s3Storages()->sync( $this->s3Storages()->where('s3_storages.team_id', $copy->team_id)->pluck('s3_storages.id')->all(), ); } /** * Replaces the selected destinations. The current primary destination stays primary when it is still selected. * * @param array $storageIds */ public function syncS3Storages(array $storageIds): void { $storageIds = collect($storageIds)->map(fn ($id): int => (int) $id)->filter()->unique()->values(); $this->s3Storages()->sync($storageIds->all()); $this->s3_storage_id = $storageIds->contains($this->s3_storage_id) ? $this->s3_storage_id : $storageIds->first(); $this->save(); } }