ShareUserController.php 3.28 KB
<?php

namespace App\Http\Container\AppSection\Controllers\Activity;

use App\Helpers\JsonResource;
use App\Models\Activity;
use App\Models\User;
use App\Models\UserShare;
use App\Support\Controller;
use Arr;
use DB;
use Illuminate\Database\Query\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ShareUserController extends Controller
{
    /**
     * @param int         $activityId
     * @param string|null $group
     * @return \Illuminate\Database\Query\Builder
     */
    protected function getShareQuery(int $activityId, ?string $group = NULL): Builder
    {
        return UserShare::query()
            ->select(['to_id', 'from_id'])
            ->where('subject_type', Activity::class)
            ->where('subject_id', $activityId)
            ->when($group, fn($query) => $query->groupBy($group))
            ->getQuery();
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param int                      $activityId
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(Request $request, int $activityId): JsonResponse
    {
        $pageSize = $request->integer('size', 20);

        $data = User::query()
            ->joinSub($this->getShareQuery($activityId, 'to_id')->addSelect(DB::raw('max(created_at) as last_share_at')), 's', 's.to_id', '=', 'users.id')
            ->with(['authTags:id,name', 'userTag:id,name,icon,frame'])
            ->select(['id', 'nick_name', 'avatar', 'identity', 'user_tag_id'])
            ->latest('last_share_at')
            ->paginate($pageSize);

        $itemQuery = $this->getShareQuery($activityId)->addSelect([
            DB::raw('created_at as share_at'),
            DB::raw('row_number() over (partition by `to_id` order by `created_at` desc) as num')
        ])->whereIn('to_id', $data->modelKeys());

        $items = DB::query()
            ->fromSub($itemQuery, 'l')
            ->selectRaw('f.*,l.to_id,l.share_at')
            ->joinSub(User::query()->select(['id', 'nick_name', 'avatar']), 'f', 'f.id', 'l.from_id')
            ->where('l.num', '<=', 4)
            ->get()->mapToGroups(fn($item) => [$item->to_id => Arr::only((array)$item, ['id', 'nick_name', 'avatar', 'share_at'])]);

        return JsonResource::success(JsonResource::SUCCESS, [
            'data'  => $data->each(fn($item) => $item->setHidden(['user_tag_id'])->setAttribute('items', $items->get($item->getKey())?->values()))->toArray(),
            'count' => $data->total()
        ]);
    }

    /**
     * @param \Illuminate\Http\Request $request
     * @param int                      $activityId
     * @param int                      $userId
     * @return \Illuminate\Http\JsonResponse
     */
    public function show(Request $request, int $activityId, int $userId): JsonResponse
    {
        $pageSize = $request->integer('size', 20);

        $data = $this->getShareQuery($activityId)
            ->select(['f.*', DB::raw('user_share.created_at as share_at')])
            ->joinSub(User::query()->select(['id', 'nick_name', 'avatar']), 'f', 'f.id', 'from_id')
            ->where('to_id', $userId)
            ->orderByDesc('share_at')
            ->paginate($pageSize);

        return JsonResource::success(JsonResource::SUCCESS, [
            'data'  => $data->items(),
            'count' => $data->total()
        ]);
    }
}