Refactor models to use new attribute cast
This commit is contained in:
parent
a8de52077f
commit
cfca6a1de5
9 changed files with 218 additions and 292 deletions
|
@ -75,7 +75,7 @@ class MicropubMediaController extends Controller
|
||||||
return [
|
return [
|
||||||
'url' => $mediaItem->url,
|
'url' => $mediaItem->url,
|
||||||
'published' => $mediaItem->created_at->toW3cString(),
|
'published' => $mediaItem->created_at->toW3cString(),
|
||||||
'mime_type' => $mediaItem->getMimeType(),
|
'mime_type' => $mediaItem->mimetype,
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Models;
|
||||||
|
|
||||||
use Cviebrock\EloquentSluggable\Sluggable;
|
use Cviebrock\EloquentSluggable\Sluggable;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
@ -58,70 +59,54 @@ class Article extends Model
|
||||||
*/
|
*/
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
/**
|
protected function html(): Attribute
|
||||||
* Process the article for display.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getHtmlAttribute(): string
|
|
||||||
{
|
{
|
||||||
$environment = new Environment();
|
return Attribute::get(
|
||||||
$environment->addExtension(new CommonMarkCoreExtension());
|
get: function () {
|
||||||
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer());
|
$environment = new Environment();
|
||||||
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer());
|
$environment->addExtension(new CommonMarkCoreExtension());
|
||||||
$markdownConverter = new MarkdownConverter($environment);
|
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer());
|
||||||
|
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer());
|
||||||
|
$markdownConverter = new MarkdownConverter($environment);
|
||||||
|
|
||||||
return $markdownConverter->convert($this->main)->getContent();
|
return $markdownConverter->convert($this->main)->getContent();
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function w3cTime(): Attribute
|
||||||
* Convert updated_at to W3C time format.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getW3cTimeAttribute(): string
|
|
||||||
{
|
{
|
||||||
return $this->updated_at->toW3CString();
|
return Attribute::get(
|
||||||
|
get: fn () => $this->updated_at->toW3CString(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function tooltipTime(): Attribute
|
||||||
* Convert updated_at to a tooltip appropriate format.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getTooltipTimeAttribute(): string
|
|
||||||
{
|
{
|
||||||
return $this->updated_at->toRFC850String();
|
return Attribute::get(
|
||||||
|
get: fn () => $this->updated_at->toRFC850String(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function humanTime(): Attribute
|
||||||
* Convert updated_at to a human readable format.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getHumanTimeAttribute(): string
|
|
||||||
{
|
{
|
||||||
return $this->updated_at->diffForHumans();
|
return Attribute::get(
|
||||||
|
get: fn () => $this->updated_at->diffForHumans(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function pubdate(): Attribute
|
||||||
* Get the pubdate value for RSS feeds.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getPubdateAttribute(): string
|
|
||||||
{
|
{
|
||||||
return $this->updated_at->toRSSString();
|
return Attribute::get(
|
||||||
|
get: fn () => $this->updated_at->toRSSString(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function link(): Attribute
|
||||||
* A link to the article, i.e. `/blog/1999/12/25/merry-christmas`.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLinkAttribute(): string
|
|
||||||
{
|
{
|
||||||
return '/blog/' . $this->updated_at->year . '/' . $this->updated_at->format('m') . '/' . $this->titleurl;
|
return Attribute::get(
|
||||||
|
get: fn () => '/blog/' . $this->updated_at->year . '/' . $this->updated_at->format('m') . '/' . $this->titleurl,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,7 +119,7 @@ class Article extends Model
|
||||||
*/
|
*/
|
||||||
public function scopeDate(Builder $query, int $year = null, int $month = null): Builder
|
public function scopeDate(Builder $query, int $year = null, int $month = null): Builder
|
||||||
{
|
{
|
||||||
if ($year == null) {
|
if ($year === null) {
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
$start = $year . '-01-01 00:00:00';
|
$start = $year . '-01-01 00:00:00';
|
||||||
|
|
|
@ -4,43 +4,11 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* App\Models\Bookmark.
|
|
||||||
*
|
|
||||||
* @property int $id
|
|
||||||
* @property string $url
|
|
||||||
* @property string|null $name
|
|
||||||
* @property string|null $content
|
|
||||||
* @property string|null $screenshot
|
|
||||||
* @property string|null $archive
|
|
||||||
* @property array|null $syndicates
|
|
||||||
* @property Carbon|null $created_at
|
|
||||||
* @property Carbon|null $updated_at
|
|
||||||
* @property-read string $longurl
|
|
||||||
* @property-read Collection|Tag[] $tags
|
|
||||||
* @property-read int|null $tags_count
|
|
||||||
*
|
|
||||||
* @method static Builder|Bookmark newModelQuery()
|
|
||||||
* @method static Builder|Bookmark newQuery()
|
|
||||||
* @method static Builder|Bookmark query()
|
|
||||||
* @method static Builder|Bookmark whereArchive($value)
|
|
||||||
* @method static Builder|Bookmark whereContent($value)
|
|
||||||
* @method static Builder|Bookmark whereCreatedAt($value)
|
|
||||||
* @method static Builder|Bookmark whereId($value)
|
|
||||||
* @method static Builder|Bookmark whereName($value)
|
|
||||||
* @method static Builder|Bookmark whereScreenshot($value)
|
|
||||||
* @method static Builder|Bookmark whereSyndicates($value)
|
|
||||||
* @method static Builder|Bookmark whereUpdatedAt($value)
|
|
||||||
* @method static Builder|Bookmark whereUrl($value)
|
|
||||||
* @mixin Eloquent
|
|
||||||
*/
|
|
||||||
class Bookmark extends Model
|
class Bookmark extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
@ -71,13 +39,10 @@ class Bookmark extends Model
|
||||||
return $this->belongsToMany('App\Models\Tag');
|
return $this->belongsToMany('App\Models\Tag');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function longurl(): Attribute
|
||||||
* The full url of a bookmark.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLongurlAttribute(): string
|
|
||||||
{
|
{
|
||||||
return config('app.url') . '/bookmarks/' . $this->id;
|
return Attribute::get(
|
||||||
|
get: fn () => config('app.url') . '/bookmarks/' . $this->id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Traits\FilterHtml;
|
use App\Traits\FilterHtml;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
@ -17,46 +18,38 @@ class Like extends Model
|
||||||
|
|
||||||
protected $fillable = ['url'];
|
protected $fillable = ['url'];
|
||||||
|
|
||||||
/**
|
protected function url(): Attribute
|
||||||
* Normalize the URL of a Like.
|
|
||||||
*
|
|
||||||
* @param string $value The provided URL
|
|
||||||
*/
|
|
||||||
public function setUrlAttribute(string $value)
|
|
||||||
{
|
{
|
||||||
$this->attributes['url'] = normalize_url($value);
|
return Attribute::set(
|
||||||
|
set: fn ($value) => normalize_url($value),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function authorUrl(): Attribute
|
||||||
* Normalize the URL of the author of the like.
|
|
||||||
*
|
|
||||||
* @param string|null $value The author’s url
|
|
||||||
*/
|
|
||||||
public function setAuthorUrlAttribute(?string $value)
|
|
||||||
{
|
{
|
||||||
$this->attributes['author_url'] = normalize_url($value);
|
return Attribute::set(
|
||||||
|
set: fn ($value) => normalize_url($value),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function content(): Attribute
|
||||||
* If the content contains HTML, filter it.
|
|
||||||
*
|
|
||||||
* @param string|null $value The content of the like
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getContentAttribute(?string $value): ?string
|
|
||||||
{
|
{
|
||||||
if ($value === null) {
|
return Attribute::get(
|
||||||
return null;
|
get: function ($value, $attributes) {
|
||||||
}
|
if ($value === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$mf2 = Mf2\parse($value, $this->url);
|
$mf2 = Mf2\parse($value, $attributes['url']);
|
||||||
|
|
||||||
if (Arr::get($mf2, 'items.0.properties.content.0.html')) {
|
if (Arr::get($mf2, 'items.0.properties.content.0.html')) {
|
||||||
return $this->filterHtml(
|
return $this->filterHtml(
|
||||||
$mf2['items'][0]['properties']['content'][0]['html']
|
$mf2['items'][0]['properties']['content'][0]['html']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
@ -37,53 +38,63 @@ class Media extends Model
|
||||||
return $this->belongsTo(Note::class);
|
return $this->belongsTo(Note::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function url(): Attribute
|
||||||
* Get the URL for an S3 media file.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getUrlAttribute(): string
|
|
||||||
{
|
{
|
||||||
if (Str::startsWith($this->path, 'https://')) {
|
return Attribute::get(
|
||||||
return $this->path;
|
get: function ($value, $attributes) {
|
||||||
}
|
if (Str::startsWith($attributes['path'], 'https://')) {
|
||||||
|
return $attributes['path'];
|
||||||
|
}
|
||||||
|
|
||||||
return config('filesystems.disks.s3.url') . '/' . $this->path;
|
return config('filesystems.disks.s3.url') . '/' . $attributes['path'];
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function mediumurl(): Attribute
|
||||||
* Get the URL for the medium size of an S3 image file.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getMediumurlAttribute(): string
|
|
||||||
{
|
{
|
||||||
$basename = $this->getBasename($this->path);
|
return Attribute::get(
|
||||||
$extension = $this->getExtension($this->path);
|
get: fn ($value, $attributes) => $this->getSizeUrl($attributes['path'], 'medium'),
|
||||||
|
);
|
||||||
return config('filesystems.disks.s3.url') . '/' . $basename . '-medium.' . $extension;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function smallmurl(): Attribute
|
||||||
* Get the URL for the small size of an S3 image file.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getSmallurlAttribute(): string
|
|
||||||
{
|
{
|
||||||
$basename = $this->getBasename($this->path);
|
return Attribute::get(
|
||||||
$extension = $this->getExtension($this->path);
|
get: fn ($value, $attributes) => $this->getSizeUrl($attributes['path'], 'small'),
|
||||||
|
);
|
||||||
return config('filesystems.disks.s3.url') . '/' . $basename . '-small.' . $extension;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function mimetype(): Attribute
|
||||||
* Give the real part of a filename, i.e. strip the file extension.
|
{
|
||||||
*
|
return Attribute::get(
|
||||||
* @param string $path
|
get: function ($value, $attributes) {
|
||||||
* @return string
|
$extension = $this->getExtension($attributes['path']);
|
||||||
*/
|
|
||||||
public function getBasename(string $path): string
|
return match ($extension) {
|
||||||
|
'gif' => 'image/gif',
|
||||||
|
'jpeg', 'jpg' => 'image/jpeg',
|
||||||
|
'png' => 'image/png',
|
||||||
|
'svg' => 'image/svg+xml',
|
||||||
|
'tiff' => 'image/tiff',
|
||||||
|
'webp' => 'image/webp',
|
||||||
|
'mp4' => 'video/mp4',
|
||||||
|
'mkv' => 'video/mkv',
|
||||||
|
default => 'application/octet-stream',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSizeUrl(string $path, string $size): string
|
||||||
|
{
|
||||||
|
$basename = $this->getBasename($path);
|
||||||
|
$extension = $this->getExtension($path);
|
||||||
|
|
||||||
|
return config('filesystems.disks.s3.url') . '/' . $basename . '-' . $size . '.' . $extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBasename(string $path): string
|
||||||
{
|
{
|
||||||
// the following achieves this data flow
|
// the following achieves this data flow
|
||||||
// foo.bar.png => ['foo', 'bar', 'png'] => ['foo', 'bar'] => foo.bar
|
// foo.bar.png => ['foo', 'bar', 'png'] => ['foo', 'bar'] => foo.bar
|
||||||
|
@ -95,40 +106,10 @@ class Media extends Model
|
||||||
}, ''), '.');
|
}, ''), '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getExtension(string $path): string
|
||||||
* Get the extension from a given filename.
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getExtension(string $path): string
|
|
||||||
{
|
{
|
||||||
$parts = explode('.', $path);
|
$parts = explode('.', $path);
|
||||||
|
|
||||||
return array_pop($parts);
|
return array_pop($parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the mime type of the media file.
|
|
||||||
*
|
|
||||||
* For now we will just use the extension, but this could be improved.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getMimeType(): string
|
|
||||||
{
|
|
||||||
$extension = $this->getExtension($this->path);
|
|
||||||
|
|
||||||
return match ($extension) {
|
|
||||||
'gif' => 'image/gif',
|
|
||||||
'jpeg', 'jpg' => 'image/jpeg',
|
|
||||||
'png' => 'image/png',
|
|
||||||
'svg' => 'image/svg+xml',
|
|
||||||
'tiff' => 'image/tiff',
|
|
||||||
'webp' => 'image/webp',
|
|
||||||
'mp4' => 'video/mp4',
|
|
||||||
'mkv' => 'video/mkv',
|
|
||||||
default => 'application/octet-stream',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Models;
|
||||||
|
|
||||||
use Cviebrock\EloquentSluggable\Sluggable;
|
use Cviebrock\EloquentSluggable\Sluggable;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
@ -105,53 +106,46 @@ class Place extends Model
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function longurl(): Attribute
|
||||||
* The Long URL for a place.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLongurlAttribute(): string
|
|
||||||
{
|
{
|
||||||
return config('app.url') . '/places/' . $this->slug;
|
return Attribute::get(
|
||||||
|
get: fn ($value, $attributes) => config('app.url') . '/places/' . $attributes['slug'],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function shorturl(): Attribute
|
||||||
* The Short URL for a place.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getShorturlAttribute(): string
|
|
||||||
{
|
{
|
||||||
return config('app.shorturl') . '/places/' . $this->slug;
|
return Attribute::get(
|
||||||
|
get: fn ($value, $attributes) => config('app.shorturl') . '/places/' . $attributes['slug'],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function uri(): Attribute
|
||||||
* This method is an alternative for `longurl`.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getUriAttribute(): string
|
|
||||||
{
|
{
|
||||||
return $this->longurl;
|
return Attribute::get(
|
||||||
|
get: fn () => $this->longurl,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function externalUrls(): Attribute
|
||||||
* Dealing with a jsonb column, so we check input first.
|
|
||||||
*
|
|
||||||
* @param string|null $url
|
|
||||||
*/
|
|
||||||
public function setExternalUrlsAttribute(?string $url)
|
|
||||||
{
|
{
|
||||||
if ($url === null) {
|
return Attribute::set(
|
||||||
return;
|
set: function ($value, $attributes) {
|
||||||
}
|
if ($value === null) {
|
||||||
$type = $this->getType($url);
|
return $attributes['external_urls'] ?? null;
|
||||||
$already = [];
|
}
|
||||||
if (array_key_exists('external_urls', $this->attributes)) {
|
|
||||||
$already = json_decode($this->attributes['external_urls'], true);
|
$type = $this->getType($value);
|
||||||
}
|
$already = [];
|
||||||
$already[$type] = $url;
|
|
||||||
$this->attributes['external_urls'] = json_encode($already);
|
if (array_key_exists('external_urls', $attributes)) {
|
||||||
|
$already = json_decode($attributes['external_urls'], true);
|
||||||
|
}
|
||||||
|
$already[$type] = $value;
|
||||||
|
|
||||||
|
return json_encode($already);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
@ -40,14 +41,11 @@ class Tag extends Model
|
||||||
return $this->belongsToMany('App\Models\Bookmark');
|
return $this->belongsToMany('App\Models\Bookmark');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function tag(): Attribute
|
||||||
* When creating a Tag model instance, invoke the nomralize method on the tag.
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
*/
|
|
||||||
public function setTagAttribute(string $value)
|
|
||||||
{
|
{
|
||||||
$this->attributes['tag'] = $this->normalize($value);
|
return Attribute::set(
|
||||||
|
set: fn ($value) => self::normalize($value),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,13 +6,14 @@ namespace App\Models;
|
||||||
|
|
||||||
use App\Traits\FilterHtml;
|
use App\Traits\FilterHtml;
|
||||||
use Codebird\Codebird;
|
use Codebird\Codebird;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Jonnybarnes\WebmentionsParser\Authorship;
|
use Jonnybarnes\WebmentionsParser\Authorship;
|
||||||
use Jonnybarnes\WebmentionsParser\Exceptions\AuthorshipParserException;
|
|
||||||
|
|
||||||
class WebMention extends Model
|
class WebMention extends Model
|
||||||
{
|
{
|
||||||
|
@ -43,72 +44,79 @@ class WebMention extends Model
|
||||||
return $this->morphTo();
|
return $this->morphTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function author(): Attribute
|
||||||
* Get the author of the webmention.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*
|
|
||||||
* @throws AuthorshipParserException
|
|
||||||
*/
|
|
||||||
public function getAuthorAttribute(): array
|
|
||||||
{
|
{
|
||||||
$authorship = new Authorship();
|
return Attribute::get(
|
||||||
$hCard = $authorship->findAuthor(json_decode($this->mf2, true));
|
get: function ($value, $attributes) {
|
||||||
|
if (
|
||||||
|
! array_key_exists('mf2', $attributes) ||
|
||||||
|
$attributes['mf2'] === null
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if ($hCard === false) {
|
$authorship = new Authorship();
|
||||||
return [];
|
$hCard = $authorship->findAuthor(json_decode($attributes['mf2'], true));
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if ($hCard === false) {
|
||||||
array_key_exists('properties', $hCard) &&
|
return null;
|
||||||
array_key_exists('photo', $hCard['properties'])
|
}
|
||||||
) {
|
|
||||||
$hCard['properties']['photo'][0] = $this->createPhotoLink($hCard['properties']['photo'][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $hCard;
|
if (
|
||||||
}
|
array_key_exists('properties', $hCard) &&
|
||||||
|
array_key_exists('photo', $hCard['properties'])
|
||||||
|
) {
|
||||||
|
$hCard['properties']['photo'][0] = $this->createPhotoLink($hCard['properties']['photo'][0]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
return $hCard;
|
||||||
* Get the published value for the webmention.
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getPublishedAttribute(): ?string
|
|
||||||
{
|
|
||||||
$mf2 = $this->mf2 ?? '';
|
|
||||||
$microformats = json_decode($mf2, true);
|
|
||||||
if (isset($microformats['items'][0]['properties']['published'][0])) {
|
|
||||||
try {
|
|
||||||
$published = carbon()->parse(
|
|
||||||
$microformats['items'][0]['properties']['published'][0]
|
|
||||||
)->toDayDateTimeString();
|
|
||||||
} catch (\Exception $exception) {
|
|
||||||
$published = $this->updated_at->toDayDateTimeString();
|
|
||||||
}
|
}
|
||||||
} else {
|
);
|
||||||
$published = $this->updated_at->toDayDateTimeString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $published;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function published(): Attribute
|
||||||
* Get the filtered HTML of a reply.
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function getReplyAttribute(): ?string
|
|
||||||
{
|
{
|
||||||
if ($this->mf2 === null) {
|
return Attribute::get(
|
||||||
return null;
|
get: function ($value, $attributes) {
|
||||||
}
|
$mf2 = $attributes['mf2'] ?? '';
|
||||||
$microformats = json_decode($this->mf2, true);
|
$microformats = json_decode($mf2, true);
|
||||||
if (isset($microformats['items'][0]['properties']['content'][0]['html'])) {
|
if (isset($microformats['items'][0]['properties']['published'][0])) {
|
||||||
return $this->filterHtml($microformats['items'][0]['properties']['content'][0]['html']);
|
try {
|
||||||
}
|
$published = carbon()->parse(
|
||||||
|
$microformats['items'][0]['properties']['published'][0]
|
||||||
|
)->toDayDateTimeString();
|
||||||
|
} catch (Exception) {
|
||||||
|
$published = $this->updated_at->toDayDateTimeString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$published = $this->updated_at->toDayDateTimeString();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return $published;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function reply(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::get(
|
||||||
|
get: function ($value, $attributes) {
|
||||||
|
if (
|
||||||
|
! array_key_exists('mf2', $attributes) ||
|
||||||
|
$attributes['mf2'] === null
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$microformats = json_decode($attributes['mf2'], true);
|
||||||
|
|
||||||
|
if (isset($microformats['items'][0]['properties']['content'][0]['html'])) {
|
||||||
|
return $this->filterHtml($microformats['items'][0]['properties']['content'][0]['html']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,11 +129,13 @@ class WebMention extends Model
|
||||||
{
|
{
|
||||||
$url = normalize_url($url);
|
$url = normalize_url($url);
|
||||||
$host = parse_url($url, PHP_URL_HOST);
|
$host = parse_url($url, PHP_URL_HOST);
|
||||||
if ($host == 'pbs.twimg.com') {
|
|
||||||
|
if ($host === 'pbs.twimg.com') {
|
||||||
//make sure we use HTTPS, we know twitter supports it
|
//make sure we use HTTPS, we know twitter supports it
|
||||||
return str_replace('http://', 'https://', $url);
|
return str_replace('http://', 'https://', $url);
|
||||||
}
|
}
|
||||||
if ($host == 'twitter.com') {
|
|
||||||
|
if ($host === 'twitter.com') {
|
||||||
if (Cache::has($url)) {
|
if (Cache::has($url)) {
|
||||||
return Cache::get($url);
|
return Cache::get($url);
|
||||||
}
|
}
|
||||||
|
@ -137,6 +147,7 @@ class WebMention extends Model
|
||||||
|
|
||||||
return $profile_image;
|
return $profile_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filesystem = new Filesystem();
|
$filesystem = new Filesystem();
|
||||||
if ($filesystem->exists(public_path() . '/assets/profile-images/' . $host . '/image')) {
|
if ($filesystem->exists(public_path() . '/assets/profile-images/' . $host . '/image')) {
|
||||||
return '/assets/profile-images/' . $host . '/image';
|
return '/assets/profile-images/' . $host . '/image';
|
||||||
|
|
|
@ -83,7 +83,6 @@ class PlacesTest extends TestCase
|
||||||
'url' => ['https://www.openstreetmap.org/way/1234'],
|
'url' => ['https://www.openstreetmap.org/way/1234'],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
$this->assertInstanceOf('App\Models\Place', $ret);
|
|
||||||
$this->assertCount(11, Place::all());
|
$this->assertCount(11, Place::all());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue