Swap the syntax highlighting library and its CSS theme (zenburn -> nord, matching tempest's class names), add padding to code blocks, and commit the missing compressed winter.js assets from the earlier asset rename. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
120 lines
3.3 KiB
PHP
120 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Models;
|
|
|
|
use Cviebrock\EloquentSluggable\Sluggable;
|
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
|
use Illuminate\Database\Eloquent\Attributes\Table;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use League\CommonMark\Environment\Environment;
|
|
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
|
use League\CommonMark\MarkdownConverter;
|
|
use Tempest\Highlight\CommonMark\HighlightExtension;
|
|
|
|
#[Table('articles')]
|
|
#[Fillable(['url', 'title', 'main', 'published'])]
|
|
class Article extends Model
|
|
{
|
|
use HasFactory;
|
|
use Sluggable;
|
|
use SoftDeletes;
|
|
|
|
/** @var array<string, string> */
|
|
protected $casts = [
|
|
'created_at' => 'datetime',
|
|
'updated_at' => 'datetime',
|
|
'deleted_at' => 'datetime',
|
|
];
|
|
|
|
/**
|
|
* Return the sluggable configuration array for this model.
|
|
*/
|
|
public function sluggable(): array
|
|
{
|
|
return [
|
|
'titleurl' => [
|
|
'source' => 'title',
|
|
],
|
|
];
|
|
}
|
|
|
|
protected function html(): Attribute
|
|
{
|
|
return Attribute::get(
|
|
get: function () {
|
|
$environment = new Environment;
|
|
$environment->addExtension(new CommonMarkCoreExtension);
|
|
$environment->addExtension(new HighlightExtension);
|
|
$markdownConverter = new MarkdownConverter($environment);
|
|
|
|
return $markdownConverter->convert($this->main)->getContent();
|
|
},
|
|
);
|
|
}
|
|
|
|
protected function w3cTime(): Attribute
|
|
{
|
|
return Attribute::get(
|
|
get: fn () => $this->updated_at->toW3CString(),
|
|
);
|
|
}
|
|
|
|
protected function tooltipTime(): Attribute
|
|
{
|
|
return Attribute::get(
|
|
get: fn () => $this->updated_at->toRFC850String(),
|
|
);
|
|
}
|
|
|
|
protected function humanTime(): Attribute
|
|
{
|
|
return Attribute::get(
|
|
get: fn () => $this->updated_at->diffForHumans(),
|
|
);
|
|
}
|
|
|
|
protected function pubdate(): Attribute
|
|
{
|
|
return Attribute::get(
|
|
get: fn () => $this->updated_at->toRSSString(),
|
|
);
|
|
}
|
|
|
|
protected function link(): Attribute
|
|
{
|
|
return Attribute::get(
|
|
get: fn () => '/blog/'.$this->updated_at->year.'/'.$this->updated_at->format('m').'/'.$this->titleurl,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Scope a query to only include articles from a particular year/month.
|
|
*/
|
|
public function scopeDate(Builder $query, ?int $year = null, ?int $month = null): Builder
|
|
{
|
|
if ($year === null) {
|
|
return $query;
|
|
}
|
|
$start = $year.'-01-01 00:00:00';
|
|
$end = ($year + 1).'-01-01 00:00:00';
|
|
if (($month !== null) && ($month !== 12)) {
|
|
$start = $year.'-'.$month.'-01 00:00:00';
|
|
$end = $year.'-'.($month + 1).'-01 00:00:00';
|
|
}
|
|
if ($month === 12) {
|
|
$start = $year.'-12-01 00:00:00';
|
|
$end = ($year + 1).'-01-01 00:00:00';
|
|
}
|
|
|
|
return $query->where([
|
|
['updated_at', '>=', $start],
|
|
['updated_at', '<', $end],
|
|
]);
|
|
}
|
|
}
|