jccp_a/laravel/app/ContentCenter/ArticleArtifact.php

45 lines
2.8 KiB
PHP

<?php
namespace App\ContentCenter;
use App\Services\Ranking\ArticleDocument;
use Carbon\CarbonImmutable;
use Symfony\Component\Yaml\Yaml;
final class ArticleArtifact
{
public function build(array $data): array
{
validator($data, ['source_key' => 'required|string|max:160', 'revision' => 'required|string|size:64', 'generation' => 'required|integer|min:1', 'title' => 'required|string|max:200', 'text' => 'present|string|max:100000', 'sent_at' => 'required|date', 'images' => 'present|array|max:30', 'images.*.sha256' => 'required|regex:/^[a-f0-9]{64}$/D', 'images.*.mime' => 'required|in:image/png,image/jpeg,image/webp,image/gif', 'images.*.bytes' => 'required|integer|min:1|max:20971520'])->validate();
validator($data, ['links' => 'sometimes|array|max:100', 'links.*.offset' => 'required|integer|min:0', 'links.*.length' => 'required|integer|min:1', 'links.*.url' => 'required|string|max:4096'])->validate();
$code = 'telefox-'.substr(hash('sha256', $data['source_key']), 0, 24);
$body = "<div v-pre>\n".implode("\n", array_map(fn ($s) => '<p>'.htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').'</p>', explode("\n", $data['text'])))."\n</div>\n\n";
$review = ReviewFormat::build($data);
if ($review) {
$body = $review['body'];
}
foreach ($data['images'] as $image) {
$body .= '![频道图片](/content-assets/'.$image['sha256'].self::extension($image['mime']).")\n\n";
}
$meta = ['title' => $review['title'] ?? $data['title'], 'createTime' => CarbonImmutable::parse($data['sent_at'], 'UTC')->setTimezone('Asia/Shanghai')->format('Y-m-d H:i:s'), 'permalink' => '/jccp/'.$code.'/', 'articleCode' => $code, 'tags' => $review['tags'] ?? [], 'sourceKey' => $data['source_key']];
$series = TitleSeries::metadata($meta['title'], $data['source_key']);
$meta = array_replace($meta, $series);
$document = ['meta' => $meta, 'body' => $body];
if (class_exists(ArticleDocument::class)) {
$document = ArticleDocument::enrich($document);
}
return ['source_key' => $data['source_key'], 'revision' => $data['revision'], 'generation' => $data['generation'], 'article_code' => $code, 'relative_path' => 'jccp/'.$code.'.md', 'permalink' => $meta['permalink'], 'title' => $document['meta']['title'], 'format_version' => 'ttc-native-v2', 'markdown' => "---\n".Yaml::dump($document['meta'], 6, 2)."---\n".$document['body'], 'images' => $data['images']];
}
public static function extension(string $mime): string
{
return ['image/png' => '.png', 'image/jpeg' => '.jpg', 'image/webp' => '.webp', 'image/gif' => '.gif'][$mime];
}
public static function hash(array $artifact): string
{
return hash('sha256', json_encode($artifact, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}
}