UpdateController.class.php 7.38 KB
<?php
/**
 * Created by PhpStorm.
 * User: liyifei2012it
 * Date: 18/5/3
 * Time: 10:33
 */
namespace Api\Controller\Path;

use Common\Common\Constant;
use Common\Common\Integral;
use Common\Common\StudyMap;
use Common\Service\MapService;
use Common\Service\MapPathService;
use Common\Service\PathContentService;
use Common\Service\PathService;
use Common\Service\RightService;
use Common\Service\UserMapService;
use Common\Service\UserPathContentService;
use Common\Service\UserPathService;

class UpdateController extends \Api\Controller\AbstractController
{
    /**
     * Update
     * @author liyifei
     * @desc 更新学习进度接口(请求学习地图详情接口时,需同时请求该接口更新进度)<br /><br />
     *      出现以下情况时,自动更新用户学习进度:<br />
     *      情况1:原学习内容A为非必学时用户已学完,管理后台修改学习内容A为必学;<br />
     *      情况2:原学习内容A、B均为必学,用户已学完内容A,管理后台修改学习内容B为非必学;
     * @param Int map_id:true 地图ID
     * @return mixed
     */
    public function Index_post()
    {
        $map_id = I('post.map_id', 0, 'intval');

        $mapServ = new MapService();
        $map = $mapServ->get($map_id);
        if (empty($map) || $map['map_status'] != Constant::MAP_STATUS_PUBLISH) {
            return false;
        }

        // 是否有学习权限
        $rightServ = new RightService();
        $isRight = $rightServ->checkUserRight($this->_login->user, $map_id);
        if (!$isRight) {
            return false;
        }

        // 该地图已完成
        $conds = [
            'uid' => $this->uid,
            'map_id' => $map_id,
        ];
        $userMapServ = new UserMapService();
        $userMap = $userMapServ->get_by_conds($conds);
        if (!empty($userMap) && $userMap['complete_status'] == Constant::COMPLETE_STATUS_IS_TRUE) {
            return false;
        }

        // 该地图下,用户未完成的学习路径
        $conds['complete_status'] = Constant::COMPLETE_STATUS_IS_FALSE;
        $userPathServ = new UserPathService();
        $userPathList = $userPathServ->list_by_conds($conds);
        $userPathIds = array_column($userPathList, 'path_id');

        // 筛选出用户在该地图未完成的学习路径中,已完成的学习内容
        $conds['path_id'] = $userPathIds;
        $conds['complete_status'] = Constant::COMPLETE_STATUS_IS_TRUE;
        $userContentServ = new UserPathContentService();
        $userContents = $userContentServ->list_by_conds($conds);
        $userContents = $this->_formatContent($userContents);

        // 地图关联的学习路径
        $mapPathServ = new MapPathService();
        $mapPathList = $mapPathServ->list_by_conds(['map_id' => $map_id]);
        $pathIds = array_column($mapPathList, 'path_id');

        // 地图关联的学习路径详情列表
        $pathServ = new PathService();
        $pathList = $pathServ->list_by_pks($pathIds);

        // 地图关联的学习路径下,必学的学习内容(仅筛选用户已学,但未完成的路径)
        $pathContentServ = new PathContentService();
        $pathContents = $pathContentServ->list_by_conds(['path_id' => $userPathIds]);
        $pathContents = $this->_formatContent($pathContents, $pathList);

        // 将已完成的学习内容,与现在必学的学习内容进行对比
        $updatePathIds = [];
        foreach ($pathContents as $path_id => $content) {
            if (!isset($userContents[$path_id])) {
                continue;
            }

            // 对比app
            $userContent = $userContents[$path_id];
            $apps = array_keys($content);
            $userApps = array_keys($userContent);
            if (array_diff($apps, $userApps)) {
                continue;
            }

            // 对比app下app_data_id
            $study_total = 0;
            $total = count($apps);
            foreach ($content as $app => $appDataIds) {
                if (!isset($userContent[$app])) {
                    continue;
                }

                if (array_diff($appDataIds, $userContent[$app])) {
                    continue;
                }

                $study_total++;
            }

            // 该路径下所有app的所有app_data_id均已学
            if ($total != $study_total) {
                continue;
            }

            // 收集该学习路径,统一修改学习状态
            $updatePathIds[] = $path_id;
        }

        // 学习路径无变化,中断程序
        if (empty($updatePathIds)) {
            return false;
        }

        // 更新路径学习状态为已完成
        $conds = [
            'uid' => $this->uid,
            'map_id' => $map_id,
            'path_id' => $updatePathIds,
        ];
        $pathData = [
            'update_time' => MILLI_TIME,
            'complete_status' => Constant::COMPLETE_STATUS_IS_TRUE,
        ];
        $userPathServ->update_by_conds($conds, $pathData);

        // 检查该学习地图下,所有学习路径是否均已完成
        $conds['path_id'] = $pathIds;
        $conds['complete_status'] = Constant::COMPLETE_STATUS_IS_TRUE;
        $completeTotal = $userPathServ->count_by_conds($conds);

        // 更新地图学习进度
        $mapData = [
            'progress' => $completeTotal,
            'complete_status' => Constant::COMPLETE_STATUS_IS_FALSE,
        ];

        // 地图学习完成,若在规定时间内,则发放勋章奖励
        $user = $this->_login->user;
        if ($completeTotal == count($pathIds)) {
            // 更新地图学习状态
            $mapData['complete_status'] = Constant::COMPLETE_STATUS_IS_TRUE;

            // 发放勋章及消息
            StudyMap::sendMedal($map, $user);
        }

        // 更新地图学习进度及学习状态
        if (!empty($userMap)) {
            $userMapServ->update($userMap['user_map_id'], $mapData);

        } else {
            $mapData['uid'] = $this->uid;
            $mapData['username'] = $user['memUsername'];
            $mapData['map_id'] = $map_id;
            $mapData['update_time'] = MILLI_TIME;
            $userMapServ->insert($mapData);
        }

        return true;
    }

    /**
     * 筛选和格式化内容列表
     * @author liyifei
     * @param array $contents 内容列表
     * @param array $pathList 学习地图内所有学习路径详情列表
     * @return array
     */
    private function _formatContent($contents, $pathList = [])
    {
        if (empty($contents) || !is_array($contents)) {
            return [];
        }

        if (is_array($pathList) && !empty($pathList)) {
            $pathList = array_combine_by_key($pathList, 'path_id');
        }

        $data = [];
        foreach ($contents as $content) {
            $path_id = $content['path_id'];

            // 根据路径是否设置闯关,筛选学习内容
            if (isset($pathList[$path_id])) {
                $path = $pathList[$path_id];

                // 开启闯关时,保留所有内容;未开启闯关时,仅保留必学内容
                if ($path['is_step'] != Constant::PATH_IS_STEP_TRUE && $content['is_learn'] != Constant::PATH_CONTENT_IS_LEARN_TRUE) {
                    continue;
                }
            }

            $app = $content['app'];
            $data[$path_id][$app][] = $content['app_data_id'];
        }

        return $data;
    }
}