- {{ $article->title }} -
-- {{ $article->user->name }} -
-- {{ '@' . $article->user->username }} -
-- {{ $user->name }} -
-- {{ '@' . $user->username }} -
-- {{ $user->bio }} -
- @endif - -- {{ __('pages/article.share_article') }} -
-diff --git a/app/Actions/Article/CreateArticleAction.php b/app/Actions/Article/CreateArticleAction.php
index 824e1528..5c6104f7 100644
--- a/app/Actions/Article/CreateArticleAction.php
+++ b/app/Actions/Article/CreateArticleAction.php
@@ -4,7 +4,7 @@
namespace App\Actions\Article;
-use App\Data\Article\CreateArticleData;
+use App\Data\CreateArticleData;
use App\Gamify\Points\ArticleCreated;
use App\Models\Article;
use App\Notifications\PostArticleToTelegram;
diff --git a/app/Actions/Discussion/CreateDiscussionAction.php b/app/Actions/Discussion/CreateDiscussionAction.php
index f1ba3d96..e37b1936 100644
--- a/app/Actions/Discussion/CreateDiscussionAction.php
+++ b/app/Actions/Discussion/CreateDiscussionAction.php
@@ -4,7 +4,7 @@
namespace App\Actions\Discussion;
-use App\Data\Discussion\CreateDiscussionData;
+use App\Data\CreateDiscussionData;
use App\Gamify\Points\DiscussionCreated;
use App\Models\Discussion;
use App\Notifications\PostDiscussionToTelegram;
diff --git a/app/Data/Article/CreateArticleData.php b/app/Data/CreateArticleData.php
similarity index 95%
rename from app/Data/Article/CreateArticleData.php
rename to app/Data/CreateArticleData.php
index 63896500..5afceb09 100644
--- a/app/Data/Article/CreateArticleData.php
+++ b/app/Data/CreateArticleData.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Data\Article;
+namespace App\Data;
use Carbon\Carbon;
use Illuminate\Http\UploadedFile;
diff --git a/app/Data/Discussion/CreateDiscussionData.php b/app/Data/CreateDiscussionData.php
similarity index 88%
rename from app/Data/Discussion/CreateDiscussionData.php
rename to app/Data/CreateDiscussionData.php
index 811eacbb..1e168435 100644
--- a/app/Data/Discussion/CreateDiscussionData.php
+++ b/app/Data/CreateDiscussionData.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\Data\Discussion;
+namespace App\Data;
use Spatie\LaravelData\Data;
diff --git a/app/Http/Controllers/ArticlesController.php b/app/Http/Controllers/ArticlesController.php
index 7b2c0dc5..26fc0172 100644
--- a/app/Http/Controllers/ArticlesController.php
+++ b/app/Http/Controllers/ArticlesController.php
@@ -5,11 +5,8 @@
namespace App\Http\Controllers;
use App\Models\Article;
-use App\Models\User;
use App\Policies\ArticlePolicy;
use Illuminate\Contracts\View\View;
-use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Cache;
final class ArticlesController extends Controller
{
@@ -18,43 +15,6 @@ public function __construct()
$this->middleware(['auth', 'verified'], ['except' => ['index', 'show']]);
}
- public function index(): View
- {
- return view('articles.index');
- }
-
- public function show(Article $article): View
- {
- /** @var User $user */
- $user = Auth::user();
-
- views($article)->record();
-
- /** @var Article $article */
- $article = Cache::remember('post-'.$article->id, now()->addHour(), fn () => $article);
-
- abort_unless(
- $article->isPublished() || ($user && $article->isAuthoredBy($user)) || ($user && $user->hasAnyRole(['admin', 'moderator'])), // @phpstan-ignore-line
- 404
- );
-
- $image = $article->getFirstMediaUrl('media');
- // @phpstan-ignore-next-line
- seo()
- ->title($article->title)
- ->description($article->excerpt(100))
- ->image($image)
- ->twitterTitle($article->title)
- ->twitterDescription($article->excerpt(100))
- ->twitterImage($image)
- ->twitterSite('laravelcm')
- ->withUrl();
-
- return view('articles.show', [
- 'article' => $article->loadCount('views'),
- ]);
- }
-
public function create(): View
{
return view('articles.new');
diff --git a/app/Livewire/Articles/Browse.php b/app/Livewire/Articles/Browse.php
deleted file mode 100644
index 6f7cba0d..00000000
--- a/app/Livewire/Articles/Browse.php
+++ /dev/null
@@ -1,78 +0,0 @@
- ['except' => ''],
- 'sortBy' => ['except' => 'recent'],
- ];
-
- public function mount(): void
- {
- $this->viewMode = session('viewMode', $this->viewMode);
- }
-
- public function changeViewMode(string $mode): void
- {
- session()->put('viewMode', $mode);
-
- $this->viewMode = $mode;
- }
-
- public function validSort(string $sort): bool
- {
- return in_array($sort, [
- 'recent',
- 'popular',
- 'trending',
- ]);
- }
-
- public function render(): View
- {
- $articles = Article::with(['tags', 'user', 'user.transactions'])
- ->withCount(['views', 'reactions'])
- ->published()
- ->notPinned()
- ->orderByDesc('sponsored_at')
- ->orderByDesc('published_at');
-
- $tags = Tag::whereHas('articles', function ($query): void {
- $query->published();
- })->orderBy('name')->get();
-
- $selectedTag = Tag::where('slug', $this->tag)->first();
-
- if ($this->tag) {
- $articles->forTag($this->tag);
- }
-
- $articles->{$this->sortBy}();
-
- return view('livewire.articles.browse', [
- 'articles' => $articles->paginate($this->perPage),
- 'tags' => $tags,
- 'selectedTag' => $selectedTag,
- 'selectedSortBy' => $this->sortBy,
- ]);
- }
-}
diff --git a/app/Livewire/Articles/Create.php b/app/Livewire/Articles/Create.php
index 29b66235..0d566bdf 100644
--- a/app/Livewire/Articles/Create.php
+++ b/app/Livewire/Articles/Create.php
@@ -5,7 +5,7 @@
namespace App\Livewire\Articles;
use App\Actions\Article\CreateArticleAction;
-use App\Data\Article\CreateArticleData;
+use App\Data\CreateArticleData;
use App\Models\Tag;
use App\Models\User;
use App\Traits\WithArticleAttributes;
diff --git a/app/Livewire/Discussions/Create.php b/app/Livewire/Discussions/Create.php
index f611c0e9..2104dd3b 100644
--- a/app/Livewire/Discussions/Create.php
+++ b/app/Livewire/Discussions/Create.php
@@ -5,7 +5,7 @@
namespace App\Livewire\Discussions;
use App\Actions\Discussion\CreateDiscussionAction;
-use App\Data\Discussion\CreateDiscussionData;
+use App\Data\CreateDiscussionData;
use App\Models\Tag;
use App\Traits\WithTagsAssociation;
use Illuminate\Contracts\View\View;
diff --git a/app/Livewire/Pages/Articles/Index.php b/app/Livewire/Pages/Articles/Index.php
new file mode 100644
index 00000000..41b956a4
--- /dev/null
+++ b/app/Livewire/Pages/Articles/Index.php
@@ -0,0 +1,32 @@
+ Article::with(['tags', 'user', 'user.transactions'])
+ ->withCount(['views', 'reactions'])
+ ->scopes(['published', 'notPinned'])
+ ->orderByDesc('sponsored_at')
+ ->orderByDesc('published_at')
+ ->paginate($this->perPage),
+ 'tags' => Tag::query()->whereHas('articles', function ($query): void {
+ $query->published();
+ })->orderBy('name')->get(),
+ ])
+ ->title(__('pages/article.title'));
+ }
+}
diff --git a/app/Livewire/Pages/Articles/SinglePost.php b/app/Livewire/Pages/Articles/SinglePost.php
new file mode 100644
index 00000000..1e89295a
--- /dev/null
+++ b/app/Livewire/Pages/Articles/SinglePost.php
@@ -0,0 +1,52 @@
+cooldown(now()->addHours(2))->record();
+
+ $article = $article->load(['media', 'user'])->loadCount('views');
+
+ abort_unless(
+ $article->isPublished() || ($user && $article->isAuthoredBy($user)) || ($user && $user->hasAnyRole(['admin', 'moderator'])), // @phpstan-ignore-line
+ 404
+ );
+
+ $image = empty($article->getFirstMediaUrl('media'))
+ ? $article->getFirstMediaUrl('media')
+ : asset('/images/socialcard.png');
+
+ // @phpstan-ignore-next-line
+ seo()
+ ->title($article->title)
+ ->description($article->excerpt(150))
+ ->image($image)
+ ->twitterTitle($article->title)
+ ->twitterDescription($article->excerpt(150))
+ ->twitterImage($image)
+ ->twitterSite('laravelcm')
+ ->withUrl();
+
+ $this->article = $article;
+ }
+
+ public function render(): View
+ {
+ return view('livewire.pages.articles.single-post')->title($this->article->title);
+ }
+}
diff --git a/app/Livewire/Pages/Articles/SingleTag.php b/app/Livewire/Pages/Articles/SingleTag.php
new file mode 100644
index 00000000..7a92a202
--- /dev/null
+++ b/app/Livewire/Pages/Articles/SingleTag.php
@@ -0,0 +1,33 @@
+ Article::with(['tags', 'user', 'user.transactions'])
+ ->whereHas('tags', function ($query): void {
+ $query->where('id', $this->tag->id);
+ })
+ ->withCount(['views', 'reactions'])
+ ->scopes(['published', 'notPinned'])
+ ->orderByDesc('sponsored_at')
+ ->orderByDesc('published_at')
+ ->paginate($this->perPage),
+ ])->title($this->tag->name);
+ }
+}
diff --git a/app/Models/Article.php b/app/Models/Article.php
index 118d270e..5dc9579a 100644
--- a/app/Models/Article.php
+++ b/app/Models/Article.php
@@ -67,10 +67,6 @@ final class Article extends Model implements HasMedia, ReactableInterface, Viewa
'is_pinned' => 'boolean',
];
- protected $with = [
- 'media',
- ];
-
protected bool $removeViewsOnDelete = true;
public function getRouteKeyName(): string
@@ -115,11 +111,6 @@ public function registerMediaCollections(): void
->acceptsMimeTypes(['image/jpg', 'image/jpeg', 'image/png']);
}
- public function showToc(): bool
- {
- return $this->show_toc;
- }
-
public function submittedAt(): ?Carbon
{
return $this->submitted_at;
diff --git a/app/Models/Tag.php b/app/Models/Tag.php
index 8dfdcbd0..44ea1db3 100644
--- a/app/Models/Tag.php
+++ b/app/Models/Tag.php
@@ -5,16 +5,21 @@
namespace App\Models;
use App\Traits\HasSlug;
-use App\Traits\ModelHelpers;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
+/**
+ * @property-read int $id
+ * @property string $name
+ * @property string $slug
+ * @property string | null $description
+ * @property array $concerns
+ */
final class Tag extends Model
{
use HasFactory;
use HasSlug;
- use ModelHelpers;
public $timestamps = false;
@@ -29,16 +34,6 @@ final class Tag extends Model
'concerns' => 'array',
];
- public function id(): int
- {
- return $this->id;
- }
-
- public function name(): string
- {
- return $this->name;
- }
-
public function articles(): MorphToMany
{
return $this->morphedByMany(Article::class, 'taggable');
diff --git a/app/Traits/ModelHelpers.php b/app/Traits/ModelHelpers.php
deleted file mode 100644
index 6fc8a4b1..00000000
--- a/app/Traits/ModelHelpers.php
+++ /dev/null
@@ -1,20 +0,0 @@
-paginate($perPage);
- }
-
- public function matches(self $model): bool
- {
- return $this->id() === $model->id();
- }
-}
diff --git a/app/Traits/WithInfiniteScroll.php b/app/Traits/WithInfiniteScroll.php
index 1805f197..def8e3dc 100644
--- a/app/Traits/WithInfiniteScroll.php
+++ b/app/Traits/WithInfiniteScroll.php
@@ -10,10 +10,10 @@ trait WithInfiniteScroll
{
use WithPagination;
- public int $perPage = 10;
+ public int $perPage = 12;
public function loadMore(): void
{
- $this->perPage += 10;
+ $this->perPage += 12;
}
}
diff --git a/app/Traits/WithTags.php b/app/Traits/WithTags.php
index 2a6a9ae2..97bd2b5d 100644
--- a/app/Traits/WithTags.php
+++ b/app/Traits/WithTags.php
@@ -24,6 +24,6 @@ public function sortBy(string $sort): void
public function tagExists(string $tag): bool
{
- return Tag::where('slug', $tag)->exists();
+ return Tag::query()->where('slug', $tag)->exists();
}
}
diff --git a/config/lcm.php b/config/lcm.php
index 5ea7d289..eda80e6c 100644
--- a/config/lcm.php
+++ b/config/lcm.php
@@ -6,13 +6,13 @@
'ads' => [
[
- 'url' => 'https://github.com/mckenziearts/laravel-notify/?utm_source=laravelcm&utm_medium=sidebar-widget',
+ 'url' => 'https://github.com/mckenziearts/laravel-notify/?utm_source=laravel.cm&utm_medium=sidebar-widget',
'image' => 'notify',
'alt' => 'Laravel Notify',
'description' => 'Découvrez la nouvelle version de Laravel Notify pour vos projets Laravel.',
],
[
- 'url' => 'https://laravelshopper.dev?utm_source=laravelcm&utm_medium=sidebar-widget',
+ 'url' => 'https://laravelshopper.dev?utm_source=laravel.cm&utm_medium=sidebar-widget',
'image' => 'shopper',
'alt' => 'Laravel Shopper',
'description' => 'Créez votre boutique en ligne aujourd\'hui avec Laravel Shopper.',
diff --git a/lang/en/global.php b/lang/en/global.php
index a49876a0..80611895 100644
--- a/lang/en/global.php
+++ b/lang/en/global.php
@@ -9,6 +9,7 @@
'by' => 'by',
'soon' => 'Soon',
'navigation' => [
+ 'home' => 'Home',
'forum' => 'Forum',
'articles' => 'Posts',
'discussions' => 'Discussions',
@@ -72,9 +73,13 @@
'view_more' => 'View more →',
'or' => 'or',
'need' => 'You need',
+ 'loading' => 'Loading...',
'discord' => [
'title' => 'Join discord',
'description' => 'Join the community Discord server and connect with other developers.',
],
+ 'ads' => [
+ 'ln_ui' => 'A fun collection of small, well-coded components to streamline your development process.',
+ ],
];
diff --git a/lang/en/pages/article.php b/lang/en/pages/article.php
index 21d6764a..bf5b5691 100644
--- a/lang/en/pages/article.php
+++ b/lang/en/pages/article.php
@@ -4,9 +4,12 @@
return [
+ 'title' => 'Laravel Cameroon Blog',
+ 'blog' => 'Le Blog de Laravel Cameroun',
+ 'blog_summary' => 'All the latest articles, tips and tutorials published just for you.',
'about_author' => 'About author',
'next_article' => 'Next article',
'prev_article' => 'Previous article',
- 'share_article' => 'Do you like this article? Share it with others',
+ 'share_article' => 'Share',
];
diff --git a/lang/fr/global.php b/lang/fr/global.php
index 41f897e2..ff22f176 100644
--- a/lang/fr/global.php
+++ b/lang/fr/global.php
@@ -9,6 +9,7 @@
'by' => 'par',
'soon' => 'Bientôt',
'navigation' => [
+ 'home' => 'Accueil',
'forum' => 'Forum',
'articles' => 'Articles',
'discussions' => 'Discussions',
@@ -72,9 +73,13 @@
'view_more' => 'En savoir plus →',
'or' => 'ou',
'need' => 'Il faut',
+ 'loading' => 'Chargement...',
'discord' => [
'title' => 'Rejoindre Discord',
'description' => 'Rejoignez le serveur Discord de la communauté et connectez-vous avec d\'autres développeurs.',
],
+ 'ads' => [
+ 'ln_ui' => 'Une collection interactives de petits composants bien codés pour optimiser votre temps de développement.',
+ ],
];
diff --git a/lang/fr/pages/article.php b/lang/fr/pages/article.php
index 068e25de..df82bfd9 100644
--- a/lang/fr/pages/article.php
+++ b/lang/fr/pages/article.php
@@ -4,9 +4,12 @@
return [
+ 'title' => 'Blog Laravel Cameroun',
+ 'blog' => 'The Laravel Cameroon Blog',
+ 'blog_summary' => 'Tous les articles, tips et tutoriels récemment publiés juste pour vous.',
'about_author' => 'À propos de l’auteur',
'next_article' => 'Article suivant',
'prev_article' => 'Article précédent',
- 'share_article' => 'Vous aimez cet article ? Faite le savoir en partageant',
+ 'share_article' => 'Partager',
];
diff --git a/resources/js/utils/helpers.js b/resources/js/utils/helpers.js
index 95ee84f8..8a5d9811 100644
--- a/resources/js/utils/helpers.js
+++ b/resources/js/utils/helpers.js
@@ -71,42 +71,3 @@ const share = function () {
}
share()
-
-const addAffiliateLink = function () {
- let articleContent = document.getElementById('content')
-
- if (!articleContent) {
- return
- }
-
- let pTags = document.getElementById('content').querySelectorAll('p')
- let i = 0
- pTags.forEach((p) => {
- if (i === 7) {
- let a = document.createElement('a')
- a.setAttribute(
- 'href',
- 'https://www.digitalocean.com/?refcode=d6dca1691fb4&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge',
- )
- a.setAttribute('target', '_blank')
- a.classList.add(
- 'relative',
- 'affiliate',
- 'block',
- 'w-full',
- 'mb-6',
- 'overflow-hidden',
- 'rounded-lg',
- 'cursor-pointer',
- )
- a.innerHTML = `
-
- Obtenez le code gratuit en créant votre serveur 🚀
- `
- p.parentNode.insertBefore(a, p.nextSibling)
- }
- i++
- })
-}
-
-addAffiliateLink()
diff --git a/resources/views/ads/ln.blade.php b/resources/views/ads/ln.blade.php
new file mode 100644
index 00000000..71d0bfef
--- /dev/null
+++ b/resources/views/ads/ln.blade.php
@@ -0,0 +1,51 @@
+
- {{ $article->user->name }} -
-- {{ '@' . $article->user->username }} -
-- {{ $user->name }} -
-- {{ '@' . $user->username }} -
-- {{ $user->bio }} -
- @endif - -- {{ __('pages/article.share_article') }} -
-+ {!! $article->excerpt(175) !!} +
+- - {{ $article->user->name }} - -
-- -
-- {!! $article->excerpt(175) !!} -
-{!! $article->excerpt(130) !!}
-
+
{{ $content }}
++ {{ $content }} +
Tous les articles récemment publiés.
-
-
+ {{ __('pages/article.blog_summary') }} +
++
+ @endif + + {{ __('global.loading') }} ++ {{ __('pages/article.share_article') }} +
++ {{ $tag->description }} +
+ @endif ++
+ @endif + + {{ __('global.loading') }} +