mailing = $mailing; $this->recipientLocale = $locale; $this->contentBlocks = $this->generateContentBlocksForLocale($locale); } /** * Build the message. */ public function build() { // Set locale for the email App::setLocale($this->recipientLocale); $fromAddress = timebank_config("mailing.from_address.{$this->mailing->type}"); $subject = "[TEST - {$this->recipientLocale}] " . $this->mailing->getSubjectForLocale($this->recipientLocale); return $this ->from($fromAddress, config('app.name')) ->subject($subject) ->view('emails.newsletter.wrapper') ->with([ 'subject' => $subject, 'mailingTitle' => $this->mailing->title, 'locale' => $this->recipientLocale, 'contentBlocks' => $this->contentBlocks, 'unsubscribeUrl' => '#test-unsubscribe-link', 'isTestMail' => true, ]); } /** * Generate content blocks for a specific locale */ protected function generateContentBlocksForLocale($locale) { $blocks = []; $contentBlocks = $this->mailing->getContentBlocksForLocale($locale); foreach ($contentBlocks as $block) { $post = \App\Models\Post::with(['translations', 'category'])->find($block['post_id']); if (!$post) { continue; } // Get translation for the specific locale $translation = $this->mailing->getPostTranslationForLocale($post->id, $locale); if (!$translation) { continue; // Skip posts without translations in this locale } // Determine post type for template selection $postType = $this->determinePostType($post); // Prepare post data for template $postData = $this->preparePostData($post, $translation); $blocks[] = [ 'type' => $postType, 'data' => $postData, 'template' => timebank_config("mailing.templates.{$postType}_block") ]; } return $blocks; } /** * Determine post type based on category or content */ protected function determinePostType($post) { // Check for ImagePost category type first if ($post->category && $post->category->type && str_starts_with($post->category->type, 'App\\Models\\ImagePost')) { return 'image'; } if ($post->category && $post->category->id) { // Map categories to post types $categoryMappings = [ 4 => 'event', // The Hague events 5 => 'event', // South-Holland events 6 => 'event', // The Netherlands events 7 => 'news', // The Hague news 8 => 'news', // General news 113 => 'article', // Article ]; return $categoryMappings[$post->category->id] ?? 'news'; } // Check if post has meeting/event data if ($post->meeting || (isset($post->from) && $post->from)) { return 'event'; } return 'news'; // default } /** * Prepare post data for email template */ protected function preparePostData($post, $translation) { // Generate fully localized URL with translated route path for recipient's language $url = LaravelLocalization::getURLFromRouteNameTranslated( $this->recipientLocale, 'routes.post.show_by_slug', ['slug' => $translation->slug] ); $data = [ 'title' => $translation->title, 'excerpt' => $translation->excerpt ?: Str::limit(strip_tags($translation->content ?? ''), 150), 'content' => $translation->content, 'url' => $url, 'date' => $post->updated_at->locale($this->recipientLocale)->translatedFormat('M j, Y'), 'author' => $post->author ? $post->author->name : null, ]; // Add category information if ($post->category) { $categoryTranslation = $post->category->translations()->where('locale', $this->recipientLocale)->first(); $data['category'] = $categoryTranslation ? $categoryTranslation->name : $post->category->translations()->first()->name; } // Add location prefix for news if ($post->category && $post->category->categoryable && $post->category->categoryable->translations) { $locationTranslation = $post->category->categoryable->translations->where('locale', $this->recipientLocale)->first(); if ($locationTranslation && $locationTranslation->name) { $data['location_prefix'] = strtoupper($locationTranslation->name); } } // Add event-specific data if ($post->meeting) { $data['venue'] = $post->meeting->venue; $data['address'] = $post->meeting->address; } // Add event date/time if available if ($translation->from) { $eventDate = \Carbon\Carbon::parse($translation->from); $data['event_date'] = $eventDate->locale($this->recipientLocale)->translatedFormat('F j'); $data['event_time'] = $eventDate->locale($this->recipientLocale)->translatedFormat('H:i'); } // Add image if available - use email conversion (resized without cropping) if ($post->hasMedia('posts')) { $data['image'] = $post->getFirstMediaUrl('posts', 'email'); // Add media caption and owner for image posts $media = $post->getFirstMedia('posts'); if ($media) { $captionKey = 'caption-' . $this->recipientLocale; $data['media_caption'] = $media->getCustomProperty($captionKey, ''); $data['media_owner'] = $media->getCustomProperty('owner', ''); } } return $data; } }