Merge pull request #227 from jonnybarnes/refactor-notes
Redo Notes a little, improve tests
This commit is contained in:
commit
9a1aae3e6c
5 changed files with 107 additions and 27 deletions
|
@ -5,14 +5,15 @@ declare(strict_types=1);
|
|||
namespace App\Models;
|
||||
|
||||
use App\Exceptions\TwitterContentException;
|
||||
use Barryvdh\LaravelIdeHelper\Eloquent;
|
||||
use Codebird\Codebird;
|
||||
use Eloquent;
|
||||
use Exception;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Database\Eloquent\Relations\{BelongsTo, BelongsToMany, HasMany, MorphMany};
|
||||
use Illuminate\Database\Eloquent\{Builder, Collection, Factories\HasFactory, Model, SoftDeletes};
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use JetBrains\PhpStorm\ArrayShape;
|
||||
use Jonnybarnes\IndieWeb\Numbers;
|
||||
use Laravel\Scout\Searchable;
|
||||
use League\CommonMark\Block\Element\{FencedCode, IndentedCode};
|
||||
|
@ -20,6 +21,11 @@ use League\CommonMark\Extension\Autolink\AutolinkExtension;
|
|||
use League\CommonMark\{CommonMarkConverter, Environment};
|
||||
use Normalizer;
|
||||
use Spatie\CommonMarkHighlighter\{FencedCodeRenderer, IndentedCodeRenderer};
|
||||
use App\Models\Tag;
|
||||
use App\Models\MicropubClient;
|
||||
use App\Models\WebMention;
|
||||
use App\Models\Place;
|
||||
use App\Models\Media;
|
||||
|
||||
/**
|
||||
* App\Models\Note.
|
||||
|
@ -102,12 +108,12 @@ class Note extends Model
|
|||
/**
|
||||
* This variable is used to keep track of contacts in a note.
|
||||
*/
|
||||
protected $contacts;
|
||||
protected ?array $contacts;
|
||||
|
||||
/**
|
||||
* Set our contacts variable to null.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
|
@ -145,9 +151,9 @@ class Note extends Model
|
|||
*
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function tags()
|
||||
public function tags(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany('App\Models\Tag');
|
||||
return $this->belongsToMany(Tag::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,9 +161,9 @@ class Note extends Model
|
|||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function client()
|
||||
public function client(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo('App\Models\MicropubClient', 'client_id', 'client_url');
|
||||
return $this->belongsTo(MicropubClient::class, 'client_id', 'client_url');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,9 +171,9 @@ class Note extends Model
|
|||
*
|
||||
* @return MorphMany
|
||||
*/
|
||||
public function webmentions()
|
||||
public function webmentions(): MorphMany
|
||||
{
|
||||
return $this->morphMany('App\Models\WebMention', 'commentable');
|
||||
return $this->morphMany(WebMention::class, 'commentable');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,9 +181,9 @@ class Note extends Model
|
|||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function place()
|
||||
public function place(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo('App\Models\Place');
|
||||
return $this->belongsTo(Place::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,9 +191,9 @@ class Note extends Model
|
|||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function media()
|
||||
public function media(): HasMany
|
||||
{
|
||||
return $this->hasMany('App\Models\Media');
|
||||
return $this->hasMany(Media::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,6 +201,7 @@ class Note extends Model
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
#[ArrayShape(['note' => "null|string"])]
|
||||
public function toSearchableArray(): array
|
||||
{
|
||||
return [
|
||||
|
@ -207,7 +214,7 @@ class Note extends Model
|
|||
*
|
||||
* @param string|null $value
|
||||
*/
|
||||
public function setNoteAttribute(?string $value)
|
||||
public function setNoteAttribute(?string $value): void
|
||||
{
|
||||
if ($value !== null) {
|
||||
$normalized = normalizer_normalize($value, Normalizer::FORM_C);
|
||||
|
@ -253,13 +260,13 @@ class Note extends Model
|
|||
$note = $this->note;
|
||||
|
||||
foreach ($this->media as $media) {
|
||||
if ($media->type == 'image') {
|
||||
if ($media->type === 'image') {
|
||||
$note .= '<img src="' . $media->url . '" alt="">';
|
||||
}
|
||||
if ($media->type == 'audio') {
|
||||
if ($media->type === 'audio') {
|
||||
$note .= '<audio src="' . $media->url . '">';
|
||||
}
|
||||
if ($media->type == 'video') {
|
||||
if ($media->type === 'video') {
|
||||
$note .= '<video src="' . $media->url . '">';
|
||||
}
|
||||
}
|
||||
|
@ -398,7 +405,10 @@ class Note extends Model
|
|||
*/
|
||||
public function getTwitterAttribute(): ?object
|
||||
{
|
||||
if ($this->in_reply_to == null || mb_substr($this->in_reply_to, 0, 20, 'UTF-8') !== 'https://twitter.com/') {
|
||||
if (
|
||||
$this->in_reply_to === null ||
|
||||
!$this->isTwitterLink($this->in_reply_to)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -569,7 +579,7 @@ class Note extends Model
|
|||
public function autoLinkHashtag(string $note): string
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'/#([^\s]*)\b/',
|
||||
'/#([^\s[:punct:]]+)/',
|
||||
function ($matches) {
|
||||
return '<a rel="tag" class="p-category" href="/notes/tagged/'
|
||||
. Tag::normalize($matches[1]) . '">#'
|
||||
|
@ -660,4 +670,9 @@ class Note extends Model
|
|||
return $address;
|
||||
});
|
||||
}
|
||||
|
||||
private function isTwitterLink(string $inReplyTo): bool
|
||||
{
|
||||
return str_starts_with($inReplyTo, 'https://twitter.com/');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* App\Models\Tag.
|
||||
|
@ -82,13 +83,6 @@ class Tag extends Model
|
|||
*/
|
||||
public static function normalize(string $tag): string
|
||||
{
|
||||
return mb_strtolower(
|
||||
preg_replace(
|
||||
'/&([a-z]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml|caron);/i',
|
||||
'$1',
|
||||
htmlentities($tag)
|
||||
),
|
||||
'UTF-8'
|
||||
);
|
||||
return Str::slug($tag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,6 +209,12 @@ EOF;
|
|||
->where('id', $noteWithLongUrl->id)
|
||||
->update(['updated_at' => $now->toDateTimeString()]);
|
||||
|
||||
$noteWithLocation = Note::create([
|
||||
'note' => 'Some location data',
|
||||
'created_at' => $now->subDay(),
|
||||
'location' => '1.23,4.56',
|
||||
]);
|
||||
|
||||
Note::factory(10)->create();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Models\{Media, Note, Tag};
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Handler\MockHandler;
|
||||
|
@ -334,4 +335,47 @@ class NotesTest extends TestCase
|
|||
$note->note
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, just reply on a cached object instead of actually querying Twitter.
|
||||
*
|
||||
* @test
|
||||
*/
|
||||
public function checkInReplyToIsTwitterLink(): void
|
||||
{
|
||||
$tempContent = (object) [
|
||||
'html' => 'something random',
|
||||
];
|
||||
Cache::put('933662564587855877', $tempContent);
|
||||
|
||||
$note = Note::find(1);
|
||||
|
||||
$this->assertSame($tempContent, $note->twitter);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function latitudeCanBeParsedFromPlainLocation(): void
|
||||
{
|
||||
$note = Note::find(18);
|
||||
|
||||
$this->assertSame(1.23, $note->latitude);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function longitudeCanBeParsedFromPlainLocation(): void
|
||||
{
|
||||
$note = Note::find(18);
|
||||
|
||||
$this->assertSame(4.56, $note->longitude);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function addressAttributeCanBeRetrievedFromPlainLocation(): void
|
||||
{
|
||||
Cache::put('1.23,4.56', '<span class="p-country-name">Antarctica</span>');
|
||||
|
||||
$note = Note::find(18);
|
||||
|
||||
$this->assertSame('<span class="p-country-name">Antarctica</span>', $note->address);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,25 @@ class TagsTest extends TestCase
|
|||
$tag = Tag::find(5); //should be first random tag for bookmarks
|
||||
$this->assertCount(1, $tag->bookmarks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider tagsProvider
|
||||
* @param string $input
|
||||
* @param string $expected
|
||||
*/
|
||||
public function canNormalize(string $input, string $expected): void
|
||||
{
|
||||
$this->assertSame($expected, Tag::normalize($input));
|
||||
}
|
||||
|
||||
public function tagsProvider(): array
|
||||
{
|
||||
return [
|
||||
['test', 'test'],
|
||||
['Test', 'test'],
|
||||
['Tést', 'test'],
|
||||
['MultiWord', 'multiword'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue