AttachService.class.php 12.5 KB
<?php
/**
 * Created by PhpStorm.
 * User: liyifei2012it
 * Date: 17/4/12
 * Time: 10:34
 */
namespace Common\Service;

use Common\Common\Attach;
use Common\Common\AttachOperation;
use Common\Common\Constant;
use Common\Model\AttachModel;
use VcySDK\Service;
use VcySDK\FileConvert;

class AttachService extends AbstractService
{
    // 构造方法
    public function __construct()
    {
        parent::__construct();
        $this->_d = new AttachModel();
    }

    /**
     * 格式化数据
     * @author liyifei
     * @param int $article_id 新闻ID
     * @param array $user 用户信息
     * @return array
     */
    public function formatData($article_id, $user)
    {
        $returnData = [];

        $attachList = $this->list_by_conds(['article_id' => $article_id]);
        if (empty($attachList)) {
            return $returnData;
        }

        $convertServ = new FileConvert(Service::instance());
        foreach ($attachList as $attach) {
            // 截取文件后缀
            $suffix = explode('.', $attach['at_name']);
            $count = count($suffix);
            $at_suffix = $suffix[$count - 1];

            $atId = $attach['at_id'];
            $formatData = [
                'at_id' => $atId,
                'at_time' => $attach['at_time'],
                'at_name' => $attach['at_name'],
                'at_size' => $attach['at_size'],
                'at_url' => $attach['at_url'],
                'at_convert_url' => $attach['at_convert_url'],
                'at_cover_url' => $attach['at_cover_url'],
                'at_suffix' => $at_suffix,
                'convert_status' => Constant::FILE_STATUS_NORMAL,
            ];

            switch ($attach['at_type']) {
                // 音频
                case Constant::ATTACH_TYPE_AUDIO:
                    $returnData['at_audio'][$atId] = $formatData;
                    break;

                // 视频
                case Constant::ATTACH_TYPE_VIDEO:
                    // 查询视频转码状态
                    if (empty($attach['at_convert_url'])) {
                        $result = $convertServ->getVodPlayUrl($atId);
                        if (!is_array($result) || !isset($result['url'])) {
                            $formatData['convert_status'] = Constant::FILE_STATUS_CONVERT;
                        }
                    }
                    $returnData['at_video'][$atId] = $formatData;
                    break;

                // 文件
                case Constant::ATTACH_TYPE_FILE:
                    // 文件转码状态
                    if (empty($attach['at_convert_url'])) {
                        $result = $convertServ->get($atId);
                        if (is_array($result) && isset($result['caConvertStatus'])) {
                            switch ($result['caConvertStatus']) {
                                // 待处理(转码中)
                                case FileConvert::CONVERT_STATUS_WATTING:
                                    $formatData['convert_status'] = Constant::FILE_STATUS_CONVERT;
                                    break;
                                // 转码中
                                case FileConvert::CONVERT_STATUS_ING:
                                    $formatData['convert_status'] = Constant::FILE_STATUS_CONVERT;
                                    break;
                                // 转码成功
                                case FileConvert::CONVERT_STATUS_SUCCESS:
                                    $formatData['convert_status'] = Constant::FILE_STATUS_NORMAL;
                                    break;
                                // 转码失败
                                default:
                                    $formatData['convert_status'] = Constant::FILE_STATUS_FAIL;
                                    break;
                            }
                        }
                    }

                    // 文件附件水印、鉴权信息
                    $params = [
                        '_id' => $article_id,
                        'user' => $user,
                    ];
                    $formatData['at_url'] = fileUrl($attach['at_url'], $params);
                    $formatData['at_convert_url'] = fileUrl($attach['at_convert_url'], $params);
                    $returnData['at_file'][$atId] = $formatData;
                    break;
            }
        }

        return $returnData;
    }

    /**
     * 格式化数据库中的附件数据
     * @author zhonglei
     * @param array $attachs 附件数据
     * @return array
     */
    public function formatDBData($attachs)
    {
        $data = [];

        // 数据分组
        foreach ($attachs as $attach) {
            $data[$attach['at_type']][] = $attach;
        }

        return $data;
    }

    /**
     * 格式化用户输入的附件数据
     * @author zhonglei
     * @param array $attachs 附件数据
     * @return array
     */
    public function formatPostData($attachs)
    {
        $data = [];

        if (!is_array($attachs) || empty($attachs)) {
            return $data;
        }

        // 数据分组
        foreach ($attachs as $k => $v) {
            if (empty($v)) {
                continue;
            }

            switch ($k) {
                // 视频
                case 'video_at_info':
                    foreach ($v as $video) {
                        $at_id = $video['at_id'];
                        $data[Constant::ATTACH_TYPE_VIDEO][$at_id] = [
                            'at_id' => $video['at_id'],
                            'at_name' => $video['at_name'],
                            'at_size' => $video['at_size'],
                            'at_time' => $video['at_time'],
                            'at_url' => $video['at_url'],
                        ];
                    }
                    break;

                // 音频
                case 'audio_at_ids':
                    if (!is_array($v)) {
                        break;
                    }

                    foreach ($v as $at_id) {
                        $data[Constant::ATTACH_TYPE_AUDIO][$at_id] = [
                            'at_id' => $at_id,
                        ];
                    }
                    break;

                // 其它文件
                case 'file_at_ids':
                    if (!is_array($v)) {
                        break;
                    }

                    foreach ($v as $at_id) {
                        $data[Constant::ATTACH_TYPE_FILE][$at_id] = [
                            'at_id' => $at_id,
                        ];
                    }
                    break;
            }
        }

        return $data;
    }

    /**
     * 比较附件数据,并返回需要新增和删除的数据
     * @author zhonglei
     * @param array $attachs_db 数据库中的附件数据
     * @param array $attachs_post 用户输入的附件数据
     * @return array
     */
    public function diffData($attachs_db, $attachs_post)
    {
        $keys = [
            Constant::ATTACH_TYPE_VIDEO,
            Constant::ATTACH_TYPE_AUDIO,
            Constant::ATTACH_TYPE_FILE,
        ];

        // 待删除附件ID数组
        $dels = [];

        // 待新增数据,$adds[附件类型][附件数据]
        $adds = [];

        // 遍历所有附件类型
        foreach ($keys as $key) {
            // 取出at_id
            $attachs_old = isset($attachs_db[$key]) ? array_column($attachs_db[$key], 'at_id') : [];
            $attachs_new = isset($attachs_post[$key]) ? array_keys($attachs_post[$key]) : [];

            if (!empty($attachs_old) || !empty($attachs_new)) {
                // 待删除数据
                $dels = array_merge($dels, array_diff($attachs_old, $attachs_new));

                // 待新增附件ID
                $at_ids = array_diff($attachs_new, $attachs_old);

                foreach ($at_ids as $at_id) {
                    $adds[$key][$at_id] = $attachs_post[$key][$at_id];
                }
            }
        }

        return [$dels, $adds];
    }

    /**
     * 保存附件数据
     * @author zhonglei
     * @param int $article_id 新闻ID
     * @param array $fixdata 附件数组
     * @return bool
     */
    public function saveData($article_id, $fixdata)
    {
        $list = $this->list_by_conds(['article_id' => $article_id]);
        $attachs_db = $this->formatDBData($list);
        $attachs_post = $this->formatPostData($fixdata);
        list($dels, $adds) = $this->diffData($attachs_db, $attachs_post);

        // 删除附件
        if (!empty($dels)) {
            $this->delete_by_conds(['article_id' => $article_id, 'at_id' => $dels]);
        }

        foreach ($adds as $k => $data) {
            switch ($k) {
                // 视频 (视频现在必须转码完成后才能提交,因此不会在保存后进行转码;在这里获取转码相关信息)
                case Constant::ATTACH_TYPE_VIDEO:
                    $convertServ = new FileConvert(Service::instance());
                    foreach ($data as $at_id => $video) {
                        $videoInfo = $convertServ->getVodPlayUrl($at_id);
                        $data[$at_id]['at_convert_url'] = str_replace('http://', '//', ($videoInfo['hd'] ?? $videoInfo['url']));
                        $data[$at_id]['at_convert_url'] = str_replace('https://', '//', $data[$at_id]['at_convert_url']);
                        $data[$at_id]['at_cover_url'] = str_replace('http://', '//', $videoInfo['coverUrl']);
                        $data[$at_id]['at_cover_url'] = str_replace('https://', '//', $data[$at_id]['at_cover_url']);
                    }
                    break;

                // 音频、文件从UC获取文件名称、文件大小、Url
                case Constant::ATTACH_TYPE_AUDIO:
                case Constant::ATTACH_TYPE_FILE:
                    $at_ids = array_keys($data);
                    $attachServ = &Attach::instance();
                    $file_list = $attachServ->listAll($at_ids);

                    foreach ($file_list as $at_id => $file) {
                        if (isset($data[$at_id])) {
                            $data[$at_id]['at_name'] = $file['atFilename'];
                            $data[$at_id]['at_time'] = $file['atDuration'];
                            $data[$at_id]['at_size'] = $file['atFilesize'];
                            $data[$at_id]['at_url'] = $file['atAttachment'];
                        }
                    }
                    break;
            }

            $convertServ = new FileConvert(Service::instance());

            // 保存数据
            foreach ($data as $at_id => $v) {
                $v['article_id'] = $article_id;
                $v['at_type'] = $k;

                // 保存成功,文件转换
                if ($this->insert($v) && $k == Constant::ATTACH_TYPE_FILE) {
                    $convertServ->convert([
                        'atIds' => [$at_id],
                        'convertType' => FileConvert::CONVERT_TYPE_HTML,
                        'high' => FileConvert::CONVERT_IS_HIGH_TRUE,
                    ]);
                }

                $attach_ids[] = $at_id;
            }
        }

        /**
         * UC附件服务器附件处理 start
         */
        $attach_serv = new AttachOperation();

        // 新增附件
        $attach_ids = [$fixdata['cover_id']];
        // 视频附件
        $video_ids = [];
        // 其他附件
        $at_ids = [];
        // 新闻内容中的附件
        $content_attach_ids = $attach_serv->match_at_ids($fixdata['content']);

        // 分离视频附件
        if (!empty($attachs_post)) {

            foreach ($attachs_post as $key=>$attach) {
                if ($key == Constant::ATTACH_TYPE_VIDEO) {
                    $video_ids = array_keys($attach);
                } else {
                    $at_ids = array_merge($at_ids, array_keys($attach));
                }
            }
        }

        $attach_ids = array_merge($attach_ids, $content_attach_ids, $at_ids);

        if (empty($attachs_db)) {
            $attach_serv->insert_attach(
                APP_DIR,
                'article',
                $article_id,
                ['attach_ids' => $attach_ids, 'video_ids' => $video_ids]
            );
        } else {
            $attach_serv->update_attach(
                APP_DIR,
                'article',
                $article_id,
                ['attach_ids' => $attach_ids, 'video_ids' => $video_ids]
            );
        }

        /**
         * UC附件服务器附件处理 end
         */

        return true;
    }
}