1
0
Fork 0
mirror of https://github.com/archtechx/laravel-tips.git synced 2025-12-11 21:14:02 +00:00

Fix content, add command, update readme

This commit is contained in:
Samuel Štancl 2021-08-27 18:37:33 +02:00
parent 3c3a5fcfd9
commit 69d86147d7
12 changed files with 70 additions and 35 deletions

View file

@ -32,7 +32,13 @@ ALWAYS use strict comparison (=== and !==). If needed, cast things go the correc
Also consider enabling strict types in your code. This will prevent passing variables of wrong data types to functions Also consider enabling strict types in your code. This will prevent passing variables of wrong data types to functions
``` ```
The `slug` matches the file name, the `author_username` is the Twitter handle of the tip author, `tweet_id` is the id of the tweet with the tip, and `images` is an array of images that should be shown between the heading and the content. The `slug` matches the file name, the `author_username` is the Twitter handle of the tip author, `tweet_id` is the id of the tweet with the tip, and `images` is an array of images that should be shown between the heading and the content.'
**Make sure you also create a record in `content/users` for your Twitter handle** if your Author is not created yet. The tip's `author_username` needs to reference an Author model.
### Helper command
You can also use the `php artisan tweet:add` command to add content, just make sure that the tweet's "dependencies" (author and possibly thread) are in place.
## Local setup ## Local setup

View file

@ -0,0 +1,35 @@
<?php
namespace App\Console\Commands;
use App\Models\Thread;
use App\Models\Tip;
use App\Twitter\Tweet;
use Illuminate\Support\Str;
use Illuminate\Console\Command;
class AddTweet extends Command
{
protected $signature = 'tweet:add {tweet}';
protected $description = 'Add a tweet';
public function handle()
{
$id = Str::of($this->argument('tweet'))->afterLast('/')->before('?');
$this->line('Fetching tweet ID ' . $id);
$tip = Tip::fromTweet(
$tweet = Tweet::fetch($id)
);
$tip->slug = $this->ask('Slug', $tip->defaultSlug());
$tip->thread_slug = $this->choice('Thread', Thread::all()->pluck('slug', 'title')->prepend('- None - ', null)->toArray(), null);
$tip->save();
$this->info("Successfully saved tip to: content/tips/{$tip->slug}.md");
}
}

View file

@ -32,7 +32,7 @@ class Thread extends Model
$table->string('slug')->unique(); $table->string('slug')->unique();
$table->string('title'); $table->string('title');
$table->string('tweet_id')->nullable(); $table->string('tweet_id')->nullable();
$table->foreignId('author_username')->constrained('authors', 'username'); $table->foreignId('author_username')->nullable()->constrained('authors', 'username');
$table->text('content'); $table->text('content');
$table->json('links')->default('{}'); $table->json('links')->default('{}');
$table->timestamp('created_at'); $table->timestamp('created_at');
@ -58,7 +58,7 @@ class Thread extends Model
if (is_numeric($this->tweet_id)) { if (is_numeric($this->tweet_id)) {
return "https://twitter.com/{$this->author_username}/status/{$this->tweet_id}"; return "https://twitter.com/{$this->author_username}/status/{$this->tweet_id}";
} }
return $this->tweet_id; return $this->tweet_id;
} }

View file

@ -19,7 +19,7 @@ use Illuminate\Support\Str;
* @property string $content * @property string $content
* @property string $tweet_id * @property string $tweet_id
* @property string $author_username * @property string $author_username
* @property string|null $thread_id * @property string|null $thread_slug
* @property string[] $images * @property string[] $images
* @property-read Author $author * @property-read Author $author
* @property-read Thread|null $thread * @property-read Thread|null $thread
@ -41,7 +41,7 @@ class Tip extends Model
$table->string('slug')->unique(); $table->string('slug')->unique();
$table->string('title'); $table->string('title');
$table->string('tweet_id'); $table->string('tweet_id');
$table->foreignId('thread_slug')->constrained('threads', 'slug')->nullable(); $table->foreignId('thread_slug')->nullable();
$table->foreignId('author_username')->constrained('authors', 'username'); $table->foreignId('author_username')->constrained('authors', 'username');
$table->json('images')->default('[]'); $table->json('images')->default('[]');
$table->timestamp('created_at'); $table->timestamp('created_at');
@ -74,7 +74,7 @@ class Tip extends Model
'title' => (string) Str::of(Str::of($tweet->text)->explode("\n")->first())->rtrim('.')->replaceMatches('/^([^a-zA-Z]*)/', ''), // remove any non-ascii characters from the beginning 'title' => (string) Str::of(Str::of($tweet->text)->explode("\n")->first())->rtrim('.')->replaceMatches('/^([^a-zA-Z]*)/', ''), // remove any non-ascii characters from the beginning
'content' => (string) Str::of($tweet->text)->explode("\n")->skip(1)->join("\n"), 'content' => (string) Str::of($tweet->text)->explode("\n")->skip(1)->join("\n"),
'tweet_id' => $tweet->id, 'tweet_id' => $tweet->id,
'thread_slug' => $threadSlug ?? Thread::firstWhere('tweet_id', $tweet->threadId)->slug, 'thread_slug' => $threadSlug ?? Thread::firstWhere('tweet_id', $tweet->threadId)?->slug,
'author_username' => Author::firstOrCreate([ 'author_username' => Author::firstOrCreate([
'username' => $tweet->author->username, 'username' => $tweet->author->username,
'name' => $tweet->author->name, 'name' => $tweet->author->name,
@ -89,7 +89,7 @@ class Tip extends Model
{ {
static::creating(function (self $model) { static::creating(function (self $model) {
$model->created_at ??= now(); $model->created_at ??= now();
$model->slug ??= Str::slug($model->title); $model->slug ??= $this->defaultSlug();
}); });
static::addGlobalScope('order', fn (Builder $query) => $query->orderBy('created_at', 'desc')); static::addGlobalScope('order', fn (Builder $query) => $query->orderBy('created_at', 'desc'));
@ -104,4 +104,9 @@ class Tip extends Model
{ {
return false; return false;
} }
public function defaultSlug(): string
{
return Str::slug($this->title);
}
} }

View file

@ -1,5 +1,5 @@
--- ---
username: archtechx username: archtechx
name: 'ARCHTECH' name: ARCHTECH
avatar: 'https://pbs.twimg.com/profile_images/1393303364390227974/uaP8Hoq1_normal.jpg' avatar: 'https://pbs.twimg.com/profile_images/1393303364390227974/uaP8Hoq1_normal.jpg'
--- ---

View file

@ -4,4 +4,5 @@ title: 'Pest Tips'
tweet_id: 1427310302656438274 tweet_id: 1427310302656438274
author_username: archtechx author_username: archtechx
created_at: 2021-08-16T19:09:23+02:00 created_at: 2021-08-16T19:09:23+02:00
links: {}
--- ---

View file

@ -0,0 +1,12 @@
---
title: 'Another pest tip: Create a using() helper to get perfect IDE support on $this calls inside your tests'
tweet_id: '1426219050250772482'
thread_slug: 'Pest Tips'
author_username: archtechx
images:
- 'https://pbs.twimg.com/media/E8ryqTuWEAQT-1H.jpg'
created_at: 2021-08-16T19:07:26+02:00
slug: create-a-using-helper-in-pest
---
Out of the box, @pestphp has amazing IDE support for the expect()-&gt;toBe() syntax, but sometimes you need to use $this — usually for things like HTTP calls.

View file

@ -1,11 +0,0 @@
---
title: 'Create a using() helper'
tweet_id: 1426219050250772482
thread_slug: pest-tips
author_username: archtechx
images:
- https://pbs.twimg.com/media/E8ryqTuWEAQT-1H.jpg
created_at: 2021-08-16T19:09:24+02:00
slug: create-a-using-helper
---
Create a using() helper to get perfect IDE support on $this calls inside your tests.

View file

@ -5,8 +5,7 @@ thread_slug: pest-tips
author_username: archtechx author_username: archtechx
images: images:
- https://pbs.twimg.com/media/E8mO3a5VEAAsjr1.jpg - https://pbs.twimg.com/media/E8mO3a5VEAAsjr1.jpg
created_at: 2021-08-16T19:07:22+02:00
created_at: 2021-08-16T19:09:22+02:00
slug: create-helper-functions-for-creating-models-in-tests-using-factories slug: create-helper-functions-for-creating-models-in-tests-using-factories
--- ---
For example: For example:

View file

@ -1,12 +0,0 @@
---
title: 'Disable Livewire polling when an element is hidden'
tweet_id: '1383079668358725636'
thread_slug: ''
author_username: abrardev99
images:
- 'https://i.ibb.co/zZ7rNn8/Livewire-polling.png'
created_at: 2021-04-16T17:20:27+02:00
slug: disable-livewire-polling-when-an-element-is-hidden
---
Livewire (v2.4.3) landed a new polling modifier that lets you limit polling when an element is not visible in the current viewport.

View file

@ -29,7 +29,7 @@
@if ($tip->images()) @if ($tip->images())
@foreach ($tip->images() as $image) @foreach ($tip->images() as $image)
<img class="shadow-xl rounded-xl" src="{{ $image->small() }}" alt="{{ $tip->title }}"> <img class="shadow-xl rounded-xl" src="{{ $image->medium() }}" alt="{{ $tip->title }}">
@endforeach @endforeach
@endif @endif

View file

@ -60,7 +60,7 @@
@if ($tip->images()) @if ($tip->images())
@foreach ($tip->images() as $image) @foreach ($tip->images() as $image)
<img class="shadow-xl rounded-xl backdrop-filter backdrop-blur-lg backdrop-saturate-125" <img class="shadow-xl rounded-xl backdrop-filter backdrop-blur-lg backdrop-saturate-125"
src="{{ $image->small() }}" alt="{{ $tip->title }}"> src="{{ $image->large() }}" alt="{{ $tip->title }}">
@endforeach @endforeach
@endif @endif