where('code', 'news_category')->where('status', 1)->value('id'); if (! $typeId) { return null; } $items = DictItem::query() ->where('dict_type_id', $typeId) ->where(function ($q) { $q->where('value', self::VALUE) ->orWhere('label', self::LABEL); }) ->orderBy('id') ->get(); if ($items->isEmpty()) { return null; } if ($items->count() === 1) { $item = $items->first(); $item->fill(['label' => self::LABEL, 'value' => self::VALUE, 'status' => 1]); $item->save(); return (int) $item->id; } $keeper = $items->sort(function (DictItem $a, DictItem $b) { $countA = self::referenceCount((int) $a->id); $countB = self::referenceCount((int) $b->id); if ($countA !== $countB) { return $countB <=> $countA; } return $a->id <=> $b->id; })->first(); if (! $keeper) { return null; } return DB::transaction(function () use ($items, $keeper) { $keeperId = (int) $keeper->id; foreach ($items as $item) { if ((int) $item->id === $keeperId) { continue; } News::query() ->where('category_dict_item_id', $item->id) ->update(['category_dict_item_id' => $keeperId]); CrawlAddress::query() ->where('category_dict_item_id', $item->id) ->update(['category_dict_item_id' => $keeperId]); $item->delete(); } $keeper->fill([ 'label' => self::LABEL, 'value' => self::VALUE, 'status' => 1, ]); $keeper->save(); return $keeperId; }); } public static function canonicalId(): ?int { $typeId = DictType::query()->where('code', 'news_category')->where('status', 1)->value('id'); if (! $typeId) { return null; } $item = DictItem::query() ->where('dict_type_id', $typeId) ->where('status', 1) ->where('value', self::VALUE) ->orderBy('id') ->first(); if ($item) { return (int) $item->id; } $item = DictItem::query() ->where('dict_type_id', $typeId) ->where('status', 1) ->where('label', self::LABEL) ->orderBy('id') ->first(); return $item ? (int) $item->id : null; } /** * @return list */ public static function categoryIds(): array { $id = self::canonicalId(); return $id ? [$id] : []; } public static function applyUniversityNewsOnly(Builder $query): Builder { $id = self::canonicalId(); return $query->where('category_dict_item_id', $id ?? -1); } public static function applyExcludeUniversityNews(Builder $query): Builder { $id = self::canonicalId(); if (! $id) { return $query; } return $query->where(function ($q) use ($id) { $q->whereNull('category_dict_item_id') ->orWhere('category_dict_item_id', '!=', $id); }); } public static function isUniversityNewsCategory(?DictItem $item): bool { if (! $item) { return false; } $canonicalId = self::canonicalId(); return $canonicalId ? (int) $item->id === $canonicalId : ($item->value === self::VALUE || $item->label === self::LABEL); } protected static function referenceCount(int $dictItemId): int { return News::query()->where('category_dict_item_id', $dictItemId)->count() + CrawlAddress::query()->where('category_dict_item_id', $dictItemId)->count(); } }