first commit
Some checks failed
Build / run (push) Has been cancelled

This commit is contained in:
maher
2025-10-29 11:42:25 +01:00
commit 703f50a09d
4595 changed files with 385164 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
<?php
namespace Common\Notifications;
use Common\Settings\Settings;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class ContactPageMessage extends Notification
{
use Queueable;
public function __construct(public $message)
{
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return MailMessage
*/
public function toMail($notifiable)
{
$siteName = app(Settings::class)->get('branding.site_name');
$userEmail = $this->message['email'];
return (new MailMessage())
->subject(
__('New message via :siteName contact page.', [
'siteName' => $siteName,
]),
)
->greeting(
__("New message via :siteName contact page from ':userEmail'", [
'siteName' => $siteName,
'userEmail' => $userEmail,
]),
)
->salutation(' ')
->from(config('mail.from.address'), config('mail.from.name'))
->replyTo($userEmail, $this->message['name'])
->line($this->message['message']);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Common\Notifications;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Arr;
class ErrorNotification extends Notification
{
use Queueable;
/**
* @var array
*/
private $config;
/**
* @param array $config
*/
public function __construct($config)
{
$this->config = $config;
}
/**
* @param User $notifiable
* @return array
*/
public function via($notifiable)
{
return ['database'];
}
/**
* @param User $notifiable
* @return array
*/
public function toArray($notifiable)
{
$config = $this->config;
if ( ! Arr::get($config, 'image')) {
$config['image'] = 'error-outline';
}
return $config;
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Common\Notifications;
use App\Models\User;
use NotificationChannels\Fcm\FcmChannel;
trait GetsUserPreferredChannels
{
/**
* @param User $notifiable
* @return array
*/
public function via($notifiable): array
{
if (!config('common.site.notif_subs_integrated')) {
return ['database', 'mail'];
}
$channels = [];
if (
$sub = $notifiable->notificationSubscriptions
->where('notif_id', static::NOTIF_ID)
->first()
) {
foreach (array_filter($sub->channels) as $channel => $isSelected) {
if ($channel === 'browser') {
$channels = array_merge($channels, [
'database',
'broadcast',
]);
} elseif ($channel === 'email') {
$channels[] = 'mail';
} elseif ($channel === 'mobile') {
$channels[] = FcmChannel::class;
} else {
$channels[] = $channel;
}
}
}
return $channels;
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace Common\Notifications;
use Auth;
use Common\Core\BaseController;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Notifications\DatabaseNotification;
class NotificationController extends BaseController
{
public function __construct(
protected DatabaseNotification $notification,
protected Request $request,
) {
$this->middleware('auth');
}
public function index(): JsonResponse
{
$pagination = Auth::user()
->notifications()
->simplePaginate(request('perPage', 10));
return $this->success(['pagination' => $pagination]);
}
public function markAsRead()
{
$data = $this->validate($this->request, [
'ids' => 'array|required_without:markAllAsUnread',
'markAllAsUnread' => 'boolean|required_without:ids',
]);
Auth::user()
->unreadNotifications()
->when(
isset($data['ids']),
fn($q) => $q->whereIn('id', $data['ids']),
)
->update(['read_at' => now()]);
$unreadCount = Auth::user()
->unreadNotifications()
->count();
return $this->success(['unreadCount' => $unreadCount, 'date' => now()]);
}
public function destroy($ids)
{
$ids = explode(',', $ids);
Auth::user()
->notifications()
->whereIn('id', $ids)
->delete();
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Common\Notifications;
use Illuminate\Database\Eloquent\Model;
use Ramsey\Uuid\Uuid;
class NotificationSubscription extends Model
{
protected $guarded = ['id'];
protected $keyType = 'string';
public $timestamps = false;
public $incrementing = false;
protected $casts = [
'user_id' => 'integer',
'channels' => 'array',
];
protected static function boot()
{
parent::boot();
static::creating(function (Model $model) {
$model->setAttribute($model->getKeyName(), Uuid::uuid4());
});
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace Common\Notifications;
use App\Models\User;
use Common\Core\BaseController;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\File;
class NotificationSubscriptionsController extends BaseController
{
public function __construct()
{
$this->middleware(['auth']);
}
public function index(User $user): JsonResponse
{
$response = $this->getConfig();
// filter out notifications user does not have permission for
$response['subscriptions'] = collect($response['subscriptions'])
->map(function ($group) use ($user) {
$group['subscriptions'] = collect($group['subscriptions'])
->filter(function ($subscription) use ($user) {
if (!isset($subscription['permissions'])) {
return true;
}
return collect($subscription['permissions'])->every(
fn($permission) => $user->hasPermission(
$permission,
),
);
})
->values()
->toArray();
return $group;
})
->filter(fn($group) => count($group['subscriptions']))
->values()
->toArray();
$subs = $user->notificationSubscriptions;
$response['user_selections'] = $subs;
return $this->success($response);
}
public function update(User $user): JsonResponse
{
$data = $this->validate(request(), [
'selections' => 'present|array',
'selections.*.notif_id' => 'required|string',
'selections.*.channels' => 'required|array',
]);
$allConfig = collect($this->getConfig()['subscriptions'])->flatMap(
fn($group) => $group['subscriptions'],
);
foreach ($data['selections'] as $selection) {
// check if user has permissions to subscribe to this notification
$config = $allConfig->firstWhere(
'notif_id',
$selection['notif_id'],
);
if (isset($config['permissions'])) {
$hasAllPermissions = collect($config['permissions'])->every(
fn($permission) => $user->hasPermission($permission),
);
if (!$hasAllPermissions) {
return $this->error(
'You do not have permission to subscribe to one of these notifications.',
[],
403,
);
}
}
$subscription = $user
->notificationSubscriptions()
->firstOrNew(['notif_id' => $selection['notif_id']]);
$newChannels = $subscription['channels'];
// can update state of all channels at once or only a single channel
foreach ($selection['channels'] as $newChannel => $isSubscribed) {
$newChannels[$newChannel] = $isSubscribed;
}
$subscription->fill(['channels' => $newChannels])->save();
}
return $this->success();
}
private function getConfig()
{
return File::getRequire(
resource_path('defaults/notification-settings.php'),
);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Common\Notifications;
use App\Models\User;
use File;
use Ramsey\Uuid\Uuid;
class SubscribeUserToNotifications
{
public function execute(User $user, ?array $notificationIds)
{
$config = File::getRequire(
resource_path('defaults/notification-settings.php'),
);
if (is_null($notificationIds)) {
$notificationIds = collect($config['subscriptions'])
->map(function ($group) {
return collect($group['subscriptions'])->pluck('notif_id');
})
->flatten(1)
->toArray();
}
$rows = array_map(function ($notifId) use ($config, $user) {
return [
'id' => Uuid::uuid4(),
'notif_id' => $notifId,
'channels' => json_encode(
collect($config['available_channels'])->mapWithKeys(
fn($channel) => [$channel => true],
),
),
'user_id' => $user->id,
];
}, $notificationIds);
$user->notificationSubscriptions()->delete();
$user->notificationSubscriptions()->insert($rows);
}
}