## 文章发布处理插件
本插件是在插件市场下载后改善的,为了让发文章的时候更爽!
后台的默认编辑器是百度编辑器,由于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 . "/";
//获取编辑器内容,5.1.4以上版本需要添加反转义函数
$content = htmlspecialchars_decode($hookParam['article']['post_content']);
$title_id= uniqid();
$preg_img="/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/";
preg_match_all($preg_img, $content,$arr_img); //正则获取所有图片
//print_r($arr_img);
//遍历替换所有的图片 //$arr_img[1] 获取所有图片路径
//_get_image_byurl 实现远程图片本地化
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(' ', '', $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' => '选择是,文章保存之后自动获取正文第一个图片作为缩略图' //表单的帮助提示
),
);
插件安装的方法:
将上面的文件按照路径安排好,在后台插件列表里安装插件,发表文章后就会自动执行上面的方法了。