Skip to content

Commit

Permalink
feat:LAR-8 refactor create article process with action and add featur…
Browse files Browse the repository at this point in the history
…es test
  • Loading branch information
Chri$ committed Oct 8, 2024
1 parent 03bfda4 commit aa324c4
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 35 deletions.
61 changes: 61 additions & 0 deletions app/Actions/Article/CreateArticleAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php


declare(strict_types=1);

namespace App\Actions\Article;

use Carbon\Carbon;
use DateTimeInterface;
use App\Data\Article\CreateArticleData;
use App\Gamify\Points\ArticleCreated;
use App\Models\Article;
use App\Notifications\PostArticleToTelegram;
use Illuminate\Support\Facades\Auth;

final class CreateArticleAction
{
public function execute(CreateArticleData $articleData): Article
{
if ($articleData->published_at && !($articleData->published_at instanceof DateTimeInterface)) {
$articleData->published_at = new Carbon(
time: $articleData->published_at,
tz: config('app.timezone')
);
}

/** @var Article $article */
$article = Article::query()->create([
'title' => $articleData->title,
'slug' => $articleData->title,
'body' => $articleData->body,
'published_at' => $articleData->published_at,
'submitted_at' => $articleData->submitted_at,
'approved_at' => $articleData->approved_at,
'show_toc' => $articleData->show_toc,
'canonical_url' => $articleData->canonical_url,
'user_id' => Auth::id(),
]);

if (collect($article->associateTags)->isNotEmpty()) {
$article->syncTags(tags: $article->associateTags);
}

if ($article->file) {
$article->addMedia($article->file->getRealPath())->toMediaCollection('media');
}

if ($article->isAwaitingApproval()) {
// Envoi de la notification sur le channel Telegram pour la validation de l'article.
Auth::user()?->notify(new PostArticleToTelegram($article));
session()->flash('status', __('Merci d\'avoir soumis votre article. Vous aurez des nouvelles que lorsque nous accepterons votre article.'));
}

if (Auth::user()?->hasAnyRole(['admin', 'moderator'])) {
givePoint(new ArticleCreated($article));
}


return $article;
}
}
23 changes: 23 additions & 0 deletions app/Data/Article/CreateArticleData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace App\Data\Article;

use Carbon\Carbon;
use Spatie\LaravelData\Data;

final class CreateArticleData extends Data
{
public function __construct(
public string $title,
public string $slug,
public string $body,
public Carbon $published_at,
public Carbon | null $submitted_at,
public Carbon | null $approved_at,
public string $show_toc,
public string $canonical_url,
public array $associateTags = [],
) {}
}
25 changes: 25 additions & 0 deletions app/Gamify/Points/ArticleCreated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace App\Gamify\Points;

use App\Models\Article;
use App\Models\User;
use QCod\Gamify\PointType;

final class ArticleCreated extends PointType
{
public int $points = 50;

public function __construct(Article $subject)
{
$this->subject = $subject;
}

public function payee(): User
{
// @phpstan-ignore-next-line
return $this->getSubject()->user;
}
}
40 changes: 5 additions & 35 deletions app/Livewire/Articles/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@

namespace App\Livewire\Articles;

use App\Events\ArticleWasSubmittedForApproval;
use App\Gamify\Points\PostCreated;
use App\Models\Article;
use App\Actions\Article\CreateArticleAction;
use App\Data\Article\CreateArticleData;
use App\Models\Tag;
use App\Models\User;
use App\Traits\WithArticleAttributes;
use App\Traits\WithTagsAssociation;
use Carbon\Carbon;
use DateTimeInterface;

use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
Expand Down Expand Up @@ -52,15 +50,7 @@ public function store(): void
/** @var User $user */
$user = Auth::user();

if ($this->published_at && ! ($this->published_at instanceof DateTimeInterface)) {
$this->published_at = new Carbon(
time: $this->published_at,
tz: config('app.timezone')
);
}

/** @var Article $article */
$article = Article::create([
$article = app(CreateArticleAction::class)->execute(CreateArticleData::from([
'title' => $this->title,
'slug' => $this->slug,
'body' => $this->body,
Expand All @@ -70,28 +60,8 @@ public function store(): void
'show_toc' => $this->show_toc,
'canonical_url' => $this->canonical_url,
'user_id' => $user->id,
]);

if (collect($this->associateTags)->isNotEmpty()) {
$article->syncTags(tags: $this->associateTags);
}

if ($this->file) {
$article->addMedia($this->file->getRealPath())->toMediaCollection('media');
}

if ($article->isAwaitingApproval()) {
if (app()->environment('production')) {
// Envoi de la notification sur le channel Telegram pour la validation de l'article.
event(new ArticleWasSubmittedForApproval($article));
}

session()->flash('status', __('Merci d\'avoir soumis votre article. Vous aurez des nouvelles que lorsque nous accepterons votre article.'));
}
]));

if ($user->hasAnyRole(['admin', 'moderator'])) {
givePoint(new PostCreated($article));
}

$user->hasRole('user') ?
$this->redirectRoute('dashboard') :
Expand Down
42 changes: 42 additions & 0 deletions tests/Feature/Actions/Article/createArticleActionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php


declare(strict_types=1);

use App\Actions\Article\CreateArticleAction;
use App\Data\Article\CreateArticleData;
use App\Models\Article;
use App\Models\Tag;


beforeEach(function (): void {
$this->user = $this->login();
$this->tagOne = Tag::factory()->create(['name' => 'Tag 1', 'concerns' => ['article']]);
$this->tagTwo = Tag::factory()->create(['name' => 'Tag 2', 'concerns' => ['article', 'post']]);
});


describe(CreateArticleAction::class, function (): void {
it('return the created article', function (): void {
$articleDataWithoutTag = CreateArticleData::from([
'title' => 'Article title',
'slug' => 'Article slug',
'published_at' => Now(),
'submitted_at' => null,
'approved_at' => null,
'show_toc' => 'Article show_toc',
'canonical_url' => 'Article canonical_url',
'body' => 'Article body',
'associateTags' => [],
]);

$article = app(CreateArticleAction::class)->execute($articleDataWithoutTag);

expect($article)
->toBeInstanceOf(Article::class)
->and($article->tags)
->toHaveCount(0)
->and($article->user_id)
->toBe($this->user->id);
});
})->group('Articles');

0 comments on commit aa324c4

Please sign in to comment.