You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.7 KiB
66 lines
2.7 KiB
<?php
|
|
namespace App\Services\CompanyNews;
|
|
|
|
use App\Models\CompanyNews;
|
|
use HTMLPurifier;
|
|
use HTMLPurifier_Config;
|
|
use Illuminate\Support\Facades\DB;
|
|
use RuntimeException;
|
|
|
|
class NewsEditor
|
|
{
|
|
public function save(int $id, int $version, array $input, ?int $actor): CompanyNews
|
|
{
|
|
return DB::transaction(function () use ($id, $version, $input, $actor) {
|
|
$news = $this->locked($id, $version);
|
|
$config = HTMLPurifier_Config::createDefault();
|
|
$config->set('Cache.DefinitionImpl', null);
|
|
$config->set('URI.AllowedSchemes', ['http' => true, 'https' => true, 'mailto' => true]);
|
|
$html = (new HTMLPurifier($config))->purify($input['content_html'] ?? '');
|
|
$news->fill([
|
|
'title' => $input['title'], 'summary' => $input['summary'] ?? null,
|
|
'content_html' => $html, 'content_source' => 'manual',
|
|
'content_updated_by' => $actor, 'content_updated_at' => now(),
|
|
'is_visible' => false, 'visible_at' => null, 'version' => $version + 1,
|
|
])->save();
|
|
$this->log($news, $actor, 'edit', ['version' => $news->version, 'content_hash' => hash('sha256', $html)]);
|
|
return $news;
|
|
});
|
|
}
|
|
|
|
public function review(int $id, int $version, string $status, ?string $note, ?int $actor): CompanyNews
|
|
{
|
|
return DB::transaction(function () use ($id, $version, $status, $note, $actor) {
|
|
$news = $this->locked($id, $version);
|
|
$from = $news->review_status;
|
|
$news->fill([
|
|
'review_status' => $status, 'review_note' => $note,
|
|
'reviewed_by' => $actor, 'reviewed_at' => now(),
|
|
'is_visible' => false, 'visible_at' => null, 'version' => $version + 1,
|
|
])->save();
|
|
$this->log($news, $actor, 'review', ['from' => $from, 'to' => $status, 'note' => $note]);
|
|
return $news;
|
|
});
|
|
}
|
|
|
|
private function locked(int $id, int $version): CompanyNews
|
|
{
|
|
$news = CompanyNews::whereKey($id)->lockForUpdate()->first();
|
|
if (!$news) {
|
|
throw new RuntimeException('新闻不存在');
|
|
}
|
|
if ($news->version !== $version) {
|
|
throw new RuntimeException('新闻已被其他管理员修改,请重新打开后操作');
|
|
}
|
|
return $news;
|
|
}
|
|
|
|
private function log(CompanyNews $news, ?int $actor, string $action, array $detail): void
|
|
{
|
|
DB::table('company_news_logs')->insert([
|
|
'news_id' => $news->id, 'actor_id' => $actor, 'action' => $action,
|
|
'detail' => json_encode($detail, JSON_UNESCAPED_UNICODE), 'created_at' => now(),
|
|
]);
|
|
}
|
|
}
|