Initial commit

This commit is contained in:
Ronald Huynen
2026-03-23 21:37:59 +01:00
commit 2547717edb
2193 changed files with 972171 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
<?php
namespace App\Jobs;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Namu\WireChat\Enums\Actions;
use Namu\WireChat\Models\Message;
class DeleteExpiredWireChatMessagesJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct()
{
$this->onQueue('low');
}
/**
* Execute the job.
*/
public function handle(): void
{
// Disappearing messages always enabled - this prevents orphaned messages
Log::info('WireChat disappearing messages: Starting cleanup');
$deletedCount = 0;
$deletedKeptCount = 0;
// Get all conversations with disappearing settings
$conversations = \Namu\WireChat\Models\Conversation::whereNotNull('disappearing_started_at')
->whereNotNull('disappearing_duration')
->get();
Log::info("WireChat disappearing messages: Found {$conversations->count()} conversations with disappearing enabled");
foreach ($conversations as $conversation) {
// Get regular messages (not kept) that should be deleted
$messages = $conversation->messages()
->withoutGlobalScopes()
->where(function ($query) {
// Messages that are not kept
$query->whereNull('kept_at')
// Or messages that are kept but have delete actions or are trashed
->orWhere(function ($query) {
$query->whereNotNull('kept_at') // Kept messages
->where(function ($query) {
$query->whereNotNull('deleted_at') // Trashed
->orWhereHas('actions', function ($query) {
$query->where('type', Actions::DELETE);
});
});
});
})
// Only messages created AFTER disappearing was enabled
->where('created_at', '>', $conversation->disappearing_started_at)
->get();
foreach ($messages as $message) {
$createdAt = $message->created_at;
if ($createdAt && $createdAt->isFuture()) {
continue; // Skip future messages
}
// Check if message is older than the conversation's duration
if ($createdAt && $createdAt->diffInSeconds(now()) > $conversation->disappearing_duration) {
try {
Log::info("WireChat disappearing messages: Deleting message {$message->id} (age: {$createdAt->diffInSeconds(now())}s, limit: {$conversation->disappearing_duration}s)");
$message->forceDelete();
$deletedCount++;
} catch (\Exception $e) {
Log::error("WireChat disappearing messages: Failed to delete message {$message->id}: {$e->getMessage()}");
}
}
}
// Get kept messages that should be deleted based on kept_messages_duration
$keptMessagesDurationDays = timebank_config('wirechat.disappearing_messages.kept_messages_duration');
if ($keptMessagesDurationDays !== null && timebank_config('wirechat.disappearing_messages.allow_users_to_keep', true)) {
$keptMessagesDuration = $keptMessagesDurationDays * 86400; // Convert days to seconds
$keptMessages = $conversation->messages()
->withoutGlobalScopes()
->whereNotNull('kept_at')
->whereNull('deleted_at')
->whereDoesntHave('actions', function ($query) {
$query->where('type', Actions::DELETE);
})
->where('kept_at', '>', $conversation->disappearing_started_at)
->get();
foreach ($keptMessages as $keptMessage) {
$keptAt = $keptMessage->kept_at;
if ($keptAt && $keptAt->isFuture()) {
continue; // Skip future kept messages
}
// Check if kept message is older than the kept messages duration
if ($keptAt && $keptAt->diffInSeconds(now()) > $keptMessagesDuration) {
try {
Log::info("WireChat disappearing messages: Deleting kept message {$keptMessage->id} (kept for: {$keptAt->diffInSeconds(now())}s, limit: {$keptMessagesDuration}s)");
$keptMessage->forceDelete();
$deletedKeptCount++;
} catch (\Exception $e) {
Log::error("WireChat disappearing messages: Failed to delete kept message {$keptMessage->id}: {$e->getMessage()}");
}
}
}
}
}
Log::info("WireChat disappearing messages: Deleted {$deletedCount} expired messages and {$deletedKeptCount} expired kept messages");
}
}

View File

@@ -0,0 +1,360 @@
<?php
namespace App\Jobs;
use App\Mail\NewsletterMail;
use App\Models\MailingBounce;
use App\Models\Mailing;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class SendBulkMailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $mailing;
protected $locale;
protected $recipients;
protected $contentBlocks;
public $timeout = 300; // 5 minutes timeout
/**
* Get the number of times the job may be attempted.
*/
public function tries(): int
{
return timebank_config('mailing.max_retries', 3) + 1; // +1 for initial attempt
}
/**
* Determine if the job should be retried based on time limits.
*/
public function retryUntil(): \DateTime
{
$abandonAfterHours = timebank_config('mailing.abandon_after_hours', 72);
return now()->addHours($abandonAfterHours);
}
/**
* Create a new job instance.
*/
public function __construct(Mailing $mailing, string $locale, array $contentBlocks, $recipients)
{
$this->mailing = $mailing;
$this->locale = $locale;
$this->contentBlocks = $contentBlocks;
$this->recipients = $recipients;
}
/**
* Execute the job.
*
* This job processes a batch of recipients for a specific locale.
* Multiple instances of this job may run in parallel for different batches/locales.
*/
public function handle(): void
{
Log::info("MAILING: Starting bulk mail batch job for Mailing ID: {$this->mailing->id}, Recipients in batch: " . count($this->recipients) . ", Locale: {$this->locale}");
$sendDelay = timebank_config('mailing.send_delay_seconds', 5);
$successCount = 0;
$failureCount = 0;
$skippedCount = 0;
foreach ($this->recipients as $recipient) {
// Skip if email is already suppressed due to bounces
if (MailingBounce::isSuppressed($recipient->email)) {
Log::warning("MAILING: Skipping suppressed email: {$recipient->email} (Mailing ID: {$this->mailing->id})");
$skippedCount++;
continue;
}
try {
// Send individual email synchronously - let NewsletterMail generate its own content blocks
$newsletterMail = new NewsletterMail($this->mailing, $recipient, null, $this->locale, true);
// Attempt to send email with comprehensive error handling
$this->sendEmailWithErrorHandling($recipient->email, $newsletterMail);
$successCount++;
// Add delay between emails to avoid rate limiting
if ($sendDelay > 0) {
sleep($sendDelay);
}
} catch (\Exception $e) {
$failureCount++;
Log::error("Failed to send newsletter to {$recipient->email}: " . $e->getMessage());
// Check if this is a bounce-related error
if ($this->isBounceError($e)) {
$bounceType = $this->determineBounceType($e);
MailingBounce::recordBounce(
$recipient->email,
$bounceType,
$e->getMessage(),
$this->mailing->id
);
Log::warning("Recorded bounce for {$recipient->email}: {$bounceType}");
}
// If it's an SMTP quota/limit error and configured to fail job, trigger retry
if ($this->isSMTPQuotaError($e) && timebank_config('mailing.fail_job_on_quota_error', true)) {
Log::error("SMTP quota/limit error detected for {$recipient->email}. Failing job for retry with extended delay.");
// Set longer delay for quota errors
$this->retryWithQuotaDelay();
throw $e; // This will trigger job retry
}
}
}
// Log summary before updating statistics
Log::info("MAILING: Completed bulk mail job for Mailing ID: {$this->mailing->id} - Success: {$successCount}, Failed: {$failureCount}, Skipped: {$skippedCount}");
// Update mailing statistics
$this->updateMailingStats($successCount, $failureCount);
}
/**
* Update mailing statistics
*/
protected function updateMailingStats(int $successCount, int $failureCount): void
{
$this->mailing->increment('sent_count', $successCount);
$this->mailing->increment('failed_count', $failureCount);
// Check if all jobs are complete by comparing sent + failed with total recipients
$totalProcessed = $this->mailing->sent_count + $this->mailing->failed_count;
if ($totalProcessed >= $this->mailing->recipients_count) {
$this->mailing->update([
'status' => 'sent',
'sent_at' => now()
]);
}
}
/**
* Handle a job failure.
*/
public function failed(\Throwable $exception): void
{
// Check if this is a quota error and provide specific guidance
if ($this->isSMTPQuotaError($exception)) {
Log::error("Bulk mail job failed due to SMTP quota/limit for mailing {$this->mailing->id}, locale {$this->locale}. This job will be retried automatically when the quota resets.");
// Don't increment failed count for quota errors as they will be retried
return;
}
Log::error("Bulk mail job failed for mailing {$this->mailing->id}, locale {$this->locale}: " . $exception->getMessage());
// Update failure count for all recipients in this batch (only for non-quota errors)
$this->mailing->increment('failed_count', $this->recipients->count());
// If this was the last job, mark mailing as sent (even with failures)
$totalProcessed = $this->mailing->sent_count + $this->mailing->failed_count;
if ($totalProcessed >= $this->mailing->recipients_count) {
$this->mailing->update([
'status' => 'sent',
'sent_at' => now()
]);
}
}
/**
* Send email with comprehensive error handling
*/
protected function sendEmailWithErrorHandling($email, $newsletterMail)
{
try {
// Use a more specific approach to detect SMTP errors
Mail::to($email)->send($newsletterMail);
// Additional verification: Check if we can still send (for services that don't throw immediate exceptions)
// This is a lightweight check that can help detect quota issues
$this->verifyEmailServiceHealth();
} catch (\Symfony\Component\Mailer\Exception\TransportException $e) {
// Specific handling for Symfony mailer transport exceptions
Log::error("Symfony Transport Exception for {$email}: " . $e->getMessage());
throw $e;
} catch (\Swift_TransportException $e) {
// Legacy SwiftMailer transport exceptions (if still in use)
Log::error("Swift Transport Exception for {$email}: " . $e->getMessage());
throw $e;
}
}
/**
* Check if the error is related to SMTP quota/limits
*/
protected function isSMTPQuotaError(\Exception $e): bool
{
$message = strtolower($e->getMessage());
// Common SMTP quota/limit error patterns
$quotaPatterns = [
'email limit',
'quota exceeded',
'rate limit',
'too many emails',
'limit reached',
'billing',
'upgrade your plan',
'sending limit',
'daily limit',
'monthly limit'
];
foreach ($quotaPatterns as $pattern) {
if (strpos($message, $pattern) !== false) {
return true;
}
}
return false;
}
/**
* Lightweight check to verify email service is still operational
*/
protected function verifyEmailServiceHealth()
{
// This method can be expanded to include specific health checks
// For now, it serves as a placeholder for future enhancements
// Future implementations could include:
// - Test connection to SMTP server
// - Check service status endpoints
// - Validate remaining quota if API available
}
/**
* Set retry delay specifically for quota errors
*/
protected function retryWithQuotaDelay()
{
// Store quota error information for custom backoff
cache()->put("bulk_mail_quota_error_{$this->mailing->id}", now(), now()->addHours(24));
}
/**
* Override backoff to handle quota errors differently
*/
public function backoff(): array
{
// Check if this is a quota error retry
if (cache()->has("bulk_mail_quota_error_{$this->mailing->id}")) {
$quotaDelayHours = timebank_config('mailing.quota_error_retry_delay_hours', 6);
return [$quotaDelayHours * 3600]; // Convert hours to seconds
}
// Use original backoff logic for non-quota errors
$baseDelayMinutes = timebank_config('mailing.retry_delay_minutes', 15);
$multiplier = timebank_config('mailing.retry_multiplier', 2);
$maxDelayHours = timebank_config('mailing.max_retry_delay_hours', 24);
$maxRetries = timebank_config('mailing.max_retries', 3);
$backoffSchedule = [];
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
$delayMinutes = $baseDelayMinutes * pow($multiplier, $attempt - 1);
$delayHours = $delayMinutes / 60;
// Cap the delay at max_retry_delay_hours
if ($delayHours > $maxDelayHours) {
$delayMinutes = $maxDelayHours * 60;
}
$backoffSchedule[] = $delayMinutes * 60; // Convert to seconds
}
return $backoffSchedule;
}
/**
* Check if the error indicates an email bounce
*/
protected function isBounceError(\Exception $e): bool
{
$message = strtolower($e->getMessage());
// Common bounce error patterns
$bouncePatterns = [
'mailbox unavailable',
'user unknown',
'no such user',
'invalid recipient',
'address rejected',
'mailbox full',
'quota exceeded',
'550 ',
'551 ',
'552 ',
'553 ',
'bounce',
'undeliverable',
'does not exist',
'mailbox not found',
];
foreach ($bouncePatterns as $pattern) {
if (strpos($message, $pattern) !== false) {
return true;
}
}
return false;
}
/**
* Determine bounce type based on error message
*/
protected function determineBounceType(\Exception $e): string
{
$message = strtolower($e->getMessage());
// Hard bounce patterns (permanent failures)
$hardBouncePatterns = [
'user unknown',
'no such user',
'invalid recipient',
'address rejected',
'does not exist',
'mailbox not found',
'550 ',
'551 ',
];
foreach ($hardBouncePatterns as $pattern) {
if (strpos($message, $pattern) !== false) {
return 'hard';
}
}
// Soft bounce patterns (temporary failures)
$softBouncePatterns = [
'mailbox full',
'quota exceeded',
'552 ',
'temporarily rejected',
];
foreach ($softBouncePatterns as $pattern) {
if (strpos($message, $pattern) !== false) {
return 'soft';
}
}
return 'unknown';
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace App\Jobs;
use App\Mail\NewMessageMail;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Namu\WireChat\Events\MessageCreated;
class SendDelayedEmail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $event;
public $sender;
public $recipient;
public $participant;
/**
* Create a new job instance.
*
* @param MessageCreated $event
* @param mixed $sender
* @param mixed $recipient
* @param mixed $participant
* @return void
*/
public function __construct(MessageCreated $event, $sender, $recipient, $participant)
{
$this->event = $event;
$this->sender = $sender;
$this->recipient = $recipient;
$this->participant = $participant;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
try {
Log::info('SendDelayedEmail job starting (v2)', [
'recipient_id' => $this->recipient->id,
'recipient_type' => get_class($this->recipient),
'participant_id' => $this->participant->id ?? 'null',
'message_id' => $this->event->message->id ?? 'null',
]);
// Refresh the participant to get the latest data
$this->participant->refresh();
// Check if the message has been read
// WireChat uses 'conversation_read_at' on the participant model
$lastRead = $this->participant->conversation_read_at ? Carbon::parse($this->participant->conversation_read_at) : null;
$messageCreatedAt = Carbon::parse($this->event->message->created_at);
Log::info('Read status check', [
'conversation_read_at' => $lastRead ? $lastRead->toDateTimeString() : 'null',
'message_created' => $messageCreatedAt->toDateTimeString(),
]);
if ($lastRead && $lastRead->greaterThanOrEqualTo($messageCreatedAt)) {
// The recipient has already read the message; do not send the email
Log::info('Recipient has already read the message', [
'recipient_id' => $this->recipient->id,
'recipient_type' => get_class($this->recipient),
'message_id' => $this->event->message->id,
]);
return;
}
// Get the recipient's language preference
$language = $this->recipient->lang_preference ?? config('app.locale', 'en');
Log::info('Language detection', [
'recipient_lang_preference' => $this->recipient->lang_preference ?? 'null',
'fallback_locale' => config('app.locale', 'en'),
'selected_language' => $language,
]);
// Send the email with the appropriate language
Mail::to($this->recipient->email)
->locale($language)
->send(new NewMessageMail(
$this->event,
$this->sender,
$this->recipient,
$language
));
Log::info('Email sent to recipient', [
'recipient_id' => $this->recipient->id,
'recipient_type' => get_class($this->recipient),
'email' => $this->recipient->email,
'language' => $language,
'message_id' => $this->event->message->id,
]);
} catch (\Exception $e) {
Log::error('Error sending SendDelayedEmail', [
'recipient_id' => $this->recipient->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
// Re-throw the exception so the job can be retried
throw $e;
}
}
/**
* The job failed to process.
*
* @param \Throwable $exception
* @return void
*/
public function failed(\Throwable $exception)
{
Log::error('SendDelayedEmail job failed', [
'recipient_id' => $this->recipient->id,
'recipient_type' => get_class($this->recipient),
'message_id' => $this->event->message->id,
'error' => $exception->getMessage(),
]);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Jobs;
use App\Mail\TagAddedMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Mail;
class SendEmailNewTag implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tagId;
/**
* Create a new job instance.
*
* @param $tagId
*/
public function __construct($tagId)
{
$this->tagId = $tagId;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// Send the email notification
Mail::to(timebank_config('mail.content_admin.email'))->send(new TagAddedMail($this->tagId));
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Jobs;
use App\Mail\ProfileEditedByAdminMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class SendProfileEditedByAdminMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
protected $profile;
protected $changedFields;
/**
* Create a new job instance.
*
* @param mixed $profile The profile that was edited
* @param array $changedFields Array of field names that were changed
* @return void
*/
public function __construct($profile, $changedFields = [])
{
$this->profile = $profile;
$this->changedFields = $changedFields;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
if (!$this->profile->email) {
Log::warning('SendProfileEditedByAdminMail: Profile has no email address', [
'profile_id' => $this->profile->id,
'profile_type' => get_class($this->profile),
]);
return;
}
Log::info('SendProfileEditedByAdminMail: Sending email', [
'profile_id' => $this->profile->id,
'profile_type' => get_class($this->profile),
'profile_email' => $this->profile->email,
'changed_fields' => $this->changedFields,
]);
Mail::to($this->profile->email)->send(
new ProfileEditedByAdminMail($this->profile, $this->changedFields)
);
Log::info('SendProfileEditedByAdminMail: Email sent successfully');
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace App\Jobs;
use App\Mail\ProfileLinkChangedMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class SendProfileLinkChangedMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $tries = 3;
public $backoff = [5, 30, 300]; // wait for 5, 30, or 300 sec before worker tries again
protected $recipient;
protected $linkedProfile;
protected $action;
/**
* Create a new job instance.
*
* @param mixed $recipient The profile receiving the notification
* @param mixed $linkedProfile The profile that was attached/detached
* @param string $action Either 'attached' or 'detached'
* @return void
*/
public function __construct($recipient, $linkedProfile, $action = 'attached')
{
$this->recipient = $recipient;
$this->linkedProfile = $linkedProfile;
$this->action = $action;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
Log::info('SendProfileLinkChangedMail: Job starting', [
'recipient_id' => $this->recipient->id,
'recipient_type' => get_class($this->recipient),
'recipient_email' => $this->recipient->email ?? 'NO EMAIL',
'linked_profile_id' => $this->linkedProfile->id,
'linked_profile_type' => get_class($this->linkedProfile),
'action' => $this->action,
]);
// Check if recipient has an email
if (empty($this->recipient->email)) {
Log::warning('SendProfileLinkChangedMail: Recipient has no email address', [
'recipient_id' => $this->recipient->id,
'recipient_type' => get_class($this->recipient),
]);
return;
}
try {
// Send the email to the recipient
Mail::to($this->recipient->email)->send(
new ProfileLinkChangedMail($this->recipient, $this->linkedProfile, $this->action)
);
Log::info('SendProfileLinkChangedMail: Email sent successfully', [
'recipient_email' => $this->recipient->email,
'action' => $this->action,
]);
} catch (\Exception $e) {
Log::error('SendProfileLinkChangedMail: Failed to send email', [
'recipient_email' => $this->recipient->email ?? 'NO EMAIL',
'action' => $this->action,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
throw $e;
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Jobs;
use App\Mail\ReactionCreatedEmail;
use App\Mail\ReactionCreatedMail;
use Cog\Contracts\Love\Reaction\Models\Reaction;
use Cog\Laravel\Love\Reaction\Events\ReactionHasBeenAdded;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendReactionCreatedMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $tries = 3;
public $backoff = [5,30,300]; // wait for 5, 30, or 300 sec before worker tries again
public $reaction;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Reaction $reaction)
{
$this->reaction = $reaction;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// Send the email to the recipient (person receiving the reaction)
Mail::to($this->reaction->getReactant()->getReactable()->email)->send(new ReactionCreatedMail($this->reaction));
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Jobs;
use App\Mail\ReservationCancelledMail;
use Cog\Contracts\Love\Reaction\Models\Reaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendReservationCancelledMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $tries = 3;
public $backoff = [5,30,300]; // wait for 5, 30, or 300 sec before worker tries again
public $data;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
\Log::info('SendReservationCancelledMail: Starting to process job', [
'reacter_email' => $this->data['reacter_email'],
'post_id' => $this->data['post_id']
]);
// Send the email to the reacter (person who cancelled the reservation)
Mail::to($this->data['reacter_email'])->send(new ReservationCancelledMail($this->data));
\Log::info('SendReservationCancelledMail: Email sent successfully', ['to' => $this->data['reacter_email']]);
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Jobs;
use App\Mail\ReservationCreatedMail;
use Cog\Contracts\Love\Reaction\Models\Reaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendReservationCreatedMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $tries = 3;
public $backoff = [5,30,300]; // wait for 5, 30, or 300 sec before worker tries again
public $reactionId;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($reactionId)
{
$this->reactionId = $reactionId;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
\Log::info('SendReservationCreatedMail: Starting to process job', ['reaction_id' => $this->reactionId]);
// Fetch the reaction from the database
$reaction = \Cog\Laravel\Love\Reaction\Models\Reaction::findOrFail($this->reactionId);
\Log::info('SendReservationCreatedMail: Reaction loaded', ['reaction_id' => $reaction->getId()]);
$reacter = $reaction->getReacter()->getReacterable();
\Log::info('SendReservationCreatedMail: Reacter loaded', [
'reacter_type' => get_class($reacter),
'reacter_id' => $reacter->id,
'reacter_email' => $reacter->email,
]);
// Send the email to the reacter (person making the reservation)
Mail::to($reacter->email)->send(new ReservationCreatedMail($reaction));
\Log::info('SendReservationCreatedMail: Email sent successfully', ['to' => $reacter->email]);
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace App\Jobs;
use App\Mail\ReservationUpdateMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class SendReservationUpdateMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $tries = 3;
public $backoff = [5, 30, 300]; // wait for 5, 30, or 300 sec before worker tries again
protected $reacter;
protected $post;
protected $message;
protected $organizer;
/**
* Create a new job instance.
*
* @param mixed $reacter The profile who made the reservation
* @param mixed $post The post/event
* @param string $message The custom message from organizer
* @param mixed $organizer The organizer sending the message
* @return void
*/
public function __construct($reacter, $post, $message, $organizer)
{
$this->reacter = $reacter;
$this->post = $post;
$this->message = $message;
$this->organizer = $organizer;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
Log::info('SendReservationUpdateMail: Starting to process job', [
'reacter_type' => get_class($this->reacter),
'reacter_id' => $this->reacter->id,
'post_id' => $this->post->id
]);
// Send the email to the reacter
Mail::to($this->reacter->email)->send(
new ReservationUpdateMail($this->reacter, $this->post, $this->message, $this->organizer)
);
Log::info('SendReservationUpdateMail: Email sent successfully', [
'to' => $this->reacter->email,
'post_id' => $this->post->id
]);
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Jobs;
use App\Mail\UserDeletedMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendUserDeletedMail implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $tries = 3;
public $backoff = [5,10,30]; // wait for 5, 10, or 30 sec before worker tries again
public $result;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($result)
{
$this->result = $result;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// Send the email
Mail::to($this->result->email)->send(new UserDeletedMail($this->result));
}
}

39
app/Jobs/TestDelayJob.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class TestDelayJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
public $delay;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($delayInSeconds)
{
$this->delay = now()->addSeconds($delayInSeconds);
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
\Log::info('Test delay job executed at ' . now());
}
}