ShowController.php 11.4 KB
<?php

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

use App\Enums\ActivitySongTypeEnum;
use App\Enums\UserOfficialStatusEnum;
use App\Enums\UserScopeEnum;
use App\Enums\UserStatusEnum;
use App\Helpers\ConfigHelper;
use App\Helpers\JsonResource;
use App\Http\Service\UserService;
use App\Models\Activity;
use App\Models\GroupHasMember;
use App\Models\Pivots\ProjectMemberPivot;
use App\Models\Project;
use App\Models\User;
use App\Models\UserDynamic;
use App\Models\UserFollowRelation;
use App\Models\UserMessage;
use App\Models\UserVisitorRelation;
use App\Models\Views\UserLastCertify;
use App\Support\Controller;
use App\Traits\UserTrait;
use Arr;
use Auth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ShowController extends Controller
{
    use UserTrait;

    public function __construct()
    {
        $this->middleware('emptyToNull');
    }

    /**
     * @param int $id
     * @return \App\Models\User|null
     */
    protected function setUser(int $id): ?User
    {
        return User::query()
            ->with(['authTags:id,name', 'styleTags:id,name', 'userTag:id,name,icon,frame'])
            ->select([
                'id', 'nick_name', 'avatar', 'sex', 'email', 'province', 'city', 'company', 'rate', 'cover', 'intro', 'identity',
                'business_id', 'business_singer_limit', 'scope', 'wechat_account', 'user_tag_id', 'chat_mode', 'phone', 'area_code', 'demo_type',
                'unionid', 'official_status', 'status'
            ])
            ->whereIn('status', [UserStatusEnum::ACTIVATE, UserStatusEnum::DISABLE])
            ->find($id);
    }

    /**
     * @throws \JsonException
     */
    public function __invoke(Request $request, int $id): JsonResponse
    {
        if (!$this->user = $this->setUser($id)) {
            return JsonResource::fail(JsonResource::USER_FOUND_ERROR);
        }

        $data = [
            ...$this->getUserBaseAttribute(),
            'broker'       => $this->getBroker(),
            'auth_tags'    => $this->getUserAttribute('authTags'),
            'user_tag'     => $this->getUserAttribute('userTag'),
            'style_tag'    => $this->getUserAttribute('styleTags'),
            'is_mine'      => (int)$this->isMine(),
            'is_follow'    => $this->isMine() ? 0 : (int)UserService::isFollower($this->user, Auth::id()),
            'show_demo'    => (int)UserService::hasDemoPermission($this->user),
            'member_count' => User::query()->where('business_id', $this->getUserKey())->count()
        ];

        if ($data['is_mine'] !== 1) {
            UserVisitorRelation::query()->create(['user_id' => $id, 'visitor_id' => Auth::id()]);
            return JsonResource::success(JsonResource::SUCCESS, $data);
        }

        User::query()->whereKey($id)->where('is_home', 0)->update(['is_home' => 1]);

        $this->user->loadMissing(['artTags:id,name']);

        return JsonResource::success(JsonResource::SUCCESS, array_merge($data, [
            'auth_status'        => $this->getAuthStatus(),
            'is_white'           => (int)UserService::inSingOrListenWhite($this->user),
            'art_tag'            => $this->getUserAttribute('artTags'),
            'info_source'        => $this->getInfoSource(),
            'project'            => $this->getProject(),
            'is_band'            => (int)$this->getUserAttribute('unionid'),
            'is_subscribe'       => (int)($this->getUserAttribute('official_status') === UserOfficialStatusEnum::SUBSCRIBE),
            'group'              => [
                'status'             => GroupHasMember::where('member_id', $this->getUserKey())->value('status') ?? 0,
                'new_audition_count' => $data['member_count'] === 0 ? 0 : UserMessage::where('receiver_id', $this->getUserKey())
                    ->whereRelation('sender', 'business_id', $this->getUserKey())
                    ->whereRelation('activity', 'song_type', ActivitySongTypeEnum::SONG)
                    ->where('is_read', 0)->where('type', 3)->where('is_bind', 1)
                    ->count()
            ],
            ...$this->getVisitorCount(),
            ...$this->getPlatformActivity(),
            ...$this->getUserCertify(),
            'show_platform_demo' => (int)$this->isScopeEquals(UserScopeEnum::SYSTEM)
        ]));
    }

    /**
     * @return array
     */
    protected function getUserBaseAttribute(): array
    {
        $column = ['id', 'avatar', 'nick_name', 'sex', 'province', 'city', 'province', 'cover', 'company', 'intro', 'identity', 'business_id', 'business_singer_limit', 'scope', 'chat_mode'];

        return $this->user->only($this->isMine() ? array_merge($column, ['email', 'area_code', 'phone', 'wechat_account']) : $column) + $this->getFollowingCount() + $this->getFollowerCount();
    }

    /**
     * @return array
     */
    public function getAuthStatus(): array
    {
        $data = ['status' => 3, 'reason' => NULL];

        return $this->isMine() ? UserLastCertify::where('user_id', $this->getUserKey())->first(['status', 'reason'])?->toArray() ?? $data : $data;
    }

    /**
     * @return ?User
     */
    protected function getBroker(): ?User
    {
        return $this->getUserAttribute('business_id') === 0 ? NULL : User::query()
            ->whereKey($this->getUserAttribute('business_id'))
            ->whereHas('authTags', fn(Builder $builder) => $builder->whereIn('user_tag_relations.tag_id', ConfigHelper::getSingerTagIds()))
            ->first(['id', 'nick_name', 'avatar']);
    }

    /**
     * @return array|null
     */
    public function getProject(): ?array
    {
        $userProject = ProjectMemberPivot::with('project:id,name,master_id')->where('user_id', $this->getUserKey())->whereIn('status', [1, 3])->first();


        return $userProject ? [
            'name'      => $userProject->getAttribute('project')?->getAttribute('name') ?? '',
            'status'    => $userProject->getAttribute('status') ?? 0,
            'is_master' => (int)($userProject->getAttribute('project')?->getAttribute('master_id') === Auth::id()),
        ] : NULL;
    }

    /**
     * @throws \JsonException
     */
    private function getInfoSource(): array
    {
        $config = ConfigHelper::getInfoScore();

        $dynamics = UserDynamic::query()
            ->selectRaw("COUNT(type = 'image' or null ) as image, COUNT(type = 'audio' or null ) as audio, COUNT(type = 'video' or null) as video")
            ->where('user_id', $this->getUserKey())
            ->withCasts(['image' => 'boolean', 'audio' => 'boolean', 'video' => 'boolean'])
            ->first();


        $content = Arr::only($this->user->toArray() + ['style' => $this->getUserAttribute('styleTags')->isNotEmpty(),] + $dynamics->toArray(), $config[ConfigHelper::INFO_SCORE_CONTENT_KEY]->keys()->toArray());

        $number = $config[ConfigHelper::INFO_SCORE_CONTENT_KEY]->only(array_keys(array_filter($content)))->sum();

        return [
            'number'            => $number,
            'is_intercept_auth' => (int)(bcsub($number, $config[ConfigHelper::INFO_SCORE_LIMIT_KEY]) < 0),
            'text'              => Arr::first($config[ConfigHelper::INFO_SCORE_TEXT_KEY], static fn($value) => $number >= $value->min && $number <= $value->max)?->content ?? ''
        ];
    }

    /**
     * @return array
     */
    private function getPlatformActivity(): array
    {

        $messageQuery  = UserMessage::where('receiver_id', $this->getUserKey())->where('is_read', 0)->where('is_bind', 0)->where('type', 3);
        $activityQuery = Activity::statusOfUp()->select('id')->where('song_type', ActivitySongTypeEnum::SONG);

        $isManageActivity = UserService::isActivityManager($this->user);


        return match ($this->getUserAttribute('scope')) {
            UserScopeEnum::SYSTEM => [
                'show_platform_activity'      => 1,
                'new_platform_activity_count' => $messageQuery->joinSub($activityQuery, 'a', 'a.id', 'activity_id')->count()
            ],
            UserScopeEnum::PROJECT => [
                'show_platform_activity'      => 1,
                'new_platform_activity_count' => $messageQuery->joinSub($activityQuery->where(function (Builder $query) use ($isManageActivity) {
                    $project        = Project::query()->whereRelation('managers', 'user_has_projects.user_id', $this->getUserKey())->get(['id', 'name', 'is_public']);
                    $publicProject  = $project->where('is_public', 1);
                    $privateProject = $project->where('is_public', 0);
                    $query
                        ->when($publicProject->isNotEmpty(), fn(Builder $query) => $query->orWhereIn('activitys.project_id', $publicProject->modelKeys()))
                        ->when($privateProject->isNotEmpty(), fn(Builder $query) => $query->orWhereIn('activitys.project_id', $privateProject->modelKeys()))
                        ->when($isManageActivity, fn(Builder $query) => $query->whereRelation('links', fn($query) => $query->where('activity_links.type', 'manager')->where('activity_links.link_id', $this->getUserKey())));
                }), 'a', 'a.id', 'activity_id')->count(),
            ],
            UserScopeEnum::UNSET => [
                'show_platform_activity'      => (int)$isManageActivity,
                'new_platform_activity_count' => $isManageActivity ? $messageQuery
                    ->joinSub($activityQuery->whereRelation('links', fn($query) => $query->where('activity_links.type', 'manager')->where('activity_links.link_id', $this->getUserKey())), 'a', 'a.id', 'activity_id')
                    ->count() : 0
            ],
        };
    }

    /**
     * @return array
     */
    private function getUserCertify(): array
    {
        $data = [
            'show_user_certify'      => (int)$this->isScopeEquals(UserScopeEnum::SYSTEM),
            'new_user_certify_count' => 0
        ];

        if ($data['show_user_certify'] === 1) {
            $data['new_user_certify_count'] = UserLastCertify::query()->where('status', 0)->count();
        }

        return $data;
    }

    /**
     * @return array
     */
    private function getVisitorCount(): array
    {
        return UserVisitorRelation::query()
            ->selectRaw('count(distinct visitor_id) as visitor_count,count(distinct if(is_read=0,visitor_id, null)) as new_visitor_count')
            ->where('user_id', $this->getUserKey())
            ->where('created_at', '>=', now()->subDays(30)->toDateTimeString())
            ->whereRelation('visitor', 'status', 1)
            ->first()?->toArray() ?? ['visitor_count' => 0, 'new_visitor_count' => 0];
    }

    /**
     * @return int[]
     */
    private function getFollowingCount(): array
    {
        return UserFollowRelation::query()
            ->selectRaw('count(distinct following_id) as following_count,count(distinct if(is_read=0,following_id, null)) as new_following_count')
            ->where('follower_id', $this->getUserKey())
            ->whereRelation('following', 'status', 1)
            ->first()?->toArray() ?? ['following_count' => 0, 'new_following_count' => 0];
    }

    /**
     * @return int[]
     */
    private function getFollowerCount(): array
    {
        return UserFollowRelation::query()
            ->selectRaw('count(distinct follower_id) as follower_count,count(distinct if(is_read=0,follower_id, null)) as new_follower_count')
            ->where('following_id', $this->getUserKey())
            ->whereRelation('follower', 'status', 1)
            ->first()?->toArray() ?? ['follower_count' => 0, 'new_follower_count' => 0];
    }
}