$value, "path" => $file, "title" => $title, "original" => $title, "ext" => $ext, "size" => filesize($file), 'type' => $type, "hash" => hash_file('sha256', $file, false), 'path_type' => $path_type, ]; return self::AttachmentAdd($data); } /** * 附件添加 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @datetime 2019-06-25T00:13:33+0800 * @param [array] $params [输入参数] */ public static function AttachmentAdd($params = []) { // 请求参数 $p = [ [ 'checked_type' => 'empty', 'key_name' => 'title', 'error_msg' => '名称有误', ], [ 'checked_type' => 'empty', 'key_name' => 'original', 'error_msg' => '原名有误', ], [ 'checked_type' => 'empty', 'key_name' => 'path_type', 'error_msg' => '路径标记有误', ], [ 'checked_type' => 'empty', 'key_name' => 'url', 'error_msg' => '地址有误', ], [ 'checked_type' => 'isset', 'key_name' => 'size', 'error_msg' => '文件大小有误', ], [ 'checked_type' => 'isset', 'key_name' => 'ext', 'error_msg' => '扩展名有误', ], [ 'checked_type' => 'empty', 'key_name' => 'hash', 'error_msg' => 'hash值有误', ], ]; $ret = ParamsChecked($params, $p); if($ret !== true) { return DataReturn($ret, -1); } // 数据组装 $data = [ 'path_type' => $params['path_type'], 'original' => empty($params['original']) ? '' : mb_substr($params['original'], -160, null, 'utf-8'), 'title' => $params['title'], 'size' => $params['size'], 'ext' => $params['ext'], 'type' => isset($params['type']) ? $params['type'] : 'file', 'hash' => $params['hash'], 'url' => self::AttachmentPathHandle($params['url']), 'add_time' => time(), ]; // 附件上传前处理钩子 $hook_name = 'plugins_service_attachment_handle_begin'; MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'params' => $params, 'data' => &$data, ]); // 添加到数据库 $attachment_id = Db::name('Attachment')->insertGetId($data); if($attachment_id > 0) { // 附件上传后处理钩子 $hook_name = 'plugins_service_attachment_handle_end'; MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'params' => &$params, 'data' => &$data, 'attachment_id' => $attachment_id, ]); $params['id'] = $attachment_id; $params['url'] = self::AttachmentPathViewHandle($data['url']); $params['add_time'] = date('Y-m-d H:i:s', $data['add_time']); return DataReturn('添加成功', 0, $params); } // 删除本地图片 if(!empty($params['path'])) { \base\FileUtil::UnlinkFile($params['path']); } return DataReturn('添加失败', -100); } /** * 获取附件总数 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @datetime 2019-06-25T22:44:52+0800 * @param [array] $where [条件] */ public static function AttachmentTotal($where) { return (int) Db::name('Attachment')->where($where)->count(); } /** * 获取附件列表 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @datetime 2019-06-25T22:44:52+0800 * @param [array] $params [参数] */ public static function AttachmentList($params = []) { $m = max(0, isset($params['m']) ? intval($params['m']) : 0); $n = max(1, isset($params['n']) ? intval($params['n']) : 20); $data = Db::name('Attachment')->where($params['where'])->order('id desc')->limit($m, $n)->select()->toArray(); if(!empty($data)) { foreach($data as &$v) { // 附件列表处理前钩子 $hook_name = 'plugins_service_attachment_list_handle_begin'; $ret = EventReturnHandle(MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'data' => &$v, ])); if(isset($ret['code']) && $ret['code'] != 0) { return $ret; } // 数据处理 $v['url'] = self::AttachmentPathViewHandle($v['url']); $v['add_time'] = date('Y-m-d H:i:s'); // 附件列表处理后钩子 $hook_name = 'plugins_service_attachment_list_handle_end'; $ret = EventReturnHandle(MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'data' => &$v, ])); if(isset($ret['code']) && $ret['code'] != 0) { return $ret; } } } return DataReturn('success', 0, $data); } /** * 附件删除 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @datetime 2019-06-25T23:35:27+0800 * @param [array] $params [输入参数] */ public static function AttachmentDelete($params = []) { // 请求参数 $p = [ [ 'checked_type' => 'empty', 'key_name' => 'id', 'error_msg' => '操作id有误', ] ]; $ret = ParamsChecked($params, $p); if($ret !== true) { return DataReturn($ret, -1); } // 获取数据 $data = Db::name('Attachment')->find(intval($params['id'])); if(empty($data)) { return DataReturn('数据不存在或已删除', -1); } // 删除文件 $path = substr(ROOT_PATH, 0, -1).$data['url']; if(file_exists($path)) { if(is_writable($path)) { if(DB::name('Attachment')->where(['id'=>$data['id']])->delete()) { // 删除附件 \base\FileUtil::UnlinkFile($path); $ret = DataReturn('删除成功', 0); } else { $ret = DataReturn('删除失败', -100); } } else { $ret = DataReturn('没有删除权限', -1); } } else { if(DB::name('Attachment')->where(['id'=>$data['id']])->delete()) { $ret = DataReturn('删除成功', 0); } else { $ret = DataReturn('删除失败', -100); } } // 处理 if($ret['code'] == 0) { // 附件删除成功后处理钩子 $hook_name = 'plugins_service_attachment_delete_success'; MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'data' => $data, ]); } return $ret; } /** * 附件根据标记删除 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @datetime 2019-06-25T23:35:27+0800 * @param [string] $path_type [唯一标记] */ public static function AttachmentPathTypeDelete($path_type) { // 获取附件数据 $where = ['path_type'=>$path_type]; $data = DB::name('Attachment')->where($where)->select()->toArray(); if(!empty($data)) { // 删除数据库数据 if(!DB::name('Attachment')->where($where)->delete()) { return DataReturn('删除失败', -1); } // 删除磁盘文件 $path = substr(ROOT_PATH, 0, -1); foreach($data as $v) { $file = $path.$v['url']; if(file_exists($file) && is_writable($file)) { \base\FileUtil::UnlinkFile($file); } } } // 附件删除成功后处理钩子 $hook_name = 'plugins_service_attachment_path_type_delete_success'; MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'data' => $data, ]); return DataReturn('删除成功', 0); } /** * 磁盘附加同步到数据库 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @date 2019-08-02 * @desc description * @param [string] $path_type [附件路径类型] */ public static function AttachmentDiskFilesToDb($path_type) { // 处理状态总数 $count = 0; $success = 0; $error = 0; // 视频/文件/图片 $path_all = [ 'video' => __MY_ROOT_PUBLIC__.'static/upload/video/'.$path_type.'/', 'file' => __MY_ROOT_PUBLIC__.'static/upload/file/'.$path_type.'/', 'image' => __MY_ROOT_PUBLIC__.'static/upload/images/'.$path_type.'/', ]; foreach($path_all as $type=>$path) { $path = GetDocumentRoot() . (substr($path, 0, 1) == "/" ? "":"/") . $path; $files =self::AttachmentDiskFilesList($path, $type, $path_type); if(!empty($files)) { $count += count($files); foreach($files as $v) { $temp = Db::name('Attachment')->where(['title'=>$v['title'], 'hash'=>$v['hash']])->find(); if(empty($temp)) { $ret = self::AttachmentAdd($v); if($ret['code'] == 0) { $success++; } else { $error++; } } else { $success++; } } } } return DataReturn('总数['.$count.'], 成功['.$success.'], 失败['.$error.']', 0); } /** * 遍历获取目录下的指定类型的文件 * @author Devil * @blog http://gong.gg/ * @version 0.0.1 * @datetime 2017-01-17T23:24:59+0800 * @param [string] $path [路径地址] * @param [string] $type [允许的文件] * @param [string] $path_type [路径类型] * @param [array] &$files [数据] * @return [array] [数据] */ public static function AttachmentDiskFilesList($path, $type, $path_type, &$files = []) { if(!is_dir($path)) return null; if(substr($path, strlen($path) - 1) != '/') $path .= '/'; $handle = opendir($path); $document_root = GetDocumentRoot(); while(false !== ($file = readdir($handle))) { if($file != 'index.html' && $file != '.' && $file != '..' && substr($file, 0, 1) != '.') { $temp_path = $path . $file; if(is_dir($temp_path)) { self::AttachmentDiskFilesList($temp_path, $type, $path_type, $files); } else { $url = self::AttachmentPathHandle(substr($temp_path, strlen($document_root))); $title = substr($url, strripos($url, '/')+1); $root_path = ROOT.'public'.$url; $files[] = array( 'url' => $url, 'original' => $title, 'title' => $title, 'type' => $type, 'path_type' => $path_type, 'size' => file_exists($root_path) ? filesize($root_path) : 0, 'hash' => file_exists($root_path) ? hash_file('sha256', $root_path, false) : '', 'ext' => substr($title, strripos($title, '.')), ); } } } return $files; } /** * 小程序富文本标签处理 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @date 2020-01-04 * @desc description * @param [string] $content [需要处理的富文本内容] */ public static function ApMiniRichTextContentHandle($content) { // 标签处理,兼容小程序rich-text $search = [ '', '

', '

', '

', '/'; preg_match_all($pattern, self::AttachmentPathHandle($content), $match); return empty($match[1]) ? [] : $match[1]; } return []; } /** * 货币信息 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @date 2020-09-10 * @desc description */ public static function CurrencyData() { // 默认从配置文件读取货币信息 $data = [ 'currency_symbol' => MyConfig('shopxo.currency_symbol'), 'currency_code' => MyConfig('shopxo.currency_code'), 'currency_rate' => MyConfig('shopxo.currency_rate'), 'currency_name' => MyConfig('shopxo.currency_name'), ]; // 钩子 $hook_name = 'plugins_service_currency_data'; MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'data' => &$data, ]); return $data; } /** * 货币信息-符号 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @date 2020-09-10 * @desc description */ public static function CurrencyDataSymbol() { $res = self::CurrencyData(); return empty($res['currency_symbol']) ? MyConfig('shopxo.currency_symbol') : $res['currency_symbol']; } /** * 编辑器文件存放地址 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @date 2021-01-27 * @desc description * @param [string] $value [位置路径名称([ - ]作为目录分隔符)] */ public static function EditorPathTypeValue($value) { // 当前操作名称, 兼容插件模块名称 $module_name = RequestModule(); $controller_name = RequestController(); $action_name = RequestAction(); // 钩子 $hook_name = 'plugins_service_editor_path_type_'.$module_name.'_'.$controller_name.'_'.$action_name; MyEventTrigger($hook_name, [ 'hook_name' => $hook_name, 'is_backend' => true, 'value' => &$value, ]); return $value; } /** * zip压缩包扩展可用格式 * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @date 2021-02-02 * @desc description * @param array $params [description] */ public static function ZipExtTypeList($params = []) { return [ 'application/zip', 'application/octet-stream', 'application/x-zip-compressed', ]; } /** * 获取用户唯一id * @author Devil * @blog http://gong.gg/ * @version 1.0.0 * @date 2021-04-15 * @desc 未登录取[uuid]前端传过来的uuid、已登录取[用户id]、都没有则返回空字符串 */ public static function UserUniqueId() { // 取参数uuid、默认空 $uid = input('uuid', ''); // 用户信息 $user = UserService::LoginUserInfo(); if(!empty($user) && !empty($user['id'])) { $uid = $user['id']; } return empty($uid) ? '' : md5($uid); } } ?>