<?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; } }