-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat:LAR-8 refactor create article process with action and add featur…
…es test
- Loading branch information
Chri$
committed
Oct 8, 2024
1 parent
03bfda4
commit aa324c4
Showing
5 changed files
with
156 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 = [], | ||
) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); |