189 lines
6.5 KiB
PHP
189 lines
6.5 KiB
PHP
<?php
|
|
|
|
namespace App\Mail;
|
|
|
|
use App\Models\Mailing;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Mail\Mailable;
|
|
use Illuminate\Queue\SerializesModels;
|
|
use Illuminate\Support\Facades\App;
|
|
use Illuminate\Support\Str;
|
|
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
|
|
|
|
class TestNewsletterMail extends Mailable
|
|
{
|
|
use Queueable, SerializesModels;
|
|
|
|
protected $mailing;
|
|
protected $contentBlocks;
|
|
protected $recipientLocale;
|
|
|
|
/**
|
|
* Create a new message instance.
|
|
*/
|
|
public function __construct(Mailing $mailing, $locale)
|
|
{
|
|
$this->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;
|
|
}
|
|
} |