| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 | <?phpnamespace addons\cms\library;use addons\cms\library\aip\AipContentCensor;use addons\cms\library\aip\AipNlp;use addons\cms\model\Autolink;use addons\cms\model\Diyform;use addons\cms\model\Fields;use addons\cms\model\Modelx;use addons\cms\model\Tag;use fast\Http;use think\Cache;use think\Config;use think\Db;use think\Hook;class Service{    /**     * 检测内容是否合法     * @param string $content 检测内容     * @param string $type    类型     * @return bool     */    public static function isContentLegal($content, $type = null)    {        $config = get_addon_config('cms');        $type = is_null($type) ? $config['audittype'] : $type;        if ($type == 'local') {            // 敏感词过滤            $handle = SensitiveHelper::init()->setTreeByFile(ADDON_PATH . 'cms/data/words.dic');            //首先检测是否合法            $isLegal = $handle->islegal($content);            return $isLegal ? true : false;        } elseif ($type == 'baiduyun') {            $client = new AipContentCensor($config['aip_appid'], $config['aip_apikey'], $config['aip_secretkey']);            $result = $client->textCensorUserDefined($content);            if (!isset($result['conclusionType']) || $result['conclusionType'] > 1) {                return false;            }        }        return true;    }    /**     * 获取标题的关键字     * @param $title     * @return array     */    public static function getContentTags($title)    {        $arr = [];        $config = get_addon_config('cms');        if ($config['nlptype'] == 'local') {            !defined('_VIC_WORD_DICT_PATH_') && define('_VIC_WORD_DICT_PATH_', ADDON_PATH . 'cms/data/dict.json');            $handle = new VicWord('json');            $result = $handle->getAutoWord($title);            foreach ($result as $index => $item) {                $arr[] = $item[0];            }        } else {            $client = new AipNlp($config['aip_appid'], $config['aip_apikey'], $config['aip_secretkey']);            $result = $client->lexer($title);            if (isset($result['items'])) {                foreach ($result['items'] as $index => $item) {                    if (!in_array($item['pos'], ['v', 'vd', 'nd', 'a', 'ad', 'an', 'd', 'm', 'q', 'r', 'p', 'c', 'u', 'xc', 'w'])) {                        $arr[] = $item['item'];                    }                }            }        }        foreach ($arr as $index => $item) {            if (mb_strlen($item) == 1) {                unset($arr[$index]);            }        }        return array_filter(array_unique($arr));    }    /**     * 内容关键字自动加链接     * 优先顺序为 站点配置自动链接 > 自动链接表 > 标签内链     */    public static function autolinks($content)    {        $links = [];        //先移除已有的自动链接        $content = preg_replace_callback('~<a data\-rel="autolink" .*?>(.*?)</a>~i', function ($match) {            return $match[1];        }, $content);        //存储所有标签        $content = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) {            return '<' . array_push($links, $match[1]) . '>';        }, $content);        $config = get_addon_config('cms');        $limit = 2; //单一标签最大替换次数        $redirect = $config['redirecturl'] ?? true; //是否是用跳转        $autolinkArr = [];        $tagList = Tag::where('autolink', 1)->cache(true)->where('status', 'normal')->select();        foreach ($tagList as $index => $item) {            $autolinkArr[$item['name']] = ['text' => $item['name'], 'type' => 'tag', 'url' => $item['fullurl']];        }        $autolinkList = Autolink::where('status', 'normal')->cache(true)->order('weigh DESC,id DESC')->select();        foreach ($autolinkList as $index => $item) {            $autolinkArr[$item['title']] = ['text' => $item['title'], 'type' => 'autolink', 'url' => $item['url'], 'target' => $item['target'], 'id' => $item['id']];        }        foreach ($config['autolinks'] as $text => $url) {            $autolinkArr[$text] = ['text' => $text, 'type' => 'config', 'url' => $url];        }        $autolinkArr = array_values($autolinkArr);        //字符串长的优先替换        usort($autolinkArr, function ($a, $b) {            if ($a['text'] == $b['text']) return 0;            return (strlen($a['text']) > strlen($b['text'])) ? -1 : 1;        });        //替换链接        foreach ($autolinkArr as $index => $item) {            $content = preg_replace_callback('/(' . $item['text'] . ')/i', function ($match) use ($item, $redirect, $config) {                if ($item['type'] == 'tag') {                    $url = $item['url'];                } elseif ($item['type'] == 'autolink' || $redirect) {                    $params = [];                    $params['url'] = $item['url'];                    if (isset($item['id'])) {                        $params['id'] = $item['id'];                    }                    $url = addon_url('cms/go/index', [], $config['urlsuffix'], true) . '?' . http_build_query($params);                } else {                    $url = $item['url'];                }                return '<a data-rel="autolink" href="' . $url . '" ' . (isset($item['target']) && $item['target'] == 'blank' ? ' target="_blank"' : '') . '>' . $match[0] . '</a>';            }, $content, $limit);            $content = preg_replace_callback('~(<a .*?>.*?</a>)~i', function ($match) use (&$links) {                return '<' . array_push($links, $match[1]) . '>';            }, $content);        }        return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) {            return $links[$match[1] - 1];        }, $content);    }    /**     * 推送消息通知     * @param string $content     内容     * @param string $type        类型     * @param string $template_id 模板ID     */    public static function notice($content, $type, $template_id)    {        try {            if ($type == 'dinghorn') {                Hook::listen('msg_notice', $template_id, [                    'content' => $content                ]);            } elseif ($type == 'vbot') {                Hook::listen('vbot_send_msg', $template_id, [                    'content' => $content                ]);            }        } catch (\Exception $e) {        }    }    /**     * 获取表字段信息     * @param string $table 表名     * @return array     */    public static function getTableFields($table)    {        $tagName = "cms-table-fields-{$table}";        $fieldlist = Cache::get($tagName);        if (!Config::get('app_debug') && $fieldlist) {            return $fieldlist;        }        $dbname = Config::get('database.database');        //从数据库中获取表字段信息        $sql = "SELECT * FROM `information_schema`.`columns` WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION";        //加载主表的列        $columnList = Db::query($sql, [$dbname, $table]);        $fieldlist = [];        foreach ($columnList as $index => $item) {            $fieldlist[] = ['name' => $item['COLUMN_NAME'], 'title' => $item['COLUMN_COMMENT'], 'type' => $item['DATA_TYPE']];        }        Cache::set($tagName, $fieldlist);        return $fieldlist;    }    /**     * 获取指定类型的自定义字段列表     */    public static function getCustomFields($source, $source_id, $values = [], $conditions = [])    {        $fields = Fields::where('source', $source)            ->where('source_id', $source_id)            ->where($conditions)            ->where('status', 'normal')            ->order('weigh desc,id desc')            ->select();        foreach ($fields as $k => $v) {            //优先取编辑的值,再次取默认值            $v->value = isset($values[$v['name']]) ? $values[$v['name']] : (is_null($v['defaultvalue']) ? '' : $v['defaultvalue']);            $v->rule = str_replace(',', '; ', $v->rule);            if (in_array($v['type'], ['checkbox', 'lists', 'images'])) {                $checked = '';                if ($v['minimum'] && $v['maximum']) {                    $checked = "{$v['minimum']}~{$v['maximum']}";                } elseif ($v['minimum']) {                    $checked = "{$v['minimum']}~";                } elseif ($v['maximum']) {                    $checked = "~{$v['maximum']}";                }                if ($checked) {                    $v->rule .= (';checked(' . $checked . ')');                }            }            if (in_array($v['type'], ['checkbox', 'radio']) && stripos($v->rule, 'required') !== false) {                $v->rule = str_replace('required', 'checked', $v->rule);            }            if (in_array($v['type'], ['selects'])) {                $v->extend .= (' ' . 'data-max-options="' . $v['maximum'] . '"');            }        }        return $fields;    }    /**     * 获取过滤列表     * @param string $source    来源类型     * @param int    $source_id 来源ID     * @param array  $filter    过滤条件     * @param array  $params    搜索参数     * @param bool   $multiple  是否为复选模式     * @return array     */    public static function getFilterList($source, $source_id, $filter, $params = [], $multiple = false)    {        $fieldsList = Fields::where('source', $source)            ->where('source_id', $source_id)            ->where('status', 'normal')            ->cache(true)            ->select();        $filterList = [];        $multiValueFields = [];        $fields = [];        if (in_array($source, ['model', 'diyform'])) {            //查找主表启用过滤搜索的字段            $model = $source == 'model' ? Modelx::get($source_id) : Diyform::get($source_id);            $setting = $model->setting;            if (isset($setting['filterfields'])) {                foreach ($setting['filterfields'] as $index => $name) {                    $title = isset($setting['titlelist'][$name]) ? $setting['titlelist'][$name] : $name;                    $filterlist = isset($setting['filterlist'][$name]) ? $setting['filterlist'][$name] : '';                    $filterlist = \app\common\model\Config::decode($filterlist);                    if (!$filterlist) {                        continue;                    }                    if (in_array($name, ['special_ids', 'channel_ids', 'images', 'tags', 'keywords'])) {                        $multiValueFields[] = $name;                    }                    $fields[] = [                        'name'    => $name,                        'title'   => $title,                        'content' => $filterlist                    ];                }            }        }        foreach ($fieldsList as $k => $v) {            if (!$v['isfilter']) {                continue;            }            $content = isset($v['filter_list']) && $v['filter_list'] ? $v['filter_list'] : $v['content_list'];            if (!$content) {                continue;            }            //多选值字段需要做特殊处理            if (in_array($v['type'], ['selects', 'checkbox', 'array', 'selectpages'])) {                $multiValueFields[] = $v['name'];            }            $fields[] = [                'name'    => $v['name'],                'title'   => $v['title'],                'content' => $content            ];        }        $filter = array_intersect_key($filter, array_flip(array_column($fields, 'name')));        foreach ($fields as $k => $v) {            $content = [];            $all = ['' => __('All')] + (is_array($v['content']) ? $v['content'] : []);            foreach ($all as $m => $n) {                $filterArr = isset($filter[$v['name']]) && $filter[$v['name']] !== '' ? ($multiple ? explode(';', $filter[$v['name']]) : [$filter[$v['name']]]) : [];                $active = ($m === '' && !$filterArr) || ($m !== '' && in_array($m, $filterArr)) ? true : false;                if ($active) {                    $current = implode(';', array_diff($filterArr, [$m]));                } else {                    $current = $multiple ? implode(';', array_merge($filterArr, [$m])) : $m;                }                $prepare = $m === '' ? array_diff_key($filter, [$v['name'] => $m]) : array_merge($filter, [$v['name'] => $current]);                //$url = '?' . http_build_query(array_merge(['filter' => $prepare], array_diff_key($params, ['filter' => ''])));                $url = '?' . str_replace(['%2C', '%3B'], [',', ';'], http_build_query(array_merge($prepare, array_intersect_key($params, array_flip(['orderby', 'orderway', 'multiple'])))));                $content[] = ['value' => $m, 'title' => $n, 'active' => $active, 'url' => $url];            }            $filterList[] = [                'name'    => $v['name'],                'title'   => $v['title'],                'content' => $content,            ];        }        foreach ($filter as $index => &$item) {            $item = is_array($item) ? $item : explode(',', str_replace(';', ',', $item));        }        return [$filterList, $filter, $params, $fields, $multiValueFields, $fieldsList];    }    /**     * 获取排序列表     * @param string $orderby     * @param string $orderway     * @param array  $orders     * @param array  $params     * @param array  $fieldsList     * @return array     */    public static function getOrderList($orderby, $orderway, $orders = [], $params = [], $fieldsList = [])    {        $lastOrderby = '';        $lastOrderway = $orderway && in_array(strtolower($orderway), ['asc', 'desc']) ? $orderway : 'desc';        foreach ($fieldsList as $index => $field) {            if ($field['isorder']) {                $orders[] = ['name' => $field['name'], 'field' => $field['name'], 'title' => $field['title']];            }        }        $orderby = in_array($orderby, array_map(function ($item) {            return $item['name'];        }, $orders)) ? $orderby : 'default';        foreach ($orders as $index => $order) {            if ($orderby == $order['name']) {                $lastOrderby = $order['field'];                break;            }        }        $orderList = [];        foreach ($orders as $k => $v) {            $url = '?' . http_build_query(array_merge($params, ['orderby' => $v['name'], 'orderway' => $v['name'] == $orderby ? ($lastOrderway == 'desc' ? 'asc' : 'desc') : 'desc']));            $v['active'] = $orderby == $v['name'] ? true : false;            $v['url'] = $url;            $orderList[] = $v;        }        return [$orderList, $lastOrderby, $lastOrderway];    }    /**     * 获取过滤的最终条件和绑定参数     * @param array $filter           过滤条件     * @param array $multiValueFields 多值字段     * @param bool  $multiple         是否为复选模式     * @return array     */    public static function getFilterWhereBind($filter, $multiValueFields, $multiple = false)    {        //构造bind数据        $bind = [];        foreach ($filter as $field => &$item) {            if (in_array($field, $multiValueFields)) {                $item = !is_array($item) && stripos($item, ',') !== false ? explode(',', $item) : $item;                if (is_array($item)) {                    foreach ($item as $index => $subitem) {                        $bind[$field . $index] = $subitem;                    }                } else {                    $bind[$field] = $item;                }            }        }        $filterWhere = function ($query) use ($filter, $multiValueFields) {            foreach ($filter as $field => $item) {                $item = is_array($item) ? $item : [$item];                if (in_array($field, $multiValueFields)) {                    $query->where(function ($query) use ($field, $item) {                        foreach ($item as $subindex => $subitem) {                            $query->whereOr("FIND_IN_SET(:" . $field . $subindex . ", `{$field}`)");                        }                    });                } else {                    $query->where(function ($query) use ($field, $item) {                        foreach ($item as $subindex => $subitem) {                            //如果匹配区间,以~分隔                            if (preg_match("/[a-zA-Z0-9\.\-]+\~[a-zA-Z0-9\.\-]+/", $subitem)) {                                $condition = explode('~', $subitem);                                //判断是否时间区间                                $op = preg_match("/\d{4}\-\d{1,2}\-\d{1,2}/", $condition[0]) ? 'between time' : 'between';                                $query->whereOr($field, $op, $condition);                            } else {                                $query->whereOr($field, $subitem);                            }                        }                    });                }            }        };        return [$filterWhere, $bind];    }    /**     * 追加_text属性值     * @param $fieldsContentList     * @param $row     */    public static function appendTextAttr(&$fieldsContentList, &$row)    {        //附加列表字段        array_walk($fieldsContentList, function ($content, $field) use (&$row) {            if (isset($row[$field])) {                if (isset($content[$row[$field]])) {                    $list = [$row[$field] => $content[$row[$field]]];                } else {                    $keys = $values = explode(',', $row[$field]);                    foreach ($values as $index => &$item) {                        $item = isset($content[$item]) ? $content[$item] : $item;                    }                    $list = array_combine($keys, $values);                }            } else {                $list = [];            }            $list = array_filter($list);            $row[$field . '_text'] = implode(',', $list);            $row[$field . '_list'] = $list;        });    }}
 |