ActivityService.php 7.48 KB
<?php

namespace App\Http\Service;

use App\Actions\ActivityWorkAuditFail;
use App\Actions\ActivityWorkAuditSuccess;
use App\Enums\ActivityAuditStatusEnum;
use App\Enums\ActivitySongTypeEnum;
use App\Enums\ActivityStatusEnum;
use App\Enums\ActivityWorkStatusEnum;
use App\Enums\ActivityWorkTypeEnum;
use App\Helpers\OperationLog;
use App\Jobs\ActivityChangeStatusJob;
use App\Jobs\ActivityMakeMediaJob;
use App\Models\Activity;
use App\Models\ActivityApplyRecord;
use App\Models\ActivityReListRecord;
use App\Models\ActivityUser;
use App\Models\Pivots\ActivityLinkPivot;
use App\Models\Pivots\ActivityTagPivot;
use App\Models\Pivots\UserActivityCollectionPivot;
use App\Models\Pivots\UserActivityViewPivot;
use App\Models\Project;
use App\Models\Views\ActivityWork;
use Arr;
use DB;
use Hikoon\LaravelApi\Exceptions\ValidationException;
use Hikoon\LaravelApi\Support\ApiCode;
use Illuminate\Support\Facades\Auth;
use Str;

class ActivityService
{
    /**
     * @param \App\Models\Activity $activity
     * @param array                $data
     * @return array
     */
    public function syncManageLink(Activity $activity, array $data = []): array
    {
        $syncData = [];

        foreach ($data as $item) {
            $syncData[$item['user_id']] = ['type' => 'manager', 'expand->permission' => $item['permission']];
        }

        return array_unique(Arr::flatten($activity->links()->wherePivot('type', 'manager')->sync($syncData)));
    }

    /**
     * @param \App\Models\Activity $activity
     * @return void
     */
    public function reUp(Activity $activity): void
    {
        DB::transaction(static function () use ($activity) {
            $activity->update(['status' => ActivityStatusEnum::UP->value, 'p_is_top' => 0, 'match_at' => NULL, 'publish_at' => now()->toDateTimeString()]);
            ActivityWork::query()->where('activity_id', $activity->getKey())->where('status', ActivityWorkStatusEnum::SUCCESS)
                ->where('type', ActivityWorkTypeEnum::SUBMIT)
                ->eachById(fn(ActivityWork $work) => ActivityReListRecord::query()->create([
                    'activity_id'  => $work->getAttribute('activity_id'),
                    'project_id'   => $work->getAttribute('project_id'),
                    'user_id'      => $work->getAttribute('user_id'),
                    'broker_id'    => $work->getAttribute('broker_id'),
                    'broker_level' => $work->getAttribute('broker_level'),
                    'operator_id'  => Auth::id()
                ]));

            ActivityUser::query()
                ->where('activity_id', $activity->getKey())
                ->where('status', ActivityWorkStatusEnum::SUCCESS)
                ->where('type', ActivityWorkTypeEnum::SUBMIT)
                ->update(['status' => ActivityWorkStatusEnum::WAIT, 'broker_id' => 0, 'broker_level' => '']);

            if ($activity->getAttribute('song_type') === ActivitySongTypeEnum::SONG->value) {
                ActivityChangeStatusJob::dispatch($activity, Auth::user());
            }
        });
    }

    /**
     * @param \App\Models\Views\ActivityWork $work
     * @return void
     * @throws \Hikoon\LaravelApi\Exceptions\ValidationException
     */
    public function auditWork(ActivityWork $work, ActivityWorkStatusEnum $status): void
    {
        if ($work->getAttribute('type') !== ActivityWorkTypeEnum::SUBMIT || $work->getAttribute('status') !== ActivityWorkStatusEnum::WAIT) {
            throw new ValidationException(ApiCode::VALIDATION_ERROR, '作品已确认结果,无法修改状态');
        }

        if ($work->getAttribute('activity_status') !== ActivityStatusEnum::UP) {
            throw new ValidationException(ApiCode::VALIDATION_ERROR, '活动状态异常,无法操作');
        }

        if ($work->user()->withoutTrashed()->doesntExist()) {
            throw new ValidationException(ApiCode::VALIDATION_ERROR, '用户已注销,无法进行操作');
        }

        ActivityWorkAuditSuccess::runIf($status === ActivityWorkStatusEnum::SUCCESS, $work);
        ActivityWorkAuditFail::runIf($status === ActivityWorkStatusEnum::REJECT, $work);
    }

    /**
     * @param int|\App\Models\Activity $activity
     * @return void
     */
    public function delete(int|Activity $activity): void
    {
        $id = $activity instanceof Activity ? $activity->getKey() : $activity;
        ActivityTagPivot::query()->where('activity_id', $id)->delete();
        ActivityLinkPivot::query()->where('activity_id', $id)->delete();
        ActivityApplyRecord::query()->where('activity_id', $id)->delete();
        UserActivityCollectionPivot::query()->where('activity_id', $id)->delete();
        UserActivityViewPivot::query()->where('activity_id', $id)->delete();
        Activity::query()->whereKey($id)->delete();
    }

    /**
     * @param array $attribute
     * @return Activity
     * @throws \Hikoon\LaravelApi\Exceptions\ValidationException
     */
    public function createDemoApply(array $attribute, bool $checkConfig = true): Activity
    {
        $project = Project::query()->whereKey($attribute['project_id'])->first(['id', 'is_can_demo_apply', 'is_demo_audit']);

        if ($project && $checkConfig && $project->getAttribute('is_can_demo_apply') !== 1) {
            throw new ValidationException(ApiCode::VALIDATION_ERROR, '厂牌未开启申请权限,请联系管理员');
        }

        if ($project?->getAttribute('is_demo_audit') !== 1) {
            $attribute = array_merge($attribute, ['audit_status' => 1, 'status' => ActivityStatusEnum::PROCESS->value, 'publish_at' => now()->toDateTimeString(), 'audit_at' => now()->toDateTimeString()]);
        }

        return DB::transaction(static function () use ($attribute) {
            $activity = Activity::query()->create(array_merge($attribute, ['song_type' => ActivitySongTypeEnum::DEMO->value]));
            OperationLog::guard()->subject($activity)->createAction()->content('歌曲《%s》,申请上架', $activity->getAttribute('song_name'));
            if ($activity->getAttribute('audit_status') === ActivityAuditStatusEnum::SUCCESS->value) {
                ActivityMakeMediaJob::dispatch($activity, ActivityStatusEnum::UP, true);
                OperationLog::guard()->subject($activity)->createAction()->content('歌曲《%s》,上架通过', $activity->getAttribute('song_name'));
            }
            return $activity;
        });

    }

    /**
     * @param array $attribute
     * @return Activity
     * @throws \Hikoon\LaravelApi\Exceptions\ValidationException
     */
    public function createActivityApply(array $attribute, bool $checkConfig = true): Activity
    {
        if ($checkConfig && Project::query()->whereKey($attribute['project_id'])->value('is_can_apply') !== 1) {
            throw new ValidationException(ApiCode::VALIDATION_ERROR, '厂牌未开启申请权限,请联系管理员');
        }

        return DB::transaction(static function () use ($attribute) {
            $activity = Activity::query()->create(array_merge($attribute, ['song_type' => ActivitySongTypeEnum::SONG->value]));
            OperationLog::guard()->subject($activity)->createAction()->content('歌曲《%s》,申请上架', $activity->getAttribute('song_name'));
            return $activity;
        });
    }

    /**
     * 检测歌词合法性
     * @param string|null $lyric
     * @return bool
     */
    public static function isLyric(?string $lyric): bool
    {
        return Str::of($lyric)->explode(PHP_EOL)
            ->reject(fn($item) => preg_match('/\[((\d{2}:\d{2}\.\d{1,8})|(ti|ar|al|by):.*)]/', $item))
            ->isEmpty();
    }
}