Usage

Creating Notifications

Every notification extends the abstract Notification class and must implement the via() method:

<?php

declare(strict_types=1);

namespace App\Notifications;

use WPZylos\Framework\Notification\Notification;
use WPZylos\Framework\Notification\MailMessage;

class WelcomeNotification extends Notification
{
    public function __construct(private string $userName) {}

    public function via(): array
    {
        return ['mail', 'database', 'admin_notice'];
    }

    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage())
            ->subject('Welcome to Our Site!')
            ->greeting('Hello, ' . $this->userName . '!')
            ->line('Thank you for registering.')
            ->line('We are excited to have you on board.')
            ->action('Get Started', 'https://example.com/dashboard');
    }

    public function toDatabase(object $notifiable): array
    {
        return [
            'message' => 'Welcome, ' . $this->userName . '!',
            'action'  => 'registration',
        ];
    }

    public function toAdminNotice(object $notifiable): \WPZylos\Framework\Notification\AdminNoticeMessage
    {
        return (new \WPZylos\Framework\Notification\AdminNoticeMessage())
            ->message('New user registered: ' . $this->userName)
            ->type('info')
            ->dismissible(true);
    }
}

Making Entities Notifiable

Add the Notifiable trait to any class that should receive notifications:

<?php

declare(strict_types=1);

namespace App\Models;

use WPZylos\Framework\Notification\Notifiable;

class User
{
    use Notifiable;

    public int $id;
    public string $email;
    public string $name;

    public function routeNotificationFor(string $channel): mixed
    {
        return match ($channel) {
            'mail'                      => $this->email,
            'database', 'admin_notice'  => $this->id,
            default                     => null,
        };
    }
}

Sending Notifications

Via the Notifiable Trait

$user->notify(new WelcomeNotification($user->name));

Via the NotificationManager

use WPZylos\Framework\Notification\NotificationManager;

$manager = $app->make(NotificationManager::class);

// Single recipient
$manager->send($user, new WelcomeNotification($user->name));

// Multiple recipients
$manager->send([$user1, $user2, $admin], new WelcomeNotification('Team'));

Channel-Specific Formatting

Mail Channel

Build rich HTML emails with MailMessage:

public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage())
        ->subject('Invoice #' . $this->invoice->number)
        ->greeting('Hello ' . $notifiable->name . '!')
        ->line('You have a new invoice for $' . $this->invoice->amount . '.')
        ->line('Due date: ' . $this->invoice->due_date)
        ->action('Pay Now', $this->invoice->payment_url)
        ->level('info');
}

The level() method accepts 'info', 'success', or 'error'.

Database Channel

Return an array of data to store as JSON:

public function toDatabase(object $notifiable): array
{
    return [
        'invoice_id' => $this->invoice->id,
        'amount'     => $this->invoice->amount,
        'message'    => 'New invoice received',
        'url'        => '/invoices/' . $this->invoice->id,
    ];
}

Admin Notice Channel

Build WordPress admin notices with AdminNoticeMessage:

public function toAdminNotice(object $notifiable): AdminNoticeMessage
{
    return (new AdminNoticeMessage())
        ->message('Invoice #' . $this->invoice->number . ' is overdue!')
        ->type('warning')       // 'success', 'error', 'warning', 'info'
        ->dismissible(true);
}

Reading Database Notifications

The Notifiable trait provides methods to query stored notifications:

// All notifications (newest first)
$all = $user->notifications();

// Unread only
$unread = $user->unreadNotifications();

// Read only
$read = $user->readNotifications();

// Mark as read
$user->markNotificationAsRead($notificationId);

Custom Channels

Implement the NotificationChannel interface:

<?php

declare(strict_types=1);

namespace App\Channels;

use WPZylos\Framework\Notification\Contracts\NotificationChannel;
use WPZylos\Framework\Notification\Notification;

class SlackChannel implements NotificationChannel
{
    public function __construct(private string $webhookUrl) {}

    public function send(object $notifiable, Notification $notification): void
    {
        if (!method_exists($notification, 'toSlack')) {
            return;
        }

        $data = $notification->toSlack($notifiable);

        wp_remote_post($this->webhookUrl, [
            'body'    => wp_json_encode($data),
            'headers' => ['Content-Type' => 'application/json'],
        ]);
    }
}

Register the custom channel:

$manager->extend('slack', new SlackChannel('https://hooks.slack.com/...'));

Then use it in your notification:

public function via(): array
{
    return ['mail', 'slack'];
}

public function toSlack(object $notifiable): array
{
    return [
        'text' => 'New order placed!',
        'channel' => '#orders',
    ];
}

Error Handling

Channel failures are caught internally and reported via WordPress action:

add_action('wpzylos_notification_failed', function (
    Notification $notification,
    object $notifiable,
    string $channelName,
    \Throwable $exception
) {
    error_log(sprintf(
        'Notification [%s] failed on channel [%s]: %s',
        $notification->type(),
        $channelName,
        $exception->getMessage()
    ));
}, 10, 4);