130 lines
4.6 KiB
PHP
130 lines
4.6 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace plugin\article\app\service\admin;
|
||
|
|
|
||
|
|
use core\exception\handler\AdminException;
|
||
|
|
use madong\helper\PropertyCopier;
|
||
|
|
use core\base\BaseService;
|
||
|
|
use core\uuid\Snowflake;
|
||
|
|
use Illuminate\Support\Str;
|
||
|
|
use plugin\article\app\dao\ContentDao;
|
||
|
|
use plugin\article\app\model\Content;
|
||
|
|
use support\Db;
|
||
|
|
|
||
|
|
class ContentService extends BaseService
|
||
|
|
{
|
||
|
|
public function __construct(ContentDao $dao)
|
||
|
|
{
|
||
|
|
$this->dao = $dao;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function save(array $data): ?\plugin\article\app\model\Content
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
return $this->transaction(function () use ($data) {
|
||
|
|
$payload = $this->normalizePayload($data);
|
||
|
|
$tagIds = $payload['tag_ids'] ?? [];
|
||
|
|
unset($payload['tag_ids']);
|
||
|
|
|
||
|
|
$model = new Content();
|
||
|
|
PropertyCopier::copyProperties((object) $payload, $model);
|
||
|
|
$model->save();
|
||
|
|
|
||
|
|
$this->syncTags($model, $tagIds);
|
||
|
|
|
||
|
|
return $model->refresh()?->load(['category', 'tags', 'createds', 'updateds']);
|
||
|
|
});
|
||
|
|
} catch (\Throwable $e) {
|
||
|
|
throw new AdminException($e->getMessage());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public function update($id, $data): void
|
||
|
|
{
|
||
|
|
try {
|
||
|
|
$this->transaction(function () use ($id, $data) {
|
||
|
|
$model = $this->dao->get($id);
|
||
|
|
if (!$model) {
|
||
|
|
throw new AdminException('内容不存在');
|
||
|
|
}
|
||
|
|
|
||
|
|
$payload = $this->normalizePayload($data, false);
|
||
|
|
$tagIds = $payload['tag_ids'] ?? null;
|
||
|
|
unset($payload['tag_ids']);
|
||
|
|
|
||
|
|
PropertyCopier::copyProperties((object) $payload, $model);
|
||
|
|
$model->save();
|
||
|
|
|
||
|
|
if ($tagIds !== null) {
|
||
|
|
$this->syncTags($model, $tagIds);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
} catch (\Throwable $e) {
|
||
|
|
throw new AdminException($e->getMessage());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function normalizePayload(array $data, bool $isCreate = true): array
|
||
|
|
{
|
||
|
|
$payload = $data;
|
||
|
|
|
||
|
|
$payload['content_type'] = $payload['content_type'] ?? 'article';
|
||
|
|
$payload['channel'] = $payload['channel'] ?? 'official';
|
||
|
|
$payload['visibility'] = isset($payload['visibility']) ? (int) $payload['visibility'] : 1;
|
||
|
|
$payload['source'] = $payload['source'] ?? 'original';
|
||
|
|
$payload['status'] = isset($payload['status']) ? (int) $payload['status'] : 0;
|
||
|
|
$payload['is_top'] = isset($payload['is_top']) ? (int) $payload['is_top'] : 0;
|
||
|
|
$payload['is_recommend'] = isset($payload['is_recommend']) ? (int) $payload['is_recommend'] : 0;
|
||
|
|
$payload['allow_comment'] = isset($payload['allow_comment']) ? (int) $payload['allow_comment'] : 1;
|
||
|
|
$payload['sort'] = isset($payload['sort']) ? (int) $payload['sort'] : 100;
|
||
|
|
$payload['view_count'] = isset($payload['view_count']) ? (int) $payload['view_count'] : 0;
|
||
|
|
$payload['like_count'] = isset($payload['like_count']) ? (int) $payload['like_count'] : 0;
|
||
|
|
$payload['comment_count'] = isset($payload['comment_count']) ? (int) $payload['comment_count'] : 0;
|
||
|
|
$payload['favorite_count'] = isset($payload['favorite_count']) ? (int) $payload['favorite_count'] : 0;
|
||
|
|
$payload['category_id'] = isset($payload['category_id']) ? (int) $payload['category_id'] : 0;
|
||
|
|
|
||
|
|
if (!empty($payload['slug'])) {
|
||
|
|
$payload['slug'] = trim((string) $payload['slug']);
|
||
|
|
} elseif ($isCreate && !empty($payload['title'])) {
|
||
|
|
$payload['slug'] = Str::slug((string) $payload['title']);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (array_key_exists('tag_ids', $payload)) {
|
||
|
|
$payload['tag_ids'] = collect($payload['tag_ids'] ?? [])
|
||
|
|
->filter(static fn($id) => $id !== null && $id !== '' && $id !== 0 && $id !== '0')
|
||
|
|
->map(static fn($id) => (int) $id)
|
||
|
|
->unique()
|
||
|
|
->values()
|
||
|
|
->all();
|
||
|
|
}
|
||
|
|
|
||
|
|
return $payload;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function syncTags(Content $model, array $tagIds): void
|
||
|
|
{
|
||
|
|
$tableName = $model->tags()->getTable();
|
||
|
|
|
||
|
|
Db::table($tableName)->where('content_id', $model->id)->delete();
|
||
|
|
|
||
|
|
if (empty($tagIds)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$now = time();
|
||
|
|
$rows = [];
|
||
|
|
foreach ($tagIds as $tagId) {
|
||
|
|
$rows[] = [
|
||
|
|
'id' => (string) Snowflake::generate(),
|
||
|
|
'content_id' => $model->id,
|
||
|
|
'tag_id' => (int) $tagId,
|
||
|
|
'created_at' => $now,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
Db::table($tableName)->insert($rows);
|
||
|
|
}
|
||
|
|
}
|