ctms/vendor/fmsoft/components/yii2-ueditor/UEditorController.php
2025-04-10 23:19:13 +08:00

461 lines
14 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* UEditor Widget扩展
* @author xbzbing<xbzbing@gmail.com>
* @link www.crazydb.com
*
* UEditor版本v1.4.3.1
* Yii 版本 2.0+
*/
namespace crazydb\ueditor;
use yii;
use yii\imagine\Image;
use yii\web\Controller;
/**
* Class UEditorController
* 负责UEditor后台响应
* @package crazydb\ueditor
*/
class UEditorController extends Controller
{
/**
* UEditor的配置
* @see http://fex-team.github.io/ueditor/#start-config
* @var array
*/
public $config;
/**
* 列出文件/图片时需要忽略的文件夹
* 主要用于处理缩略图管理兼容比如elFinder之类的程序
* @var array
*/
public $ignoreDir = [
'.thumbnails'
];
/**
* 缩略图设置
* 默认为200*200如果设置为空数组则不生成缩略图
* @var array
*/
public $thumbnail = ['height' => 200, 'width' => 200];
/**
* 图片缩放设置
* 默认不缩放。
* 配置如 ['height'=>200,'width'=>200]
* @var array
*/
public $zoom = [];
/**
* 水印设置
* 参考配置如下:
* ['path'=>'水印图片位置','start'=>[0, 0]]
* 默认位置为[0, 0],可不配置
* @var array
*/
public $watermark = [];
/**
* 默认 action
* @var string
*/
public $defaultAction = 'index';
/**
* Web根目录
* @var string
*/
protected $webroot;
public function init()
{
parent::init();
//CSRF 基于 POST 验证UEditor 无法添加自定义 POST 数据,同时由于这里不会产生安全问题,故简单粗暴地取消 CSRF 验证。
//如需 CSRF 防御,可以使用 server_param 方法,然后在这里将 Get 的 CSRF 添加到 POST 的数组中。。。
Yii::$app->request->enableCsrfValidation = false;
//当客户使用低版本IE时会使用swf上传插件维持认证状态可以参考文档UEditor「自定义请求参数」部分。
//http://fex.baidu.com/ueditor/#server-server_param
//保留UE默认的配置引入方式
if (file_exists(__DIR__ . '/config.json'))
$CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", '', file_get_contents(__DIR__ . '/config.json')), true);
else
$CONFIG = [];
if (!is_array($this->config))
$this->config = [];
if (!is_array($CONFIG))
$CONFIG = [];
$default = [
'imagePathFormat' => '/upload/image/{yyyy}{mm}{dd}/{time}{rand:8}',
'scrawlPathFormat' => '/upload/image/{yyyy}{mm}{dd}/{time}{rand:8}',
'snapscreenPathFormat' => '/upload/image/{yyyy}{mm}{dd}/{time}{rand:8}',
'catcherPathFormat' => '/upload/image/{yyyy}{mm}{dd}/{time}{rand:8}',
'videoPathFormat' => '/upload/video/{yyyy}{mm}{dd}/{time}{rand:8}',
'filePathFormat' => '/upload/file/{yyyy}{mm}{dd}/{rand:8}_{filename}',
'imageManagerListPath' => '/upload/image/',
'fileManagerListPath' => '/upload/file/',
];
$this->config = $this->config + $default + $CONFIG;
$this->webroot = Yii::getAlias('@webroot');
if(!is_array($this->thumbnail))
$this->thumbnail = false;
}
/**
* 蛋疼的统一后台入口
*/
public function actionIndex()
{
$action = strtolower(Yii::$app->request->get('action', 'config'));
$actions = [
'uploadimage' => 'upload-image',
'uploadscrawl' => 'upload-scrawl',
'uploadvideo' => 'upload-video',
'uploadfile' => 'upload-file',
'listimage' => 'list-image',
'listfile' => 'list-file',
'catchimage' => 'catch-image',
'config' => 'config',
'listinfo' => 'list-info'
];
if (isset($actions[$action]))
return $this->run($actions[$action]);
else
return $this->show(['state' => 'Unknown action.']);
}
/**
* 显示配置信息
*/
public function actionConfig()
{
return $this->show($this->config);
}
/**
* 上传图片
*/
public function actionUploadImage()
{
$config = [
'pathFormat' => $this->config['imagePathFormat'],
'maxSize' => $this->config['imageMaxSize'],
'allowFiles' => $this->config['imageAllowFiles']
];
$fieldName = $this->config['imageFieldName'];
$result = $this->upload($fieldName, $config);
return $this->show($result);
}
/**
* 上传涂鸦
*/
public function actionUploadScrawl()
{
$config = [
'pathFormat' => $this->config['scrawlPathFormat'],
'maxSize' => $this->config['scrawlMaxSize'],
'allowFiles' => $this->config['scrawlAllowFiles'],
'oriName' => 'scrawl.png'
];
$fieldName = $this->config['scrawlFieldName'];
$result = $this->upload($fieldName, $config, 'base64');
return $this->show($result);
}
/**
* 上传视频
*/
public function actionUploadVideo()
{
$config = [
'pathFormat' => $this->config['videoPathFormat'],
'maxSize' => $this->config['videoMaxSize'],
'allowFiles' => $this->config['videoAllowFiles']
];
$fieldName = $this->config['videoFieldName'];
$result = $this->upload($fieldName, $config);
return $this->show($result);
}
/**
* 上传文件
*/
public function actionUploadFile()
{
$config = [
'pathFormat' => $this->config['filePathFormat'],
'maxSize' => $this->config['fileMaxSize'],
'allowFiles' => $this->config['fileAllowFiles']
];
$fieldName = $this->config['fileFieldName'];
$result = $this->upload($fieldName, $config);
return $this->show($result);
}
/**
* 文件列表
*/
public function actionListFile()
{
$allowFiles = $this->config['fileManagerAllowFiles'];
$listSize = $this->config['fileManagerListSize'];
$path = $this->config['fileManagerListPath'];
$result = $this->manage($allowFiles, $listSize, $path);
return $this->show($result);
}
/**
* 图片列表
*/
public function actionListImage()
{
$allowFiles = $this->config['imageManagerAllowFiles'];
$listSize = $this->config['imageManagerListSize'];
$path = $this->config['imageManagerListPath'];
$result = $this->manage($allowFiles, $listSize, $path);
return $this->show($result);
}
/**
* 获取远程图片
*/
public function actionCatchImage()
{
/* 上传配置 */
$config = [
'pathFormat' => $this->config['catcherPathFormat'],
'maxSize' => $this->config['catcherMaxSize'],
'allowFiles' => $this->config['catcherAllowFiles'],
'oriName' => 'remote.png'
];
$fieldName = $this->config['catcherFieldName'];
/* 抓取远程图片 */
$list = [];
if (isset($_POST[$fieldName])) {
$source = $_POST[$fieldName];
} else {
$source = $_GET[$fieldName];
}
foreach ($source as $imgUrl) {
$item = new Uploader($imgUrl, $config, 'remote');
$info = $item->getFileInfo();
$info['thumbnail'] = $this->imageHandle($info['url']);
$list[] = [
'state' => $info['state'],
'url' => $info['url'],
'source' => $imgUrl
];
}
/* 返回抓取数据 */
return [
'state' => count($list) ? 'SUCCESS' : 'ERROR',
'list' => $list
];
}
/**
* 各种上传
* @param $fieldName
* @param $config
* @param $base64
* @return array
*/
protected function upload($fieldName, $config, $base64 = 'upload')
{
$up = new Uploader($fieldName, $config, $base64);
$info = $up->getFileInfo();
if ($this->thumbnail && $info['state'] == 'SUCCESS' && in_array($info['type'], ['.png', '.jpg', '.bmp', '.gif'])) {
$info['thumbnail'] = Yii::$app->request->baseUrl . $this->imageHandle($info['url']);
}
$info['url'] = Yii::$app->request->baseUrl . $info['url'];
$info['original'] = htmlspecialchars($info['original']);
$info['width'] = $info['height'] = 500;
return $info;
}
/**
* 自动处理图片
* @param $fullName
* @return mixed|string
*/
protected function imageHandle($fullName)
{
if (substr($fullName, 0, 1) != '/')
$fullName = '/' . $fullName;
$file = $fullName;
//先处理缩略图
if ($this->thumbnail && !empty($this->thumbnail['height']) && !empty($this->thumbnail['width'])) {
$file = pathinfo($file);
$file = $file['dirname'] . '/' . $file['filename'] . '_thumbnail.' . $file['extension'];
Image::thumbnail($this->webroot . $fullName, intval($this->thumbnail['width']), intval($this->thumbnail['height']))
->save($this->webroot . $file);
}
//再处理缩放,默认不缩放
//...缩放效果非常差劲--
if (isset($this->zoom['height']) && isset($this->zoom['width'])) {
$size = $this->getSize($this->webroot . $fullName);
if ($size && $size[0] > 0 && $size[1] > 0) {
$ratio = min([$this->zoom['height'] / $size[0], $this->zoom['width'] / $size[1], 1]);
Image::thumbnail($this->webroot . $fullName, ceil($size[0] * $ratio), ceil($size[1] * $ratio))
->save($this->webroot . $fullName);
}
}
//最后生成水印
if (isset($this->watermark['path']) && file_exists($this->watermark['path'])) {
if (!isset($this->watermark['start']))
$this->watermark['start'] = [0, 0];
Image::watermark($file, $this->watermark['path'], $this->watermark['start'])
->save($file);
}
return $file;
}
/**
* 获取图片的大小
* 主要用于获取图片大小并
* @param $file
* @return array
*/
protected function getSize($file)
{
if (!file_exists($file))
return [];
$info = pathinfo($file);
$image = null;
switch (strtolower($info['extension'])) {
case 'gif':
$image = imagecreatefromgif($file);
break;
case 'jpg':
case 'jpeg':
$image = imagecreatefromjpeg($file);
break;
case 'png':
$image = imagecreatefrompng($file);
break;
default:
break;
}
if ($image == null)
return [];
else
return [imagesx($image), imagesy($image)];
}
/**
* 文件和图片管理action使用
* @param $allowFiles
* @param $listSize
* @param $path
* @return array
*/
protected function manage($allowFiles, $listSize, $path)
{
$allowFiles = substr(str_replace('.', '|', join('', $allowFiles)), 1);
/* 获取参数 */
$size = isset($_GET['size']) ? $_GET['size'] : $listSize;
$start = isset($_GET['start']) ? $_GET['start'] : 0;
$end = $start + $size;
/* 获取文件列表 */
$path = $this->webroot . (substr($path, 0, 1) == '/' ? '' : '/') . $path;
$files = $this->getFiles($path, $allowFiles);
if (!count($files)) {
$result = [
'state' => 'no match file',
'list' => [],
'start' => $start,
'total' => count($files),
];
return $result;
}
/* 获取指定范围的列表 */
$len = count($files);
for ($i = min($end, $len) - 1, $list = []; $i < $len && $i >= 0 && $i >= $start; $i--) {
$list[] = $files[$i];
}
/* 返回数据 */
$result = [
'state' => 'SUCCESS',
'list' => $list,
'start' => $start,
'total' => count($files),
];
return $result;
}
/**
* 遍历获取目录下的指定类型的文件
* @param $path
* @param $allowFiles
* @param array $files
* @return array|null
*/
protected function getFiles($path, $allowFiles, &$files = [])
{
if (!is_dir($path)) return null;
if (in_array(basename($path), $this->ignoreDir)) return null;
if (substr($path, strlen($path) - 1) != '/') $path .= '/';
$handle = opendir($path);
//baseUrl用于兼容使用alias的二级目录部署方式
$baseUrl = Yii::$app->request->baseUrl;
while (false !== ($file = readdir($handle))) {
if ($file != '.' && $file != '..') {
$path2 = $path . $file;
if (is_dir($path2)) {
$this->getFiles($path2, $allowFiles, $files);
} else {
if ($this->action->id == 'list-image' && $this->thumbnail) {
$pat = "/\_thumbnail\.(" . $allowFiles . ")$/i";
} else {
$pat = "/\.(" . $allowFiles . ")$/i";
}
if (preg_match($pat, $file)) {
$files[] = [
'url' => $baseUrl . substr($path2, strlen($this->webroot)),
'mtime' => filemtime($path2)
];
}
}
}
}
return $files;
}
/**
* 最终显示结果,自动输出 JSONP 或者 JSON
* @param array $result
* @return array
*/
protected function show($result)
{
$callback = Yii::$app->request->get('callback', null);
if ($callback && is_string($callback)) {
Yii::$app->response->format = yii\web\Response::FORMAT_JSONP;
return [
'callback' => $callback,
'data' => $result
];
}
Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
return $result;
}
}