$formData['id'] ?? null]; $project = Project::updateOrCreate($uniqueIdentifier, $formData); $project->upsertBoundingBox($formData); $project->upsertMailRecipients($formData); } private function upsertBoundingBox($formData) { $boundingBoxesData = array_map(function ($boundingBox) { $boundingBox['project_id'] = $this->id; unset($boundingBox['created_at']); unset($boundingBox['updated_at']); $boundingBox['id'] ??= null; return $boundingBox; }, $formData['boundingBoxes'] ?? []); ProjectBoundingBox::upsert( $boundingBoxesData, ['id', 'project_id'], [ 'name', 'top_left_latitude', 'top_left_longitude', 'bottom_right_latitude', 'bottom_right_longitude' ] ); } private function upsertMailRecipients($formData) { $mailRecipientsData = array_map(function ($mailRecipient) { $mailRecipient['project_id'] = $this->id; unset($mailRecipient['created_at']); unset($mailRecipient['updated_at']); $mailRecipient['id'] ??= null; return $mailRecipient; }, $formData['mail_recipients'] ?? []); ProjectEmailRecipient::upsert( $mailRecipientsData, ['id', 'project_id'], ['name', 'email',] ); } private function getMosaicPath() { return sprintf('%s/%s', $this->download_path, 'weekly_mosaic'); } public function getMosaicList(): \Illuminate\Support\Collection { return collect(Storage::files($this->getMosaicPath())) ->filter(fn($file) => Str::endsWith($file, '.tif')) ->sortByDesc(function ($file) { $parts = explode('_', str_replace('.tif', '', $file)); $week = $parts[1]; $year = $parts[2]; return $year.sprintf('%02d', $week); }) ->values(); } protected static function boot() { parent::boot(); // TODO: Change the autogenerated stub static::deleting(function ($project) { $project->boundingBoxes()->delete(); $project->emailRecipients()->delete(); $project->mailings()->each(function ($mailing) { $mailing->attachments()->delete(); $mailing->recipients()->delete(); }); $project->mailings()->delete(); }); } public function reports() { return $this->hasMany(ProjectReport::class); } public function getAttachmentPathAttribute() { return storage_path(sprintf('%s/attachments', $this->download_path)); return '/storage/'.$this->download_path.'/attachments'; } public function boundingBoxes() { return $this->hasMany(ProjectBoundingBox::class); } public function emailRecipients() { return $this->hasMany(ProjectEmailRecipient::class); } public function mailings() { return $this->hasMany(ProjectMailing::class); } public function downloads() { return $this->hasMany(ProjectDownload::class); } public function allMosaicsPresent(Carbon $endDate) { // end date is in the future if ($endDate->isFuture()) { throw new \Exception('End date is in the future'); } $mosaicsNotPresentInFilesystem = $this->getMosiacFilenameListByEndDate($endDate) ->filter(function ($filename) { return !$this->getMosaicList()->contains(function ($mosaicFilename) use ($filename) { return Str::endsWith( $mosaicFilename, substr($filename, -16)); }); }); if ($mosaicsNotPresentInFilesystem->count() === 0) { return true; } $message = sprintf( 'Missing mosaics: %s', $mosaicsNotPresentInFilesystem->implode(', ') ); throw new \Exception($message); } public function getMosiacFilenameListByEndDate(Carbon $endDate): \Illuminate\Support\Collection { $result = collect([]); for ($i = 0; $i < 4; $i++) { $week = $endDate->weekOfYear; $year = $endDate->year; if ($week === 53) { $year--; } $result->add(sprintf('week_%02d_%04d.tif', $week, $year)); $endDate = $endDate->subWeek(); } return $result; } }