## 文章发布处理插件 本插件是在插件市场下载后改善的,为了让发文章的时候更爽! 后台的默认编辑器是百度编辑器,由于CMF框架暂时是没有完善好远程文件下载的方法,所以在本插件中,实现了远程下载图片的方法,远程下载文件的路径是固定的,可以自行完善。 插件包含功能:自动发布文章,截取文章内容作为摘要,**远程图片下载**,内容的首张图片作为**缩略图** CMF插件整体流程: 1,文章保存时候触发钩子: > \app\portal\controller\AdminArticleController.php public function addPost() 158行: hook('portal_admin_after_save_article', $hookParam); 2,插件实现: > \plugins\portal_admin_after_save_article 在根目录下的plugins文件夹里添加插件,插件的名称自定义;这里与钩子名称一致:portal_admin_after_save_article 里面为实现插件的主体文件:PortalAdminAfterSaveArticlePlugin.php > \plugins\portal_admin_after_save_article\PortalAdminAfterSaveArticlePlugin.php <?php namespace plugins\portal_admin_after_save_article; use cmf\lib\Plugin; use think\Db; use app\portal\model\PortalPostModel; class PortalAdminAfterSaveArticlePlugin extends Plugin { public $info = [ 'name' => 'PortalAdminAfterSaveArticle', 'title' => '后台文章保存之后自动处理', 'description' => '自动发布、自动截取文章摘要、远程图片下载/自动获取文章缩略图', 'status' => 1, 'author' => 'FREE', 'version' => '1.0' ]; //安装插件 public function install() { return true; } //卸载插件 public function uninstall() { return true; } //实现钩子:portal_admin_after_save_article public function PortalAdminAfterSaveArticle($hookParam) { trace($hookParam, 'error'); $config = $this->getConfig(); $updateData = array(); //只有添加文章时执行自动发布 if ($hookParam['is_add']) { //是否自动发布 if ($config['auto_publish'] == '1') { $updateData['post_status'] = 1; $updateData['published_time'] = time(); } } $auto_excerpt = trim($config['auto_excerpt']); //文章摘要为空 if (trim($hookParam['article']['post_excerpt']) == false && !empty($hookParam['article']['post_content'])) { //是否自动截取摘要 if (!empty($auto_excerpt)) { $updateData['post_excerpt'] = $this->_getSummary($hookParam['article']['post_content'], 0, $auto_excerpt); Db::name("portal_post")->where(['id' => $hookParam['article']['id']])->update($updateData); } } $content=""; //判断图片内容是否远程上传 if($this->_get_fileType($hookParam['article']['post_content'])){ //创建上传目录(绝对路径) $date = date("Ymd"); $uploadPath = WEB_ROOT . 'upload' . DIRECTORY_SEPARATOR . "images" . DIRECTORY_SEPARATOR . $date . DIRECTORY_SEPARATOR; if (!file_exists($uploadPath)) { mkdir("$uploadPath", 0777, true); } //相对路径(前台用) $savePath = "/upload/images/" . $date . "/"; //实现远程图片本地化 $content = $hookParam['article']['post_content']; $title_id= uniqid(); $preg_img="#<img.*src=\"(.*)\".*/>#iUs"; //全局正则表达式匹配 preg_match_all($preg_img, $content,$arr_img); //全局替换 foreach ($arr_img[1] as $imgid=>$v){ $img_id = $title_id."_".$imgid.".jpg"; $content= str_replace($v, $savePath.$img_id,$content); $this->get_image_byurl($v,$img_id,$savePath); } //更新内容 if (!empty($content)) { Db::name("portal_post")->where(['id' => $hookParam['article']['id']])->update(['post_content'=> $content]); } } //自动获取缩略图 if ($config['auto_thumbnail'] == '1') { if (empty($hookParam['article']['more']['thumbnail'])) { $data=[]; $data['id']=$hookParam['article']['id']; $content1 = empty( $content ) ? $hookParam['article']['post_content'] : $content ; $pattern1 = "/\<img.*?src\=\"(.*?)\"[^>]*>/i"; preg_match_all($pattern1,$content1 ,$matchContent1); if(!empty($matchContent1[1][0])){ $rurl = $matchContent1[1][0]; $data['more']['thumbnail']=$rurl; $post = new PortalPostModel(); $post->allowField(true)->isUpdate(true)->data($data, true)->save(); } } } } /** * [判断图片是否远程图片] * @param [string] $content [文章内容] * @return [bool] [true为远程,false为本地] */ private function _get_fileType($content){ $pattern = "/\<img.*?src\=\"(.*?)\"[^>]*>/i"; preg_match_all($pattern,$content,$matches); // var_dump($matches); // 得到匹配成功的二维数组,0为完整图片,1为图片url ; 判断第一个图片是否远程图片 $url = $matches[1][0]; $preg = "/^http(s)?:\\/\\/.+/"; if(preg_match($preg,$url)) { return true; }else //本地 { return false; } } /** * 文章简介截取方法 * @param $content 文章内容 * @param int $s 开始截取位置 * @param int $e 截取结束位置 * @param string $char 字符编码 * @return string */ private function _getSummary($content, $s = 0, $e = 100, $char = 'utf-8') { if (empty($content)) { return ''; } $newContent = strip_tags(htmlspecialchars_decode($content)); $newContent = str_replace('&nbsp;', '', $newContent); $patternArr = array('/\s/', '/ /'); $replaceArr = array('', ''); $newContent = preg_replace($patternArr, $replaceArr, $newContent); $newContent = mb_substr($newContent, $s, $e, $char); return trim($newContent); } /** * [get_image_byurl 下载远程图片到本地] * @param [type] $url [原始图片URL] * @param [type] $img_name [本地图片名称] * @param string $filename [本地图片存放地址] * @return [type] [文件名] */ function get_image_byurl($url,$img_name,$filename="") { if ($url == "") { return false; } $ext = strrchr($url, "."); //得到图片的扩展名 if($ext != ".gif" && $ext != ".jpg" && $ext != ".bmp") { $ext = ".jpg"; } if($filename == "") { $filename ="./upload/images/".$img_name; } //以流的形式保存图片 $return_content = $this->http_get_data($url); $fp= @fopen($filename,"a"); //将文件绑定到流 fwrite($fp,$return_content); //写入文件 @fclose($write_fd); return($filename); //返回文件名 } /** * [http_get_data 远程请求获取图片] * @param [type] $url [图片URL] * @return [type] [图片二进制流] */ function http_get_data($url) { $ch = curl_init (); curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, 'GET' ); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false ); curl_setopt ( $ch, CURLOPT_URL, $url ); ob_start (); curl_exec ( $ch ); $return_content = ob_get_contents (); ob_end_clean (); $return_code = curl_getinfo ( $ch, CURLINFO_HTTP_CODE ); return $return_content; } } 插件的独立配置文件,供给后台设置 > \plugins\portal_admin_after_save_article\config.php <?php return array( 'auto_publish' => array(// 在后台插件配置表单中的键名 ,会是config[text] 'title' => '文章自动发布', // 表单的label标题 'type' => 'radio',// 表单的类型:text,password,textarea,checkbox,radio,select等 'options' => [ '1' => '是', '0' => '否' ], 'value' => '1',// 表单的默认值 'tip' => '选择是,文章保存之后自动发布,无需再执行"编辑->发布->保存"流程' //表单的帮助提示 ), 'auto_excerpt' => array(// 在后台插件配置表单中的键名 ,会是config[text] 'title' => '自动截取文章摘要', // 表单的label标题 'type' => 'text',// 表单的类型:text,password,textarea,checkbox,radio,select等 'value' => '100',// 表单的默认值 'tip' => '截取文章内容的字符数,留空则不截取' //表单的帮助提示 ), 'auto_thumbnail' => array(// 在后台插件配置表单中的键名 ,会是config[text] 'title' => '自动生成文章缩略图', // 表单的label标题 'type' => 'radio',// 表单的类型:text,password,textarea,checkbox,radio,select等 'options' => [ '1' => '是', '0' => '否' ], 'value' => '1',// 表单的默认值 'tip' => '选择是,文章保存之后自动获取正文第一个图片作为缩略图' //表单的帮助提示 ), ); 插件安装的方法: 将上面的文件按照路径安排好,在后台插件列表里安装插件,发表文章后就会自动执行上面的方法了。