Merge pull request #227 from jonnybarnes/refactor-notes

Redo Notes a little, improve tests
This commit is contained in:
Jonny Barnes 2021-04-29 20:10:20 +01:00 committed by GitHub
commit 9a1aae3e6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 27 deletions

View file

@ -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/');
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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'],
];
}
}