vendor and env first commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use League\CommonMark\Environment\Environment;
|
||||
use League\CommonMark\Extension\Table\TableExtension;
|
||||
use Vanguard\Announcements\Database\Factories\AnnouncementFactory;
|
||||
use Vanguard\User;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $title
|
||||
* @property string $body
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $deleted_at
|
||||
*/
|
||||
class Announcement extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'announcements';
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function creator(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
public function wasReadBy(User $user): bool
|
||||
{
|
||||
return $user->announcements_last_read_at < $this->created_at;
|
||||
}
|
||||
|
||||
public function getParsedBodyAttribute(): HtmlString
|
||||
{
|
||||
$environment = Environment::createCommonMarkEnvironment();
|
||||
|
||||
$environment->addExtension(new TableExtension);
|
||||
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'escape',
|
||||
'allow_unsafe_links' => false,
|
||||
], $environment);
|
||||
|
||||
return new HtmlString(
|
||||
$converter->convertToHtml($this->attributes['body'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected static function newFactory(): AnnouncementFactory
|
||||
{
|
||||
return new AnnouncementFactory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements;
|
||||
|
||||
use Event;
|
||||
use Route;
|
||||
use Vanguard\Announcements\Events\EmailNotificationRequested;
|
||||
use Vanguard\Announcements\Hooks\NavbarItemsHook;
|
||||
use Vanguard\Announcements\Hooks\ScriptsHook;
|
||||
use Vanguard\Announcements\Hooks\StylesHook;
|
||||
use Vanguard\Announcements\Listeners\ActivityLogSubscriber;
|
||||
use Vanguard\Announcements\Listeners\SendEmailNotification;
|
||||
use Vanguard\Announcements\Repositories\AnnouncementsRepository;
|
||||
use Vanguard\Announcements\Repositories\EloquentAnnouncements;
|
||||
use Vanguard\Plugins\Plugin;
|
||||
use Vanguard\Plugins\Vanguard;
|
||||
use Vanguard\Support\Sidebar\Item;
|
||||
|
||||
class Announcements extends Plugin
|
||||
{
|
||||
/**
|
||||
* A sidebar item for the plugin.
|
||||
*/
|
||||
public function sidebar(): ?Item
|
||||
{
|
||||
return Item::create(__('Announcements'))
|
||||
->icon('fas fa-bullhorn')
|
||||
->route('announcements.index')
|
||||
->permissions('announcements.manage')
|
||||
->active('announcements*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugin services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->singleton(AnnouncementsRepository::class, EloquentAnnouncements::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
$this->registerViews();
|
||||
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
|
||||
|
||||
$this->loadViewsFrom(__DIR__.'/../resources/views', 'announcements');
|
||||
$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'announcements');
|
||||
$this->loadJsonTranslationsFrom(__DIR__.'/../resources/lang');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__.'/../database/migrations' => database_path('migrations'),
|
||||
], 'migrations');
|
||||
|
||||
$this->mapRoutes();
|
||||
|
||||
$this->registerHooks();
|
||||
|
||||
$this->registerEventListeners();
|
||||
|
||||
$this->publishAssets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugin views.
|
||||
*/
|
||||
protected function registerViews(): void
|
||||
{
|
||||
$viewsPath = __DIR__.'/../resources/views';
|
||||
|
||||
$this->publishes([
|
||||
$viewsPath => resource_path('views/vendor/plugins/announcements'),
|
||||
], 'views');
|
||||
|
||||
$this->loadViewsFrom($viewsPath, 'announcements');
|
||||
}
|
||||
|
||||
/**
|
||||
* Map all plugin related routes.
|
||||
*/
|
||||
protected function mapRoutes(): void
|
||||
{
|
||||
$this->mapWebRoutes();
|
||||
|
||||
if ($this->app['config']->get('auth.expose_api')) {
|
||||
$this->mapApiRoutes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map web plugin related routes.
|
||||
*/
|
||||
protected function mapWebRoutes(): void
|
||||
{
|
||||
Route::group([
|
||||
'namespace' => 'Vanguard\Announcements\Http\Controllers\Web',
|
||||
'middleware' => 'web',
|
||||
], function () {
|
||||
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Map API plugin related routes.
|
||||
*/
|
||||
protected function mapApiRoutes(): void
|
||||
{
|
||||
Route::group([
|
||||
'namespace' => 'Vanguard\Announcements\Http\Controllers\Api',
|
||||
'middleware' => 'api',
|
||||
'prefix' => 'api',
|
||||
], function () {
|
||||
$this->loadRoutesFrom(__DIR__.'/../routes/api.php');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugin event listeners.
|
||||
*/
|
||||
private function registerEventListeners(): void
|
||||
{
|
||||
// Register activity log subscriber only if
|
||||
// UserActivity plugin is installed.
|
||||
if ($this->app->bound('Vanguard\UserActivity\Repositories\Activity\ActivityRepository')) {
|
||||
Event::subscribe(ActivityLogSubscriber::class);
|
||||
}
|
||||
|
||||
Event::listen(EmailNotificationRequested::class, SendEmailNotification::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all necessary view hooks for the plugin.
|
||||
*/
|
||||
private function registerHooks(): void
|
||||
{
|
||||
Vanguard::hook('navbar:items', NavbarItemsHook::class);
|
||||
Vanguard::hook('app:styles', StylesHook::class);
|
||||
Vanguard::hook('app:scripts', ScriptsHook::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish public assets.
|
||||
*/
|
||||
protected function publishAssets(): void
|
||||
{
|
||||
$this->publishes([
|
||||
realpath(__DIR__.'/../dist') => $this->app['path.public'].'/vendor/plugins/announcements',
|
||||
], 'public');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
|
||||
class Created
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
public function __construct(public Announcement $announcement, public $sendEmailNotification = false)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
|
||||
class Deleted
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
public function __construct(public Announcement $announcement)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
|
||||
class EmailNotificationRequested
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
public function __construct(public Announcement $announcement)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
|
||||
class Updated
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
public function __construct(public Announcement $announcement)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Hooks;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Vanguard\Announcements\Repositories\AnnouncementsRepository;
|
||||
use Vanguard\Plugins\Contracts\Hook;
|
||||
|
||||
class NavbarItemsHook implements Hook
|
||||
{
|
||||
public function __construct(private readonly AnnouncementsRepository $announcements)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the hook action.
|
||||
*/
|
||||
public function handle(): View
|
||||
{
|
||||
$announcements = $this->announcements->latest(5);
|
||||
$announcements->load('creator');
|
||||
|
||||
return view('announcements::partials.navbar.list', compact('announcements'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Hooks;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Vanguard\Plugins\Contracts\Hook;
|
||||
|
||||
class ScriptsHook implements Hook
|
||||
{
|
||||
/**
|
||||
* Execute the hook action.
|
||||
*/
|
||||
public function handle(): View
|
||||
{
|
||||
return view('announcements::partials.scripts');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Hooks;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Vanguard\Plugins\Contracts\Hook;
|
||||
|
||||
class StylesHook implements Hook
|
||||
{
|
||||
/**
|
||||
* Execute the hook action.
|
||||
*/
|
||||
public function handle(): View
|
||||
{
|
||||
return view('announcements::partials.styles');
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Spatie\QueryBuilder\AllowedFilter;
|
||||
use Spatie\QueryBuilder\AllowedInclude;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
use Vanguard\Announcements\Events\EmailNotificationRequested;
|
||||
use Vanguard\Announcements\Http\Requests\AnnouncementRequest;
|
||||
use Vanguard\Announcements\Http\Resources\AnnouncementResource;
|
||||
use Vanguard\Announcements\Repositories\AnnouncementsRepository;
|
||||
use Vanguard\Http\Controllers\Api\ApiController;
|
||||
|
||||
/**
|
||||
* Class AnnouncementsController
|
||||
*/
|
||||
class AnnouncementsController extends ApiController
|
||||
{
|
||||
public function __construct(private readonly AnnouncementsRepository $announcements)
|
||||
{
|
||||
$this->middleware('permission:announcements.manage')->except('index', 'show');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a paginated list of announcements.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$this->validate($request, ['per_page' => 'numeric|max:50']);
|
||||
|
||||
$announcements = QueryBuilder::for(Announcement::class)
|
||||
->allowedIncludes([
|
||||
AllowedInclude::relationship('user', 'creator'),
|
||||
])
|
||||
->allowedFilters([
|
||||
AllowedFilter::partial('title'),
|
||||
AllowedFilter::partial('body'),
|
||||
AllowedFilter::exact('user', 'user_id'),
|
||||
])
|
||||
->allowedSorts('title', 'created_at')
|
||||
->defaultSort('-created_at')
|
||||
->paginate($request->per_page);
|
||||
|
||||
return AnnouncementResource::collection($announcements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the announcement inside the database.
|
||||
*/
|
||||
public function store(AnnouncementRequest $request): AnnouncementResource
|
||||
{
|
||||
$announcement = $this->announcements->createFor(
|
||||
auth()->user(),
|
||||
$request->title,
|
||||
$request->body
|
||||
);
|
||||
|
||||
if ($request->email_notification) {
|
||||
EmailNotificationRequested::dispatch($announcement);
|
||||
}
|
||||
|
||||
return new AnnouncementResource($announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single announcement resource.
|
||||
*/
|
||||
public function show($announcementId): AnnouncementResource
|
||||
{
|
||||
$announcement = QueryBuilder::for(Announcement::where('id', $announcementId))
|
||||
->allowedIncludes([
|
||||
AllowedInclude::relationship('user', 'creator'),
|
||||
])
|
||||
->first();
|
||||
|
||||
return new AnnouncementResource($announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates announcement details.
|
||||
*/
|
||||
public function update(Announcement $announcement, AnnouncementRequest $request): AnnouncementResource
|
||||
{
|
||||
$announcement = $this->announcements->update(
|
||||
$announcement,
|
||||
$request->title,
|
||||
$request->body
|
||||
);
|
||||
|
||||
return new AnnouncementResource($announcement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes announcement from the system.
|
||||
*/
|
||||
public function destroy(Announcement $announcement): JsonResponse
|
||||
{
|
||||
$this->announcements->delete($announcement);
|
||||
|
||||
return $this->respondWithSuccess();
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Http\Controllers\Api;
|
||||
|
||||
use Vanguard\Http\Controllers\Api\ApiController;
|
||||
|
||||
class ReadAnnouncementsController extends ApiController
|
||||
{
|
||||
/**
|
||||
* Update the timestamp when announcements were last read
|
||||
* by the currently authenticated user.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
auth()->user()->forceFill([
|
||||
'announcements_last_read_at' => now(),
|
||||
])->save();
|
||||
|
||||
return $this->respondWithSuccess();
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Vanguard\Announcements\Repositories\AnnouncementsRepository;
|
||||
use Vanguard\Http\Controllers\Controller;
|
||||
|
||||
class AnnouncementListController extends Controller
|
||||
{
|
||||
public function __construct(private readonly AnnouncementsRepository $announcements)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the plugin index page.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$announcements = $this->announcements->paginate(7);
|
||||
$announcements->load('creator');
|
||||
|
||||
return view('announcements::list', compact('announcements'));
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Http\Controllers\Web;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
use Vanguard\Announcements\Events\EmailNotificationRequested;
|
||||
use Vanguard\Announcements\Http\Requests\AnnouncementRequest;
|
||||
use Vanguard\Announcements\Repositories\AnnouncementsRepository;
|
||||
use Vanguard\Http\Controllers\Controller;
|
||||
|
||||
/**
|
||||
* Class AnnouncementsController
|
||||
*/
|
||||
class AnnouncementsController extends Controller
|
||||
{
|
||||
public function __construct(private readonly AnnouncementsRepository $announcements)
|
||||
{
|
||||
$this->middleware('permission:announcements.manage')->except('show');
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the plugin index page.
|
||||
*/
|
||||
public function index(): View
|
||||
{
|
||||
$announcements = $this->announcements->paginate();
|
||||
$announcements->load('creator');
|
||||
|
||||
return view('announcements::index', compact('announcements'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the create announcement form.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('announcements::add-edit', ['edit' => false]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the announcement inside the database.
|
||||
*/
|
||||
public function store(AnnouncementRequest $request): RedirectResponse
|
||||
{
|
||||
$announcement = $this->announcements->createFor(
|
||||
auth()->user(),
|
||||
$request->title,
|
||||
$request->body
|
||||
);
|
||||
|
||||
if ($request->email_notification) {
|
||||
EmailNotificationRequested::dispatch($announcement);
|
||||
}
|
||||
|
||||
return redirect()->route('announcements.index')
|
||||
->withSuccess(__('Announcement created successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders "view announcement" page.
|
||||
*/
|
||||
public function show(Announcement $announcement): View
|
||||
{
|
||||
return view('announcements::show', compact('announcement'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the form for editing the announcement.
|
||||
*/
|
||||
public function edit(Announcement $announcement): View
|
||||
{
|
||||
return view('announcements::add-edit', [
|
||||
'edit' => true,
|
||||
'announcement' => $announcement,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates announcement details.
|
||||
*/
|
||||
public function update(Announcement $announcement, AnnouncementRequest $request): RedirectResponse
|
||||
{
|
||||
$this->announcements->update(
|
||||
$announcement,
|
||||
$request->title,
|
||||
$request->body
|
||||
);
|
||||
|
||||
return redirect()->route('announcements.index')
|
||||
->withSuccess(__('Announcement updated successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes announcement from the system.
|
||||
*/
|
||||
public function destroy(Announcement $announcement): RedirectResponse
|
||||
{
|
||||
$this->announcements->delete($announcement);
|
||||
|
||||
return redirect()->route('announcements.index')
|
||||
->withSuccess(__('Announcement deleted successfully.'));
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Http\Controllers\Web;
|
||||
|
||||
use Vanguard\Http\Controllers\Controller;
|
||||
|
||||
class ReadAnnouncementsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Update the timestamp when announcements were last read
|
||||
* by the currently authenticated user.
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
auth()->user()->forceFill([
|
||||
'announcements_last_read_at' => now(),
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Http\Requests;
|
||||
|
||||
use Vanguard\Http\Requests\Request;
|
||||
|
||||
class AnnouncementRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'title' => 'required|max:150',
|
||||
'body' => 'required|max:1500',
|
||||
'email_notifications' => 'boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Vanguard\Http\Resources\UserResource;
|
||||
|
||||
class AnnouncementResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $this->id,
|
||||
'user_id' => (int) $this->user_id,
|
||||
'title' => $this->title,
|
||||
'body' => $this->body,
|
||||
'parsed_body' => (string) $this->parsed_body,
|
||||
'created_at' => (string) $this->created_at,
|
||||
'updated_at' => (string) $this->updated_at,
|
||||
'user' => new UserResource($this->whenLoaded('creator')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Listeners;
|
||||
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Illuminate\Support\Str;
|
||||
use Vanguard\Announcements\Events\Created;
|
||||
use Vanguard\Announcements\Events\Deleted;
|
||||
use Vanguard\Announcements\Events\Updated;
|
||||
use Vanguard\UserActivity\Logger;
|
||||
|
||||
class ActivityLogSubscriber
|
||||
{
|
||||
public function __construct(private Logger $logger)
|
||||
{
|
||||
}
|
||||
|
||||
public function onCreate(Created $event): void
|
||||
{
|
||||
$this->logger->log(__('announcements::log.created_announcement', [
|
||||
'id' => $event->announcement->id,
|
||||
'title' => Str::limit($event->announcement->title, 50),
|
||||
]));
|
||||
}
|
||||
|
||||
public function onUpdate(Updated $event): void
|
||||
{
|
||||
$this->logger->log(__('announcements::log.created_announcement', [
|
||||
'id' => $event->announcement->id,
|
||||
]));
|
||||
}
|
||||
|
||||
public function onDelete(Deleted $event): void
|
||||
{
|
||||
$this->logger->log(__('announcements::log.deleted_announcement', [
|
||||
'id' => $event->announcement->id,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the listeners for the subscriber.
|
||||
*/
|
||||
public function subscribe(Dispatcher $events): void
|
||||
{
|
||||
$class = self::class;
|
||||
|
||||
$events->listen(Created::class, "{$class}@onCreate");
|
||||
$events->listen(Updated::class, "{$class}@onUpdate");
|
||||
$events->listen(Deleted::class, "{$class}@onDelete");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Listeners;
|
||||
|
||||
use Mail;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
use Vanguard\Announcements\Events\EmailNotificationRequested;
|
||||
use Vanguard\Announcements\Mail\AnnouncementEmail;
|
||||
use Vanguard\User;
|
||||
|
||||
class SendEmailNotification
|
||||
{
|
||||
/**
|
||||
* Handle the event.
|
||||
*/
|
||||
public function handle(EmailNotificationRequested $event): void
|
||||
{
|
||||
User::chunk(200, function ($users) use ($event) {
|
||||
foreach ($users as $user) {
|
||||
$this->sendEmailTo($user, $event->announcement);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function sendEmailTo(User $user, Announcement $announcement): void
|
||||
{
|
||||
Mail::to($user)->send(new AnnouncementEmail($announcement));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
|
||||
class AnnouncementEmail extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(public Announcement $announcement)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*/
|
||||
public function build(): self
|
||||
{
|
||||
$subject = sprintf('[%s] %s', __('Announcement'), $this->announcement->title);
|
||||
|
||||
return $this->subject($subject)
|
||||
->markdown('announcements::mail.notification');
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Repositories;
|
||||
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
use Vanguard\User;
|
||||
|
||||
interface AnnouncementsRepository
|
||||
{
|
||||
/**
|
||||
* Get latest announcements.
|
||||
*
|
||||
* @return Collection<Announcement>
|
||||
*/
|
||||
public function latest(int $count = 5): Collection;
|
||||
|
||||
/**
|
||||
* Paginate announcements in descending order.
|
||||
*/
|
||||
public function paginate(int $perPage = 10): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Create an announcement for user.
|
||||
*/
|
||||
public function createFor(User $user, string $title, string $body): Announcement;
|
||||
|
||||
/**
|
||||
* Find announcement by ID.
|
||||
*/
|
||||
public function find(int $id): ?Announcement;
|
||||
|
||||
/**
|
||||
* Update announcement.
|
||||
*/
|
||||
public function update(Announcement $announcement, string $title, string $body): Announcement;
|
||||
|
||||
/**
|
||||
* Remove announcement from the system.
|
||||
*/
|
||||
public function delete(Announcement $announcement): bool;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Vanguard\Announcements\Repositories;
|
||||
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Vanguard\Announcements\Announcement;
|
||||
use Vanguard\Announcements\Events\Created;
|
||||
use Vanguard\Announcements\Events\Deleted;
|
||||
use Vanguard\Announcements\Events\Updated;
|
||||
use Vanguard\User;
|
||||
|
||||
class EloquentAnnouncements implements AnnouncementsRepository
|
||||
{
|
||||
/**
|
||||
* Get latest announcements.
|
||||
*
|
||||
* @return Collection<Announcement>
|
||||
*/
|
||||
public function latest(int $count = 5): Collection
|
||||
{
|
||||
return Announcement::latest()->take($count)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate announcements in descending order.
|
||||
*/
|
||||
public function paginate(int $perPage = 10): LengthAwarePaginator
|
||||
{
|
||||
return Announcement::latest()->paginate($perPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an announcement for user.
|
||||
*/
|
||||
public function createFor(User $user, string $title, string $body): Announcement
|
||||
{
|
||||
$announcement = Announcement::create([
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
|
||||
Created::dispatch($announcement);
|
||||
|
||||
return $announcement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find announcement by ID.
|
||||
*/
|
||||
public function find($id): ?Announcement
|
||||
{
|
||||
return Announcement::find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update announcement.
|
||||
*/
|
||||
public function update(Announcement $announcement, string $title, string $body): Announcement
|
||||
{
|
||||
$announcement->update([
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
]);
|
||||
|
||||
Updated::dispatch($announcement);
|
||||
|
||||
return $announcement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove announcement from the system.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(Announcement $announcement): bool
|
||||
{
|
||||
if ($announcement->delete()) {
|
||||
Deleted::dispatch($announcement);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user