Initial project files: BESCMS full source

This commit is contained in:
bes
2026-08-13 23:37:46 +08:00
parent fa6cddb540
commit 2e26f85723
2166 changed files with 396625 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+289
View File
@@ -0,0 +1,289 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Attachment extends \Phpcmf\Common {
public $type;
public $path;
public $load_file;
public function __construct() {
parent::__construct();
$this->type = [
0 => [
'name' => dr_lang('本地磁盘'),
],
];
$this->path = FCPATH.'ThirdParty/Storage/';
$local = dr_dir_map($this->path, 1);
$this->load_file = [];
foreach ($local as $dir) {
if (is_file($this->path.$dir.'/App.php')) {
$cfg = require $this->path.$dir.'/App.php';
if ($cfg['id']) {
$this->load_file[] = $this->path.$dir.'/Config.html';
$this->type[$cfg['id']] = $cfg;
}
}
}
}
public function index() {
$data = is_file(WRITEPATH.'config/system.php') ? require WRITEPATH.'config/system.php' : [];
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$image = \Phpcmf\Service::L('input')->post('image');
$save = [
'SYS_ATTACHMENT_SAFE' => (int)$post['SYS_ATTACHMENT_SAFE'],
'SYS_ATTACHMENT_GUEST' => (int)$post['SYS_ATTACHMENT_GUEST'],
'SYS_ATTACHMENT_CF' => (int)$post['SYS_ATTACHMENT_CF'],
'SYS_ATTACHMENT_REL' => (int)$post['SYS_ATTACHMENT_REL'],
'SYS_ATTACHMENT_DB' => (int)$post['SYS_ATTACHMENT_DB'],
'SYS_ATTACHMENT_PAGESIZE' => (int)$post['SYS_ATTACHMENT_PAGESIZE'],
'SYS_ATTACHMENT_URL' => $post['SYS_ATTACHMENT_URL'],
'SYS_ATTACHMENT_PATH' => addslashes($post['SYS_ATTACHMENT_PATH']),
'SYS_ATTACHMENT_SAVE_TYPE' => intval($post['SYS_ATTACHMENT_SAVE_TYPE']),
'SYS_ATTACHMENT_DOWN_REMOTE' => intval($post['SYS_ATTACHMENT_DOWN_REMOTE']),
'SYS_ATTACHMENT_DOWN_SIZE' => intval($post['SYS_ATTACHMENT_DOWN_SIZE']),
'SYS_ATTACHMENT_SAVE_DIR' => addslashes($post['SYS_ATTACHMENT_SAVE_DIR']),
'SYS_ATTACHMENT_SAVE_ID' => intval($post['SYS_ATTACHMENT_SAVE_ID']),
'SYS_AVATAR_URL' => $image['avatar_url'],
'SYS_AVATAR_PATH' => addslashes($image['avatar_path']),
];
if ($image['cache_path']) {
if ($save['SYS_ATTACHMENT_PATH'] && $image['cache_path'] == $save['SYS_ATTACHMENT_PATH']) {
$this->_json(0, dr_lang('附件上传目录不能与缩略图存储目录相同'));
} elseif ($save['SYS_AVATAR_PATH'] && $image['cache_path'] == $save['SYS_AVATAR_PATH']) {
$this->_json(0, dr_lang('头像存储目录不能与缩略图存储目录相同'));
}
}
$save['cache_path'] = $image['cache_path'];
foreach (['SYS_ATTACHMENT_PATH' => '附件上传', 'SYS_AVATAR_PATH' => '头像上传', 'cache_path' => '缩略图上传'] as $key => $name) {
if (isset($save[$key]) && $save[$key] &&
(strpos($save[$key], 'config') !== false || strpos($save[$key], CONFIGPATH) !== false)) {
$this->_json(0, dr_lang('%s目录不能包含config目录', $name));
}
}
unset($save['cache_path']);
\Phpcmf\Service::M('System')->save_config($data, $save);
unset($image['avatar_url'], $image['avatar_path']);
// 图片参数
\Phpcmf\Service::M('Site')->config(
SITE_ID,
'watermark',
\Phpcmf\Service::L('input')->post('watermark')
);
$image = \Phpcmf\Service::L('input')->post('image');
unset($image['avatar_url'], $image['avatar_path']);
\Phpcmf\Service::M('site')->config(SITE_ID, 'image', $image);
\Phpcmf\Service::L('input')->system_log('设置附件参数');
// 自动更新缓存
\Phpcmf\Service::M('cache')->sync_cache('');
$this->_json(1, dr_lang('操作成功'));
}
$page = intval(\Phpcmf\Service::L('input')->get('page'));
$site = \Phpcmf\Service::M('Site')->config(SITE_ID);
$locate = [
'left-top' => '左上',
'center-top' => '中上',
'right-top' => '右上',
'left-middle' => '左中',
'center-middle' => '正中',
'right-middle' => '右中',
'left-bottom' => '左下',
'center-bottom' => '中下',
'right-bottom' => '右下',
];
$image = $site['image'];
$image['avatar_url'] = defined('SYS_AVATAR_URL') ? SYS_AVATAR_URL : '';
$image['avatar_path'] = defined('SYS_AVATAR_PATH') ? SYS_AVATAR_PATH : '';
\Phpcmf\Service::V()->assign([
'page' => $page,
'data' => $data,
'form' => dr_form_hidden(['page' => $page]),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'附件设置' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-folder'],
'存储策略' => [\Phpcmf\Service::L('Router')->class.'/remote_index', 'fa fa-cloud'],
'help' => [359],
]
),
'image' => $image,
'locate' => $locate,
'waterfile' => dr_file_map(WRITEPATH.'watermark/', 1),
'watermark' => $site['watermark'],
'remote' => \Phpcmf\Service::C()->get_cache('attachment'),
]);
\Phpcmf\Service::V()->display('attachment_index.html');
}
public function remote_index() {
\Phpcmf\Service::V()->assign([
'list' => \Phpcmf\Service::M()->table('attachment_remote')->getAll(),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'附件设置' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-folder'],
'存储策略' => [\Phpcmf\Service::L('Router')->class.'/remote_index', 'fa fa-cloud'],
'添加' => [\Phpcmf\Service::L('Router')->class.'/add', 'fa fa-plus'],
'help' => [88],
]
),
]);
\Phpcmf\Service::V()->display('attachment_remote.html');
}
public function add() {
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data', true);
$rt = \Phpcmf\Service::M()->table('attachment_remote')->insert([
'type' => intval($data['type']),
'name' => (string)$data['name'],
'url' => trim((string)$data['url']),
'value' => dr_array2string($data['value']),
]);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
// 自动更新缓存
\Phpcmf\Service::M('cache')->sync_cache('attachment');
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'附件设置' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-folder'],
'存储策略' => [\Phpcmf\Service::L('Router')->class.'/remote_index', 'fa fa-cloud'],
'添加' => [\Phpcmf\Service::L('Router')->class.'/add', 'fa fa-plus'],
'help' => [88],
]
),
]);
\Phpcmf\Service::V()->display('attachment_add.html');
}
public function edit() {
$id = intval($_GET['id']);
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data', true);
$rt = \Phpcmf\Service::M()->table('attachment_remote')->update($id,
[
'type' => intval($data['type']),
'name' => (string)$data['name'],
'url' => trim((string)$data['url']),
'value' => dr_array2string($data['value']),
]
);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
// 自动更新缓存
\Phpcmf\Service::M('cache')->sync_cache('attachment');
$this->_json(1, dr_lang('操作成功'));
}
$data = \Phpcmf\Service::M()->table('attachment_remote')->get($id);
$data['value'] = dr_string2array($data['value']);
$data['value'] = $data['value'][intval($data['type'])];
\Phpcmf\Service::V()->assign([
'data' => $data,
'form' => dr_form_hidden(),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'附件设置' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-folder'],
'存储策略' => [\Phpcmf\Service::L('Router')->class.'/remote_index', 'fa fa-cloud'],
'添加' => [\Phpcmf\Service::L('Router')->class.'/add', 'fa fa-plus'],
'修改' => ['hide:'.\Phpcmf\Service::L('Router')->class.'/edit', 'fa fa-edit'],
'help' => [88],
]
),
]);
\Phpcmf\Service::V()->display('attachment_add.html');
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
\Phpcmf\Service::M()->table('attachment_remote')->deleteAll($ids);
\Phpcmf\Service::L('input')->system_log('批量删除远程附件策略: '. implode(',', $ids));
// 自动更新缓存
\Phpcmf\Service::M('cache')->sync_cache('attachment');
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 上传字体文件或图片
public function upload_index() {
$at = dr_safe_filename($_GET['at']);
if ($at == 'font') {
$rt = \Phpcmf\Service::L('upload')->upload_file([
'save_name' => 'null',
'save_path' => WRITEPATH.'watermark/',
'form_name' => 'file_data',
'file_exts' => ['ttf'],
'file_size' => 50 * 1024 * 1024,
'attachment' => [
'value' => [
'path' => 'null'
]
],
]);
} else {
$rt = \Phpcmf\Service::L('upload')->upload_file([
'save_name' => 'null',
'save_path' => WRITEPATH.'watermark/',
'form_name' => 'file_data',
'file_exts' => ['png', 'jpg', 'jpeg'],
'file_size' => 10 * 1024 * 1024,
'attachment' => [
'value' => [
'path' => 'null'
]
],
]);
}
if (!$rt['code']) {
exit(dr_array2string($rt));
}
$this->_json(1, dr_lang('上传成功'));
}
}
+782
View File
@@ -0,0 +1,782 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 附件
class Attachments extends \Phpcmf\Table {
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'附件管理' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-folder'],
'已归档的附件' => [\Phpcmf\Service::L('Router')->class.'/db_index', 'fa fa-folder'],
'未归档的附件' => [\Phpcmf\Service::L('Router')->class.'/unused_index', 'fa fa-folder-o'],
'变更储存策略' => ['add:'.\Phpcmf\Service::L('Router')->class.'/remote_edit', 'fa fa-edit', '500px', '400px'],
'help' => [356],
]
)
]);
}
// 附件目录(资源管理器)
public function index() {
$rel = $this->_dir_rel_path(\Phpcmf\Service::L('input')->get('path'));
$listing = $this->_dir_listing($rel);
if ($listing === null) {
$rel = '';
$listing = $this->_dir_listing($rel);
}
$p = [
'size' => 9999,
'exts' => '*',
'count' => 20,
'attachment' => 0,
'image_reduce' => 0,
'chunk' => 10 * 1024 * 1024,
];
$upload = [
'url' => dr_web_prefix(SELF.'?c='.\Phpcmf\Service::L('Router')->class.'&m=dir_upload')
.'&siteid='.SITE_ID,
'param' => $p,
];
$uriprefix = trim(APP_DIR.'/'.\Phpcmf\Service::L('Router')->class, '/');
$parent_rel = '';
if ($listing['rel'] !== '') {
$norm = str_replace('\\', '/', $listing['rel']);
$d = dirname($norm);
$parent_rel = ($d === '.' || $d === '') ? '' : str_replace('\\', '/', $d);
}
\Phpcmf\Service::V()->assign([
'dir' => IS_DEV ? SYS_UPLOAD_PATH : dr_safe_replace_path(SYS_UPLOAD_PATH),
'url' => SYS_UPLOAD_URL,
'rel' => $listing['rel'],
'parent_rel' => $parent_rel,
'dirs' => $listing['dirs'],
'files' => $listing['files'],
'breadcrumb' => $this->_dir_breadcrumb($listing['rel']),
'upload' => $upload,
'uriprefix' => $uriprefix,
'dir_delete_url' => dr_url($uriprefix.'/dir_delete'),
'dir_mkdir_url' => dr_url($uriprefix.'/dir_mkdir'),
'dir_replace_url' => dr_url($uriprefix.'/dir_replace'),
'dir_folder_size_url' => dr_url($uriprefix.'/dir_folder_size'),
'dir_js' => [
'confirm_del' => addslashes(dr_lang('你确定要删除它们吗?')),
'mkdir_title' => addslashes(dr_lang('新建文件夹')),
'name_empty' => addslashes(dr_lang('名称不能为空')),
'upload_fail' => addslashes(dr_lang('上传失败')),
],
'meta_title' => dr_lang('附件目录'),
]);
\Phpcmf\Service::V()->display('attachment_dir.html');
}
/**
* AJAX:递归统计文件夹及子目录文件总大小
*/
public function dir_folder_size() {
if (function_exists('set_time_limit')) {
@set_time_limit(300);
}
$rel = $this->_dir_rel_path(\Phpcmf\Service::L('input')->get('path'));
if ($rel === '') {
$this->_json(0, dr_lang('参数错误'));
}
list($ok, $abs, $r) = $this->_dir_safe($rel);
if (!$ok || !is_dir($abs)) {
$this->_json(0, dr_lang('目录不存在'));
}
$root = rtrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, SYS_UPLOAD_PATH), DIRECTORY_SEPARATOR);
$rootReal = realpath($root);
if ($rootReal === false) {
$this->_json(0, dr_lang('目录无效或不存在'));
}
$bytes = $this->_dir_tree_size($abs, $rootReal);
$this->_json(1, 'ok', [
'size' => $bytes,
'size_text' => dr_format_file_size($bytes),
]);
}
/**
* 递归统计目录下所有文件字节(不跟随符号链接)
*/
protected function _dir_tree_size($absDir, $rootReal) {
$total = 0;
if (!is_dir($absDir)) {
return 0;
}
$absDir = rtrim($absDir, DIRECTORY_SEPARATOR);
if (is_link($absDir)) {
return 0;
}
if ($fp = @opendir($absDir)) {
while (($name = readdir($fp)) !== false) {
if ($name === '.' || $name === '..') {
continue;
}
$sub = $absDir.DIRECTORY_SEPARATOR.$name;
if (is_link($sub)) {
continue;
}
if (is_file($sub)) {
$sz = @filesize($sub);
if ($sz !== false) {
$total += $sz;
}
} elseif (is_dir($sub)) {
$rp = realpath($sub);
if ($rp !== false && $this->_dir_under_root($rootReal, $rp)) {
$total += $this->_dir_tree_size($rp, $rootReal);
}
}
}
closedir($fp);
}
return $total;
}
/**
* 附件目录内上传(写入当前文件夹,并走附件归档)
*/
public function dir_upload() {
if (!IS_POST) {
$this->_json(0, dr_lang('请求错误'));
}
$rel = $this->_dir_rel_path(\Phpcmf\Service::L('input')->post('path'));
list($ok, $abs, $r) = $this->_dir_safe($rel);
if (!$ok || !is_dir($abs)) {
$this->_json(0, dr_lang('目录无效或不存在'));
}
$cfg = [
'form_name' => 'file_data',
'file_exts' => ['*'],
'file_size' => 9999 * 1024 * 1024,
'attachment' => \Phpcmf\Service::M('Attachment')->get_attach_info(0),
'watermark' => 0,
'save_name' => 'null',
];
if ($r !== '') {
$cfg['path'] = $r;
}
$rt = \Phpcmf\Service::L('upload')->upload_file($cfg);
if (!$rt['code']) {
exit(dr_array2string($rt));
}
$data = [];
if (defined('SYS_ATTACHMENT_CF') && SYS_ATTACHMENT_CF && $rt['data']['md5']) {
$att = \Phpcmf\Service::M()->table('attachment')
->where('uid', $this->uid)
->where('filemd5', $rt['data']['md5'])
->where('fileext', $rt['data']['ext'])
->where('filesize', $rt['data']['size'])
->getRow();
if ($att) {
$storage = new \Phpcmf\Library\Storage($this);
$storage->delete(\Phpcmf\Service::M('Attachment')->get_attach_info(0), $rt['data']['file']);
$rt['data'] = $this->get_attachment($att['id']);
if ($rt['data']) {
$rt['data']['name'] = $rt['data']['filename'];
}
$data = dr_return_data($att['id'], 'ok');
}
}
if (!$data) {
$data = \Phpcmf\Service::M('Attachment')->save_data($rt['data']);
if (!$data['code']) {
exit(dr_array2string($data));
}
}
exit(dr_array2string(['code' => 1, 'msg' => dr_lang('上传成功'), 'id' => $data['code'], 'info' => $rt['data']]));
}
/**
* 覆盖重传指定文件(扩展名须一致)
*/
public function dir_replace() {
if (!IS_POST) {
$this->_json(0, dr_lang('请求错误'));
}
$file = isset($_FILES['file_data']) ? $_FILES['file_data'] : null;
$maxBytes = 9999 * 1024 * 1024;
if ($file && !empty($file['size']) && $file['size'] > $maxBytes) {
$this->_json(0, dr_lang('文件大小超出网站限制'));
}
$rel = $this->_dir_rel_path(\Phpcmf\Service::L('input')->post('replace'));
if ($rel === '') {
$this->_json(0, dr_lang('参数错误'));
}
list($ok, $abs, $r) = $this->_dir_safe($rel);
if (!$ok || !is_file($abs)) {
$this->_json(0, dr_lang('文件不存在'));
}
$name = basename(str_replace('\\', '/', $abs));
$oldExt = strpos($name, '.') !== false ? strtolower(trim(strrchr($name, '.'), '.')) : '';
$cfg = [
'form_name' => 'file_data',
'file_exts' => $oldExt !== '' ? [$oldExt] : ['*'],
'file_name' => $abs,
];
$rt = \Phpcmf\Service::L('upload')->update_file($cfg);
if (!$rt['code']) {
exit(dr_array2string($rt));
}
exit(dr_array2string(['code' => 1, 'msg' => dr_lang('上传成功')]));
}
/**
* 删除所选文件或空目录
*/
public function dir_delete() {
if (!IS_POST) {
$this->_json(0, dr_lang('请求错误'));
}
$paths = \Phpcmf\Service::L('input')->post('paths');
if (!$paths || !is_array($paths)) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
foreach ($paths as $p) {
$rel = $this->_dir_rel_path($p);
if ($rel === '') {
$this->_json(0, dr_lang('禁止删除附件根目录'));
}
list($ok, $abs, $r) = $this->_dir_safe($rel);
if (!$ok) {
continue;
}
if (is_file($abs)) {
if (!@unlink($abs)) {
$this->_json(0, dr_lang('文件删除失败'));
}
} elseif (is_dir($abs)) {
$items = @scandir($abs);
$left = $items ? array_diff($items, ['.', '..']) : [];
if ($left) {
$this->_json(0, dr_lang('目录非空,无法删除'));
}
if (!@rmdir($abs)) {
$this->_json(0, dr_lang('目录删除失败'));
}
}
}
$this->_json(1, dr_lang('操作成功'));
}
/**
* 在当前目录下新建文件夹
*/
public function dir_mkdir() {
if (!IS_POST) {
$this->_json(0, dr_lang('请求错误'));
}
$rel = $this->_dir_rel_path(\Phpcmf\Service::L('input')->post('path'));
$name = trim((string) \Phpcmf\Service::L('input')->post('name'));
$name = dr_safe_filename($name);
if ($name === '' || strpos($name, '.') === 0) {
$this->_json(0, dr_lang('名称不规范'));
}
list($ok, $parentAbs, $r) = $this->_dir_safe($rel);
if (!$ok || !is_dir($parentAbs)) {
$this->_json(0, dr_lang('当前目录无效'));
}
$newAbs = rtrim($parentAbs, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$name;
if (file_exists($newAbs)) {
$this->_json(0, dr_lang('已存在同名文件或目录'));
}
if (!dr_mkdirs($newAbs)) {
$this->_json(0, dr_lang('目录创建失败'));
}
$this->_json(1, dr_lang('操作成功'));
}
/**
* 规范化相对路径(相对 SYS_UPLOAD_PATH
* 按段解析,禁止路径跳出上传根(..),避免简单替换字符串被绕过
*/
protected function _dir_rel_path($raw) {
$raw = (string) $raw;
if ($raw === '' || strpos($raw, "\0") !== false) {
return '';
}
$raw = str_replace('\\', '/', $raw);
$raw = str_replace(["\r", "\n", '<', '>', '{', '}'], '', $raw);
$raw = trim($raw, '/');
if ($raw === '') {
return '';
}
$parts = explode('/', $raw);
$out = [];
foreach ($parts as $p) {
if ($p === '' || $p === '.') {
continue;
}
if ($p === '..') {
if (empty($out)) {
return '';
}
array_pop($out);
continue;
}
$p = trim($p);
if ($p === '' || $p === '.' || $p === '..') {
continue;
}
$out[] = $p;
}
return implode('/', $out);
}
/**
* 是否位于上传根目录之下
*/
protected function _dir_under_root($rootReal, $candidate) {
$root = strtolower(str_replace('\\', '/', rtrim($rootReal, '/\\')));
$path = strtolower(str_replace('\\', '/', $candidate));
return $path === $root || strpos($path, $root.'/') === 0;
}
/**
* 解析安全绝对路径
*/
protected function _dir_safe($rel) {
$rel = $this->_dir_rel_path($rel);
$root = rtrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, SYS_UPLOAD_PATH), DIRECTORY_SEPARATOR);
if (!is_dir($root)) {
return [false, '', ''];
}
$rootReal = realpath($root);
if ($rootReal === false) {
return [false, '', ''];
}
if ($rel === '') {
return [true, $rootReal.DIRECTORY_SEPARATOR, ''];
}
$sub = str_replace('/', DIRECTORY_SEPARATOR, $rel);
$full = $rootReal.DIRECTORY_SEPARATOR.$sub;
if (is_file($full) || is_dir($full)) {
$rp = realpath($full);
if ($rp !== false && $this->_dir_under_root($rootReal, $rp)) {
return [true, $rp, $rel];
}
return [false, '', ''];
}
return [false, '', ''];
}
/**
* 列出目录内容
*/
protected function _dir_listing($rel) {
list($ok, $abs, $r) = $this->_dir_safe($rel);
if (!$ok || !is_dir($abs)) {
return null;
}
$dirs = [];
$files = [];
if ($fp = @opendir($abs)) {
while (($name = readdir($fp)) !== false) {
if ($name === '.' || $name === '..' || $name === '.DS_Store') {
continue;
}
if (strtolower(substr($name, -4)) === '.php') {
continue;
}
$full = $abs.DIRECTORY_SEPARATOR.$name;
$childRel = $r === '' ? $name : $r.'/'.$name;
if (is_dir($full)) {
$dirs[] = [
'name' => $name,
'path' => $childRel,
'path_esc' => htmlspecialchars($childRel, ENT_QUOTES, 'UTF-8'),
'mtime' => filemtime($full),
];
} elseif (is_file($full)) {
$ext = strtolower(trim(strrchr($name, '.'), '.'));
$files[] = [
'name' => $name,
'path' => $childRel,
'path_esc' => htmlspecialchars($childRel, ENT_QUOTES, 'UTF-8'),
'size' => filesize($full),
'mtime' => filemtime($full),
'ext' => $ext,
'url' => SYS_UPLOAD_URL.str_replace('\\', '/', $childRel),
'is_image' => dr_is_image($ext),
'is_mp4' => $ext === 'mp4',
];
}
}
closedir($fp);
}
usort($dirs, function ($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
usort($files, function ($a, $b) {
return strcasecmp($a['name'], $b['name']);
});
return [
'rel' => $r,
'dirs' => $dirs,
'files' => $files,
];
}
/**
* 面包屑
*/
protected function _dir_breadcrumb($rel) {
$crumbs = [['name' => dr_lang('附件根目录'), 'path' => '']];
if ($rel === '') {
return $crumbs;
}
$parts = explode('/', $rel);
$acc = '';
foreach ($parts as $p) {
if ($p === '') {
continue;
}
$acc = $acc === '' ? $p : $acc.'/'.$p;
$crumbs[] = ['name' => $p, 'path' => $acc];
}
return $crumbs;
}
// 已归档管理
public function db_index() {
$field = [
'uid' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'uid',
'name' => '账号',
],
'related' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'related',
'name' => dr_lang('附件归属'),
],
'fileext' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'fileext',
'name' => dr_lang('扩展名'),
],
'filename' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'filename',
'name' => dr_lang('附件名称'),
],
'attachment' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'attachment',
'name' => dr_lang('附件路径'),
],
];
$remote = (int)$_GET['remote'];
$where_list = 'id in (select id from '.\Phpcmf\Service::M()->dbprefix('attachment').' where siteid='.SITE_ID.')';
$remote && $where_list.= ' and `remote`='.$remote;
$this->_init([
'table' => 'attachment_data',
'field' => $field,
'order_by' => 'id desc',
'where_list' => $where_list,
'date_field' => 'inputtime',
]);
$this->_List();
// 快捷上传字段参数
$p = [
'size' => 9999,
'exts' => '*',
'count' => 20,
'attachment' => $remote,
'image_reduce' => 0,
'chunk' => 10 * 1024 * 1024,
];
$upload = [
'url' => dr_web_prefix(SELF.'?c=api&token='.dr_get_csrf_token())
.'&siteid='.SITE_ID.'&m=upload&p='.dr_authcode($p, 'ENCODE'),
'param' => $p,
'back' => dr_now_url(),
];
\Phpcmf\Service::V()->assign([
'field' => $field,
'table' => 'data',
'remote' => \Phpcmf\Service::M()->table('attachment_remote')->getAll(0, 'id'),
'upload' => $upload,
]);
\Phpcmf\Service::V()->display('attachment_admin.html');
}
// 未归档的附件
public function unused_index() {
$field = [
'author' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'author',
'name' => dr_lang('账号'),
],
'fileext' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'fileext',
'name' => dr_lang('扩展名'),
],
'uid' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'uid',
'name' => 'uid',
],
];
$remote = (int)$_GET['remote'];
$where_list = 'siteid='.SITE_ID;
$remote && $where_list.= ' and `remote`='.$remote;
$this->_init([
'table' => 'attachment_unused',
'field' => $field,
'order_by' => 'id desc',
'where_list' => $where_list,
'date_field' => 'inputtime',
]);
$this->_List();
\Phpcmf\Service::V()->assign([
'field' => $field,
'table' => 'unused',
'remote' => \Phpcmf\Service::M()->table('attachment_remote')->getAll(0, 'id'),
]);
\Phpcmf\Service::V()->display('attachment_admin.html');
}
public function remote_edit() {
if (IS_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
if ($post['o'] == $post['n']) {
$this->_json(0, dr_lang('储存策略不能相同'));
}
\Phpcmf\Service::M()->table('attachment_unused')->where('remote', intval($post['o']))->update(0, [
'remote' => intval($post['n'])
]);
\Phpcmf\Service::M()->table('attachment_data')->where('remote', intval($post['o']))->update(0, [
'remote' => intval($post['n'])
]);
dr_dir_delete(WRITEPATH.'attach');
dr_mkdirs(WRITEPATH.'attach');
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'remote' => \Phpcmf\Service::M()->table('attachment_remote')->getAll(0, 'id'),
]);
\Phpcmf\Service::V()->display('attachment_remote_edit.html');
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$table = \Phpcmf\Service::L('input')->post('table');
$table != 'data' && $table = 'unused';
$data = \Phpcmf\Service::M()->db->table('attachment_'.$table)->whereIn('id', $ids)->get()->getResultArray();
if (!$data) {
$this->_json(0, dr_lang('所选附件不存在'));
}
foreach ($data as $t) {
$rt = \Phpcmf\Service::M('attachment')->_delete_file($t);
if (!$rt['code']) {
return dr_return_data(0, $rt['msg']);
}
}
$this->_json(1, dr_lang('操作成功'));
}
// 强制归档
public function edit() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$data = \Phpcmf\Service::M()->db->table('attachment_unused')->whereIn('id', $ids)->get()->getResultArray();
if (!$data) {
$this->_json(0, dr_lang('所选附件不存在'));
}
$related = 'Save';
foreach ($data as $t) {
// 更新主索引表
\Phpcmf\Service::M()->table('attachment')->update($t['id'], array(
'related' => $related
));
\Phpcmf\Service::M()->table('attachment_data')->insert(array(
'id' => $t['id'],
'uid' => $t['uid'],
'remote' => $t['remote'],
'author' => $t['author'],
'related' => $related,
'fileext' => $t['fileext'],
'filesize' => $t['filesize'],
'filename' => $t['filename'],
'inputtime' => $t['inputtime'],
'attachment' => $t['attachment'],
'attachinfo' => '',
));
// 删除未归档附件
\Phpcmf\Service::M()->table('attachment_unused')->delete($t['id']);
}
$this->_json(1, dr_lang('操作成功'));
}
// 变更储存策略
public function type_edit() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$rid = intval(\Phpcmf\Service::L('input')->post('remote'));
if ($rid < 0) {
$this->_json(0, dr_lang('你还没有选择储存策略'));
}
$table = \Phpcmf\Service::L('input')->post('table');
$table != 'data' && $table = 'unused';
\Phpcmf\Service::M()->table('attachment_'.$table)->where_in('id', $ids)->update(0, [
'remote' => $rid
]);
dr_dir_delete(WRITEPATH.'attach');
dr_mkdirs(WRITEPATH.'attach');
$this->_json(1, dr_lang('操作成功'));
}
// 重新上传附件
public function file_edit() {
$id = \Phpcmf\Service::L('input')->get('id');
if (!$id) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$data = $this->get_attachment($id, true);
if (!$data) {
$this->_json(0, dr_lang('附件信息不存在'));
}
\Phpcmf\Service::V()->assign([
'data' => $data,
]);
\Phpcmf\Service::V()->display('attachment_upload.html');
}
// 重新上传附件
public function upload_edit() {
$id = \Phpcmf\Service::L('input')->get('id');
if (!$id) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$data = $this->get_attachment($id, true);
if (!$data) {
$this->_json(0, dr_lang('附件信息不存在'));
}
$rt = \Phpcmf\Service::L('upload')->upload_file([
'save_name' => str_replace('.'.$data['fileext'], '', basename($data['attachment'])),
'path' => dirname($data['attachment']),
'form_name' => 'file_data',
'file_exts' => [$data['fileext']],
'file_size' => 1000 * 1024 * 1024,
'attachment' => \Phpcmf\Service::M('Attachment')->get_attach_info($data['remote']),
]);
if (!$rt['code']) {
exit(dr_array2string($rt));
}
\Phpcmf\Service::M()->table('attachment_data')->update($id, ['filesize' => $rt['data']['size']]);
\Phpcmf\Service::M()->table('attachment_unused')->update($id, ['filesize' => $rt['data']['size']]);
$this->_json(1, dr_lang('上传成功'), $rt['data']);
}
}
+631
View File
@@ -0,0 +1,631 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 缓存更新
class Cache extends \Phpcmf\Common {
public function index() {
$list = [
['系统配置缓存', 'update_cache'],
['表或表字段异常时,更新数据结构', 'update_db'],
['附件地址未更新时,更新附件缓存', 'update_attachment'],
['清理自定义路由缓存', 'update_rewrite_routes'],
['手动清理缩略图文件(如果生成过静态页面,请慎用)', 'update_thumb'],
['清理全部系统日志、操作日志、邮件日志、短信日志、慢查询日志等', 'update_log'],
];
if (dr_is_app('ueditor') && is_file(CMSPATH.'Field/Ueditor.php')) {
$list[] = ['生成百度编辑器到其他域名', 'update_ueditor'];
}
if (is_file(APPSPATH.'Module/install.lock') && is_file(APPSPATH.'Module/Config/Content.php')) {
if (is_dir(APPSPATH.'Cms')) {
// 已存在 Cms 目录,直接删除旧的 Module 目录
dr_dir_delete(APPSPATH.'Module', true);
if (is_dir(APPSPATH.'Module')) {
$this->_admin_msg(0, dr_lang('请手动删除目录[%s]', APPSPATH.'Module'));
} else {
$this->_admin_msg(1, dr_lang('CMS迁移成功,请更新系统缓存'), dr_now_url());
}
} else {
// 重命名目录 Module -> Cms,判断是否重命名失败
@rename(APPSPATH.'Module', APPSPATH.'Cms');
if (is_dir(APPSPATH.'Module')) {
$this->_admin_msg(0, dr_lang('请手动将目录[%s]重命名为[%s]', APPSPATH.'Module', APPSPATH.'Cms'));
} else {
$this->_admin_msg(1, dr_lang('CMS迁移成功,请更新系统缓存'), dr_now_url());
}
}
} elseif (is_file(APPSPATH.'Cms/install.lock') && is_file(APPSPATH.'Cms/Models/Module.php')) {
if (is_file(APPSPATH.'Module/Config/Content.php')) {
// 已存在 Cms 目录,直接删除旧的 Module 目录
dr_dir_delete(APPSPATH.'Module', true);
if (is_dir(APPSPATH.'Module')) {
$this->_admin_msg(0, dr_lang('请手动将目录[%s]删除', APPSPATH.'Module'));
}
}
$need = false;
foreach ([APPSPATH.'Cms/Models/', APPSPATH.'Cms/Libraries/'] as $path) {
if (!is_dir($path)) {
continue;
}
$files = dr_file_map($path);
if (!$files) {
continue;
}
foreach ($files as $file) {
if (substr($file, -4) !== '.php' || !is_file($path.$file)) {
continue;
}
$code = file_get_contents($path.$file);
if ($code && (strpos($code, 'Phpcmf\\Model\\Module') !== false || strpos($code, 'Phpcmf\\Library\\Module') !== false)) {
$need = true;
break 2;
}
}
}
if ($need) {
$error = [];
$replace = [
'Phpcmf\\Model\\Module' => 'Phpcmf\\Model\\Cms',
'Phpcmf\\Library\\Module' => 'Phpcmf\\Library\\Cms',
];
foreach ([APPSPATH.'Cms/Models/', APPSPATH.'Cms/Libraries/'] as $path) {
if (!is_dir($path)) {
continue;
}
$files = dr_file_map($path);
if (!$files) {
continue;
}
foreach ($files as $file) {
if (substr($file, -4) !== '.php') {
continue;
}
$filepath = $path.$file;
if (!is_file($filepath)) {
continue;
}
$code = file_get_contents($filepath);
if (!$code) {
continue;
}
$new = str_replace(array_keys($replace), array_values($replace), $code);
if ($new === $code) {
continue;
}
if (@file_put_contents($filepath, $new) === false) {
$error[] = $filepath;
}
}
}
if ($error) {
$this->_admin_msg(0, dr_lang('文件无法写入'), '', implode('<br>', $error));
} else {
$this->_admin_msg(1, dr_lang('CMS命名空间迁移成功,请更新系统缓存'), dr_now_url());
}
}
}
$sync = [];
$local = \Phpcmf\Service::Apps();
foreach ($local as $dir => $path) {
if (is_file($path.'Config/Cache.html')) {
$sync[] = $path.'Config/Cache.html';
}
}
\Phpcmf\Service::V()->assign([
'sync' => $sync,
'list' => $list,
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'系统更新' => ['cache/index', 'fa fa-refresh'],
'系统体检' => ['check/index', 'fa fa-wrench'],
'help' => [378],
]
),
]);
\Phpcmf\Service::V()->display('cache.html');
}
public function update_index() {
$page = intval($_GET['page']);
$next = dr_url('cache/update_index');
if (!$page) {
file_put_contents(WRITEPATH.'install.lock', SYS_TIME);
if (is_file(WRITEPATH.'update.lock')) {
@unlink(WRITEPATH.'update.lock');
if (is_file(WRITEPATH.'update.lock')) {
$this->_html_msg(0, dr_lang('%s目录请给可写入权限', IS_DEV ? WRITEPATH : 'cache'));
}
}
$this->_html_msg(1, dr_lang('正在更新升级程序'), $next.'&page=1');
}
switch ($page) {
case 1:
$dir = [
WRITEPATH.'cloud/',
WRITEPATH.'watermark/',
];
foreach ($dir as $path) {
if (!is_dir($path)) {
dr_mkdirs($path);
}
if (!dr_check_put_path($path)) {
$this->_html_msg(0, dr_lang('目录创建失败'), '', $path);
}
}
// 移动水印目录
if (is_dir(WEBPATH.'config/watermark/')) {
\Phpcmf\Service::L('file')->copy_dir(WEBPATH.'config/watermark/', WEBPATH.'config/watermark/', WRITEPATH.'watermark/');
}
// 判断public
if (defined('IS_VERSION') && IS_VERSION) {
} else {
// 传统结构时复制目录到根目录去
$path = ROOTPATH.'public/';
if (is_dir($path)) {
\Phpcmf\Service::L('file')->copy_dir($path, $path, ROOTPATH);
dr_dir_delete($path, true);
}
if (is_dir($path)) {
$this->_html_msg(0, dr_lang('目录移动失败'), '', '请手动将['.$path.']下面的文件移动到网站根目录中['.ROOTPATH.'],再删除public目录');
}
}
// 移动头像目录
$path = ROOTPATH.'api/member/';
if (is_dir($path)) {
\Phpcmf\Service::L('file')->copy_dir($path, $path, SYS_UPLOAD_PATH.'member/');
dr_dir_delete($path, true);
}
$this->_html_msg(1, dr_lang('正在升级文件目录结构'), $next.'&page='.($page+1));
break;
case 2:
// 判断模块表
if (!IS_USE_MODULE
&& \Phpcmf\Service::M()->is_table_exists('module')
&& is_file(dr_get_app_dir('module').'/Config/App.php')
) {
// 表示模块表已经操作,手动安装模块
$rs = file_put_contents(dr_get_app_dir('module').'/install.lock', 'fix');
if (!$rs) {
$this->_html_msg(0, dr_lang('目录无法写入'), '', dr_get_app_dir('module'));
}
}
$local = dr_dir_map(APPSPATH, 1); // 搜索本地模块
foreach ($local as $dir) {
if (is_file(APPSPATH.$dir.'/Config/App.php')) {
$file = APPSPATH.$dir.'/Controllers/Search.php';
if (is_file($file)) {
// 替换搜索控制器
$code = file_get_contents($file);
if ($code && strpos($code, '\Phpcmf\Home\Search') !== false) {
file_put_contents($file, str_replace(
['\Phpcmf\Home\Search', '_Module_Search'],
['\Phpcmf\Home\Module', '_Search'],
$code
));
}
}
$file = APPSPATH.$dir.'/Controllers/Recycle.php';
if (is_file($file)) {
// 替换搜索控制器
$code = file_get_contents($file);
if ($code && strpos($code, '_Admin_Recycle_Edit') === false) {
file_put_contents($file, str_replace(
'public function index() {',
' public function edit() {
$this->_Admin_Recycle_Edit();
}
public function index() {
',
$code
));
}
}
}
}
// 升级插件兼容测试
$error = [];
$table_app = [
'module' => 'module',
SITE_ID.'_form' => 'form',
'module_form' => 'mform',
'member_notice' => 'notice',
'member_scorelog' => 'scorelog',
'member_paylog' => 'pay',
'member_explog' => 'explog',
];
$app_name = [
'module' => '建站系统',
'form' => '表单系统',
'mform' => '模块内容表单',
'notice' => '提醒消息',
'pay' => '支付系统',
'scorelog' => '积分系统',
'explog' => '经验值系统',
'member' => '用户系统',
];
foreach ($table_app as $table => $name) {
if (\Phpcmf\Service::M()->is_table_exists($table) && \Phpcmf\Service::M()->table($table)->counts()) {
$cpath = dr_get_app_dir($name);
if (is_dir($cpath)) {
file_put_contents($cpath.'/install.lock', 1);
} else {
$error[] = $app_name[$name];
}
}
}
// 用户系统
if (\Phpcmf\Service::M()->is_table_exists('member_menu') && !dr_is_app('member')) {
$error[] = $app_name['member'];
}
if ($error) {
$this->_html_msg(0, '需要手动安装这些应用插件:'.implode('、', $error).'
<br><br><a href="http://help.xunruicms.com/1104.html" target="_blank">查看解决方案</a><br><br>将以上问题处理之后继续更新此脚本', 0);
}
$this->_html_msg(1, dr_lang('正在升级程序兼容性'), $next.'&page='.($page+1));
break;
case 3:
$prefix = \Phpcmf\Service::M()->prefix;
$db = \Phpcmf\Service::M()->db;
$T = \Phpcmf\Service::M('table');
// 增加长度
$T->edit_field($prefix.'member', 'salt', 'VARCHAR(50)', 'NOT NULL', '随机加密码');
$table = $prefix.'cron';
if (!$db->fieldExists('site', $table)) {
$T->add_field($table, 'site', 'INT(10)', 'NOT NULL', '站点');
}
$table = $prefix.'site';
if (!$db->fieldExists('displayorder', $table)) {
$T->add_field($table, 'displayorder', 'INT(10)', 'DEFAULT NULL', '排序');
}
$table = $prefix.'member_data';
if (!$db->fieldExists('is_email', $table)) {
$T->add_field($table, 'is_email', 'tinyint(1)', 'DEFAULT NULL', '邮箱认证');
}
$table = $prefix.'member_paylog';
if ($db->tableExists($table)) {
if (!$db->fieldExists('site', $table)) {
$T->add_field($table, 'site', 'INT(10)', 'NOT NULL', '站点');
}
if ($db->fieldExists('username', $table)) {
$T->drop_field($table, 'username');
}
if ($db->fieldExists('tousername', $table)) {
$T->drop_field($table, 'tousername');
}
}
$T->edit_field($prefix.'admin_notice', 'to_rid', 'varchar(100)', 'NOT NULL', '指定角色组');
$T->edit_field($prefix.'admin_notice', 'to_uid', 'varchar(100)', 'NOT NULL', '指定管理员');
$table = $prefix.'member_group_verify';
if ($db->tableExists($table) && !$db->fieldExists('price', $table)) {
$T->add_field($table, 'price', 'decimal(10,2)', 'DEFAULT NULL', '已费用');
}
$table = $prefix.'member_scorelog';
if ($db->tableExists($table) && !$db->fieldExists('username', $table)) {
$T->add_field($table, 'username', 'VARCHAR(100)', 'DEFAULT NULL', '');
}
$table = $prefix.'member_notice';
if ($db->tableExists($table) && !$db->fieldExists('mark', $table)) {
$T->add_field($table, 'mark', 'VARCHAR(100)', 'DEFAULT NULL', '');
$T->edit_field($prefix.'member_notice', 'type', 'tinyint(2)', 'unsigned NOT NULL', '类型');
}
$table = $prefix.'member_explog';
if ($db->tableExists($table) && !$db->fieldExists('username', $table)) {
$T->add_field($table, 'username', 'VARCHAR(100)', 'DEFAULT NULL', '');
}
$table = $prefix.'member_oauth';
if ($db->tableExists($table) && !$db->fieldExists('unionid', $table)) {
$T->add_field($table, 'unionid', 'VARCHAR(100)', 'DEFAULT NULL', '');
}
$table = $prefix.'member';
if (!$db->fieldExists('login_attr', $table)) {
$T->add_field($table, 'login_attr', 'VARCHAR(100)', 'DEFAULT NULL', '');
}
$table = $prefix.'member_menu';
if ($db->tableExists($table) && !$db->fieldExists('site', $table)) {
$T->add_field($table, 'site', 'TEXT', 'DEFAULT NULL', '');
}
$table = $prefix.'member_menu';
if ($db->tableExists($table) && !$db->fieldExists('client', $table)) {
$T->add_field($table, 'client', 'TEXT', 'DEFAULT NULL', '');
}
$table = $prefix.'member_level';
if (!$db->tableExists($table)) {
$T->create_table($table, [
'id' => 'smallint(5) unsigned NOT NULL AUTO_INCREMENT',
'gid' => 'smallint(5) unsigned NOT NULL COMMENT \'用户id\'',
'name' => 'varchar(255) NOT NULL COMMENT \'名称\'',
'stars' => 'int(10) NOT NULL COMMENT \'图标\'',
'value' => 'int(10) unsigned NOT NULL COMMENT \'升级值要求\'',
'note' => 'text NOT NULL COMMENT \'备注\'',
'apply' => 'tinyint(1) unsigned NOT NULL COMMENT \'是否允许升级\'',
'setting' => 'text NOT NULL COMMENT \'等级配置\'',
'displayorder' => 'smallint(5) NOT NULL COMMENT \'排序\'',
], [
'PRIMARY KEY (`id`)',
'KEY `value` (`value`)',
'KEY `apply` (`apply`)',
'KEY `gid` (`gid`)',
'KEY `displayorder` (`displayorder`)',
], '用户组级别表');
} else {
$T->edit_field($table, 'stars', 'int(10)', 'unsigned NOT NULL', '图标');
if (!$db->fieldExists('setting', $table)) {
$T->add_field($table, 'setting', 'TEXT', 'DEFAULT NULL', '');
}
if (!$db->fieldExists('displayorder', $table)) {
$T->add_field($table, 'displayorder', 'INT(10)', 'DEFAULT NULL', '排序');
}
}
$table = $prefix.'admin_menu';
if (!$db->fieldExists('site', $table)) {
$T->add_field($table, 'site', 'TEXT', 'DEFAULT NULL', '');
}
$table = $prefix.'admin';
if (!$db->fieldExists('history', $table)) {
$T->add_field($table, 'history', 'TEXT', 'DEFAULT NULL', '');
}
$table = $prefix.'admin_setting';
if (!$db->tableExists($table)) {
$T->create_table($table, [
'name' => 'varchar(50) NOT NULL',
'value' => 'mediumtext NOT NULL',
], [
'PRIMARY KEY (`name`)',
], '系统属性参数表');
}
if (IS_USE_MEMBER) {
$table = $prefix.'member_setting';
if (!$db->tableExists($table)) {
$T->create_table($table, [
'name' => 'varchar(50) NOT NULL',
'value' => 'mediumtext NOT NULL',
], [
'PRIMARY KEY (`name`)',
], '用户属性参数表');
} else {
if ($db->fieldExists('id', $table)) {
// 处理id字段
$data = $db->table('member_setting')->get()->getResultArray();
$T->drop_table($table);
$T->create_table($table, [
'name' => 'varchar(50) NOT NULL',
'value' => 'mediumtext NOT NULL',
], [
'PRIMARY KEY (`name`)',
], '用户属性参数表');
if ($data) {
foreach ($data as $t) {
\Phpcmf\Service::M()->table('member_setting')->replace([
'name' => $t['name'],
'value' => $t['value'],
]);
}
}
}
}
if (!$db->table('member_setting')->where('name', 'auth2')->get()->getRowArray()) {
// 权限数据
\Phpcmf\Service::M()->table('member_setting')->replace([
'name' => 'auth2',
'value' => '{"1":{"public":{"home":{"show":"0","is_category":"0"},"form_public":[],"share_category_public":{"show":"1","add":"1","edit":"1","code":"1","verify":"1","exp":"","score":"","money":"","day_post":"","total_post":""},"category_public":[],"mform_public":"","form":null,"share_category":null,"category":null,"mform":null}}}',
]);
}
}
$table = $prefix.'admin_min_menu';
if (!$db->tableExists($table)) {
$T->create_table($table, [
'id' => 'smallint(5) unsigned NOT NULL AUTO_INCREMENT',
'pid' => "smallint(5) unsigned NOT NULL COMMENT '上级菜单id'",
'name' => "text NOT NULL COMMENT '菜单语言名称'",
'site' => "text NOT NULL COMMENT '站点归属'",
'uri' => "varchar(255) DEFAULT NULL COMMENT 'uri字符串'",
'url' => "varchar(255) DEFAULT NULL COMMENT '外链地址'",
'mark' => "varchar(255) DEFAULT NULL COMMENT '菜单标识'",
'hidden' => "tinyint(1) unsigned DEFAULT NULL COMMENT '是否隐藏'",
'icon' => "varchar(255) DEFAULT NULL COMMENT '图标标示'",
'displayorder' => "int(5) DEFAULT NULL COMMENT '排序值'",
], [
'PRIMARY KEY (`id`)',
'KEY `list` (`pid`)',
'KEY `displayorder` (`displayorder`)',
'KEY `mark` (`mark`)',
'KEY `hidden` (`hidden`)',
'KEY `uri` (`uri`)',
], '后台简化菜单表');
}
// 模块
$is_module = $db->tableExists('module');
if ($is_module) {
$module = \Phpcmf\Service::M()->table('module')->order_by('displayorder ASC,id ASC')->getAll();
// 栏目模型字段修正
$db->table('field')->where('relatedname', 'share-'.SITE_ID)->update(['relatedname' => 'catmodule-share']);
if ($module) {
foreach ($module as $m) {
if (!\Phpcmf\Service::M()->table('field')->where('relatedname', 'module')
->where('relatedid', $m['id'])->where('fieldname', 'author')->counts()) {
$db->table('field')->insert(array(
'name' => '笔名',
'fieldname' => 'author',
'fieldtype' => 'Text',
'relatedid' => $m['id'],
'relatedname' => 'module',
'isedit' => 1,
'ismain' => 1,
'ismember' => 1,
'issystem' => 1,
'issearch' => 1,
'disabled' => 0,
'setting' => dr_array2string(array(
'is_right' => 1,
'option' => array(
'width' => 200, // 表单宽度
'fieldtype' => 'VARCHAR', // 字段类型
'fieldlength' => '255', // 字段长度
'value' => '{name}'
),
'validate' => array(
'xss' => 1, // xss过滤
)
)),
'displayorder' => 0,
));
}
}
}
}
// 站点
foreach ($this->site as $siteid) {
// 升级资料库
$table = $prefix.$siteid.'_block';
if ($db->tableExists($table)) {
// 创建code字段 代码
if (!$db->fieldExists('code', $table)) {
$T->add_field($table, 'code', 'VARCHAR(100)', 'NOT NULL', '');
}
}
// 升级栏目表
if ($is_module) {
$table = $prefix . $siteid . '_share_category';
if ($db->tableExists($table)) {
// 创建字段 代码
if (!$db->fieldExists('disabled', $table)) {
$T->add_field($table, 'disabled', 'tinyint(1)', "DEFAULT '0'", '');
$db->table($table)->update(['disabled' => 0]);
}
$db->table($table)->where('disabled', null)->update(['disabled' => 0]);
if (!$db->fieldExists('ismain', $table)) {
$T->add_field($table, 'ismain', 'tinyint(1)', "DEFAULT '0'", '');
$db->table($table)->update(['ismain' => 1]);
}
}
if ($module) {
foreach ($module as $m) {
if (!$db->tableExists($prefix . $siteid . '_' . $m['dirname'])) {
continue;
}
// 增加长度
$table = $prefix . $siteid . '_' . $m['dirname'];
if ($db->fieldExists('inputip', $table)) {
$T->edit_field($table, 'inputip', 'VARCHAR(100)', 'NOT NULL', '客户端ip信息');
}
$table = $prefix . $siteid . '_' . $m['dirname'] . '_recycle';
if ($db->tableExists($table)) {
// 创建字段 删除理由
if (!$db->fieldExists('result', $table)) {
$T->add_field($table, 'result', 'Text', 'NOT NULL', '');
}
}
$table = $prefix . $siteid . '_' . $m['dirname'] . '_support';
if ($db->tableExists($table)) {
// 创建字段 游客点赞
if (!$db->fieldExists('agent', $table)) {
$T->add_field($table, 'agent', 'VARCHAR(200)', 'DEFAULT NULL', '');
}
}
$table = $prefix . $siteid . '_' . $m['dirname'] . '_oppose';
if ($db->tableExists($table)) {
// 创建字段 游客点赞
if (!$db->fieldExists('agent', $table)) {
$T->add_field($table, 'agent', 'VARCHAR(200)', 'DEFAULT NULL', '');
}
}
$table = $prefix . $siteid . '_' . $m['dirname'] . '_verify';
if (!$db->fieldExists('vid', $table)) {
$T->add_field($table, 'vid', 'INT(10)', 'DEFAULT NULL', '');
}
if (!$db->fieldExists('islock', $table)) {
$T->add_field($table, 'islock', 'tinyint(1)', 'DEFAULT NULL', '');
}
// 点击时间
$table = $prefix . $siteid . '_' . $m['dirname'] . '_hits';
foreach (['day_time', 'week_time', 'month_time', 'year_time'] as $a) {
if (!$db->fieldExists($a, $table)) {
$T->add_field($table, $a, 'INT(10)', 'DEFAULT NULL', '');
}
}
$table = $prefix . $siteid . '_' . $m['dirname'] . '_category';
if ($db->tableExists($table)) {
if (!$db->fieldExists('disabled', $table)) {
$T->add_field($table, 'disabled', 'tinyint(1)', "DEFAULT '0'", '');
$db->table($table)->update(['disabled' => 0]);
}
$db->table($table)->where('disabled', null)->update(['disabled' => 0]);
if (!$db->fieldExists('ismain', $table)) {
$T->add_field($table, 'ismain', 'tinyint(1)', "DEFAULT '0'", '');
$db->table($table)->update(['ismain' => 1]);
}
}
// 栏目模型字段修正
$db->table('field')->where('relatedname', $m['dirname'] . '-' . $siteid)->update(['relatedname' => 'catmodule-' . $m['dirname']]);
}
}
}
}
$this->_html_msg(1, dr_lang('正在升级数据表结构'), $next.'&page='.($page+1));
break;
default:
\Phpcmf\Service::M('cache')->update_db();
\Phpcmf\Service::M('cache')->update_cache();
\Phpcmf\Service::M('cache')->update_data_cache();
$this->_html_msg(1, dr_lang('更新完成'));
break;
}
}
}
+55
View File
@@ -0,0 +1,55 @@
<?php namespace Phpcmf\Control\Admin;
class Category extends \Phpcmf\Admin\Category
{
public function index() {
$this->_Admin_List();
}
public function all_add() {
$this->_Admin_All_Add();
}
public function add() {
$this->_Admin_Add();
}
public function edit() {
$this->_Admin_Edit();
}
public function url_edit() {
$this->_Admin_Url_Edit();
}
public function move_edit() {
$this->_Admin_Move_Edit();
}
public function show_edit() {
$this->_Admin_Show_Edit();
}
public function displayorder_edit() {
$this->_Admin_Order();
}
public function html_edit() {
$this->_Admin_Html_Edit();
}
public function htmlall_edit() {
$this->_Admin_Html_All_Edit();
}
public function phpall_edit() {
$this->_Admin_Php_All_Edit();
}
public function del() {
$this->_Admin_Del();
}
}
+563
View File
@@ -0,0 +1,563 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Check extends \Phpcmf\Common
{
private $_list = [
'01' => '文件上传检测',
'02' => 'PHP环境检测',
'03' => '目录权限检测',
'15' => '服务器环境检测',
'04' => '后台入口名称检测',
'05' => '数据库权限检测',
'06' => '模板完整性检测',
//'07' => '数据库表结构检测',
//'08' => '程序兼容性检测',
'09' => '项目安全性检测',
'10' => '数据负载优化检测',
'12' => 'HTTPS检测',
'13' => '应用插件兼容性检测',
'16' => '自动任务配置检测',
];
public function index() {
if (IS_USE_MODULE) {
$this->_list['14'] = '移动端检测';
$this->_list['11'] = '移动端检测';
}
if (is_file(WRITEPATH.'install.info')) {
unlink(WRITEPATH.'install.info');
unlink(WRITEPATH.'install.error');
}
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'系统体检' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-wrench'],
'系统更新' => ['cache/index', 'fa fa-refresh'],
'PHP环境' => [\Phpcmf\Service::L('Router')->class.'/php_index', 'fa fa-code'],
'SERVER变量' => [\Phpcmf\Service::L('Router')->class.'/server_index', 'fa fa-cog'],
]
),
'list' => $this->_list,
]);
\Phpcmf\Service::V()->display('check_index.html');
}
public function do_index() {
$id = $_GET['id'];
switch ($id) {
case '01':
$post = intval(ini_get("post_max_size"));
$file = intval(ini_get("upload_max_filesize"));
if ($file > $post) {
$this->_json(0,dr_lang('系统配置不合理,post_max_size值(%s)必须大于upload_max_filesize值(%s)', $post, $file));
} elseif ($file < 10) {
$this->_json(1,dr_lang('系统环境只允许上传%sMB文件,可以设置upload_max_filesize值提升上传大小', $file));
} elseif ($post < 10) {
$this->_json(1,dr_lang('系统环境要求每次发布内容不能超过%sMB(含文件),可以设置post_max_size值提升发布大小', $post));
}
break;
case '02':
$rt = [];
if (!function_exists('mb_substr')) {
$rt[] = dr_lang('PHP不支持mbstring扩展,必须开启');
}
if (!function_exists('imagettftext')) {
$rt[] = dr_lang('PHP扩展库:GD库未安装或GD库版本太低,可能无法正常显示验证码和图片缩略图');
}
if (!function_exists('curl_init')) {
$rt[] = dr_lang('PHP不支持CURL扩展,必须开启');
}
if (!function_exists('mb_convert_encoding')) {
$rt[] = dr_lang('PHP的mb函数不支持,无法使用百度关键词接口');
}
if (!function_exists('imagecreatetruecolor')) {
$rt[] = dr_lang('PHP的GD库版本太低,无法支持验证码图片');
}
if (!function_exists('ini_get')) {
$rt[] = dr_lang('系统函数ini_get未启用,将无法获取到系统环境参数');
}
if (!function_exists('gzopen')) {
$rt[] = dr_lang('zlib扩展未启用,您将无法进行在线升级、无法下载应用插件等');
}
if (!function_exists('gzinflate')) {
$rt[] = dr_lang('函数gzinflate未启用,您将无法进行在线升级、无法下载应用插件等');
}
if (!function_exists('fsockopen')) {
$rt[] = dr_lang('PHP不支持fsockopen,可能充值接口无法使用、手机短信无法发送、电子邮件无法发送、一键登录无法登录等');
}
if (!function_exists('openssl_open')) {
$rt[] = dr_lang('PHP不支持openssl,可能充值接口无法使用、手机短信无法发送、电子邮件无法发送、一键登录无法登录等');
}
if (!ini_get('allow_url_fopen')) {
$rt[] = dr_lang('allow_url_fopen未启用,远程图片无法保存、网络图片无法上传、可能充值接口无法使用、手机短信无法发送、电子邮件无法发送、一键登录无法登录等');
}
if (!class_exists('ZipArchive')) {
$rt[] = dr_lang('php_zip扩展未开启,无法使用应用市场功能');
}
$url = 'https://www.xunruicms.com/';
if ($this->cmf_license['cloud']) {
$url = $this->cmf_license['cloud'];
}
if (!fopen($url, "rb")) {
$rt[] = dr_lang('fopen无法获取远程数据,无法使用在线下载插件和在线升级');
}
if ($rt) {
$this->halt(implode('<br>', $rt), 0);
}
break;
case '03':
list($thumb_path) = dr_thumb_path();
list($avatar_path) = dr_avatar_path();
$rt = [];
$dir = [
WRITEPATH => '无法生成系统缓存文件',
$avatar_path => '无法上传头像',
WRITEPATH.'cloud/' => '无法下载应用插件',
WRITEPATH.'data/' => '无法生成系统配置文件,会导致系统配置无效',
WRITEPATH.'file/' => '无法生成系统缓存文件,会导致系统无法运行',
$thumb_path => '无法生成缩略图缓存文件',
SYS_UPLOAD_PATH => '无法上传附件',
APPSPATH => '无法创建模块、创建表单、下载应用插件',
TPLPATH => '无法创建模块模板和应用插件模板',
];
foreach ($dir as $path => $note) {
if (!is_dir($path)) {
dr_mkdirs($path);
}
if (!dr_check_put_path($path)) {
$rt[] = dr_lang($note).'【'.(IS_DEV ? $path : dr_safe_replace_path($path)).'】';
}
}
if ($rt) {
$this->halt(implode('<br>', $rt), 0);
}
break;
case '04':
if (SELF == 'admin.php') {
$this->halt(dr_lang('为了系统安全,请修改根目录admin.php的文件名'), 0);
}
break;
case '05':
$field = \Phpcmf\Service::M('table')->show_full_colunms(\Phpcmf\Service::M()->dbprefix('admin'));
if (!$field) {
$this->halt(dr_lang('无法获取到数据表字段结构,请检查数据库账号是否具备读取表结构的权限'), 0);
}
break;
case '06':
// 语言文件兼容处理
if (is_dir(CONFIGPATH.'language/') && !is_dir(CONFIGPATH.'language/')) {
\Phpcmf\Service::L('file')->copy_dir(CONFIGPATH.'language/', CONFIGPATH.'language/', ROOTPATH.'api/language/');
}
$rt = [];
// 语言文件
$lang = dr_catcher_data(LANG_PATH.'lang.js', 5, false);
if ($lang && strlen($lang) < 10) {
$rt[] = dr_lang('语言JS文件异常:%s', LANG_PATH.'lang.js');
} elseif ($lang && strpos($lang, 'finecms_datepicker_lang') === false) {
$rt[] = dr_lang('语言JS文件异常:%s', LANG_PATH.'lang.js');
}
// 模板文件
if (!is_file(TPLPATH.'pc/'.SITE_TEMPLATE.'/home/index.html')) {
$rt[] = dr_lang('前端模板【电脑版】不存在:%s', 'TPLPATH/pc/'.SITE_TEMPLATE.'/home/index.html');
}
if (IS_USE_MEMBER) {
if (!is_file(TPLPATH.'pc/'.SITE_TEMPLATE.'/member/index.html')) {
$rt[] = dr_lang('用户中心模板【电脑版】不存在:%s', 'TPLPATH/pc/'.SITE_TEMPLATE.'/member/index.html');
} elseif (!is_file(TPLPATH.'pc/'.SITE_TEMPLATE.'/member/msg.html')) {
$rt[] = dr_lang('用户中心模板【电脑版】不存在:%s', 'TPLPATH/pc/'.SITE_TEMPLATE.'/member/msg.html');
}
}
// 必备模板检测
foreach (['msg.html', '404.html'] as $tt) {
if (!is_file(TPLPATH.'pc/'.SITE_TEMPLATE.'/home/'.$tt)) {
$rt[] = dr_lang('前端模板【电脑版】不存在:%s', 'TPLPATH/pc/'.SITE_TEMPLATE.'/home/'.$tt);
}
}
if ($rt) {
$this->halt(implode('<br>', $rt), 0);
}
// 移动端模板检测
if (!is_file(TPLPATH.'mobile/'.SITE_TEMPLATE.'/home/index.html')) {
$this->halt(dr_lang('前端模板【手机版】不存在:%s', 'TPLPATH/mobile/'.SITE_TEMPLATE.'/home/index.html'), 1);
}
if (IS_USE_MEMBER) {
if (!is_file(TPLPATH.'mobile/'.SITE_TEMPLATE.'/member/index.html')) {
$this->halt(dr_lang('用户中心模板【手机版】不存在:%s', 'TPLPATH/mobile/'.SITE_TEMPLATE.'/member/index.html'), 1);
} elseif (!is_file(TPLPATH.'mobile/'.SITE_TEMPLATE.'/member/msg.html')) {
$this->halt(dr_lang('用户中心模板【手机版】不存在:%s', 'TPLPATH/mobile/'.SITE_TEMPLATE.'/member/msg.html'), 1);
}
}
break;
case '07':
break;
case '08':
// 程序兼容性
break;
case '09':
$rt = [];
// 搜索根目录
$local = dr_file_map(WEBPATH, 1); // 搜索根目录
foreach ($local as $file) {
if (in_array(strtolower(substr(strrchr($file, '.'), 1)), ['zip', 'rar', 'sql'])) {
$rt[] = dr_lang('文件不安全【%s】请及时清理', '/'.$file.'');
}
$str = file_get_contents(WEBPATH.$file, 0, null, 0, 9286630);
if ($str && strlen($str) >= 9286630) {
$rt[] = dr_lang('存在大文件文件【%s】请及时清理', '/'.$file.'');
}
}
if (is_file(WEBPATH.'cache/api.php')) {
$code = dr_catcher_data(SITE_URL.'cache/api.php/test', 5, false);
if (strpos($code, 'phpcmf') !== false) {
$rt[] = '<a href="javascript:dr_help(1005);">'.dr_lang('目录[cache]需要设置禁止访问');
}
}
$code = file_get_contents(WEBPATH.'index.php');
if ($code && substr_count($code, '<?php') > 1) {
$rt[] = dr_lang('首页入口文件index.php疑似被篡改');
}
if (function_exists('ini_get')) {
$pfile = ini_get('auto_prepend_file');
if ($pfile) {
$rt[] = '<font color="#ff7f50">'.dr_lang('php.ini中auto_prepend_file参数疑似可疑代码:%s', dr_strcut($pfile, 20));
}
$afile = ini_get('auto_append_file');
if ($afile) {
$rt[] = '<font color="#ff7f50">'.dr_lang('php.ini中auto_append_file参数疑似可疑代码:%s', dr_strcut($afile, 20));
}
}
if (!dr_is_app('safe')) {
$rt[] = '<font color="green">'.dr_lang('安装「系统安全加固」插件可以大大提高安全等级');
}
if ($rt) {
$this->halt(implode('<br>', $rt), 0);
}
$this->_json(1,dr_lang('完成'));
break;
case '10':
// 数据负载
$rt = [];
// 任务队列
$cron = \Phpcmf\Service::M()->table('cron')->counts();
if ($cron > 10) {
$rt[] = '<font color="red">'.dr_lang('【任务队列】含有大量未执行的任务,会影响加载速度,建议删除不需要的任务').'</font>';
}
// 模块数据检测
if (IS_USE_MODULE) {
$module = \Phpcmf\Service::M()->table('module')->getAll();
if ($module) {
foreach ($module as $m) {
$site = dr_string2array($m['site']);
$mform = \Phpcmf\Service::M()->is_table_exists('module_form') ? \Phpcmf\Service::M()->table('module_form')->where('module', $m['dirname'])->getAll() : [];
foreach ($this->site_info as $siteid => $s) {
if (isset($site[$siteid]) && $site[$siteid]) {
$r = $this->_check_table_counts($siteid . '_' . $m['dirname'], $m['dirname'] . dr_lang('模块主表'));
$r && $rt[] = $r;
if ($mform) {
foreach ($mform as $mm) {
$r = $this->_check_table_counts(
$siteid . '_' . $m['dirname'] . '_form_' . $mm['table'],
$m['dirname'] . dr_lang('模块') . $mm['name'] . dr_lang('表')
);
$r && $rt[] = $r;
}
}
}
}
}
}
}
if ($rt) {
$this->halt(implode('<br>', $rt), 0);
}
$this->_json(1,dr_lang('正常'));
break;
case '11':
// 域名检测
if (!function_exists('stream_context_create')) {
$this->halt(dr_lang('函数没有被启用:%s', 'stream_context_create'), 0);
}
$error = $tips = [];
list($a, $data) = \Phpcmf\Service::M('Site')->domain();
if ($data) {
foreach ($data as $name => $domain) {
$url = '';
$cname = '';
if ($name == 'mobile_domain') {
if ($domain) {
$url = dr_http_prefix($domain) . '/api.php';
} else {
$tips[] = dr_lang('当前站点没有绑定手机域名,可能无法使用移动端界面');
}
$cname = '移动端';
} elseif (strpos($name, 'module_') === 0) {
// 模块
if ($domain) {
$url = dr_http_prefix($domain) . '/api.php';
}
$cname = '模块';
} elseif (strpos($name, 'client_') === 0) {
// 终端
if ($domain) {
$url = dr_http_prefix($domain) . '/api.php';
}
$cname = '终端';
}
if ($url && $cname) {
$code = dr_catcher_data($url, 5, false);
if ($code != 'phpcmf ok') {
$error[] = dr_lang('[%s]域名绑定异常,无法访问:%s,可以尝试手动访问此地址,如果提示phpcmf ok就表示成功', dr_lang($cname), $url);
}
}
}
}
// 验证附件域名
list($a, $b) = dr_thumb_path();
list($c, $d) = dr_avatar_path();
$domain = [
['name' => dr_lang('附件域名'), 'path' => SYS_UPLOAD_PATH, 'url' => SYS_UPLOAD_URL],
['name' => dr_lang('缩略图域名'), 'path' => $a, 'url' => $b],
['name' => dr_lang('头像域名'), 'path' => $c, 'url' => $d],
];
foreach ($domain as $t) {
if (!file_put_contents($t['path'].'api.html', 'phpcmf ok')) {
$this->_json(0, (IS_DEV ? $t['path'] : dr_safe_replace_path($t['path'])).' '.dr_lang('无法写入文件'));
}
$code = dr_catcher_data($t['url'].'api.html', 5, false);
if ($code != 'phpcmf ok') {
$error[] = dr_lang('[%s]异常,无法访问:%s,可以尝试手动访问此地址,如果提示phpcmf ok就表示成功', $t['name'], $t['url'].'api.html');
}
}
// 重复验证
if (is_file(WRITEPATH.'config/domain_sso.php')) {
$domains = require WRITEPATH.'config/domain_sso.php';
if ($domains) {
// 获取去掉重复数据的数组
$unique_arr = array_unique ( $domains );
// 获取重复数据的数组
$repeat_arr = array_diff_assoc ( $domains, $unique_arr );
if ($repeat_arr) {
foreach ($repeat_arr as $t) {
$error[] = dr_lang('域名【%s】被多处重复配置,可能会影响到此域名的作用域或访问异常', $t);
}
}
}
}
if ($error) {
$this->_json(0, implode('<br>', $error));
} elseif ($tips) {
$this->_json(1, implode('<br>', $tips));
} else {
$this->_json(1, dr_lang(dr_lang('完成')));
}
break;
case '12':
// https
if (SYS_HTTPS) {
if (strpos(FC_NOW_URL, 'https://') !== false) {
$this->_json(1,dr_lang('正常'));
} else {
$this->_json(0,'<a href="javascript:dr_help(751);">'.dr_lang('服务器无法识别HTTPS证书,查看解决方案').'</a>');
}
} else {
$this->_json(0,'<a href="javascript:dr_help(668);">'.dr_lang('系统没有开启HTTPS服务,查看解决方案').'</a>');
}
break;
case '13':
// 应用插件
$func = [];
$local = \Phpcmf\Service::Apps();
$custom = file_get_contents(CONFIGPATH.'custom.php');
foreach ($local as $dir => $path) {
if (is_file($path.'Config/App.php')) {
// 变量重定义
if (is_file($path.'Config/Init.php')) {
$code = file_get_contents($path.'Config/Init.php');
if (preg_match_all("/\s+function (.+)\(/", $code, $arr)) {
foreach ($arr[1] as $a) {
$name = trim($a);
if (strpos($name, "'") !== false) {
continue;
}
if (isset($func[$name]) && $func[$name]) {
$this->_json(0,dr_lang('应用[%s]中的函数[%s]存在于%s之中,不能被重复定义', $dir, $name, $func[$name]));
}
$func[$name] = $dir;
if (function_exists($name)) {
if (preg_match("/\s+function ".$name."\(/", $custom)) {
// 存在于自定义函数库中
} else {
$this->_json(0, dr_lang('应用[%s]中的函数[%s]是系统函数,不能定义', $dir, $name));
}
}
}
}
}
//
}
}
if (!is_file(ROOTPATH.'static/assets/js/my.js') && is_dir(ROOTPATH.'static/assets/js/')) {
@file_put_contents(ROOTPATH.'static/assets/js/my.js', '');
}
$this->_json(1, dr_lang(dr_lang('完成')));
break;
case '14':
// 移动端检测
$error = [];
// 开起自动识别,又开启了首页静态
if ($this->site_info[SITE_ID]['SITE_AUTO'] && $this->site_info[SITE_ID]['SITE_INDEX_HTML']) {
$error[] = '<a href="javascript:dr_help(664);">'.dr_lang('当前站点已经开启[首页静态]模式,将无法实现移动端自动跳转功能,查看解决方案').'</a>';
}
$config = $this->get_cache('site', SITE_ID, 'mobile');
if (!$this->site_info[SITE_ID]['SITE_IS_MOBILE'] && $config && $config['tohtml']) {
$error[] = '<a href="javascript:dr_help(506);">'.dr_lang('当前站点没有绑定移动端域名,将无法实现移动端静态页面功能,查看解决方案').'</a>';
}
if ($error) {
$this->_json(0, implode('<br>', $error));
}
// 单独域名判断
if (!$this->site_info[SITE_ID]['SITE_IS_MOBILE']) {
$this->_json(1,dr_lang('当前项目没有绑定移动端域名'));
}
$this->_json(1, dr_lang(dr_lang('完成')));
break;
case '15':
// 服务器环境
if (is_file(ROOTPATH.'test.php')) {
$error[] = dr_lang('根目录检测文件test.php,当项目正式上线后需要删除,以免影响网站安全');
}
if (IS_DEV) {
$error[] = dr_lang('根目录index.php中的开发者模式已开启,当项目正式上线后需要关闭,以免影响网站安全');
}
if ($error) {
$this->_json(0, implode('<br>', $error));
}
$this->_json(1, dr_lang(dr_lang('完成')));
break;
case '16':
// 自动任务检测
if (is_file(WRITEPATH.'config/run_time.php')) {
$time = file_get_contents(WRITEPATH.'config/run_time.php');
$this->_json(1, dr_lang('最近执行时间:%s', $time));
}
$this->_json(0, '<a href="javascript:dr_help(353);">'.dr_lang('没有配置自动任务功能,无法自动清理缓存和更新缓存,查看解决方案').'</a>');
break;
case '99':
break;
}
$this->_json(1, dr_lang(dr_lang('完成')));
}
public function php_index() {
phpinfo();
}
public function server_index() {
echo '<pre style="background: #f1f5f8;padding: 10px">';
print_r($_SERVER);
}
private function halt($msg, $code) {
$this->_json($code, $msg);
}
private function _check_table_counts($table, $name) {
$ptable = \Phpcmf\Service::M()->dbprefix($table);
if (!\Phpcmf\Service::M()->db->tableExists($ptable)) {
return dr_lang('数据表【%s】不存在,请创建', $name.'/'.$ptable);
}
$counts = \Phpcmf\Service::M()->table($table)->counts();
if ($counts > 1000000) {
return '<font color="green">'.dr_lang('数据表【%s】数据量超过100万,会影响加载速度,建议对其进行数据优化', $name.'/'.$ptable).'</font>';
}
}
}
File diff suppressed because it is too large Load Diff
+153
View File
@@ -0,0 +1,153 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 任务队列
class Cron extends \Phpcmf\Table
{
private $type;
public function __construct()
{
parent::__construct();
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'任务管理' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-indent'],
'任务设置' => ['add:'.\Phpcmf\Service::L('Router')->class.'/edit', 'fa fa-cog'],
'help' => [353],
]
)
]);
// 表单显示名称
$this->name = dr_lang('任务队列');
$this->is_data = 0;
// 初始化数据表
$this->_init([
'table' => 'cron',
'field' => [
'type' => [
'ismain' => 1,
'fieldtype' => 'Text',
'fieldname' => 'type',
],
],
'date_field' => 'inputtime',
'order_by' => 'id desc,status asc',
]);
// 任务类别
$this->type = [
'email' => dr_lang('邮件发送'),
'notice' => dr_lang('消息通知'),
];
}
// 任务管理
public function index() {
list($tpl, $data) = $this->_List();
if ($data['list']) {
foreach ($data['list'] as $i => $t) {
$data['list'][$i]['value'] = ('<pre>'.str_replace([PHP_EOL, "'", '"'], ["<br>", "", ""], var_export(dr_string2array($t['value']), true)).'</pre>');
$t['error'] && $data['list'][$i]['error'] = ('<pre>'.str_replace([PHP_EOL, "'", '"'], ["<br>", "", ""], var_export(dr_string2array($t['error']), true)).'</pre>');
}
}
$run_time = '';
if (is_file(WRITEPATH.'config/run_time.php')) {
$run_time = file_get_contents(WRITEPATH.'config/run_time.php');
}
\Phpcmf\Service::V()->assign([
'type' => $this->type,
'list' => $data['list'],
'run_time' => $run_time,
]);
\Phpcmf\Service::V()->display($tpl);
}
public function edit() {
if (is_file(WRITEPATH.'config/system.php')) {
$data = require WRITEPATH.'config/system.php';
} else {
$data = [];
}
if (IS_POST) {
$post = \Phpcmf\Service::L('input')->post('data', true);
\Phpcmf\Service::M('System')->save_config($data, [
'SYS_CRON_AUTH' => dr_safe_replace($post['SYS_CRON_AUTH'] ?? ''),
]);
\Phpcmf\Service::L('input')->system_log('设置自动任务权限');
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'data' => $data,
'form' => dr_form_hidden(),
]);
\Phpcmf\Service::V()->display('cron_edit.html');
}
public function show() {
list($tpl, $data) = $this->_Show(\Phpcmf\Service::L('input')->get('id'));
\Phpcmf\Service::V()->assign([
'show_error' => var_export(dr_string2array($data['error']), true),
'show_value' => var_export(dr_string2array($data['value']), true),
]);
\Phpcmf\Service::V()->display($tpl);exit;
}
// 后台删除任务
public function del() {
$this->_Del(
\Phpcmf\Service::L('input')->get_post_ids(),
null,
null,
\Phpcmf\Service::M()->dbprefix($this->init['table'])
);
}
// 执行任务
public function post_add() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if ($ids) {
foreach ($ids as $id) {
\Phpcmf\Service::M('cron')->do_cron_id($id);
//\Phpcmf\Service::L('thread')->cron(['action' => 'cron', 'id' => $id ], 1);
}
$this->_json(1, dr_lang('任务已提交,等待执行结果'));
} else {
$this->_json(0, dr_lang('所选数据不存在'));
}
}
// 单个执行任务
public function do_add() {
$id = (int)\Phpcmf\Service::L('input')->get('id');
if (!$id) {
$this->_json(0, dr_lang('所选数据不存在'));
}
$rt = \Phpcmf\Service::M('cron')->do_cron_id($id);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
$this->_json(1, dr_lang('任务执行完成'));
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Debug extends \Phpcmf\Common
{
public function index() {
$this->_echo_msg(IS_DEV ? 1 : 0, '开发者模式:'.(IS_DEV ? '已开启' : '未开启'));
$this->_echo_msg(1, '客户端字符串:'.$_SERVER['HTTP_USER_AGENT']);
$this->_echo_msg(1, 'PHP版本:'.PHP_VERSION.'');
$db = \Phpcmf\Service::M()->db;
$driver = isset($db->DBDriver) ? $db->DBDriver : 'unknown';
$this->_echo_msg(1, '数据库驱动:'.$driver);
$this->_echo_msg(1, '数据库版本:'.$db->getVersion());
$this->_echo_msg(1, '内核版本:'.FRAME_NAME.' - '.FRAME_VERSION);
$this->_echo_msg(1, 'CMS版本:'.$this->cmf_version['version'].' - '.dr_date($this->cmf_version['downtime'], 'Y-m-d H:i:s'));
$local = \Phpcmf\Service::Apps();
foreach ($local as $dir => $path) {
if (is_file($path.'Config/App.php')) {
$key = strtolower($dir);
$cfg = require $path.'Config/App.php';
if (is_file($path.'Config/Version.php')) {
$vsn = require $path.'Config/Version.php';
$this->_echo_msg(1, $cfg['name'].' - 版本:'.$vsn['version'].' - '.dr_date($vsn['downtime'], 'Y-m-d H:i:s'));
}
}
}
}
function _echo_msg($code, $msg) {
echo '<div style="border-bottom: 1px dashed #9699a2; padding: 5px;">';
if (!$code) {
echo '<b style="color:red;text-decoration:none;">'.$msg.'</b>';
} else {
echo '<font color=green>'.$msg.'</font>';
}
echo '</div>';
}
}
+154
View File
@@ -0,0 +1,154 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Email extends \Phpcmf\Common
{
private $form; // 表单验证配置
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'邮件服务器' => ['email/index', 'fa fa-envelope'],
'添加' => ['add:email/add', 'fa fa-plus', '600px'],
'help' => [361],
]
));
// 表单验证配置
$this->form = [
'host' => [
'name' => '服务器',
'rule' => [
'empty' => dr_lang('服务器不能为空')
],
'filter' => [],
'length' => '200'
],
'port' => [
'name' => '端口号',
'filter' => ['intval'],
'length' => '30'
],
'user' => [
'name' => '邮箱账号',
'filter' => [],
'rule' => [
'empty' => dr_lang('邮箱账号不能为空')
],
'length' => '200'
],
'pass' => [
'name' => '邮箱密码',
'filter' => [],
'length' => '200'
],
];
}
public function index() {
\Phpcmf\Service::V()->assign([
'list' => \Phpcmf\Service::M()->table('mail_smtp')->order_by('displayorder asc')->getAll(),
]);
\Phpcmf\Service::V()->display('email_index.html');
}
public function add() {
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
if (\Phpcmf\Service::L('input')->post('type')) {
$data['host'] = 'mail';
}
$this->_validation($data);
\Phpcmf\Service::L('input')->system_log('添加SMTP服务器: '.$data['name']);
$data['displayorder'] = intval($data['displayorder']);
\Phpcmf\Service::M()->table('mail_smtp')->insert($data);
// 自动更新缓存
\Phpcmf\Service::M('cache')->sync_cache('email');
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden()
]);
\Phpcmf\Service::V()->display('email_add.html');
exit;
}
public function edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M()->table('mail_smtp')->get($id);
if (!$data) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$this->_validation($data);
if ($data['pass'] == '******') {
unset($data['pass']);
}
\Phpcmf\Service::M()->table('mail_smtp')->update($id, $data);
\Phpcmf\Service::L('input')->system_log('修改邮件服务器: '.$data['name']);
\Phpcmf\Service::M('cache')->sync_cache('email'); // 自动更新缓存
$this->_json(1, dr_lang('操作成功'));
}
$data['pass'] = '******';
\Phpcmf\Service::V()->assign([
'data' => $data,
'form' => dr_form_hidden(),
]);
\Phpcmf\Service::V()->display('email_add.html');
exit;
}
// 保存数据
public function save_edit() {
$i = intval(\Phpcmf\Service::L('input')->get('id'));
\Phpcmf\Service::M()->table('mail_smtp')->save(
$i,
dr_safe_replace(\Phpcmf\Service::L('input')->get('name')),
dr_safe_replace(\Phpcmf\Service::L('input')->get('value'))
);
\Phpcmf\Service::L('input')->system_log('修改邮件服务器排序值: '. $i);
\Phpcmf\Service::M('cache')->sync_cache('email'); // 自动更新缓存
$this->_json(1, dr_lang('更改成功'));
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
\Phpcmf\Service::M()->table('mail_smtp')->deleteAll($ids);
\Phpcmf\Service::M('cache')->sync_cache('email'); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量删除邮件服务器: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 验证数据
private function _validation($data) {
list($data, $return) = \Phpcmf\Service::L('Form')->validation($data, $this->form);
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
}
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Email_log extends \Phpcmf\Common
{
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'错误日志' => ['email_log/index', 'fa fa-calendar'],
]
));
}
public function index() {
$data = $list = [];
$file = WRITEPATH.'email_log.txt';
if (is_file(WRITEPATH.'email_log.txt')) {
$data = explode(PHP_EOL, str_replace(array(chr(13), chr(10)), PHP_EOL, file_get_contents($file)));
$data = $data ? array_reverse($data) : [];
$page = max(1, (int)\Phpcmf\Service::L('input')->get('page'));
$limit = ($page - 1) * SYS_ADMIN_PAGESIZE;
$i = $j = 0;
foreach ($data as $v) {
if ($v && $i >= $limit && $j < SYS_ADMIN_PAGESIZE) {
$list[] = $v;
$j ++;
}
$i ++;
}
}
$total = $data ? max(0, count($data) - 1) : 0;
\Phpcmf\Service::V()->assign(array(
'list' => $list,
'total' => $total,
'mypages' => \Phpcmf\Service::L('input')->page(\Phpcmf\Service::L('Router')->url('email_log/index'), $total, 'admin')
));
\Phpcmf\Service::V()->display('email_log.html');
}
public function del() {
@unlink(WRITEPATH.'email_log.txt');
exit($this->_json(1, dr_lang('操作成功')));
}
}
+131
View File
@@ -0,0 +1,131 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Error extends \Phpcmf\Common {
public function index() {
$time = (int)strtotime(\Phpcmf\Service::L('input')->get('time'));
!$time && $time = SYS_TIME;
$list = [];
$total = 0;
$file = WRITEPATH.'error/log-'.date('Y-m-d', $time).'.php';
if (is_file($file)) {
if (filesize($file) > 1024*1024*2) {
$list[] = [
'time' => date('Y-m-d', $time),
'type' => '<span class="label label-warning"> '.dr_lang('提醒').' </span>',
'message' => '此日志文件大于2MB,请使用Ftp等工具查看此文件:'.$file,
];
} else {
$c = file_get_contents($file);
$data = explode(PHP_EOL, trim(str_replace('<?php defined(\'BASEPATH\') OR exit(\'No direct script access allowed\'); ?>'.PHP_EOL.PHP_EOL, '', str_replace(array(chr(13), chr(10)), PHP_EOL, $c)), PHP_EOL));
$data && $data = array_reverse($data);
$page = max(1, (int)\Phpcmf\Service::L('input')->get('page'));
//$total = max(0, count($data));
$total = max(0, substr_count($c, '- '.date('Y-m-d', $time).' '));
$limit = ($page - 1) * SYS_ADMIN_PAGESIZE;
$i = $j = 0;
foreach ($data as $t) {
if ($t && $i >= $limit && $j < SYS_ADMIN_PAGESIZE) {
$v = explode(' --> ', $t);
$time2 = $v ? explode(' - ', $v[0]) : [ 0 => '', 1 => '' ];
if ($time2[1]) {
$value = [
'time' => $time2[1] ? $time2[1] : '',
'type' => '',
];
if ($time2[0] == 'DEBUG') {
$value['type'] = '<span class="label label-success"> '.dr_lang('调试').' </span>';
} elseif ($time2[0] == 'INFO') {
$value['type'] = '<span class="label label-default"> '.dr_lang('信息').' </span>';
} elseif ($time2[0] == 'WARNING') {
$value['type'] = '<span class="label label-warning"> '.dr_lang('提醒').' </span>';
} else {
$value['type'] = '<span class="label label-danger"> '.dr_lang('错误').' </span>';
}
if (strpos((string)$v[1], '{br}')) {
// phpcmf模式
$vv = explode('{br}', $v[1]);
$value['message'] = $vv[0];
unset($vv[0]);
$value['json'] = str_replace("'", '\\\'', $vv[1]);
unset($vv[1]);
$value['info'] = '错误:'.$value['message'].'<br>';
foreach ($vv as $p) {
$value['info'].= $p.'<br>';
}
$value['info'] = str_replace("'", '\\\'', $value['info']);
} else {
// ci4模式
$value['message'] = str_replace([PHP_EOL, chr(13), chr(10)], ' ', htmlentities((string)$v[1]));
if (preg_match('/'.$value['time'].' \-\->(.*)\{main\}/sU', $c, $mt)) {
$value['info'] = str_replace("'", '\\\'', str_replace([PHP_EOL, chr(13), chr(10)], '<br>', $mt[1]));
}
}
$value['message'] = str_replace("'", '\\\'', $value['message']);
$list[] = $value;
$j ++;
}
}
$i ++;
}
}
}
$time = date('Y-m-d', $time);
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'系统日志' => ['error/index', 'fa fa-shield'],
]
),
'list' => $list,
'time' => $time,
'total' => $total,
'mypages' => \Phpcmf\Service::L('input')->page(\Phpcmf\Service::L('Router')->url(\Phpcmf\Service::L('Router')->class.'/index', ['time' => $time]), $total, 'admin')
]);
\Phpcmf\Service::V()->display('error_log.html');
}
public function log_show() {
$time = dr_safe_filename($_GET['time']);
!$time && $time = date('Y-m-d');
$file = WRITEPATH.'error/log-'.$time.'.php';
if (!$file) {
exit('文件不存在:'.$file);
}
if (filesize($file) > 1024*1024*2) {
exit('此日志文件大于2MB,请使用Ftp等工具查看此文件:'.$file);
}
$code = file_get_contents($file);
\Phpcmf\Service::V()->assign([
'file' => $file,
'code' => $code,
'menu' => [],
]);
\Phpcmf\Service::V()->display('error_file.html');exit;
}
public function del() {
$time = dr_safe_filename($_GET['time']);
!$time && $time = date('Y-m-d');
$file = WRITEPATH.'error/log-'.$time.'.php';
unlink($file);
$this->_json(1, dr_lang('操作成功'));
}
}
+905
View File
@@ -0,0 +1,905 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Field extends \Phpcmf\Common {
public $name;
public $data;
public $ftype;
public $backurl; // 返回链接
public $cachename; // 缓存名称
public $namespace;
public $relatedid;
public $relatedname;
public function __construct() {
parent::__construct();
$this->name = dr_lang('字段管理');
$this->namespace = ''; // 设置应用目录
// 字段来源相关表
\Phpcmf\Service::M('Field')->relatedid = $this->relatedid = (int)\Phpcmf\Service::L('input')->get('rid');
\Phpcmf\Service::M('Field')->relatedname = $this->relatedname = \Phpcmf\Service::L('input')->get('rname');
list($ismain, $issearch, $iscategory) = $this->_set_init();
// 可用字段类别
$this->ftype = \Phpcmf\Service::L('Field')->app($this->namespace)->type(\Phpcmf\Service::M('Field')->func);
// 判断类别权限
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'返回' => ['url:'.$this->backurl, 'fa fa-reply'],
$this->name => ['url:'.dr_url('field/index', ['rname'=>$this->relatedname, 'rid'=>$this->relatedid]), 'fa fa-code', 'field/index'],
'添加' => ['url:'.dr_url('field/add', ['rname'=>$this->relatedname, 'rid'=>$this->relatedid]), 'fa fa-plus', 'field/add'],
'导入' => ['add:field/import_add{rname='.$this->relatedname.'&rid='.$this->relatedid.'}', 'fa fa-sign-in', '60%', '70%'],
'修改' => ['hide:field/edit', 'fa fa-edit'],
]
),
'rid' => $this->relatedid,
'rname' => $this->relatedname,
'ftype' => $this->ftype,
'ismain' => $ismain,
'issearch' => $issearch,
'namespace' => $this->namespace,
'iscategory' => $iscategory,
]);
}
public function index() {
$field = \Phpcmf\Service::M('Field')->get_all_field();
if ($field) {
$field = dr_array_sort($field, 'displayorder', 'asc');
$group = [];
$mygroup = [];
// 分组和合并字段筛选
foreach ($field as $t) {
if ($t['fieldtype'] == 'Group' || $t['fieldtype'] == 'Merge') {
if (preg_match_all('/\{(.+)\}/U', $t['setting']['option']['value'], $value)) {
foreach ($value[1] as $v) {
$group[$t['fieldtype']][$v] = $t['fieldname'];
}
}
$mygroup[$t['fieldtype']][$t['fieldname']] = $t;
}
}
$data = [];
$group_data = [];
$ftype = [];
foreach ($this->ftype as $t) {
$ftype[$t['id']] = strpos($t['id'], $t['name']) !== false ? $t['id'] : $t['name'].' '.$t['id'];
}
// 主字段
foreach ($field as $t) {
// 验证字段对象的有效性
$obj = \Phpcmf\Service::L('Field')->get($t['fieldtype']);
if ($obj) {
if ($obj->use_xss) {
// 强制开启xss
$t['setting']['validate']['xss'] = 1;
} elseif ($obj->close_xss) {
// 强制关闭xss
$t['setting']['validate']['xss'] = 0;
}
}
$t['ftype'] = isset($ftype[$t['fieldtype']]) ? $ftype[$t['fieldtype']] : $t['fieldtype'];
// 重复了 删除记录
if (isset($data[$t['fieldname']]) && $data[$t['fieldname']]) {
\Phpcmf\Service::M()->table('field')->delete($t['id']);
}
if (isset($group['Merge'][$t['fieldname']])) {
$group_data['Merge'][$t['fieldname']] = $t;
} elseif (isset($group['Group'][$t['fieldname']])) {
// 属于分组字段
$group_data['Group'][$t['fieldname']] = $t;
} elseif ($t['fieldtype'] == 'Group') {
$data[$t['fieldname']] = '';
} elseif ($t['fieldtype'] == 'Merge') {
$data[$t['fieldname']] = '';
} else {
$data[$t['fieldname']] = $t;
}
}
if ($mygroup['Merge']) {
foreach ($mygroup['Merge'] as $m) {
$list = [];
foreach ($group['Merge'] as $fieldname => $t) {
$m['fieldname'] == $t && $list[] = $group_data['Merge'][$fieldname];
}
$list && $data[$m['fieldname']] = $list;
}
}
if ($mygroup['Group']) {
foreach ($mygroup['Group'] as $m) {
$list = [];
foreach ($group['Group'] as $fieldname => $t) {
$m['fieldname'] == $t && $list[] = $group_data['Group'][$fieldname];
}
$list && $data[$m['fieldname']] = $list;
}
}
$list = [];
foreach ($data as $fname => $t) {
if (isset($t['id'])) {
$list[$t['fieldname']] = $t;
} elseif ($mygroup['Group'][$fname]) {
$mygroup['Group'][$fname]['spacer'] = $group['Merge'][$fname] ? '<span class="tree-icon">└</span>' : '';
$list[$fname] = $mygroup['Group'][$fname];
foreach ($t as $f) {
$f['spacer'] = $group['Merge'][$fname] ? '<span class="tree-icon">└</span><span class="tree-icon">└</span>' : '<span class="tree-icon">└</span>';
$f['id'] && $list[$f['fieldname']] = $f;
}
} elseif ($mygroup['Merge'][$fname]) {
$list[] = $mygroup['Merge'][$fname];
foreach ($t as $f) {
$f['spacer'] = '<span class="tree-icon">└</span>';
if ($f['id']) {
$list[$f['fieldname']] = $f;
if ($mygroup['Group'][$f['fieldname']] && $data[$f['fieldname']]) {
foreach ($data[$f['fieldname']] as $ff) {
$ff['spacer'] = '<span class="tree-icon">└</span><span class="tree-icon">└</span>';
$ff['id'] && $list[$ff['fieldname']] = $ff;
}
}
}
}
}
}
//print_r($data);
} else {
$list = [];
}
\Phpcmf\Service::V()->assign(array(
'list' => $list,
'role' => \Phpcmf\Service::C()->get_cache('auth'),
));
\Phpcmf\Service::V()->display('field_index.html');
}
public function add() {
$id = 0;
$page = max((int)\Phpcmf\Service::L('input')->post('page'), 0);
// 初始化部分值
$data = [
'ismember' => 1,
'ismain' => 1,
'fieldtype' => '',
'setting' => [
'option' => [],
'validate' => [
'xss' => 1,
'required' => 0,
],
],
];
// 提交表单
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data', false);
$field = \Phpcmf\Service::L('field')->get($data['fieldtype']);
if (!$field) {
$this->_json(0, dr_lang('字段类别(%s)文件不存在', $data['fieldtype']));
} elseif (empty($data['name'])) {
$this->_json(0, dr_lang('字段显示名称不能为空'));
} elseif (empty($data['fieldname'])) {
$this->_json(0, dr_lang('字段名称不能为空'));
} elseif (!preg_match('/^[a-z]+[a-z0-9\_]+$/i', $data['fieldname'])) {
$this->_json(0, dr_lang('字段(%s)名称不规范', $data['fieldname']));
} elseif (strlen($data['fieldname']) > 30) {
$this->_json(0, dr_lang('字段(%s)名称太长', $data['fieldname']));
} else {
if (\Phpcmf\Service::M('Field')->exitsts($data['fieldname'])) {
if (\Phpcmf\Service::M('Field')->table('field')
->where('relatedid', (int)$this->relatedid)
->where('relatedname', (string)$this->relatedname)
->where('fieldname', (string)$data['fieldname'])
->counts()) {
$this->_json(0, dr_lang('字段(%s)已经存在', $data['fieldname']));
} elseif (\Phpcmf\Service::M('Field')->is_sys_field($data['fieldname'])) {
$this->_json(0, dr_lang('字段(%s)是系统保留字段,禁止创建', $data['fieldname']));
} else {
// 已经存在的字段是否创建
if (!isset($_GET['is_op_add'])) {
$this->_json(-1, dr_lang('字段(%s)是已经存在于表中,请更换名字,否则可能会影响程序的运行', $data['fieldname']));
}
}
$is_create = 0;
} else {
$is_create = 1;
}
$rt = $field->edit_config($data);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
$rt = \Phpcmf\Service::M('Field')->add($data, $field, $is_create);
if (!$rt['code']) {
$this->_json(0, dr_lang($rt['msg']));
}
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('添加'.$this->name.'【'.$data['fieldname'].'】'.$data['name']); // 记录日志
$this->_json(1, dr_lang('操作成功'));
}
}
\Phpcmf\Service::V()->assign([
'id' => $id,
'page' => $page,
'data' => $data,
'form' => dr_form_hidden(['page' => $page]),
'role' => \Phpcmf\Service::C()->get_cache('auth'),
'cat_show' => 0,
]);
\Phpcmf\Service::V()->display('field_add.html');
}
public function edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$page = max((int)\Phpcmf\Service::L('input')->get('page'), 0);
$data = \Phpcmf\Service::M()->table('field')->get($id);
if (!$data) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
$data['setting'] = dr_string2array($data['setting']);
// 加载系统编辑器
if ($data['fieldtype'] == 'Ueditor' && !is_file(CMSPATH.'Field/Ueditor.php')) {
$data['fieldtype'] = 'Editor';
}
// 验证字段对象的有效性
$obj = \Phpcmf\Service::L('Field')->get($data['fieldtype']);
if ($obj) {
if ($obj->use_xss) {
// 强制开启xss
$data['setting']['validate']['xss'] = 1;
} elseif ($obj->close_xss) {
// 强制关闭xss
$data['setting']['validate']['xss'] = 0;
}
}
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data', false);
$field = \Phpcmf\Service::L('field')->get($post['fieldtype']);
if (!$field) {
$this->_json(0, dr_lang('字段类别(%s)文件不存在', $post['fieldtype']));
}
$rt = $field->edit_config($post);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
$rt = \Phpcmf\Service::M('Field')->edit(
$data,
$post,
$field->alter_sql($data['fieldname'], $post['setting']['option'], $data['name'])
);
if (!$rt['code']) {
$this->_json(0, dr_lang($rt['msg']));
}
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改'.$this->name.'【'.$data['fieldname'].'】'.$data['name']); // 记录日志
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'id' => $id,
'data' => $data,
'page' => $page,
'form' => dr_form_hidden(['page' => $page]),
'role' => \Phpcmf\Service::C()->get_cache('auth'),
'is_edit' => $obj->is_edit,
]);
\Phpcmf\Service::V()->display('field_add.html');
}
public function type_edit() {
$my = dr_safe_filename(\Phpcmf\Service::L('input')->get('my'));
$to = dr_safe_filename(\Phpcmf\Service::L('input')->get('to'));
$int = ['Cat', 'Date', 'Linkage', 'Touchspin', 'Uid'];
$text = ['Catids', 'Files', 'Ftable', 'Image', 'Property', 'Redirect', 'Textarea', 'Editor'];
$json = ['Checkbox', 'Linkage', 'Members', 'Related', 'Selects'];
$char = ['Color', 'File', 'Text', 'Textbtn', 'Time', 'Select', 'Radio'];
if (in_array($my, $int)) {
if (in_array($to, $int)) {
$this->_json(1, dr_lang('同一类型'));
}
$this->_json(0, dr_lang('当前字段存储的数据是%s,变更后建议手动去数据库将其字段数据类型改成合适的类型,确定继续变更吗?', 'INT'));
} elseif (in_array($my, $text)) {
if (in_array($to, $text)) {
$this->_json(1, dr_lang('同一类型'));
} elseif (stripos($to, 'editor') !== false) {
$this->_json(1, dr_lang('同一类型'));
}
$this->_json(0, dr_lang('当前字段存储的数据是%s,变更后建议手动去数据库将其字段数据类型改成合适的类型,确定继续变更吗?', 'TEXT'));
} elseif (in_array($my, $json)) {
if (in_array($to, $json)) {
$this->_json(1, dr_lang('同一类型'));
}
$this->_json(0, dr_lang('当前字段存储的数据是%s,变更后建议手动去数据库将其字段数据类型改成合适的类型,确定继续变更吗?', 'JSON'));
} elseif (in_array($my, $char)) {
if (in_array($to, $char)) {
$this->_json(1, dr_lang('同一类型'));
}
$this->_json(0, dr_lang('当前字段存储的数据是%s,变更后建议手动去数据库将其字段数据类型改成合适的类型,确定继续变更吗?', 'CHAR'));
} elseif (stripos($my, 'editor') !== false && stripos($to, 'editor') !== false) {
$this->_json(1, dr_lang('同一类型'));
} else {
$this->_json(0, dr_lang('变更字段类别可能会影响已有的数据,你确定吗?'));
}
}
/**
* 通用操作
*/
public function option() {
$id = (int)\Phpcmf\Service::L('input')->get('id');
$data = \Phpcmf\Service::M()->table('field')->get($id);
if (!$data) {
$this->_json(0, dr_lang('字段不存在'));
}
switch (\Phpcmf\Service::L('input')->get('op')) {
case 'disabled':
$value = $data['disabled'] == 1 ? 0 : 1;
\Phpcmf\Service::M()->table('field')->save($id, 'disabled', $value);
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log(($value ? '禁用' : '启用').$this->name.'【'.$data['fieldname'].'】'); // 记录日志
$this->_json(1, dr_lang(($value ? '禁用' : '启用').'成功'), ['value' => $value]);
break;
case 'xss':
// 验证字段对象的有效性
$obj = \Phpcmf\Service::L('Field')->get($data['fieldtype']);
if ($obj) {
if ($obj->use_xss) {
// 强制开启xss
$this->_json(0, dr_lang('该字段已经强制启用了XSS过滤'));
} elseif ($obj->close_xss) {
// 强制关闭xss
$this->_json(0, dr_lang('该字段已经强制关闭了XSS过滤'));
}
}
$data['setting'] = dr_string2array($data['setting']);
$data['setting']['validate']['xss'] = $value = $data['setting']['validate']['xss'] ? 0 : 1;
\Phpcmf\Service::M()->table('field')->save($id, 'setting', dr_array2string($data['setting']));
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log($this->name.'【'.$data['fieldname'].'】'.($value ? '开启XSS' : '关闭XSS')); // 记录日志
$this->_json(1, dr_lang('操作成功'), ['value' => $value]);
break;
case 'member':
$value = $data['ismember'] ? 0 : 1;
\Phpcmf\Service::M()->table('field')->save($id, 'ismember', $value);
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log($this->name.'【'.$data['fieldname'].'】'.($value ? '前端显示' : '前端隐藏')); // 记录日志
$this->_json(1, dr_lang('操作成功'), ['value' => $value]);
break;
case 'save':
\Phpcmf\Service::M()->table('field')->save($id, 'displayorder', dr_safe_replace(\Phpcmf\Service::L('input')->get('value')));
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改排序值: '. $this->name.'【'.$data['fieldname'].'】');
$this->_json(1, dr_lang('操作成功'));
break;
}
$this->_json(0, dr_lang('未知操作'));
}
// 删除字段
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$rt = \Phpcmf\Service::M('Field')->delete_field($ids);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('删除字段'. $this->name.' '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 导出
public function export() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M()->table('field')->get($id);
if (!$data) {
$this->_admin_msg(0, dr_lang('字段(%s)不存在', $id));
}
unset($data['id']);
unset($data['relatedid']);
unset($data['relatedname']);
$data['setting'] = dr_string2array($data['setting']);
\Phpcmf\Service::V()->assign([
'data' => dr_array2string($data),
]);
\Phpcmf\Service::V()->display('api_export_code.html');exit;
}
// 导出
public function export_all() {
$ids = \Phpcmf\Service::L('input')->get('ids');
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$rt = '';
foreach ($ids as $id) {
$id = intval($id);
$data = \Phpcmf\Service::M()->table('field')->get($id);
if (!$data) {
$this->_admin_msg(0, dr_lang('字段(%s)不存在', $id));
}
unset($data['id']);
unset($data['relatedid']);
unset($data['relatedname']);
$data['setting'] = dr_string2array($data['setting']);
$rt.= dr_array2string($data).PHP_EOL;
}
\Phpcmf\Service::V()->assign([
'data' => $rt,
]);
\Phpcmf\Service::V()->display('api_export_code.html');exit;
}
// 导入
public function import_add() {
if (IS_AJAX_POST) {
$code = \Phpcmf\Service::L('input')->post('code');
$arr = explode(PHP_EOL, $code);
if (!$arr) {
$this->_json(0, dr_lang('代码不能为空'));
}
$save = [];
foreach ($arr as $t) {
if ($t) {
$data = dr_string2array($t);
if (!$data) {
$this->_json(0, dr_lang('代码解析失败'));
}
$field = \Phpcmf\Service::L('field')->get($data['fieldtype']);
if (!$field) {
$this->_json(0, dr_lang('字段类别(%s)文件不存在', $data['fieldtype']));
} elseif (empty($data['name'])) {
$this->_json(0, dr_lang('字段显示名称不能为空'));
}
if (empty($data['fieldname'])) {
$data['fieldname'] = $data['name'];
}
if (!preg_match('/^[a-z]+[a-z0-9\_]+$/i', $data['fieldname'])) {
$this->_json(0, dr_lang('字段(%s)名称不规范', $data['fieldname']));
} elseif (strlen($data['fieldname']) > 30) {
$this->_json(0, dr_lang('字段(%s)名称太长', $data['fieldname']));
} elseif (\Phpcmf\Service::M('Field')->exitsts($data['fieldname'])) {
$this->_json(0, dr_lang('字段(%s)已经存在', $data['fieldname']));
} else {
$save[] = $data;
}
}
}
if (!$save) {
$this->_json(0, dr_lang('没有可用的导入字段'));
}
// 入库操作
foreach ($save as $data) {
$field = \Phpcmf\Service::L('field')->get($data['fieldtype']);
if (isset($data['id'])) {
unset($data['id']);
}
$data['setting'] = dr_string2array($data['setting']);
$rt = \Phpcmf\Service::M('Field')->add($data, $field);
if (!$rt['code']) {
$this->_json(0, dr_lang($rt['msg']));
}
}
$this->_cache(); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('导入字段:'.$this->name); // 记录日志
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'data' => '',
'form' => dr_form_hidden(),
]);
\Phpcmf\Service::V()->display('api_export_code.html');
exit;
}
// 联动更新缓存
private function _cache() {
list($case_name, $a) = explode('-', $this->relatedname);
if (function_exists('myfield_cache_'.$case_name)) {
call_user_func('myfield_cache_'.$case_name);
} else {
switch ($case_name) {
case 'form':
// _网站表单 form-站点id, 表单id
\Phpcmf\Service::M('cache')->sync_cache('form', 'form', 1); // 自动更新缓存
break;
case 'tag':
// _网站tag
\Phpcmf\Service::M('cache')->sync_cache('tag', 'tag', 1); // 自动更新缓存
break;
case 'linkage':
// 联动菜单
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
break;
case 'member':
// _用户主表
\Phpcmf\Service::M('cache')->sync_cache('member'); // 自动更新缓存
break;
case 'navigator':
// _导航链接
\Phpcmf\Service::M('cache')->sync_cache('navigator', 'navigator', 1); // 自动更新缓存
break;
case 'order':
// 订单插件
break;
case 'page':
// 网站单页
\Phpcmf\Service::M('cache')->sync_cache('page', 'page', 1); // 自动更新缓存
break;
case 'table':
// 任意表
break;
case 'module':
// 模块字段
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
break;
case 'mform':
// 模块表单
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
break;
case 'category':
// 栏目自定义字段
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
break;
case 'site':
// 网站信息
\Phpcmf\Service::L('cache')->del_data('my-site-'.SITE_ID);
break;
default:
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
break;
}
}
}
// 初始化设置
private function _set_init() {
$local = \Phpcmf\Service::Apps(true);
if ($local) {
foreach ($local as $dir => $path) {
if (is_file($path.'Config/Myfield.php')) {
require $path.'Config/Myfield.php';
}
}
}
$ismain = $issearch = $iscategory = 0;
list($case_name, $a) = explode('-', $this->relatedname);
if (function_exists('myfield_init_'.$case_name)) {
$rt = call_user_func_array('myfield_init_'.$case_name, [
$this->relatedname,
$this->relatedid
]);
if (!$rt['code']) {
$this->_admin_msg(0, $rt['msg']);
}
$this->data = $rt['data']['data'];
$this->name = $rt['data']['name'];
$this->backurl = $rt['data']['backurl'];
if (isset($rt['data']['ismain']) && $rt['data']['ismain']) {
$ismain = 1;
}
\Phpcmf\Service::M('Field')->func = $case_name; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $this->data;
} else {
switch ($case_name) {
case 'form':
// _网站表单 form-站点id, 表单id
list($a, $siteid) = explode('-', $this->relatedname);
$this->data = \Phpcmf\Service::M()->init(['db' => $siteid, 'table' => $siteid.'_form'])->get($this->relatedid);
if (!$this->data) {
$this->_admin_msg(0, dr_lang('表单【%s】不存在', $this->relatedid));
}
$this->name = dr_lang('表单【%s】字段', $this->data['name']);
$this->backurl = ''; // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'form'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $this->data;
break;
case 'site':
// 网站信息
$ismain = 1;
$this->name = dr_lang('自定义字段');
$this->backurl = \Phpcmf\Service::L('Router')->url('cms/site_param/index'); // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'site'; // 重要标识: 函数和识别码
break;
case 'tag':
// _网站tag
$ismain = 1;
$this->name = dr_lang('自定义字段');
$this->backurl = \Phpcmf\Service::L('Router')->url('tag/home/index'); // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'tag'; // 重要标识: 函数和识别码
break;
case 'linkage':
// 联动菜单
$ismain = 1;
$this->name = dr_lang('联动菜单字段');
$this->backurl = ''; // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'linkage'; // 重要标识: 函数和识别码
break;
case 'member':
// _用户主表
$ismain = 1;
$this->name = dr_lang('自定义字段');
$this->backurl = \Phpcmf\Service::L('Router')->url('member/field/index'); // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'member'; // 重要标识: 函数和识别码
break;
case 'navigator':
// _导航链接
$ismain = 1;
$this->name = dr_lang('自定义字段');
$this->backurl = \Phpcmf\Service::L('Router')->url('navigator/home/index'); // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'navigator'; // 重要标识: 函数和识别码
break;
case 'order':
// 订单插件
$ismain = 1;
$this->name = dr_lang('自定义字段');
$this->backurl = \Phpcmf\Service::L('Router')->url('order/field/index'); // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'order'; // 重要标识: 函数和识别码
break;
case 'page':
// 网站单页
$ismain = 1;
$this->name = dr_lang('自定义字段');
$this->backurl = \Phpcmf\Service::L('Router')->url('page/home/index'); // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'page'; // 重要标识: 函数和识别码
break;
case 'table':
// 任意表
$ismain = 1;
$this->name = '【'.\Phpcmf\Service::M()->dbprefix($a).'】';
\Phpcmf\Service::M('Field')->data = $a;
\Phpcmf\Service::M('Field')->func = 'table'; // 重要标识: 函数和识别码
break;
case 'module':
// 模块字段
$this->data = \Phpcmf\Service::M()->table('module')->get($this->relatedid);
if (!$this->data) {
$this->_admin_msg(0, dr_lang('模块【%s】不存在', $this->relatedid));
}
$this->backurl = ''; // 返回uri地址
$this->name = dr_lang('模块【%s】字段', $this->data['dirname']);
\Phpcmf\Service::M('Field')->func = 'module'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $this->data;
$this->namespace = $this->data['dirname'];
break;
case 'mform':
// 模块表单
$this->data = \Phpcmf\Service::M()->table('module_form')->get($this->relatedid);
if (!$this->data) {
$this->_admin_msg(0, dr_lang('模块【%s】不存在', $this->relatedid));
}
$this->backurl = ''; // 返回uri地址
$this->name = dr_lang('模块【%s】的表单【%s】字段', $a, $this->data['name']);
\Phpcmf\Service::M('Field')->func = 'mform'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $this->data;
$this->namespace = $this->data['module'];
break;
case 'category':
// 栏目自定义字段
$ismain = 1;
$this->name = dr_lang('栏目自定义字段');
$this->backurl = ''; // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'category'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $a;
$this->module = \Phpcmf\Service::L('cache')->get('module-'.SITE_ID.'-'.$a);
if (!$this->module) {
$this->_admin_msg(0, dr_lang('模块【%s】缓存不存在', $a));
}
break;
case 'catmodule':
// 识别栏目模型字段
$ismain = 1;
$issearch = 1;
$iscategory = 1;
$module = $a;
$cache = \Phpcmf\Service::L('cache')->get('module-'.SITE_ID.'-'.$module);
if (!$cache) {
$this->_admin_msg(0, dr_lang('模块【%s】缓存不存在', $module));
}
if ($this->relatedid) {
$this->data = dr_cat_value($cache['mid'], $this->relatedid);
if (!$this->data) {
$this->_admin_msg(0, dr_lang('模块【%s】栏目【%s】缓存不存在', $module, $this->relatedid));
}
if ($module == 'share') {
$this->data['tid'] != 1 && $this->_admin_msg(0, dr_lang('模块栏目才支持创建'));
$this->data['dirname'] = $this->data['mid'];
$this->backurl = \Phpcmf\Service::L('Router')->url('category/index'); // 返回uri地址
$this->name = dr_lang('模块【%s】栏目【#%s】模型字段', $this->data['mid'], $this->relatedid);
} else {
$this->data['dirname'] = $module;
$this->backurl = \Phpcmf\Service::L('Router')->url($module.'/category/index'); // 返回uri地址
$this->name = dr_lang('模块【%s】栏目【#%s】模型字段', $module, $this->relatedid);
}
} else {
$this->data = [
'dirname' => $module,
];
$this->name = dr_lang('模块【%s】栏目公共模型字段', $module);
$this->backurl = \Phpcmf\Service::L('Router')->url('module/module_category/field_index', ['dir' => $module]); // 返回uri地址
}
$this->module = $cache;
\Phpcmf\Service::M('Field')->func = 'category_data'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $this->data;
$this->namespace = $module;
break;
default:
if (strpos($this->relatedname, 'comment-module') !== false) {
// 模块评论字段
if (!dr_is_app('comment')) {
$this->_admin_msg(0, dr_lang('系统没有安装评论插件'));
}
$ismain = 1;
list($a, $b, $module) = explode('-', $this->relatedname);
$cache = \Phpcmf\Service::L('cache')->get('module-' . SITE_ID . '-' . $module);
if (!$cache) {
$this->_admin_msg(0, dr_lang('模块【%s】缓存不存在', $module));
}
$this->name = '模块【' . $cache['name'] . '】评论字段';
$this->data = $cache['dirname'];
$this->backurl = ''; // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'comment'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $cache['dirname'];
$this->namespace = $cache['dirname'];
} elseif (strpos($this->relatedname, 'comment-mform') !== false) {
// 模块评论字段
if (!dr_is_app('comment')) {
$this->_admin_msg(0, dr_lang('系统没有安装评论插件'));exit;
}
$ismain = 1;
list($a, $b, $module, $fid) = explode('-', $this->relatedname);
$cache = \Phpcmf\Service::L('cache')->get('module-'.SITE_ID.'-'.$module);
if (!$cache) {
$this->_admin_msg(0, dr_lang('模块【%s】缓存不存在', $module));
} elseif (!$cache['form'][$fid]) {
$this->_admin_msg(0, dr_lang('模块【%s】表单【%s】缓存不存在', $module, $fid));
}
$this->name = '模块【'.$cache['name'].'】表单【'.$cache['form'][$fid]['name'].'】评论字段';
$this->data = $cache['dirname'].'_form_'.$cache['form'][$fid]['table'];
$this->backurl = ''; // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'comment'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $this->data;
$this->namespace = $cache['dirname'];
} elseif (strpos($this->relatedname, 'comment-form') !== false) {
// 表单评论字段
if (!dr_is_app('comment')) {
$this->_admin_msg(0, dr_lang('系统没有安装评论插件'));exit;
}
$ismain = 1;
list($a, $b, $fid) = explode('-', $this->relatedname);
$cache = \Phpcmf\Service::L('cache')->get('form-'.$this->relatedid, $fid);
if (!$cache) {
$this->_admin_msg(0, dr_lang('表单【%s】缓存不存在', $fid));
}
$this->name = '表单【'.$cache['name'].'】评论字段';
$this->data = 'form_'.$cache['table'];
$this->backurl = ''; // 返回uri地址
\Phpcmf\Service::M('Field')->func = 'comment'; // 重要标识: 函数和识别码
\Phpcmf\Service::M('Field')->data = $this->data;
} elseif (function_exists('myfield_info_'.$case_name)) {
// 其他自定义
$rt = call_user_func_array('myfield_info_'.$case_name, array(
$this->relatedname,
$this->relatedid
));
if (is_array($rt)) {
list(
$ismain,
$this->name,
$this->data,
\Phpcmf\Service::M('Field')->func,
$this->backurl
) = $rt;
\Phpcmf\Service::M('Field')->data = $this->data;
} else {
$this->_admin_msg(0, $rt);
}
}
break;
}
}
\Phpcmf\Service::V()->assign('fmid', \Phpcmf\Service::M('Field')->func);
if (!$this->name) {
$this->_admin_msg(0, dr_lang('字段来源未定义'));
}
return [$ismain, $issearch, $iscategory];
}
}
+492
View File
@@ -0,0 +1,492 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Home extends \Phpcmf\Common
{
public function home() {
$this->index();
}
public function main() {
if (is_file(WRITEPATH.'update.txt')) {
unlink(WRITEPATH.'update.txt');
dr_redirect(dr_url('cache/index'));
} elseif (is_file(WRITEPATH.'check.txt')) {
unlink(WRITEPATH.'check.txt');
dr_redirect(dr_url('check/index'));
}
$local = \Phpcmf\Service::Apps(1);
if ($local) {
foreach ($local as $dir => $path) {
if (is_file(dr_get_app_dir($dir).'Config/Panel.php')) {
\Phpcmf\Service::V()->admin(dr_get_app_dir($dir).'Views/');
require dr_get_app_dir($dir).'Config/Panel.php';
exit;
}
}
}
$table_data = [];
if (is_file(WRITEPATH.'config/main.php')) {
$table_data = require WRITEPATH.'config/main.php';
}
// 验证权限
if ($table_data && !dr_in_array(1, $this->admin['roleid'])) {
// 不是超管用户
$auth = \Phpcmf\Service::M('system')->get_setting('index_main');
if ($auth) {
foreach ($table_data as $name => $t) {
$key = md5($name);
if (isset($auth[$key]) && !dr_array_intersect($this->admin['roleid'], (array)$auth[$key])) {
unset($table_data[$name]); // 无权限移除
}
}
}
}
$menu = [
'控制台' => ['home/main', 'fa fa-home'],
'自定义控制台' => ['home/edit', 'fa fa-edit'],
//'后台功能地图' => ['js:dr_sitemap', 'fa fa-sitemap'],
'访问项目首页' => ['blank:api/gohome', 'fa fa-send'],
];
if (!dr_in_array(1, $this->admin['roleid'])) {
unset($menu['自定义控制台']);
}
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu($menu),
'admin' => $this->admin,
'domain' => dr_get_domain_name(ROOT_URL),
'license' => $this->cmf_license,
'table_data' => $table_data,
'cmf_update' => $this->cmf_version['updatetime'],
'cmf_version' => $this->cmf_version['version'],
]);
\Phpcmf\Service::V()->display($table_data ? 'index_main.html' : 'main.html');
}
public function init_edit() {
$file = WRITEPATH.'config/main.php';
\Phpcmf\Service::L('Config')->file($file, '后台自定义面板', 32)->to_require([]);
$this->_json(1, dr_lang('自定义面板恢复成功'));
}
//后台自定义面板
public function edit() {
if (!dr_in_array(1, $this->admin['roleid'])) {
$this->_admin_msg(0, dr_lang('无权限操作'));
}
$file = WRITEPATH.'config/main.php';
if (IS_POST) {
$data = \Phpcmf\Service::L('input')->post('tables');
\Phpcmf\Service::L('Config')->file($file, '后台自定义面板', 32)->to_require($data);
$this->_json(1, dr_lang('操作成功'));
exit;
}
if (is_file($file)) {
$data = require $file;
} else {
$data = [];
}
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'控制台' => ['home/main', 'fa fa-home'],
'自定义控制台' => ['home/edit', 'fa fa-edit'],
'help' => [718],
]
),
'tables' => $this->_main_table(),
'table_data' => $data,
]);
\Phpcmf\Service::V()->display('index_edit.html');
}
//后台自定义面板 权限划分
public function auth_edit() {
$name = \Phpcmf\Service::L('input')->get('name');
$data = \Phpcmf\Service::M('system')->get_setting('index_main');
if (IS_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
if (!$post) {
$post = [];
}
$post[] = 1;
$data[$name] = array_unique($post);
\Phpcmf\Service::M('system')->save_setting('index_main', $data);
\Phpcmf\Service::M('system')->cache();
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'data' => $data[$name],
'form' => dr_form_hidden(),
'role' => \Phpcmf\Service::C()->get_cache('auth'),
]);
\Phpcmf\Service::V()->display('index_auth_edit.html');
}
public function index() {
// 账号是否强制了简化模式
if (!IS_API_HTTP) {
if (\Phpcmf\Service::M('auth')->is_admin_min_mode()) {
$this->min();exit;
} elseif ($this->admin['setting']['admin_min']) {
// 自己切换的
$this->min();exit;
}
}
$menu = \Phpcmf\Service::L('cache')->get('menu-admin');
if (!$menu) {
$m = \Phpcmf\Service::M('menu')->cache();
$menu = $m['admin'];
}
$first = 0;
$mstring = $string = '';
$menu_top = $my_menu = [];
if ($this->admin['adminid'] > 1) {
foreach ($menu as $t) {
dr_in_array($t['mark'], $this->admin['system']['mark']) && $my_menu[$t['id']] = $t;
}
} else {
$my_menu = $menu;
}
// 挂钩点
$rt = \Phpcmf\Hooks::trigger_callback('admin_menu', $menu, $my_menu);
if ($rt && isset($rt['code']) && $rt['code']) {
$my_menu = $rt['msg'];
}
// 默认的首页内容
$main_url = dr_url('home/main');
$main_name = dr_lang('后台首页');
$main_link = '';
$main_menu = [];
if (isset($_GET['go']) && $_GET['go']) {
$go = urldecode((string)\Phpcmf\Service::L('input')->get('go'));
$url = parse_url($go);
if (isset($url['query']) && $url['query']) {
parse_str($url['query'], $p);
$uri = trim($p['s'].'/'.$p['c'].'/'.$p['m'], '/');
$main_menu = \Phpcmf\Service::L('cache')->get('menu-admin-uri', $uri);
if ($main_menu) {
$first = $main_menu['tid'];
$main_url = dr_url($uri);
$main_name = dr_lang($main_menu['name'] ? $main_menu['name'] : '默认首页');
$main_link = 'Mlink('.$main_menu['tid'].', '.$main_menu['pid'].', '.$main_menu['id'].', \'\');';
}
}
}
if ($my_menu) {
// 加载全部插件的
$local = \Phpcmf\Service::Apps();
foreach ($local as $dir => $path) {
// 判断插件目录
if (is_file($path.'install.lock') && is_file($path.'Models/Auth.php') && is_file($path.'Config/App.php')) {
$cfg = require $path.'Config/App.php';
if ($cfg['type'] == 'app' && !$cfg['ftype']) {
$obj = \Phpcmf\Service::M('auth', $dir);
if (method_exists($obj, 'get_admin_menu_data')) {
$my_menu = $obj->get_admin_menu_data($my_menu);
}
}
}
}
// 权限判断并筛选
foreach ($my_menu as $tid => $top) {
if (!$top['left']) {
unset($my_menu[$tid]);
continue; // 没有分组菜单就不要
} elseif (SITE_ID > 1 && !dr_in_array(SITE_ID, $top['site'])) {
unset($my_menu[$tid]);
continue; // 没有划分本站点就不显示
} elseif ($top['mark'] && strpos($top['mark'], 'app-') === 0) {
// 判断应用模块权限
list($a, $mm) = explode('-', $top['mark']);
if ($mm) {
$mp = dr_get_app_dir($mm);
if (is_file($mp.'Config/App.php')) {
$config = require $mp.'Config/App.php';
// 如果是内容模块
if ((isset($config['ftype']) && $config['ftype'] == 'module') || $config['type'] == 'module') {
if (!$this->get_cache('module-'.SITE_ID.'-content', $mm)) {
unset($top[$tid]);
unset($my_menu[$tid]);
continue;
}
}
}
}
}
$left_string = '';
!$first && $first = $tid;
foreach ($top['left'] as $if => $left) {
if (!$left['link']) {
unset($top['left'][$if]);
unset($my_menu[$tid]['left'][$if]);
continue; // 没有链接菜单就不要
} elseif (SITE_ID > 1 && !dr_in_array(SITE_ID, $left['site'])) {
unset($top['left'][$if]);
unset($my_menu[$tid]['left'][$if]);
continue; // 没有划分本站点就不显示
}
// 链接菜单开始
$link_string = '';
foreach ($left['link'] as $i => $link) {
if (SITE_ID > 1 && !dr_in_array(SITE_ID, $link['site'])) {
unset($left['link'][$i]);
unset($my_menu[$tid]['left'][$if]['link'][$i]);
continue; // 没有划分本站点就不显示
} elseif ($link['uri'] && !\Phpcmf\Service::M('auth')->_is_admin_auth($link['uri'], 1)) {
// 判断权限
unset($left['link'][$i]);
unset($my_menu[$tid]['left'][$if]['link'][$i]);
continue;
} elseif ($link['mark'] && $left['mark'] == 'content-module') {
// 内容模块权限判断
list($ac, $name, $cname) = explode('-', $link['mark']);
if ($ac == 'module' && !$this->get_cache('module-'.SITE_ID.'-content', $name)) {
unset($left['link'][$i]);
unset($my_menu[$tid]['left'][$if]['link'][$i]);
continue;
}
// 网站表单权限判断
if ($ac == 'app' && $name == 'form' && !$this->get_cache('form-'.SITE_ID, $cname)) {
unset($left['link'][$i]);
unset($my_menu[$tid]['left'][$if]['link'][$i]);
continue;
}
} elseif (SITE_ID > 1 && $link['uri'] && $link['uri'] == 'cloud/local') {
// 多站点不显示应用
unset($left['link'][$i]);
unset($my_menu[$tid]['left'][$if]['link'][$i]);
continue;
} elseif ($link['mark'] && $left['mark'] == 'content-verify') {
// 内容模块审核部分权限判断
list($ac, $ab, $name, $cc, $dd) = explode('-', $link['mark']);
if ($ac.'-'.$ab == 'verify-module' && !$this->get_cache('module-'.SITE_ID.'-content', $name)) {
unset($left['link'][$i]);
unset($my_menu[$tid]['left'][$if]['link'][$i]);
continue;
}
} elseif (IS_OEM_CMS && $link['uri'] == 'cloud/bf') {
// oem版排除对比菜单
unset($left['link'][$i]);
unset($my_menu[$tid]['left'][$if]['link'][$i]);
continue;
}
$left['link'][$i]['url'] = $link['url'] ? $link['url'] : \Phpcmf\Service::L('Router')->url($link['uri']);
$left['link'][$i]['icon'] = $link['icon'] ? $link['icon'] : 'fa fa-th-large';
if (!$main_menu) {
$main_menu = $link;
}
$link_string = 'true';
}
if (!$link_string) {
unset($top['left'][$if]);
unset($my_menu[$tid]['left'][$if]);
continue; // 没有链接菜单就不要
}
$left_string = 'true';
$top['left'][$if] = $left;
}
if (!$left_string) {
$first == $tid && $first = 0;
unset($my_menu[$tid]);
continue; // 没有分组菜单就不要
}
$my_menu[$tid] = $top;
unset($top['left']);
$menu_top[$tid] = $top;
}
}
if (!$menu_top && SITE_ID > 1) {
$this->_admin_msg(0, dr_lang('没有给当前站点分配管理菜单权限'));
}
if (IS_API_HTTP) {
$vue_menu = [];
foreach ($my_menu as $i => $top) {
$vue_menu[$i] = [
'heading' => $top['name'],
'route' => $top['mark'],
'fontIcon' => $top['icon'],
'pages' => [],
];
foreach ($top['left'] as $f => $left) {
$vue_menu[$i]['pages'][$f] = [
'sectionTitle' => $left['name'],
'route' => $left['mark'],
'fontIcon' => $left['icon'],
'sub' => [],
];
foreach ($left['link'] as $l => $link) {
$vue_menu[$i]['pages'][$f]['sub'][] = [
'heading' => $link['name'],
'route' => '/'.$link['uri'],
'fontIcon' => $link['icon'],
];
}
}
}
$this->_json(1, 'ok', ['menu' => $vue_menu]);
}
\Phpcmf\Service::V()->assign([
'top' => $menu_top,
'first' => $first,
'my_menu' => $my_menu,
'is_index' => 1,
'main_url' => $main_url,
'main_link' => $main_link,
'main_menu' => $main_menu,
'main_name' => $main_name,
'is_search_help' => IS_OEM_CMS ? 0 : CI_DEBUG,
]);
\Phpcmf\Service::V()->display('index.html');exit;
}
// 简化模式界面
public function min() {
$menu = \Phpcmf\Service::L('cache')->get('menu-admin-min');
if (!$menu) {
$m = \Phpcmf\Service::M('menu')->cache();
$menu = $m['admin-min'];
}
$admin_menu = \Phpcmf\Service::L('cache')->get('menu-admin-uri');
$my_menu = $menu;
// 默认的首页内容
$main_url = dr_url('home/main');
$main_link = '';
$main_menu = [];
if (isset($_GET['go']) && $_GET['go']) {
$go = urldecode((string)\Phpcmf\Service::L('input')->get('go'));
$url = parse_url($go);
if (isset($url['query']) && $url['query']) {
parse_str($url['query'], $p);
$uri = trim($p['s'].'/'.$p['c'].'/'.$p['m'], '/');
$main_menu = \Phpcmf\Service::L('cache')->get('menu-admin-uri', $uri);
if ($main_menu) {
$first = $main_menu['tid'];
$main_url = dr_url($uri);
$main_link = 'Mlink('.$main_menu['tid'].', '.$main_menu['pid'].', '.$main_menu['id'].', \'\');';
}
}
}
if ($my_menu) {
// 加载全部插件的
$local = \Phpcmf\Service::Apps();
foreach ($local as $dir => $path) {
// 判断插件目录
if (is_file($path.'install.lock') && is_file($path.'Models/Auth.php') && is_file($path.'Config/App.php')) {
$cfg = require $path.'Config/App.php';
if ($cfg['type'] == 'app' && !$cfg['ftype']) {
$obj = \Phpcmf\Service::M('auth', $dir);
if (method_exists($obj, 'get_admin_menu_data')) {
$my_menu = $obj->get_admin_menu_data($my_menu);
}
}
}
}
// 权限判断并筛选
foreach ($my_menu as $tid => $left) {
if (!$left['link']) {
continue; // 没有分组菜单就不要
}
// 链接菜单开始
$link_string = '';
foreach ($left['link'] as $i => $link) {
if ($link['uri'] && !$this->_is_admin_auth($link['uri'])) {
// 判断权限
unset($left['link'][$i]);
continue;
} elseif ($link['mark'] && $left['mark'] == 'content-module') {
// 内容模块权限判断
list($ac, $name) = explode('-', $link['mark']);
if ($ac == 'module' && !$this->get_cache('module-'.SITE_ID.'-content', $name)) {
unset($left['link'][$i]);
continue;
}
// 网站表单权限判断
list($ac, $name, $cname) = explode('-', $link['mark']);
if ($ac == 'app' && $name == 'form' && !$this->get_cache('form-'.SITE_ID, $cname)) {
unset($left['link'][$i]);
continue;
}
} elseif (SITE_ID > 1 && $link['uri'] && $admin_menu[$link['uri']] && !dr_in_array(SITE_ID, $admin_menu[$link['uri']]['site'])) {
// 没有划分本站点就不显示
unset($left['link'][$i]);
continue;
} elseif (SITE_ID > 1 && $link['uri'] && $link['uri'] == 'cloud/local') {
// 多站点不显示应用
unset($left['link'][$i]);
continue;
} elseif ($link['mark'] && $left['mark'] == 'content-form') {
// 网站表单权限判断
} elseif ($link['mark'] && $left['mark'] == 'content-verify') {
// 内容模块审核部分权限判断
list($ac, $ab, $name, $cc) = explode('-', $link['mark']);
if ($ac.'-'.$ab == 'verify-module' && !$this->get_cache('module-'.SITE_ID.'-content', $name)) {
unset($left['link'][$i]);
continue;
}
}
$left['link'][$i]['url'] = $link['url'] ? $link['url'] :\Phpcmf\Service::L('Router')->url($link['uri']);
$left['link'][$i]['icon'] = $link['icon'] ? $link['icon'] : 'fa fa-th-large';
$link_string.= 'true';
if (!$main_menu) {
$first = $tid;
$main_menu = $link;
}
}
if (!$link_string) {
unset($my_menu[$tid]);
continue; // 没有链接菜单就不要
}
$my_menu[$tid] = $left;
}
}
\Phpcmf\Service::V()->assign([
'first' => $first,
'is_min' => 1,
'is_mode' => \Phpcmf\Service::M('auth')->is_admin_min_mode(),
'my_menu' => $my_menu,
'is_index' => 1,
'main_url' => $main_url,
'main_link' => $main_link,
'main_menu' => $main_menu,
'is_search_help' => IS_OEM_CMS ? 0 : CI_DEBUG,
]);
\Phpcmf\Service::V()->display('index_min.html');exit;
}
}
+685
View File
@@ -0,0 +1,685 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 联动菜单
class Linkage extends \Phpcmf\Common {
public function index() {
\Phpcmf\Service::V()->assign([
'list' => \Phpcmf\Service::M('Linkage')->table('linkage')->getAll(),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'联动菜单' => ['linkage/index', 'fa fa-columns'],
'创建菜单' => ['add:linkage/add', 'fa fa-plus'],
'修改' => ['hide:linkage/edit', 'fa fa-edit'],
'数据管理' => ['hide:linkage/list_index', 'fa fa-table'],
'help' => [354],
]
),
]);
\Phpcmf\Service::V()->display('linkage_index.html');
}
public function add() {
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$this->_validation(0, $data);
\Phpcmf\Service::L('input')->system_log('创建联动菜单('.$data['name'].')');
$rt = \Phpcmf\Service::M('Linkage')->create($data);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden()
]);
\Phpcmf\Service::V()->display('linkage_add.html');
exit;
}
public function edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('Linkage')->table('linkage')->get($id);
if (!$data) {
$this->_admin_msg(0, dr_lang('联动菜单(%s)不存在', $id));
}
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$data['code'] = strtolower($data['code']);
$this->_validation($id, $data);
$rt = \Phpcmf\Service::M('Linkage')->table('linkage')->update($id, $data);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
\Phpcmf\Service::L('input')->system_log('修改联动菜单('.$data['name'].')');
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'data' => $data,
'form' => dr_form_hidden()
]);
\Phpcmf\Service::V()->display('linkage_add.html');exit;
}
public function export_down() {
$key = (int)\Phpcmf\Service::L('input')->get('key');
$file = WRITEPATH.'temp/linkage-export-file-'.$this->uid.'-'.$key.'.json';
if (!is_file($file)) {
$this->_html_msg(0, dr_lang('导出文件不存在'));
}
set_time_limit(0);
$handle = fopen($file,"rb");
if (FALSE === $handle) {
$this->_html_msg(0, dr_lang('文件已经损坏'));
}
$filesize = filesize($file);
$link = \Phpcmf\Service::M()->table('linkage')->get($key);
header('Content-Type: application/octet-stream');
header("Accept-Ranges:bytes");
header("Accept-Length:".$filesize);
header("Content-Disposition: attachment; filename=".urlencode($link['name'].'.json'));
while (!feof($handle)) {
$contents = fread($handle, 4096);
echo $contents;
ob_flush(); //把数据从PHP的缓冲中释放出来
flush(); //把被释放出来的数据发送到浏览器
}
fclose($handle);
exit;
}
public function export() {
$key = (int)\Phpcmf\Service::L('input')->get('key');
$page = (int)\Phpcmf\Service::L('input')->get('page');
$file = WRITEPATH.'temp/linkage-export-file-'.$this->uid.'-'.$key.'.json';
if (!$page) {
$nums = \Phpcmf\Service::M()->table('linkage_data_'.$key)->counts();
if (!$nums) {
$this->_json(0, dr_lang('数据为空,无法导出'));
}
$this->_html_msg(1, dr_lang('正在准备导出数据'), dr_url('linkage/export', ['key'=>$key, 'page' => 1]));
} elseif ($page == 2) {
$nums = \Phpcmf\Service::M()->table('linkage_data_'.$key)->counts();
$this->_html_msg(1, dr_lang('导出完毕,共计%s条数据', $nums), dr_url('linkage/export_down', ['key'=>$key]), dr_lang('请关闭本窗口'));
}
$data = \Phpcmf\Service::M()->db->table('linkage_data_'.$key)->orderBy('id DESC')->get()->getResultArray();
$rt = file_put_contents($file, dr_array2string($data));
if (!$rt) {
$this->_html_msg(0, '文件写入失败');
}
$this->_html_msg(1, dr_lang('正在整理数据...'), dr_url('linkage/export', ['key'=>$key, 'page' => 2]));
}
public function import_add() {
$key = (int)\Phpcmf\Service::L('input')->get('key');
$page = (int)\Phpcmf\Service::L('input')->get('page');
$file = WRITEPATH.'temp/linkage-import-file-'.$this->uid.'-'.$key.'.json';
$table = 'linkage_data_'.$key;
if (!$page) {
if (!is_file($file)) {
$this->_html_msg(0, dr_lang('导入文件不存在'));
}
\Phpcmf\Service::M()->table($table)->clear_all();
$this->_html_msg(1, dr_lang('正在准备导入数据'), dr_url('linkage/import_add', ['key'=>$key, 'page' => 1]));
}
if (!is_file($file)) {
$nums = \Phpcmf\Service::M()->table('linkage_data_'.$key)->counts();
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
$this->_html_msg(1, dr_lang('导入完毕,共计%s条数据', $nums), '', dr_lang('请关闭本窗口'));
}
// 开始导入
$data = dr_string2array(file_get_contents($file));
if (!is_array($data)) {
$this->_html_msg(0, dr_lang('导入信息验证失败'));
}
foreach ($data as $t) {
if (is_numeric($t['cname'])) {
$t['cname'] = 'a'.$t['cname'];
} elseif (!preg_match('/^[a-z]+[a-z0-9\_]+$/i', $t['cname'])) {
$t['cname'] = dr_safe_filename($t['cname']);
}
$rt = \Phpcmf\Service::M('Linkage')->table($table)->insert($t);
if ($rt['code']) {
$count++;
}
}
unlink($file);
$this->_html_msg(1, dr_lang('正在导入数据...'), dr_url('linkage/import_add', ['key'=>$key, 'page' => 2]));
}
public function import() {
$key = (int)\Phpcmf\Service::L('input')->get('key');
\Phpcmf\Service::V()->assign([
'add_url' => dr_url('linkage/import_add', ['key' => $key]),
'upload_url' => dr_url('linkage/import_upload', ['key' => $key]),
]);
\Phpcmf\Service::V()->display('linkage_import.html');
exit;
}
// 上传处理
function import_upload() {
$key = (int)\Phpcmf\Service::L('input')->get('key');
$file = WRITEPATH.'temp/linkage-import-file-'.$this->uid.'-'.$key.'.json';
$rt = \Phpcmf\Service::L('upload')->upload_file([
'save_file' => $file, // 上传的固定文件路径
'form_name' => 'file_data', // 固定格式
'file_exts' => ['json'], // 上传的扩展名
'file_size' => 2 * 1024 * 1024, // 上传的大小限制
'attachment' => \Phpcmf\Service::M('Attachment')->get_attach_info('null'), // 固定文件时必须这样写
]);
if (!$rt['code']) {
// 失败了
exit(dr_array2string($rt));
}
// 验证json格式内容
$data = dr_string2array(file_get_contents($file));
if (!is_array($data)) {
unlink($file);
$this->_json(0, dr_lang('导入信息验证失败'));
}
// 上传成功了
exit(dr_array2string($rt));
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$rt = \Phpcmf\Service::M('Linkage')->delete_all($ids);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量联动菜单: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 验证数据
private function _validation($id, $data) {
// 表单验证配置
$config = [
'name' => [
'name' => '名称',
'rule' => [
'empty' => dr_lang('名称不能为空')
],
'filter' => [],
'length' => '200'
],
'code' => [
'name' => '别名',
'rule' => [
'empty' => dr_lang('别名不能为空'),
'table' => dr_lang('别名格式不正确'),
],
'filter' => [],
'length' => '200'
],
];
list($data, $return) = \Phpcmf\Service::L('Form')->validation($data, $config);
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
} elseif (\Phpcmf\Service::M('Linkage')->table('linkage')->is_exists($id, 'code', $data['code'])) {
$this->_json(0, dr_lang('别名已经存在'), ['field' => 'code']);
}
}
public function displayorder_edit() {
// 查询数据
$id = (int)\Phpcmf\Service::L('input')->get('id');
$key = (int)\Phpcmf\Service::L('input')->get('key');
$row = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->get($id);
if (!$row) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
$value = (int)\Phpcmf\Service::L('input')->get('value');
$rt = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->save($id, 'displayorder', $value);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改联动菜单值('.$row['name'].')的排序值为'.$value);
$this->_json(1, dr_lang('操作成功'));
}
// 禁用或者启用
public function hidden_edit() {
$id = (int)\Phpcmf\Service::L('input')->get('id');
$key = (int)\Phpcmf\Service::L('input')->get('key');
$row = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->get($id);
if (!$row) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
$i = intval(\Phpcmf\Service::L('input')->get('id'));
$v = $row['hidden'] ? 0 : 1;
\Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->update($id, ['hidden' => $v]);
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改联动菜单状态: '. $i);
$this->_json(1, dr_lang($v ? '此菜单已被禁用' : '此菜单已被启用'), ['value' => $v]);
}
public function list_del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
$key = (int)\Phpcmf\Service::L('input')->get('key');
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$rt = \Phpcmf\Service::M('Linkage')->delete_list_all($key, $ids);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量删除联动菜单: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
public function close_edit() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
$key = (int)\Phpcmf\Service::L('input')->get('key');
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
\Phpcmf\Service::M()->table('linkage_data_'.$key)->where_in('id', $ids)->update(null, [
'hidden' => 1,
]);
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量禁用联动菜单: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'));
}
public function open_edit() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
$key = (int)\Phpcmf\Service::L('input')->get('key');
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
\Phpcmf\Service::M()->table('linkage_data_'.$key)->where_in('id', $ids)->update(null, [
'hidden' => 0,
]);
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量启用联动菜单: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'));
}
// 变更分类
public function pid_edit() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
$key = (int)\Phpcmf\Service::L('input')->get('key');
$pid = (int)\Phpcmf\Service::L('input')->post('pid');
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$rt = \Phpcmf\Service::M('Linkage')->edit_pid_all($key, $pid, $ids);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量更改联动菜单分类: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 数据列表
public function list_index() {
$key = (int)\Phpcmf\Service::L('input')->get('key');
$pid = (int)\Phpcmf\Service::L('input')->get('pid');
$link = \Phpcmf\Service::M('Linkage')->table('linkage')->get($key);
if (!$link) {
$this->_admin_msg(0, dr_lang('联动菜单不存在'));
}
$select = dr_fieldform('{"name":"pid","fieldname":"pid","ismain":"1","fieldtype":"Linkage","setting":{"option":{"linkage":"'.$link['code'].'","file":"","ck_child":"0","value":"","css":""},"validate":{"required":"0","pattern":"","errortips":"","check":"","filter":"","formattr":"","tips":""}},"ismember":"1"}', 0, 1, 1);
\Phpcmf\Service::V()->assign([
'key' => $key,
'pid' => $pid,
'list' => \Phpcmf\Service::M('Linkage')->getList($link, $pid),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'联动菜单' => ['linkage/index', 'fa fa-columns'],
'数据管理' => ['hide:linkage/list_index', 'fa fa-table'],
'修改' => ['hide:linkage/list_edit', 'fa fa-edit'],
'添加' => ['linkage/list_add{key='.$key.'&pid='.$pid.'}', 'fa fa-plus'],
'help' => [354],
]
),
'select' => str_replace('data[pid]', 'pid', $select),
]);
\Phpcmf\Service::V()->display('linkage_list_index.html');
}
// 快速添加数据
public function listk_add() {
$pid = (int)\Phpcmf\Service::L('input')->get('pid');
$key = (int)\Phpcmf\Service::L('input')->get('key');
$link = \Phpcmf\Service::M('Linkage')->table('linkage')->get($key);
if (!$link) {
$this->_admin_msg(0, dr_lang('联动菜单不存在'));
}
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data', true);
$rt = \Phpcmf\Service::M('Linkage')->add_list($key, $data);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('创建联动菜单('.$data['name'].')');
$this->_json(1, $rt['msg']);
}
$select = '';
if ($pid) {
$top = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->get($pid);
if ($top) {
$select = '<input type="hidden" name="data[pid]" value="'.$pid.'">';
$select.= '<p class="form-control-static"> '.$top['name'].' </p>';
}
}
if (!$select) {
$select = '<input type="hidden" name="data[pid]" value="0">';
$select.= '<p class="form-control-static"> '.dr_lang('顶级').' </p>';
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'select' => $select
]);
\Phpcmf\Service::V()->display('linkage_list_add.html');
exit;
}
// 添加数据
public function list_add() {
$pid = (int)\Phpcmf\Service::L('input')->get('pid');
$key = (int)\Phpcmf\Service::L('input')->get('key');
$link = \Phpcmf\Service::M('Linkage')->table('linkage')->get($key);
if (!$link) {
$this->_admin_msg(0, dr_lang('联动菜单不存在'));
}
$field = \Phpcmf\Service::M('Linkage')->get_fields($key);
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$post['name'] = trim($post['name']);
if (!$post['name']) {
$this->_json(0, dr_lang('名称不能为空'));
} elseif (!$post['cname']) {
$this->_json(0, dr_lang('别名不能为空'));
} elseif (is_numeric($post['cname'])) {
$this->_json(0, dr_lang('别名不能是数字'));
} elseif (!preg_match('/^[a-z]+[a-z0-9\_]+$/i', $post['cname'])) {
$this->_json(0, dr_lang('别名名称不规范'));
} elseif (\Phpcmf\Service::M()->db->table('linkage_data_'.$key)->where('cname', $post['cname'])->countAllResults()) {
$this->_json(0, dr_lang('别名已经存在'));
}
$update = [
'pid' => $post['pid'],
'name' => $post['name'],
'cname' => $post['cname'],
];
if ($field) {
list($save, $return, $attach) = \Phpcmf\Service::L('form')->validation($post, null, $field, []);
// 输出错误
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
}
$update = dr_array22array($update, $save[1]);
}
$update['site'] = SITE_ID;
$rt = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->insert($update);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
// 附件归档
SYS_ATTACHMENT_DB && $attach && \Phpcmf\Service::M('Attachment')->handle(
$this->member['id'],
\Phpcmf\Service::M()->dbprefix('linkage_data_'.$key),
$attach
);
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('创建联动菜单('.$post['name'].')');
$this->_json(1, dr_lang('操作成功'));
}
$select = '';
if ($pid) {
$top = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->get($pid);
if ($top) {
$select = '<input type="hidden" name="data[pid]" value="'.$pid.'">';
$select.= '<p class="form-control-static"> '.$top['name'].' </p>';
}
}
if (!$select) {
$select = '<input type="hidden" name="data[pid]" value="0">';
$select.= '<p class="form-control-static"> '.dr_lang('顶级').' </p>';
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'联动菜单' => ['linkage/index', 'fa fa-columns'],
'数据管理' => ['linkage/list_index{key='.$key.'}', 'fa fa-table'],
'修改' => ['hide:linkage/list_edit', 'fa fa-edit'],
'添加' => ['linkage/list_add{key='.$key.'&pid='.$pid.'}', 'fa fa-plus'],
'help' => [354],
]
),
'select' => $select,
'myfield' => \Phpcmf\Service::L('field')->toform($this->uid, $field, []),
'reply_url' => dr_url('linkage/list_index', ['key'=> $key, 'pid' => $pid]),
]);
\Phpcmf\Service::V()->display('linkage_list_edit.html');
}
// 修改数据
public function list_edit() {
$id = (int)\Phpcmf\Service::L('input')->get('id');
$key = (int)\Phpcmf\Service::L('input')->get('key');
$link = \Phpcmf\Service::M('Linkage')->table('linkage')->get($key);
if (!$link) {
$this->_admin_msg(0, dr_lang('联动菜单不存在'));
}
$data = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->get($id);
if (!$data) {
$this->_admin_msg(0, dr_lang('联动菜单数据#%s不存在', $id));
}
$field = \Phpcmf\Service::M('Linkage')->get_fields($key);
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$post['name'] = trim($post['name']);
if (!$post['name']) {
$this->_json(0, dr_lang('名称不能为空'));
} elseif (!$post['cname']) {
$this->_json(0, dr_lang('别名不能为空'));
} elseif (is_numeric($post['cname'])) {
$this->_json(0, dr_lang('别名不能是数字'));
} elseif (!preg_match('/^[a-z]+[a-z0-9\_]+$/i', $post['cname'])) {
$this->_json(0, dr_lang('别名名称不规范'));
} else if (\Phpcmf\Service::M()->db->table('linkage_data_'.$key)->where('id<>', $id)->where('cname', $post['cname'])->countAllResults()) {
$this->_json(0, dr_lang('别名已经存在'));
}
$update = [
'pid' => $post['pid'],
'name' => $post['name'],
'cname' => $post['cname'],
];
if ($field) {
list($save, $return, $attach) = \Phpcmf\Service::L('form')->validation($post, null, $field, $data);
// 输出错误
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
}
$update = dr_array22array($update, $save[1]);
}
$rt = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->update($id, $update);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
// 附件归档
SYS_ATTACHMENT_DB && $attach && \Phpcmf\Service::M('Attachment')->handle(
$this->member['id'],
\Phpcmf\Service::M()->dbprefix('linkage_data_'.$key),
$attach
);
\Phpcmf\Service::M('cache')->sync_cache('linkage', '', 1); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改联动菜单('.$post['name'].')');
$this->_json(1, dr_lang('操作成功'));
}
$select = '';
if ($data['pid']) {
$top = \Phpcmf\Service::M('Linkage')->table('linkage_data_'.$key)->get($data['pid']);
if ($top) {
$select = '<input type="hidden" name="data[pid]" value="'.$data['pid'].'">';
$select.= '<p class="form-control-static"> '.$top['name'].' </p>';
}
}
if (!$select) {
$select = '<input type="hidden" name="data[pid]" value="0">';
$select.= '<p class="form-control-static"> '.dr_lang('顶级').' </p>';
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'data' => $data,
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'联动菜单' => ['linkage/index', 'fa fa-columns'],
'数据管理' => ['linkage/list_index{key='.$key.'}', 'fa fa-table'],
'修改' => ['hide:linkage/list_edit', 'fa fa-edit'],
'添加' => ['linkage/list_add{key='.$key.'&pid='.$data['pid'].'}', 'fa fa-plus'],
'help' => [354],
]
),
'select' => $select,
'myfield' => \Phpcmf\Service::L('field')->toform($this->uid, $field, $data),
'reply_url' => dr_url('linkage/list_index', ['key'=> $key, 'pid' => $data['pid']]),
]);
\Phpcmf\Service::V()->display('linkage_list_edit.html');
exit;
}
// 一键生成
public function cache_index() {
$key = (int)\Phpcmf\Service::L('input')->get('key');
$link = \Phpcmf\Service::M('Linkage')->table('linkage')->get($key);
if (!$link) {
$this->_html_msg(0, dr_lang('联动菜单不存在'));
}
$page = (int)\Phpcmf\Service::L('input')->get('page');
$psize = 10; // 每页处理的数量
$total = (int)\Phpcmf\Service::L('input')->get('total');
if (!$page) {
$path = WRITEPATH.'linkage/'.SITE_ID.'_'.$link['code'].'/';
dr_dir_delete($path);
$links = \Phpcmf\Service::M('Linkage')->repair($link, SITE_ID); // 修复菜单
$pids = \Phpcmf\Service::M('Linkage')->get_child_pids();
$total = dr_count($pids);
if (!$total) {
$this->_html_msg(0, dr_lang('无可用数据'));
}
// 存储执行
\Phpcmf\Service::L('cache')->set_auth_data('linkage-all-'.$key, $links, SITE_ID);
\Phpcmf\Service::L('cache')->set_auth_data('linkage-cache-'.$key, array_chunk($pids, $psize), SITE_ID);
$this->_html_msg(1, dr_lang('正在执行中...'), dr_url('linkage/cache_index', ['key' => $key]).'&total='.$total.'&page='.($page+1));
}
$tpage = ceil($total / $psize); // 总页数
$pids = \Phpcmf\Service::L('cache')->get_auth_data('linkage-cache-'.$key, SITE_ID);
if (!$pids) {
$this->_html_msg(0, dr_lang('临时数据读取失败'));
} elseif (!isset($pids[$page-1]) || $page > $tpage) {
// 生成级联关系
$links = \Phpcmf\Service::L('cache')->get_auth_data('linkage-all-'.$key, SITE_ID);
\Phpcmf\Service::M('Linkage')->get_json($link, $links);
$this->_html_msg(1, dr_lang('更新完成'));
}
$field = \Phpcmf\Service::M('Linkage')->get_fields($key);
foreach ($pids[$page-1] as $pid) {
\Phpcmf\Service::M('linkage')->cache_list($link, $pid, $field);
}
$this->_html_msg( 1, dr_lang('正在执行中【%s】...', "$tpage/$page"),
dr_url('linkage/cache_index', ['key' => $key, 'total' => $total, 'page' => $page + 1])
);
}
}
+250
View File
@@ -0,0 +1,250 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Login extends \Phpcmf\Common
{
public function index() {
$url = '';
if (isset($_GET['go']) && $_GET['go']) {
$url = pathinfo(urldecode((string)\Phpcmf\Service::L('input')->get('go')));
$url = $url['basename'] && $url['basename'] != SELF ? $url['basename'] : '';
}
// 避免安装时的卡顿超时
if (is_file(WRITEPATH.'install.test')) {
set_time_limit(0);
// 创建后台默认菜单
\Phpcmf\Service::M('Menu')->init('admin');
\Phpcmf\Service::M('Menu')->init('admin_min');
// 完成之后更新缓存
\Phpcmf\Service::M('cache')->update_cache();
unlink(WRITEPATH.'install.test');
}
if (IS_AJAX_POST) {
$sn = $is_login = 0;
// 回调钩子
$data = \Phpcmf\Service::L('input')->post('data');
\Phpcmf\Hooks::trigger('admin_login_before', $data);
$rs = \Phpcmf\Hooks::trigger_callback('admin_login_post', $data);
if ($rs && isset($rs['code']) && $rs['msg']) {
// 返回登陆类型
if (!$rs['code']) {
// 登陆失败
$this->_json(0, $rs['msg']);
} else {
// 登陆成功
$is_login = 1;
}
}
if (!$is_login) {
// 账号登录
if (defined('SYS_ADMIN_LOGINS') && SYS_ADMIN_LOGINS) {
$sn = (int)$this->session()->get('fclogin_error_sn');
$time = (int)$this->session()->get('fclogin_error_time');
if (defined('SYS_ADMIN_LOGIN_TIME') && SYS_ADMIN_LOGIN_TIME && $time && SYS_TIME - $time > (SYS_ADMIN_LOGIN_TIME * 60)) {
// 超过时间了
\Phpcmf\Service::C()->session()->set('fclogin_error_sn', 0);
\Phpcmf\Service::C()->session()->set('fclogin_error_time', 0);
}
}
if (SYS_ADMIN_CODE && !\Phpcmf\Service::L('form')->check_captcha('code')) {
$this->_json(0, dr_lang('验证码不正确'));
} elseif (!IS_DEV && defined('SYS_ADMIN_LOGINS') && SYS_ADMIN_LOGINS && $sn && $sn > SYS_ADMIN_LOGINS) {
$msg = dr_lang('失败次数已达到%s次,已被禁止登录', SYS_ADMIN_LOGINS);
$msg2 = dr_lang('后台登录密码错误的次数已达到%s次', SYS_ADMIN_LOGINS);
$user = \Phpcmf\Service::M()->table('member')->where('username', $data['username'])->getRow();
if ($user) {
\Phpcmf\Service::M()->table('member_data')->update($user['id'], ['is_lock' => 1]);
$user['email'] && \Phpcmf\Service::M('member')->sendmail($user['email'], $msg2, 'admin_password_error.html', $data);
}
\Phpcmf\Service::L('input')->system_log($msg2, 1, [], $data['username']);
$this->_json(0, $msg);
} elseif (empty($data['username']) || empty($data['password'])) {
$this->_json(0, dr_lang('账号或密码必须填写'));
} else {
if (defined('SYS_ADMIN_LOGIN_AES') && SYS_ADMIN_LOGIN_AES && !isset($_POST['is_aes'])) {
$this->_json(0, IS_DEV ? '登陆模板不支持AES加密传输,请在cache/config/system.php中配置SYS_ADMIN_LOGIN_AES=0' : dr_lang('当前登录模板不支持AES加密传输'));
}
$data['username'] = dr_safe_username($data['username']);
$login = \Phpcmf\Service::M('auth')->login(
$data['username'],
$data['password'],
!IS_DEV && defined('SYS_ADMIN_SMS_CHECK') && SYS_ADMIN_SMS_CHECK
);
if (isset($this->admin) && is_array($this->admin)) {
$this->admin['uid'] = 0;
$this->admin['username'] = $data['username'];
}
if ($login['code']) {
// 登录成功
if ($login['code'] == "sms") {
$this->_json(9, dr_lang('向%s的手机发送验证码:',
substr($login['msg'], 0, 3).'****'.substr($login['msg'],-4)),
dr_authcode($login['msg'], 'ENCODE')
);
}
} else {
// 登录失败
if ($login['data'] == 3) {
// 密码错误时记录日志
\Phpcmf\Service::L('input')->password_log($data);
// 记录错误计次
if (defined('SYS_ADMIN_LOGINS') && SYS_ADMIN_LOGINS) {
\Phpcmf\Service::C()->session()->set('fclogin_error_sn', $sn + 1);
\Phpcmf\Service::C()->session()->set('fclogin_error_time', SYS_TIME);
}
} else {
// 写入日志
\Phpcmf\Service::L('input')->system_log($login['msg'], 1, [], dr_safe_replace($data['username']));
}
$this->_json(0, $login['msg']);
}
}
}
\Phpcmf\Service::L('input')->system_log('登录后台成功', 1, [], $data['username']);
if ($sn) {
// 解除禁止登陆
\Phpcmf\Service::C()->session()->set('fclogin_error_sn', 0);
\Phpcmf\Service::C()->session()->set('fclogin_error_time', 0);
}
if (IS_API_HTTP) {
return $this->_json(1, 'ok', $login['data'], true);
}
if (!$url) {
$url = SELF.'?time='.SYS_TIME;
if (isset($data['mode']) && $data['mode']) {
// 模式选择
$admin = \Phpcmf\Service::M()->table('admin')->where('uid', $login['code'])->getRow();
$setting = (array)dr_string2array($admin['setting']);
if ($data['mode'] == 2) {
// 简化
$setting['admin_min'] = 1;
file_put_contents(WRITEPATH.'config/admin.mode', 1);
} else {
// 完整
if (\Phpcmf\Service::M('auth')->is_admin_min_mode()) {
$this->_json(0, dr_lang('此账号无法使用完整模式'));
}
$setting['admin_min'] = 0;
@unlink(WRITEPATH.'config/admin.mode');
}
\Phpcmf\Service::M()->table('admin')->update($login['code'], [
'setting' => dr_array2string($setting)
]);
}
}
$url = dr_redirect_safe_check(\Phpcmf\Service::L('input')->xss_clean($url, true));
// 写入日志
$this->admin = $login['data'];
return $this->_json(1, 'ok', ['sync' => [], 'url' => $url], true);
}
// 检测登录了就跳转首页
if ($this->member) {
$uid = (int)$this->session()->get('uid');
if ($uid == $this->member['uid']) {
$rt = \Phpcmf\Service::M('auth')->member($this->member, 1);
if (!$rt['code']) {
$this->_admin_msg(0, $rt['msg']);
} else {
dr_redirect(SELF);exit;
}
}
}
$license = \Phpcmf\Service::R(MYPATH.'Config/License.php');
$name = dr_oauth_list();
if (dr_is_app('weixin')) {
$name['wechat'] = [];
}
$oauth = [];
if ($name) {
$ourl = ADMIN_URL.SELF.'?c=api&m=oauth&is_admin_call=1&name=';
foreach ($name as $value => $t) {
if (!isset($this->member_cache['oauth'][$value]['id'])
|| !$this->member_cache['oauth'][$value]['id']) {
continue;
}
if (in_array($value, ['weixin', 'wechat'])) {
if (dr_is_weixin_app()) {
dr_is_app('weixin') && $oauth['wechat'] = [
'title' => '微信公众号登录',
'name' => 'wechat',
'url' => OAUTH_URL.'index.php?s=weixin&c=member&m=login_url&back='.urlencode($ourl.'wechat'),
];
} else {
$oauth[$value] = [
'title' => ($value == 'weixin' ? '微信扫码' : '微信公众号').'登录',
'name' => $value,
'url' => OAUTH_URL.'index.php?s=api&c=oauth&m=index&name='.$value.'&type=login&back='.urlencode($ourl.$value),
];
}
} else {
$oauth[$value] = [
'title' => $t['name'].'登录',
'name' => $value,
'url' => OAUTH_URL.'index.php?s=api&c=oauth&m=index&name='.$value.'&type=login&back='.urlencode($ourl.$value),
];
}
}
}
$mode = is_file(WRITEPATH.'config/admin.mode') ? 2 : 1;
$mytpl = '';
$rs = \Phpcmf\Hooks::trigger_callback('admin_login_html', $data);
if ($rs && isset($rs['code']) && $rs['code']) {
$mytpl = $rs['msg'];
}
\Phpcmf\Service::V()->assign([
'mode' => $mode,
'form' => dr_form_hidden(),
'oauth' => $oauth,
'mytpl' => $mytpl,
'license' => $license,
'crypto_iv' => substr(md5(SYS_KEY), 10, 16),
'crypto_key' => substr(md5(SYS_KEY), 0, 16),
'sms_url' => WEB_DIR.SELF.'?c=login&m=sms',
'login_url' => WEB_DIR.SELF.'?c=login&go='.urlencode($url).'&'.($is_sms ? 'is_sms=1' : ''),
'rlogin_url' => WEB_DIR.SELF.'?c=login&go='.urlencode($url),
]);
if (isset($_GET['is_cloud']) && $_GET['is_cloud']) {
\Phpcmf\Service::V()->display('cloud_login_admin.html');exit;
} else {
\Phpcmf\Service::V()->display('login.html');exit;
}
}
// 子站客户端自动登录
public function fclient() {
$file = ROOTPATH.'api/fclient/login.php';
if (!is_file($file)) {
$this->_admin_msg(0, '子站客户端程序'.(IS_DEV ? $file : '').'未安装');
}
require $file;
}
public function out() {
$this->session()->remove('uid');
$this->session()->remove('admin');
$this->session()->remove('siteid');
return $this->_json(1, dr_lang('您已经安全退出系统了'), 0, true);
}
}
+281
View File
@@ -0,0 +1,281 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Menu extends \Phpcmf\Common
{
private $form; // 表单验证配置
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'后台菜单' => ['menu/index', 'fa fa-list-alt'],
'初始化菜单' => ['ajax:menu/init', 'fa fa-refresh'],
'help' => [927],
]
));
// 表单验证配置
$this->form = [
'name' => [
'name' => '菜单名称',
'rule' => [
'empty' => dr_lang('菜单名称不能为空')
],
'filter' => [],
'length' => '200'
],
'icon' => [
'name' => '菜单图标',
'rule' => [
'empty' => dr_lang('菜单图标不能为空')
],
'filter' => [],
'length' => '100'
],
'uri' => [
'name' => '系统路径',
'rule' => [
'empty' => dr_lang('系统路径不能为空')
],
'filter' => [],
'length' => '200'
],
'url' => [
'name' => '实际地址',
'rule' => [
'empty' => dr_lang('实际地址不能为空')
],
'filter' => [
'url'
],
'length' => '200'
],
];
}
public function index() {
\Phpcmf\Service::V()->assign([
'data' => \Phpcmf\Service::M('menu')->gets('admin'),
'color' => ['blue', 'red', 'green', 'dark', 'yellow'],
]);
\Phpcmf\Service::V()->display('menu_index.html');
}
public function add() {
$pid = intval(\Phpcmf\Service::L('input')->get('pid'));
$top = \Phpcmf\Service::M('menu')->get_top('admin');
$type = $pid ? (isset($top[$pid]) ? 2 : 3) : 1;
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$data = $this->_validation($type, $data);
if ($data['uri'] && \Phpcmf\Service::M()->table('admin_menu')->where('uri', $data['uri'])->counts()) {
// 链接菜单判断重复
$this->_json(0, dr_lang('系统路径已经存在'), ['field' => 'uri']);
}
$rt = \Phpcmf\Service::M('menu')->_add('admin', $pid, $data);
if ($rt['code']) {
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('添加后台菜单: '.$data['name']);
$this->_json(1, dr_lang('操作成功'));
} else {
$this->_json(0, $rt['msg']);
}
}
\Phpcmf\Service::V()->assign([
'type' => $type,
'form' => dr_form_hidden()
]);
\Phpcmf\Service::V()->display('menu_add.html');
exit;
}
public function site_add() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
$data = \Phpcmf\Service::M()->db->table('admin_menu')->whereIN('id', $ids)->get()->getResultArray();
if (!$data) {
$this->_json(0, dr_lang('无可用菜单'));
}
$sids = \Phpcmf\Service::L('input')->post('siteid');
if (!$sids) {
foreach ($data as $t) {
\Phpcmf\Service::M()->db->table('admin_menu')->where('id', $t['id'])->update([
'site' => ''
]);
}
$this->_json(1, dr_lang('取消成功'));
}
foreach ($data as $t) {
$value = dr_string2array($t['site']);
foreach ($sids as $sid) {
$value[$sid] = $sid;
}
\Phpcmf\Service::M()->db->table('admin_menu')->where('id', $t['id'])->update([
'site' => dr_array2string($value)
]);
}
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
$this->_json(1, dr_lang('划分成功'));
}
public function site_del() {
$id = (int)\Phpcmf\Service::L('input')->get('id');
$data = \Phpcmf\Service::M('menu')->getRowData('admin', $id);
if (!$data) {
$this->_json(0, dr_lang('菜单不存在'));
}
$sid = (int)\Phpcmf\Service::L('input')->get('sid');
if (!$sid) {
$this->_json(0, dr_lang('站点id不存在'));
}
$value = dr_string2array($data['site']);
unset($value[$sid]);
\Phpcmf\Service::M()->db->table('admin_menu')->where('id', $id)->update([
'site' => dr_array2string($value)
]);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
$this->_json(1, dr_lang('删除成功'));
}
public function edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('menu')->getRowData('admin', $id);
if (!$data) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
$pid = intval($data['pid']);
$top = \Phpcmf\Service::M('menu')->get_top('admin');
$type = $pid ? (isset($top[$pid]) ? 2 : 3) : 1;
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$data = $this->_validation($type, $data);
if ($data['uri'] && \Phpcmf\Service::M()->table('admin_menu')->where('id<>'.$id)->where('uri', $data['uri'])->counts()) {
// 链接菜单判断重复
$this->_json(0, dr_lang('系统路径已经存在'), ['field' => 'uri']);
}
\Phpcmf\Service::M('menu')->_update('admin', $id, $data);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改后台菜单: '.$data['name']);
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'type' => $type,
'data' => $data,
'form' => dr_form_hidden(),
'select' => \Phpcmf\Service::M('Menu')->parent_select('admin', $type, $pid)
]);
\Phpcmf\Service::V()->display('menu_add.html');
exit;
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
\Phpcmf\Service::M('menu')->_delete('admin', $ids);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量删除后台菜单: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 初始化
public function init() {
\Phpcmf\Service::M('menu')->init('admin');
\Phpcmf\Service::L('input')->system_log('初始化后台菜单');
\Phpcmf\Service::M('cache')->update_cache(); // 自动更新缓存
$this->_json(1, dr_lang('初始化菜单成功,请按F5刷新整个页面'));
}
// 隐藏或者启用
public function use_edit() {
$i = intval(\Phpcmf\Service::L('input')->get('id'));
$v = \Phpcmf\Service::M('menu')->_uesd('admin', $i);
if ($v == -1) {
$this->_json(0, dr_lang('数据#%s不存在', $i), ['value' => $v]);
}
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改后台菜单状态: '. $i);
$this->_json(1, dr_lang($v ? '此菜单已被隐藏' : '此菜单已被启用'), ['value' => $v]);
}
// 保存数据
public function save_edit() {
$i = intval(\Phpcmf\Service::L('input')->get('id'));
\Phpcmf\Service::M('menu')->_save(
'admin',
$i,
dr_safe_replace(\Phpcmf\Service::L('input')->get('name')),
dr_safe_replace(\Phpcmf\Service::L('input')->get('value'))
);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改后台菜单信息: '. $i);
$this->_json(1, dr_lang('更改成功'));
}
// 验证数据
private function _validation($type, $data) {
if ($type != 3) {
// 非链接菜单时不录入url和uri
unset($this->form['url'], $this->form['uri']);
} else {
// url和uri 只验证一个
if ($data['url']) {
unset($this->form['uri']);
}
if ($data['uri']) {
unset($this->form['url']);
}
}
//$type是菜单级别 1 2 3
if (in_array($type, [2, 1]) && !$data['mark']) {
$this->_json(0, dr_lang('标识字符不能为空'), ['field' => 'mark']);
}
list($data, $return) = \Phpcmf\Service::L('form')->validation($data, $this->form);
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
}
$data['uri'] = strtolower((string)$data['uri']);
return $data;
}
}
+296
View File
@@ -0,0 +1,296 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Min_menu extends \Phpcmf\Common {
private $form; // 表单验证配置
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'简化菜单' => ['min_menu/index', 'fa fa-list-alt'],
'初始化菜单' => ['ajax:min_menu/init', 'fa fa-refresh'],
'help' => [961],
]
));
// 表单验证配置
$this->form = [
'name' => [
'name' => '菜单名称',
'rule' => [
'empty' => dr_lang('菜单名称不能为空')
],
'filter' => [],
'length' => '200'
],
'icon' => [
'name' => '菜单图标',
'rule' => [
'empty' => dr_lang('菜单图标不能为空')
],
'filter' => [],
'length' => '100'
],
'uri' => [
'name' => '系统路径',
'rule' => [
'empty' => dr_lang('系统路径不能为空')
],
'filter' => [],
'length' => '200'
],
'url' => [
'name' => '实际地址',
'rule' => [
'empty' => dr_lang('实际地址不能为空')
],
'filter' => [
'url'
],
'length' => '200'
],
];
}
public function index() {
\Phpcmf\Service::V()->assign([
'data' => \Phpcmf\Service::M('Menu')->gets('admin_min'),
'color' => ['blue', 'red', 'green', 'dark', 'yellow'],
]);
\Phpcmf\Service::V()->display('min_menu_list.html');
}
public function add() {
$pid = intval(\Phpcmf\Service::L('input')->get('pid'));
$top = \Phpcmf\Service::M('Menu')->get_top('admin_min');
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
if ($pid) {
if (!$data['id']) {
$this->_json(0, dr_lang('没有选择菜单'));
}
$menu = \Phpcmf\Service::M('Menu')->getRowData('admin', $data['id']);
if (!$menu) {
$this->_json(0, dr_lang('所选菜单不存在'));
}
$data = [
'pid' => $pid,
'name' => $menu['name'],
'mark' => $menu['mark'],
'icon' => $menu['icon'],
'uri' => $menu['uri'],
'url' => $menu['url'],
'displayorder' => $data['displayorder'],
];
}
$data = $this->_validation($data);
\Phpcmf\Service::L('input')->system_log('添加简化菜单: '.$data['name']);
$rt = \Phpcmf\Service::M('Menu')->_add('admin_min', $pid, $data);
if ($rt['code']) {
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
$this->_json(1, dr_lang('操作成功'));
} else {
$this->_json(0, $rt['msg']);
}
}
$select = '<select class="form-control" name="data[id]">';
$select.= '<option value="0"> -- </option>';
$topdata = \Phpcmf\Service::M()->table('admin_menu')->where('pid=0')->order_by('displayorder ASC,id ASC')->getAll();
foreach ($topdata as $t) {
$leftdata = \Phpcmf\Service::M()->table('admin_menu')->where('pid='.$t['id'])->order_by('displayorder ASC,id ASC')->getAll();
$is_left = '';
foreach ($leftdata as $c) {
$linkdata = \Phpcmf\Service::M()->table('admin_menu')->where('pid='.$c['id'])->order_by('displayorder ASC,id ASC')->getAll();
$is_link = '';
if ($linkdata) {
foreach ($linkdata as $k) {
if ($k['uri'] && !$this->_is_admin_auth($k['uri'])) {
continue;
}
$is_link.= '<option value="'.$k['id'].'">&nbsp;&nbsp;&nbsp;└ '.$k['name'].'</option>';
}
}
if ($is_link) {
$is_left.= '<optgroup label=" └ '.$c['name'].'">';
$is_left.= $is_link;
$is_left.= '</optgroup>';
}
}
if ($is_left) {
$select.= '<optgroup label="'.$t['name'].'">';
$select.= $is_left;
$select.= '</optgroup>';
}
}
$select.= '</select>';
\Phpcmf\Service::V()->assign([
'top' => $top,
'type' => $pid,
'form' => dr_form_hidden(),
'select' => $select
]);
\Phpcmf\Service::V()->display('min_menu_add.html');
exit;
}
public function edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('Menu')->getRowData('admin_min', $id);
if (!$data) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
$top = \Phpcmf\Service::M('Menu')->get_top('admin_min');
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$data = $this->_validation($data);
if ($data['uri']
&& \Phpcmf\Service::M()->table('admin_min_menu')->where('id<>'.$id)->where('uri', $data['uri'])->counts()) {
// 链接菜单判断重复
$this->_json(0, dr_lang('系统路径已经存在'), ['field' => 'uri']);
}
\Phpcmf\Service::M('Menu')->_update('admin_min', $id, $data);
\Phpcmf\Service::L('input')->system_log('修改简化菜单: '.$data['name']);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
$this->_json(1, dr_lang('操作成功'));
}
if ($data['pid']) {
$select = '<select class="form-control" name="data[pid]">';
$topdata = \Phpcmf\Service::M()->table('admin_min_menu')->where('pid=0')->order_by('displayorder ASC,id ASC')->getAll();
foreach ($topdata as $t) {
$select.= '<option value="'.$t['id'].'" '.($data['pid'] == $t['id'] ? 'selected' : '').'>'.$t['name'].'</option>';
}
$select.= '</select>';
} else {
$select = '<input type="hidden" value="0" name="data[pid]" /><div class="form-control-static"><label>'.dr_lang('顶级').'</label></div>';
}
\Phpcmf\Service::V()->assign([
'top' => $top,
'type' => $data['pid'],
'data' => $data,
'form' => dr_form_hidden(),
'select' => $select
]);
\Phpcmf\Service::V()->display('min_menu_edit.html');
exit;
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
}
\Phpcmf\Service::M('Menu')->_delete('admin_min', $ids);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('批量删除简化菜单: '. implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 初始化
public function init() {
\Phpcmf\Service::M('Menu')->init('admin_min');
\Phpcmf\Service::L('input')->system_log('初始化简化菜单');
\Phpcmf\Service::M('cache')->update_cache(); // 自动更新缓存
$this->_json(1, dr_lang('初始化菜单成功,请按F5刷新整个页面'));
}
// 隐藏或者启用
public function use_edit() {
$i = intval(\Phpcmf\Service::L('input')->get('id'));
$v = \Phpcmf\Service::M('Menu')->_uesd('admin_min', $i);
if ($v == -1) {
$this->_json(0, dr_lang('数据#%s不存在', $i), ['value' => $v]);
}
\Phpcmf\Service::L('input')->system_log('修改简化菜单状态: '. $i);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
$this->_json(1, dr_lang($v ? '此菜单已被隐藏' : '此菜单已被启用'), ['value' => $v]);
}
// 保存数据
public function save_edit() {
$i = intval(\Phpcmf\Service::L('input')->get('id'));
\Phpcmf\Service::M('Menu')->_save(
'admin_min',
$i,
dr_safe_replace(\Phpcmf\Service::L('input')->get('name')),
dr_safe_replace(\Phpcmf\Service::L('input')->get('value'))
);
\Phpcmf\Service::M('cache')->sync_cache(''); // 自动更新缓存
\Phpcmf\Service::L('input')->system_log('修改简化菜单信息: '. $i);
$this->_json(1, dr_lang('更改成功'));
}
// 验证数据
private function _validation($data) {
if (!$data['pid']) {
// 非链接菜单时不录入url和uri
unset($this->form['url'], $this->form['uri']);
} else {
// url和uri 只验证一个
if ($data['url']) {
unset($this->form['uri']);
}
if ($data['uri']) {
unset($this->form['url']);
}
}
// 顶级验证mark
if (!$data['pid']) {
if (!$data['mark']) {
$this->_json(0, dr_lang('标识字符不能为空'), ['field' => 'mark']);
}
/*
elseif (!\Phpcmf\Service::M()->table('admin_menu')->where('mark', $data['mark'])->counts()) {
$this->_json(0, dr_lang('标识字符没有存在于完整菜单中'), ['field' => 'mark']);
}*/
}
if ($data['uri'] && !\Phpcmf\Service::M()->table('admin_menu')->where('uri', $data['uri'])->counts()) {
// 验证是否操作员完整菜单中
$this->_json(0, dr_lang('系统路径没有存在于完整菜单中'), ['field' => 'uri']);
}
if ($data['mark']) {
list($a, $b) = explode('-', $data['mark']);
if ($a == 'module' && !is_dir(dr_get_app_dir($b))) {
$this->_json(0, dr_lang('模块[%s]不存在', $b), ['field' => 'mark']);
}
}
list($data, $return) = \Phpcmf\Service::L('form')->validation($data, $this->form);
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
}
$data['uri'] = strtolower((string)$data['uri']);
return $data;
}
}
+143
View File
@@ -0,0 +1,143 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Notice extends \Phpcmf\Common
{
private $field;
public function __construct() {
parent::__construct();
$this->field = [
'msg' => [
'name' => dr_lang('内容'),
'ismain' => 1,
'fieldname' => 'msg',
'fieldtype' => 'Text',
],
'username' => [
'name' => dr_lang('申请人'),
'ismain' => 1,
'fieldname' => 'username',
'fieldtype' => 'Text',
],
'op_username' => [
'name' => dr_lang('处理人'),
'ismain' => 1,
'fieldname' => 'op_username',
'fieldtype' => 'Text',
]
];
$menu = [
'处理记录' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-bell-slash'],
'待处理' => [\Phpcmf\Service::L('Router')->class.'/my_index', 'fa fa-bell-o'],
];
if (dr_in_array(1, $this->admin['roleid'])) {
$menu['全部'] = [\Phpcmf\Service::L('Router')->class.'/all_index', 'fa fa-bell'];
}
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu($menu),
'field' => $this->field,
]);
}
// 处理记录
public function index() {
list($list, $total, $param) = \Phpcmf\Service::M()->init([
'table' => 'admin_notice',
'where_list' => 'op_uid='. $this->uid . ' and (site=0 or site='.SITE_ID.')',
'field' => $this->field,
'date_field' => 'inputtime',
'order' => 'inputtime desc'
])->limit_page();
if ($param['keyword']) {
$param['keyword'] = htmlspecialchars($param['keyword']);
}
\Phpcmf\Service::V()->assign([
'list' => $list,
'total' => $total,
'param' => $param,
'mypages' => \Phpcmf\Service::L('input')->page(\Phpcmf\Service::L('Router')->url(\Phpcmf\Service::L('Router')->class.'/'.\Phpcmf\Service::L('Router')->method), $total, 'admin')
]);
\Phpcmf\Service::V()->display('notice_index.html');
}
// 待处理
public function my_index() {
if (\Phpcmf\Service::M('auth')->is_post_user()) {
$where = '`to_uid`='.$this->uid.' and `status`<>3 and (site=0 or site='.SITE_ID.')';
} else {
$where = '((`to_uid`='.$this->uid.') '.($this->admin['roleid'] ? ' or (`to_rid` IN ('.implode(',', $this->admin['roleid']).'))' : '').' or (`to_uid`=0 and `to_rid`=0)) and `status`<>3 and (site=0 or site='.SITE_ID.')';
}
list($list, $total, $param) = \Phpcmf\Service::M()->init([
'table' => 'admin_notice',
'where_list' => $where,
'field' => $this->field,
'date_field' => 'inputtime',
'order' => 'inputtime desc'
])->limit_page();
if ($param['keyword']) {
$param['keyword'] = htmlspecialchars($param['keyword']);
}
\Phpcmf\Service::V()->assign([
'list' => $list,
'total' => $total,
'param' => $param,
'mypages' => \Phpcmf\Service::L('input')->page(\Phpcmf\Service::L('Router')->url(\Phpcmf\Service::L('Router')->class.'/'.\Phpcmf\Service::L('Router')->method), $total, 'admin')
]);
\Phpcmf\Service::V()->display('notice_index.html');
}
// 全部
public function all_index() {
if (!dr_in_array(1, $this->admin['roleid'])) {
$this->_admin_msg(0, dr_lang('需要超级管理员账号操作'));
}
list($list, $total, $param) = \Phpcmf\Service::M()->init([
'table' => 'admin_notice',
'field' => $this->field,
'date_field' => 'inputtime',
'where_list' => '(site=0 or site='.SITE_ID.')',
'order' => 'inputtime desc'
])->limit_page();
if ($param['keyword']) {
$param['keyword'] = htmlspecialchars($param['keyword']);
}
\Phpcmf\Service::V()->assign([
'list' => $list,
'total' => $total,
'param' => $param,
'mypages' => \Phpcmf\Service::L('input')->page(\Phpcmf\Service::L('Router')->url(\Phpcmf\Service::L('Router')->class.'/'.\Phpcmf\Service::L('Router')->method, $param), $total, 'admin')
]);
\Phpcmf\Service::V()->display('notice_index.html');
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('所选数据不存在'));
}
\Phpcmf\Service::M()->db->table('admin_notice')->whereIn('id', $ids)->delete();
$this->_json(1, dr_lang('操作成功'));
}
}
@@ -0,0 +1,73 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Password_log extends \Phpcmf\Common
{
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'密码错误记录' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-unlock-alt'],
]
));
}
public function index() {
$file = WRITEPATH.'password_log.php';
$data = $list = [];
if (filesize($file) > 1024*1024*2) {
$list[] = [
'time' => SYS_TIME,
'username' => '账号',
'message' => '此日志文件大于2MB,请使用Ftp等工具查看此文件:'.$file,
];
} else {
$code = file_get_contents($file);
if ($code) {
$data = explode(PHP_EOL, str_replace(array(chr(13), chr(10)), PHP_EOL, $code));
if ($data) {
unset($data[0]);
$data = array_reverse($data);
}
$page = max(1, (int)\Phpcmf\Service::L('input')->get('page'));
$limit = ($page - 1) * SYS_ADMIN_PAGESIZE;
$i = $j = 0;
foreach ($data as $v) {
$val = dr_string2array($v);
if ($val && $i >= $limit && $j < SYS_ADMIN_PAGESIZE) {
$list[] = $val;
$j ++;
}
$i ++;
}
}
}
$total = max(0, dr_count($data) - 1);
\Phpcmf\Service::V()->assign(array(
'list' => $list,
'total' => $total,
'mypages' => \Phpcmf\Service::L('input')->page(dr_url(\Phpcmf\Service::L('Router')->class.'/index'), $total, 'admin')
));
\Phpcmf\Service::V()->display('password_log.html');
}
public function del() {
unlink(WRITEPATH.'password_log.php');
$this->_json(1, dr_lang('操作成功'));
}
}
+290
View File
@@ -0,0 +1,290 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Role extends \Phpcmf\Common {
private $form; // 表单验证配置
public function __construct() {
parent::__construct();
// 不是超级管理员
if (!dr_in_array(1, $this->admin['roleid'])) {
$this->_admin_msg(0, dr_lang('需要超级管理员账号操作'));
}
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'角色权限' => ['role/index', 'fa fa-users'],
'添加' => ['add:role/add', 'fa fa-plus', '500px', '400px'],
'权限划分' => ['hide:role/auth_edit', 'fa fa-user-md'],
'help' => ['824'],
]
));
// 表单验证配置
$this->form = [
'name' => [
'name' => '角色名称',
'rule' => [
'empty' => dr_lang('角色名称不能为空')
],
'filter' => [],
'length' => '200'
],
];
}
public function index() {
\Phpcmf\Service::V()->assign([
'data' => \Phpcmf\Service::M('auth')->get_role_all(),
]);
\Phpcmf\Service::V()->display('role_index.html');
}
public function add() {
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$this->_validation($data);
\Phpcmf\Service::L('input')->system_log('添加角色组('.$data['name'].')');
if (\Phpcmf\Service::M('auth')->add_role($data)) {
\Phpcmf\Service::M('cache')->sync_cache('auth');
$this->_json(1, dr_lang('操作成功'));
} else {
$this->_json(0, dr_lang('操作失败'));
}
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden()
]);
\Phpcmf\Service::V()->display('role_add.html');
exit;
}
public function edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('auth')->get_role($id);
if (!$data) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
if (IS_AJAX_POST) {
$temp = $post = \Phpcmf\Service::L('input')->post('data');
$this->_validation($post);
$post['application'] = $data['application'];
$post['application']['tid'] = $temp['application']['tid'];
$post['application']['mode'] = $temp['application']['mode'];
$post['application']['verify'] = $temp['application']['verify'];
\Phpcmf\Service::M('auth')->update_role($id, $post);
\Phpcmf\Service::M('cache')->sync_cache('auth');
\Phpcmf\Service::L('input')->system_log('修改角色组('.$post['name'].')');
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'id' => $id,
'data' => $data,
'form' => dr_form_hidden(),
]);
\Phpcmf\Service::V()->display('role_add.html');
exit;
}
// 复制动作
public function copy_edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('auth')->get_role($id);
if (!$data) {
$this->_json(0, dr_lang('数据#%s不存在', $id));
}
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
if (!$post['ids']) {
$this->_json(0, dr_lang('没有选择目标角色组'));
} elseif (!$post['option']) {
$this->_json(0, dr_lang('没有选择复制项目'));
}
$save = [];
if (dr_in_array(1, $post['option'])) {
$save['site'] = dr_array2string($data['site']);
}
if (dr_in_array(2, $post['option'])) {
$save['system'] = dr_array2string($data['system']);
$save['module'] = dr_array2string($data['module']);
}
if (!$save) {
$this->_json(0, dr_lang('没有选择复制项目'));
}
foreach ($post['ids'] as $rid) {
\Phpcmf\Service::M('auth')->table('admin_role')->update($rid, $save);
}
\Phpcmf\Service::M('cache')->sync_cache('auth');
\Phpcmf\Service::L('input')->system_log('修改角色组('.$data['name'].')到'.implode('、', $post['ids']));
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'id' => $id,
'role' => \Phpcmf\Service::M('auth')->get_role_all()
]);
\Phpcmf\Service::V()->display('role_copy.html');
exit;
}
// 角色组权限,超级管理员有权限
public function auth_edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('auth')->get_role($id);
if (!$data) {
$this->_admin_msg(0, dr_lang('角色组(%s)不存在', $id));
}
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$module = \Phpcmf\Service::L('input')->post('module');
\Phpcmf\Service::M('auth')->table('admin_role')->update($id, [
'system' => dr_array2string($post),
'module' => dr_array2string($module),
]);
\Phpcmf\Service::M('cache')->sync_cache('auth');
\Phpcmf\Service::L('input')->system_log('设置角色组('.$data['name'].')权限');
$this->_json(1, dr_lang('操作成功'));
}
//print_r($data);
#print_r($this->_M('Menu')->gets('admin'));
$page = intval(\Phpcmf\Service::L('input')->get('page'));
$module_auth = IS_USE_MODULE ? \Phpcmf\Service::M('module', 'cms')->module_auth() : [];
\Phpcmf\Service::V()->assign([
'data' => $data,
'page' => $page,
'form' => dr_form_hidden(['page' => $page]),
'menu_data' => \Phpcmf\Service::M('Menu')->gets('admin', 'mark<>\'cloud\''),
'module_auth' => $module_auth,
]);
\Phpcmf\Service::V()->display('role_auth.html');
}
public function site_edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('auth')->get_role($id);
if (!$data) {
$this->_admin_msg(0, dr_lang('角色组(%s)不存在', $id));
}
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
\Phpcmf\Service::M('auth')->table('admin_role')->update($id, ['site' => dr_array2string($post)]);
\Phpcmf\Service::M('cache')->sync_cache('auth');
\Phpcmf\Service::L('input')->system_log('设置角色组('.$data['name'].')站点权限');
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'data' => $data,
'form' => dr_form_hidden(),
]);
\Phpcmf\Service::V()->display('role_site.html');exit;
}
public function verify_edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M('auth')->get_role($id);
if (!$data) {
$this->_admin_msg(0, dr_lang('角色组(%s)不存在', $id));
} elseif (!IS_USE_MEMBER) {
$this->_admin_msg(0, dr_lang('需要安装用户系统插件,才能使用本功能'));
}
$verify = \Phpcmf\Service::M()->table('admin_verify')->getAll(30);
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
foreach ($verify as $v) {
$rs = dr_string2array($v['verify']);
if ($rs) {
foreach ($rs['role'] as $i => $t) {
if (isset($post[$v['id']]) && dr_in_array($i, $post[$v['id']])) {
// 表示选择的
if (!isset($rs['role'][$i])) {
$rs['role'][$i] = []; // 不存在时重新定义
} elseif (!is_array($rs['role'][$i]) && $rs['role'][$i]) {
if ($id == $rs['role'][$i]) {
$rs['role'][$i] = []; // 值相同时
} else {
$rs['role'][$i] = [
(int)$rs['role'][$i]
]; // 老版本的单值
}
}
$rs['role'][$i][] = $id;
} else {
// 表示没选中
foreach ($t as $k => $kt) {
if ($id == $kt) {
unset($rs['role'][$i][$k]);
}
}
}
}
}
\Phpcmf\Service::M()->table('admin_verify')->update($v['id'], [
'verify' => dr_array2string($rs)
]);
}
\Phpcmf\Service::M('cache')->sync_cache('');
\Phpcmf\Service::L('input')->system_log('设置角色组('.$data['name'].')审核权限');
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'rid' => $id,
'form' => dr_form_hidden(),
'verify' => $verify,
]);
\Phpcmf\Service::V()->display('role_verify.html');exit;
}
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('你还没有选择呢'));
} elseif (dr_in_array(1, $ids)) {
$this->_json(0, dr_lang('超级管理员角色组不能删除'));
}
\Phpcmf\Service::M('auth')->delete_role($ids);
\Phpcmf\Service::M('cache')->sync_cache('auth');
\Phpcmf\Service::L('input')->system_log('批量删除角色组: '. @implode(',', $ids));
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids]);
}
// 验证数据
private function _validation($data) {
list($data, $return) = \Phpcmf\Service::L('Form')->validation($data, $this->form);
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
}
}
}
+345
View File
@@ -0,0 +1,345 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 管理员
class Root extends \Phpcmf\Table
{
public $role;
private $myrole;
private $mywhere;
public function __construct()
{
parent::__construct();
if (!dr_in_array(1, $this->admin['roleid'])) {
// 不是超级管理员
if (dr_is_app('cqx')) {
$this->myrole = \Phpcmf\Service::M('content', 'cqx')->myrole();
} else {
$this->myrole = $this->admin['roleid'];
}
$this->role = \Phpcmf\Service::M('auth')->get_role_all($this->myrole);
$this->mywhere = '`uid` IN (select uid from `'.\Phpcmf\Service::M()->dbprefix('admin_role_index').'` where roleid in ('.implode(',', $this->myrole).'))';
} else {
$this->role = \Phpcmf\Service::M('auth')->get_role_all();
$this->myrole = [];
}
\Phpcmf\Service::V()->assign([
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'管理员' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-user'],
'添加' => [\Phpcmf\Service::L('Router')->class.'/add', 'fa fa-plus'],
'修改' => ['hide:'.\Phpcmf\Service::L('Router')->class.'/edit', 'fa fa-edit'],
'登录记录' => ['hide:root/login_index', 'fa fa-calendar'],
'help' => [813],
]
),
]);
$this->name = dr_lang('管理员');
}
public function index() {
$p = [
'rid' => intval($_GET['rid']),
'keyword' => dr_safe_replace($_GET['keyword']),
];
$where = [];
if ($p['keyword']) {
$where[] = '`username` LIKE "%'.$p['keyword'].'%"';
}
if ($this->myrole) {
$where[] = $this->mywhere;
}
if ($p['rid']) {
$where[] = '`uid` IN (select uid from `'.\Phpcmf\Service::M()->dbprefix('admin_role_index').'` where roleid='.$p['rid'].')';
}
$this->_init([
'table' => 'admin',
'join_list' => ['member', 'member.id=admin.uid', 'left'],
'order_by' => 'uid desc',
'where_list' => implode(' AND ', $where),
]);
list($a, $data) = $this->_List($p);
if ($data['list']) {
foreach ($data['list'] as $i => $t) {
$role = \Phpcmf\Service::M()->db->table('admin_role_index')->where('uid', $t['uid'])->get()->getResultArray();
if ($role) {
foreach ($role as $r) {
$data['list'][$i]['role'][$r['roleid']] = $this->role[$r['roleid']]['name'];
}
}
}
}
\Phpcmf\Service::V()->assign('p', $p);
\Phpcmf\Service::V()->assign('list', $data['list']);
\Phpcmf\Service::V()->display('root_index.html');
}
// 登录记录
public function login_index() {
$uid = (int)\Phpcmf\Service::L('input')->get('id');
$where = 'uid='.$uid;
if ($this->myrole) {
$where.= ' and '.$this->mywhere;
}
$this->_init([
'table' => 'admin_login',
'order_by' => 'logintime desc',
'where_list' => $where,
]);
list($a, $data) = $this->_List(['uid' => $uid]);
\Phpcmf\Service::V()->assign([
'list' => $data['list'],
'user' => dr_member_info($uid),
]);
\Phpcmf\Service::V()->display('root_login.html');
}
public function ck_index() {
$name = dr_safe_replace($_GET['name']);
$data = \Phpcmf\Service::M()->db->table('member')->where('username', $name)->get()->getRowArray();
$this->_json($data ? 0 : 1, 'ok');
}
public function status_edit() {
$uid = intval($_GET['id']);
$data = \Phpcmf\Service::M()->db->table('member_data')->where('id', $uid)->get()->getRowArray();
if ($data['is_lock']) {
\Phpcmf\Service::M()->db->table('member_data')->where('id', $uid)->update(['is_lock' => 0]);
$this->_json(1, dr_lang('解除登录锁定'));
} else {
if ($this->uid == $uid) {
$this->_json(0, dr_lang('无法对自己设置状态'));
} elseif (1 == $uid) {
$this->_json(0, dr_lang('不能设置超管账号'));
}
\Phpcmf\Service::M()->db->table('member_data')->where('id', $uid)->update(['is_lock' => 1]);
$this->_json(1, dr_lang('登录已锁定,将无法登陆账号'));
}
}
public function add() {
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$name = dr_safe_replace($post['username']);
if (!$name) {
$this->_json(0, dr_lang('账号不能为空'), ['field' => 'username']);
} elseif (!$post['role']) {
$this->_json(0, dr_lang('至少要选择一个角色组'), ['field' => 'role']);
}
if ($this->myrole) {
foreach ($post['role'] as $t) {
if (!in_array($t, $this->myrole)) {
$this->_json(0, dr_lang('存在无权限操作的角色组'), ['field' => 'role']);
}
}
}
$data = \Phpcmf\Service::M()->db->table('member')->where('username', $name)->get()->getRowArray();
if (!$data) {
// 注册账号
$rt = \Phpcmf\Service::L('form')->check_username($name);
if (!$rt['code']) {
$this->_json(0, $rt['msg'], ['field' => 'username']);
}
if (!\Phpcmf\Service::L('Form')->check_email($post['email'])) {
$this->_json(0, dr_lang('邮箱格式不正确'), ['field' => 'email']);
} elseif (!\Phpcmf\Service::L('Form')->check_phone($post['phone'])) {
$this->_json(0, dr_lang('手机号码格式不正确'), ['field' => 'phone']);
} elseif (empty($post['password'])) {
$this->_json(0, dr_lang('密码必须填写'), ['field' => 'password']);
} elseif ($post['name'] && $this->member_cache['config']['unique_name']
&& \Phpcmf\Service::M()->db->table('member')->where('name', $post['name'])->countAllResults()) {
$this->_json(0, dr_lang('%s已经注册', MEMBER_CNAME), ['field' => 'name']);
}
$rt = \Phpcmf\Service::L('Form')->check_password($post['password'], $name);
if (!$rt['code']) {
$this->_json(0, $rt['msg'], ['field' => 'password']);
}
$rt = \Phpcmf\Service::M('member')->register(0, [
'username' => $post['username'],
'phone' => $post['phone'],
'email' => $post['email'],
'name' => $post['name'],
'password' => dr_safe_password($post['password']),
]);
if (!$rt['code']) {
// 注册失败
$this->_json(0, $rt['msg'], ['field' => $rt['data']['field']]);
}
$data = $rt['data'];
}
if (\Phpcmf\Service::M()->table('admin')->where('uid', $data['id'])->counts()) {
$this->_json(0, dr_lang('此账号已经是管理员'));
}
$rt = \Phpcmf\Service::M()->table('admin')->insert([
'uid' => $data['id'],
'setting' => '',
'usermenu' => '',
]);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
if (dr_in_array(1, $post['role'])) {
// 超管模式
\Phpcmf\Service::M()->table('admin_role_index')->insert([
'uid' => $data['id'],
'roleid' => 1,
]);
} else {
foreach ($post['role'] as $t) {
\Phpcmf\Service::M()->table('admin_role_index')->insert([
'uid' => $data['id'],
'roleid' => $t,
]);
}
}
\Phpcmf\Service::M()->table('member_data')->update($data['id'], ['is_admin' => 1]);
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign([
'post_url' =>\Phpcmf\Service::L('Router')->url('root/add'),
'reply_url' =>\Phpcmf\Service::L('Router')->url('root/index'),
]);
\Phpcmf\Service::V()->display('root_add.html');
}
public function edit() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$data = \Phpcmf\Service::M()->db->table('admin')->where('uid', $id)->get()->getRowArray();
if (!$data) {
$this->_admin_msg(0, dr_lang('账号不存在'));
}
$member = \Phpcmf\Service::M()->db->table('member')->where('id', $data['uid'])->get()->getRowArray();
if (!$member) {
$this->_admin_msg(0, dr_lang('账号不存在'));
}
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
if (!$post['role']) {
$this->_json(0, dr_lang('至少要选择一个角色组'), ['field' => 'role']);
} elseif (!\Phpcmf\Service::L('Form')->check_email($post['email'])) {
$this->_json(0, dr_lang('邮箱格式不正确'), ['field' => 'email']);
} elseif (!\Phpcmf\Service::L('Form')->check_phone($post['phone'])) {
$this->_json(0, dr_lang('手机号码格式不正确'), ['field' => 'phone']);
} elseif (\Phpcmf\Service::M()->db->table('member')->where('id<>'. $member['id'])->where('email', $post['email'])->countAllResults()) {
$this->_json(0, dr_lang('邮箱%s已经注册', $post['email']), ['field' => 'email']);
} elseif (\Phpcmf\Service::M()->db->table('member')->where('id<>'. $member['id'])->where('phone', $post['phone'])->countAllResults()) {
$this->_json(0, dr_lang('手机号码%s已经注册', $post['phone']), ['field' => 'phone']);
} elseif ($post['name'] && $this->member_cache['config']['unique_name']
&& \Phpcmf\Service::M()->db->table('member')->where('id<>'. $member['id'])->where('name', $post['name'])->countAllResults()) {
$this->_json(0, dr_lang('%s已经注册', MEMBER_CNAME), ['field' => 'name']);
} elseif ($this->myrole) {
foreach ($post['role'] as $t) {
if (!in_array($t, $this->myrole)) {
$this->_json(0, dr_lang('存在无权限操作的角色组'), ['field' => 'role']);
}
}
}
if ($post['username'] != $member['username']) {
// 改账号时
$rs = \Phpcmf\Service::L('Form')->check_username($post['username']);
if (!$rs['code']) {
$this->_json(0, $rs['msg'], ['field' => 'username']);
} elseif (\Phpcmf\Service::M()->db->table('member')->where('username', $post['username'])->countAllResults()) {
$this->_json(0, dr_lang('账号%s已经注册', $post['username']), ['field' => 'username']);
}
\Phpcmf\Service::M()->table('member')->update($member['id'], [
'username' => $post['username'],
'phone' => $post['phone'],
'email' => $post['email'],
'name' => $post['name'],
]);
\Phpcmf\Service::M('member')->clear_cache($member['id'], $member['username']);
} else {
\Phpcmf\Service::M()->table('member')->update($member['id'], [
'phone' => $post['phone'],
'email' => $post['email'],
'name' => $post['name'],
]);
}
if ($post['password']) {
$rt = \Phpcmf\Service::L('Form')->check_password($post['password'], $post['username']);
if (!$rt['code']) {
$this->_json(0, $rt['msg'], ['field' => 'password']);
}
\Phpcmf\Service::M('member')->edit_password($member, $post['password']);
}
if ($id > 1) {
\Phpcmf\Service::M()->db->table('admin_role_index')->where('uid', $member['id'])->delete();
foreach ($post['role'] as $t) {
\Phpcmf\Service::M()->table('admin_role_index')->replace([
'uid' => $member['id'],
'roleid' => $t,
]);
}
}
$this->_json(1, dr_lang('操作成功'));
}
$data = $data + $member;
$role = \Phpcmf\Service::M()->db->table('admin_role_index')->where('uid', $data['uid'])->get()->getResultArray();
if ($role) {
foreach ($role as $r) {
$data['role'][$r['roleid']] = $this->role[$r['roleid']]['name'];
}
}
// 不是超级管理员,排除超管账号
if (!dr_in_array(1, $this->admin['roleid'])) {
unset($this->role[1]);
if (isset($data['role'][1])) {
$this->_admin_msg(0, dr_lang('无权限编辑'));
}
}
\Phpcmf\Service::V()->assign([
'edit' => 1,
'data' => $data,
'post_url' =>\Phpcmf\Service::L('Router')->url('root/add'),
'reply_url' =>\Phpcmf\Service::L('Router')->url('root/index'),
]);
\Phpcmf\Service::V()->display('root_add.html');
}
// 后台删除url内容
public function del() {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (dr_in_array(1, $ids)) {
$this->_json(0, dr_lang('创始人账号不能删除'));
} elseif (dr_in_array($this->uid, $ids)) {
$this->_json(0, dr_lang('不能删除自己'));
}
// 批量操作
foreach ($ids as $u) {
// 不是超级管理员,排除超管账号
if ($this->myrole && !\Phpcmf\Service::M()->table('admin_role_index')->where('uid', $u)->where($this->mywhere)->counts()) {
$this->_json(0, dr_lang('存在无权限操作的角色组'), ['field' => 'role']);
}
\Phpcmf\Service::M()->db->table('admin')->where('uid', $u)->delete();
\Phpcmf\Service::M()->db->table('admin_login')->where('uid', $u)->delete();
\Phpcmf\Service::M()->db->table('admin_role_index')->where('uid', $u)->delete();
\Phpcmf\Service::M()->table('member_data')->update($u, ['is_admin' => 0]);
}
$this->_json(1, dr_lang('操作成功'));
}
}
+87
View File
@@ -0,0 +1,87 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Sms extends \Phpcmf\Common
{
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'短信设置' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-envelope'],
'发送短信' => [\Phpcmf\Service::L('Router')->class.'/add', 'fa fa-send'],
'help' => ['393'],
]
));
}
public function index() {
$file = WRITEPATH.'config/sms.php';
$cfile = WRITEPATH.'config/cache.php';
$cache = is_file($cfile) ? require $cfile : [];
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
$cache['SYS_CACHE_SMS'] = (int)\Phpcmf\Service::L('input')->post('SYS_CACHE_SMS');
if (!\Phpcmf\Service::L('Config')->file($cfile, '缓存配置文件')->to_require_one($cache)) {
$this->_json(0, dr_lang('配置文件写入失败'));
}
if (!\Phpcmf\Service::L('Config')->file($file, '短信配置文件')->to_require_one($data)) {
$this->_json(0, dr_lang('配置文件写入失败'));
}
\Phpcmf\Service::L('input')->system_log('配置短信接口'); // 记录日志
$this->_json(1, dr_lang('操作成功'));
}
\Phpcmf\Service::V()->assign(array(
'data' => is_file($file) ? require $file : [],
'cache' => $cache,
));
\Phpcmf\Service::V()->display('sms_index.html');
}
public function add() {
$file = WRITEPATH.'config/sms.php';
if (!is_file($file)) {
$this->_admin_msg(0, dr_lang('没有配置短信参数,不能使用发送功能'));
}
if (IS_AJAX_POST) {
$data = \Phpcmf\Service::L('input')->post('data');
if ($data['content'] && strlen($data['content']) < 10) {
$this->_json(0, dr_lang('短信内容太短了'));
} elseif (!$data['mobiles']) {
$this->_json(0, dr_lang('手机号码不能为空'));
}
$ok = 0;
$mobile = explode(',', trim(str_replace(',,', ',', str_replace(array(PHP_EOL, chr(13), chr(10)), ',', $data['mobiles'])), ','));
foreach ($mobile as $m) {
$rt = \Phpcmf\Service::M('member')->sendsms_text($m, $data['content']);
if ($rt['code']) {
$ok ++;
}
}
\Phpcmf\Service::L('input')->system_log('发送系统短信'); // 记录日志
$this->_json(1, dr_lang('发送成功%s个手机', $ok));
}
\Phpcmf\Service::V()->display('sms_add.html');
}
}
+58
View File
@@ -0,0 +1,58 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Sms_log extends \Phpcmf\Common
{
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'短信记录' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-envelope'],
]
));
}
public function index() {
$data = $list = [];
$file = file_get_contents(WRITEPATH.'sms_log.txt');
if ($file) {
$data = explode(PHP_EOL, str_replace(array(chr(13), chr(10)), PHP_EOL, $file));
$data = $data ? array_reverse($data) : [];
$page = max(1, (int)\Phpcmf\Service::L('input')->get('page'));
$limit = ($page - 1) * SYS_ADMIN_PAGESIZE;
$i = $j = 0;
foreach ($data as $v) {
if ($i >= $limit && $j < SYS_ADMIN_PAGESIZE) {
$list[] = $v;
$j ++;
}
$i ++;
}
}
$total = max(0, dr_count($data) - 1);
\Phpcmf\Service::V()->assign(array(
'list' => $list,
'total' => $total,
'mypages' => \Phpcmf\Service::L('input')->page(\Phpcmf\Service::L('Router')->url('sms_log/index'), $total, 'admin')
));
\Phpcmf\Service::V()->display('sms_log.html');
}
public function del() {
unlink(WRITEPATH.'sms_log.txt');
$this->_json(1, dr_lang('操作成功'));
}
}
+93
View File
@@ -0,0 +1,93 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Sql_log extends \Phpcmf\Common
{
public function __construct() {
parent::__construct();
\Phpcmf\Service::V()->assign('menu', \Phpcmf\Service::M('auth')->_admin_menu(
[
'前端慢查询记录' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-database'],
]
));
}
public function index() {
$dir = dr_file_map(WRITEPATH.'database/Sql/');
$time = (int)\Phpcmf\Service::L('input')->get('time');
if (!$time) {
$time = 'sql';
}
$data = $list = [];
$file = WRITEPATH.'database/Sql/'.$time.'.txt';
if (filesize($file) > 1024*1024*2) {
$list[] = [
$time,
'',
'10',
'message' => '此日志文件大于2MB,请使用Ftp等工具查看此文件:'.$file,
];
} else {
$code = file_get_contents($file);
if ($code) {
$data = explode(PHP_EOL, str_replace(array(chr(13), chr(10)), PHP_EOL, $code));
$data = $data ? array_reverse($data) : [];
$page = max(1, (int)\Phpcmf\Service::L('input')->get('page'));
$limit = ($page - 1) * SYS_ADMIN_PAGESIZE;
$i = $j = 0;
foreach ($data as $v) {
$val = dr_string2array($v);
if ($val && $i >= $limit && $j < SYS_ADMIN_PAGESIZE) {
$list[] = $val;
$j ++;
}
$i ++;
}
}
}
$total = max(0, dr_count($data) - 1);
\Phpcmf\Service::V()->assign(array(
'time' => $time,
'mdir' => $dir,
'list' => $list,
'total' => $total,
'used' => is_file(WRITEPATH.'database/sql.lock'),
'mypages' => \Phpcmf\Service::L('input')->page(dr_url(\Phpcmf\Service::L('Router')->class.'/index', ['time' => $time]), $total, 'admin')
));
\Phpcmf\Service::V()->display('sql_log.html');
}
public function add() {
$file = WRITEPATH.'database/sql.lock';
if (is_file($file)) {
unlink($file);
} else {
$size = file_put_contents($file, 'ok');
if (!$size) {
dr_mkdirs(dirname($file));
$this->_json(0, dr_lang('Cache目录权限不可写入'));
}
}
$this->_json(1, dr_lang('操作成功'));
}
public function del() {
dr_dir_delete(WRITEPATH.'database/Sql/');
$this->_json(1, dr_lang('操作成功'));
}
}
+115
View File
@@ -0,0 +1,115 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class System extends \Phpcmf\Common
{
public function index() {
if (is_file(WRITEPATH.'config/system.php')) {
$data = require WRITEPATH.'config/system.php'; // 加载网站系统配置文件
} else {
$data = [];
}
$logo = [
'logo' => [
'ismain' => 1,
'fieldtype' => 'File',
'fieldname' => 'logo',
'setting' => ['option' => ['ext' => 'jpg,gif,png,jpeg,webp,svg', 'size' => 10, 'input' => 1]]
]
];
$site = \Phpcmf\Service::M('Site')->config(SITE_ID);
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data', true);
$save = [
'SYS_DEBUG' => (int)$post['SYS_DEBUG'],
'SYS_AUTO_FORM' => (int)$post['SYS_AUTO_FORM'],
'SYS_CRON_AUTH' => dr_safe_replace($post['SYS_CRON_AUTH']),
'SYS_SMS_IMG_CODE' => intval($post['SYS_SMS_IMG_CODE']),
'SYS_GO_404' => intval($post['SYS_GO_404']),
'SYS_301' => intval($post['SYS_301']),
'SYS_THEME_ROOT_PATH' => intval($post['SYS_THEME_ROOT_PATH']),
'SYS_TABLE_ISFOOTER' => intval($post['SYS_TABLE_ISFOOTER']),
'SYS_URL_ONLY' => (int)$post['SYS_URL_ONLY'],
'SYS_URL_REL' => (int)$post['SYS_URL_REL'],
'SYS_NOT_UPDATE' => (int)$post['SYS_NOT_UPDATE'],
'SYS_NOT_ADMIN_CACHE' => (int)$post['SYS_NOT_ADMIN_CACHE'],
'SYS_ADMIN_MODE' => intval($post['SYS_ADMIN_MODE']),
'SYS_ADMIN_LOG' => intval($post['SYS_ADMIN_LOG']),
'SYS_ADMIN_CODE' => intval($post['SYS_ADMIN_CODE']),
'SYS_ADMIN_LOGINS' => intval($post['SYS_ADMIN_LOGINS']),
'SYS_LOGIN_AES' => intval($post['SYS_LOGIN_AES']),
'SYS_ADMIN_LOGIN_TIME' => intval($post['SYS_ADMIN_LOGIN_TIME']),
'SYS_ADMIN_PAGESIZE' => intval($post['SYS_ADMIN_PAGESIZE']),
'SYS_ADMIN_OAUTH' => intval($post['SYS_ADMIN_OAUTH']),
'SYS_ADMIN_SMS_LOGIN' => intval($post['SYS_ADMIN_SMS_LOGIN']),
'SYS_ADMIN_SMS_CHECK' => intval($post['SYS_ADMIN_SMS_CHECK']),
'SYS_KEY' => dr_safe_filename($post['SYS_KEY'] == '************' ? $data['SYS_KEY'] : $post['SYS_KEY']),
'SYS_HTTPS' => (int)$post['SYS_HTTPS'],
'SYS_CSRF' => (int)$post['SYS_CSRF'],
'SYS_CSRF_TIME' => (int)$post['SYS_CSRF_TIME'],
'SYS_API_CODE' => (int)$post['SYS_API_CODE'],
'SYS_API_REL' => (int)$post['SYS_API_REL'],
'SYS_API_TOKEN' => (string)$post['SYS_API_TOKEN'],
];
if ($save['SYS_HTTPS'] && $data['SYS_HTTPS'] != $save['SYS_HTTPS']
&& !\Phpcmf\Service::L('input')->post('https_test')) {
// 表示开启https时需要点击测试按钮
$this->_json(0, dr_lang('开启HTTPS时需要点击旁边的测试按钮'), ['field' => 'https']);
}
foreach ($data as $name => $value) {
strpos($name, 'SYS_CACHE') === 0 && $save[$name] = intval($post[$name]);
}
\Phpcmf\Service::M('System')->save_config($data, $save);
// 项目信息储存
$site_post = \Phpcmf\Service::L('input')->post('site');
foreach ([
'SITE_NAME',
'SITE_LANGUAGE',
'SITE_TIMEZONE',
'SITE_TIME_FORMAT',
'logo'
] as $name) {
$site['config'][$name] = $site_post[$name];
}
$rt = \Phpcmf\Service::M('Site')->config(SITE_ID, 'config', $site['config']);
if (!is_array($rt)) {
$this->_json(0, dr_lang('项目信息(#%s)不存在', SITE_ID));
}
\Phpcmf\Service::L('input')->system_log('设置系统配置参数');
$this->_json(1, dr_lang('操作成功'));
}
$page = (int)\Phpcmf\Service::L('input')->get('page');
\Phpcmf\Service::V()->assign([
'data' => $data,
'site' => $site['config'],
'page' => $page,
'form' => dr_form_hidden(['page' => $page]),
'lang' => dr_dir_map(ROOTPATH.'api/language/', 1),
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'系统参数' => ['system/index', 'fa fa-cog'],
'help' => [503],
]
),
'config' => \Phpcmf\Service::M('System')->config,
'logofield' => dr_fieldform($logo['logo'], $site['config']['logo']),
]);
\Phpcmf\Service::V()->display('system_index.html');
}
}
@@ -0,0 +1,60 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class System_cache extends \Phpcmf\Common
{
public function index() {
$file = WRITEPATH.'config/cache.php';
if (IS_AJAX_POST) {
$config = \Phpcmf\Service::L('input')->post('data');
$config['SYS_CACHE_LIST'] = $config['SYS_CACHE_SEARCH'] = $config['SYS_CACHE_SHOW']; // 统一视为缓存时间
if (!\Phpcmf\Service::L('Config')->file($file, '缓存配置文件')->to_require_one($config)) {
$this->_json(0, dr_lang('配置文件写入失败'));
}
\Phpcmf\Service::L('input')->system_log('配置缓存参数'); // 记录日志
$this->_json(1, dr_lang('操作成功'));
}
$data = is_file($file) ? require $file : [];
if (!isset($data['SYS_CACHE_CRON']) or empty($data['SYS_CACHE_CRON'])) {
$data['SYS_CACHE_CRON'] = 3;
}
$page = intval(\Phpcmf\Service::L('input')->get('page'));
$run_time = '';
if (is_file(WRITEPATH.'config/run_time.php')) {
$run_time = file_get_contents(WRITEPATH.'config/run_time.php');
}
\Phpcmf\Service::V()->assign([
'page' => $page,
'form' => dr_form_hidden(['page' => $page]),
'data' => $data,
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'缓存设置' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-clock-o'],
'help' => [504],
]
),
'cache_var' => [
'SHOW' => '缓存时间',
//'ATTACH' => '网站附件',
//'LIST' => '查询缓存',
//'SEARCH' => '搜索缓存',
],
'run_time' => $run_time,
]);
\Phpcmf\Service::V()->display('system_cache.html');
}
}
+91
View File
@@ -0,0 +1,91 @@
<?php namespace Phpcmf\Control\Admin;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class System_log extends \Phpcmf\Common {
public function index() {
$time = (int)strtotime(\Phpcmf\Service::L('input')->get('time'));
!$time && $time = SYS_TIME;
$file = WRITEPATH.'log/'.date('Ym', $time).'/'.date('d', $time).'.php';
$list = [];
$data = explode(PHP_EOL, str_replace(array(chr(13), chr(10)), PHP_EOL, file_get_contents($file)));
$data = array_reverse($data);
$page = max(1, (int)\Phpcmf\Service::L('input')->get('page'));
$total = max(0, dr_count($data) - 1);
$limit = ($page - 1) * SYS_ADMIN_PAGESIZE;
$i = $j = 0;
$key = 1;
$time = date('Y-m-d', $time);
foreach ($data as $v) {
if ($v && $i >= $limit && $j < SYS_ADMIN_PAGESIZE) {
$v = dr_string2array($v);
if ($v) {
\Phpcmf\Service::L('cache')->set_data('system_log_'.USER_HTTP_CODE.$time.'_'.$key, $v, 3600);
$list[$key] = $v;
$j ++;
$key ++;
}
}
$i ++;
}
\Phpcmf\Service::V()->assign(array(
'list' => $list,
'time' => $time,
'menu' => \Phpcmf\Service::M('auth')->_admin_menu(
[
'操作日志' => [\Phpcmf\Service::L('Router')->class.'/index', 'fa fa-calendar'],
]
),
'total' => $total,
'mypages' => \Phpcmf\Service::L('input')->page(\Phpcmf\Service::L('Router')->url('system_log/index', ['time' => $time]), $total, 'admin')
));
\Phpcmf\Service::V()->display('system_log.html');
}
public function show_index() {
$key = intval($_GET['id']);
$time = dr_safe_filename($_GET['time']);
!$time && $time = date('Y-m-d');
$cache = \Phpcmf\Service::L('cache')->get_data('system_log_'.USER_HTTP_CODE.$time.'_'.$key);
if (!$cache) {
$this->_json(0, dr_lang('查看超时,请重新进入'));
}
$cache['msg'] = $cache['action'];
if ($cache['param']) {
$cache['msg'].= '<br><hr><pre>'.(var_export($cache['param'], true)).'</pre>';
}
$cache['msg'].= '<br><hr>'.htmlspecialchars((string)$cache['url']);
$cache['msg'] = str_replace([PHP_EOL, chr(13), chr(10)], '<br>', $cache['msg']);
echo '<link href="'.THEME_PATH.'assets/global/css/admin.min.css" rel="stylesheet" type="text/css" />
<div style="padding: 20px">';
echo $cache['msg'];
exit('</div>');
}
public function del() {
$time = dr_safe_filename($_GET['time']);
!$time && $time = date('Y-m-d');
$time = strtotime($time);
$file = WRITEPATH.'log/'.date('Ym', $time).'/'.date('d', $time).'.php';
unlink($file);
$this->_json(1, dr_lang('操作成功'));
}
}
+527
View File
@@ -0,0 +1,527 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 通用接口处理
class Api extends \Phpcmf\Common {
/**
* ip地址
*/
public function ip_address() {
$value = dr_safe_replace(\Phpcmf\Service::L('input')->get('value'));
if (!$value) {
exit(dr_lang('IP地址为空'));
}
list($value, $port) = explode('-', $value);
$address = \Phpcmf\Service::L('ip')->address($value);
echo ('<a href="https://www.baidu.com/s?wd='.$value.'&action=xunruicms" target="_blank">'.dr_lang('IP归属地:%s', $address).'</a>');
if ($port) {
echo '
<br>'.dr_lang('源端口号:%s', (int)$port);
}
exit;
}
/**
* 保存浏览器定位坐标
*/
public function map_position() {
$value = dr_safe_replace(\Phpcmf\Service::L('input')->get('value'));
$cookie = \Phpcmf\Service::L('input')->get_cookie('map_position');
if ($cookie != $value) {
\Phpcmf\Service::L('input')->set_cookie('map_position', $value, 10000);
exit('ok');
}
exit('none');
}
/**
* 二维码显示
*/
public function qrcode() {
$value = urldecode(\Phpcmf\Service::L('input')->get('text'));
$thumb = urldecode(\Phpcmf\Service::L('input')->get('thumb'));
$matrixPointSize = (int)\Phpcmf\Service::L('input')->get('size');
$errorCorrectionLevel = dr_safe_replace(\Phpcmf\Service::L('input')->get('level'));
//生成二维码图片
require_once CMSPATH.'Library/Phpqrcode.php';
$file = WRITEPATH.'file/qrcode-'.md5($value.$thumb.$matrixPointSize.$errorCorrectionLevel).'-qrcode.png';
if (!IS_DEV && is_file($file)) {
$QR = imagecreatefrompng($file);
} else {
\QRcode::png($value, $file, $errorCorrectionLevel, $matrixPointSize, 3);
if (!is_file($file)) {
exit('二维码生成失败');
}
$QR = imagecreatefromstring(file_get_contents($file));
if ($thumb) {
if (stripos($thumb, 'phar://') !== false) {
exit('图片地址不规范');
} elseif (filter_var($thumb, FILTER_VALIDATE_URL) !== false || file_exists($thumb)) {
$img = getimagesize($thumb);
if (!$img) {
exit('此图片不是一张可用的图片');
}
$code = dr_catcher_data($thumb);
if (!$code) {
exit('图片参数不规范');
}
$logo = imagecreatefromstring($code);
$QR_width = imagesx($QR);//二维码图片宽度
$logo_width = imagesx($logo);//logo图片宽度
$logo_height = imagesy($logo);//logo图片高度
$logo_qr_width = $QR_width / 4;
$scale = $logo_width/$logo_qr_width;
$logo_qr_height = $logo_height/$scale;
$from_width = ($QR_width - $logo_qr_width) / 2;
//重新组合图片并调整大小
imagecopyresampled($QR, $logo, (int)$from_width, (int)$from_width, 0, 0, (int)$logo_qr_width, (int)$logo_qr_height, (int)$logo_width, (int)$logo_height);
imagepng($QR, $file);
} else {
exit('图片地址不规范');
}
}
}
// 输出图片
ob_start();
ob_clean();
header("Content-type: image/png");
$QR && imagepng($QR);
exit;
}
/**
* 搜索
*/
public function search() {
if (function_exists('dr_module_api_search')) {
dr_module_api_search();
} else {
exit('需要升级最新版的【内容建站系统】插件');
}
}
/**
* 检查关键字
*/
public function checktitle() {
if (function_exists('dr_module_checktitle')) {
dr_module_checktitle();
} else {
exit('需要升级最新版的【内容建站系统】插件');
}
}
/**
* 提取关键字
*/
public function getkeywords() {
exit(dr_get_keywords(dr_safe_replace(\Phpcmf\Service::L('input')->get('title'))));
}
/**
* 存储临时表单内容
*/
public function save_form_data() {
if (IS_POST && $this->member && $this->member['is_admin']) {
$rt = \Phpcmf\Service::L('cache')->init('file')->save(
md5(\Phpcmf\Service::L('input')->get('name')),
\Phpcmf\Service::L('input')->post('data'),
7200
);
var_dump($rt);
}
exit;
}
/**
* 删除临时表单内容
*/
public function delete_form_data() {
\Phpcmf\Service::L('cache')->init('file')->delete(md5(\Phpcmf\Service::L('input')->get('name', true)));
$this->_json(1, dr_lang('清除成功'));
exit;
}
/**
* 验证码
*/
public function captcha() {
$code = \Phpcmf\Service::L('captcha')->create(
max(0, intval($_GET['width'])), max(0, intval($_GET['height']))
);
\Phpcmf\Service::L('cache')->set_auth_data('web-captcha-'.USER_HTTP_CODE, $code, SITE_ID);
IS_DEV && log_message('debug', '图片验证码生成('.USER_HTTP_CODE.')验证码:'.$code);
exit;
}
/**
* 汉字转换拼音
*/
public function pinyin() {
$name = dr_safe_replace(\Phpcmf\Service::L('input')->get('name'));
if (!$name) {
exit('');
}
$py = \Phpcmf\Service::L('pinyin')->result($name);
if (strlen($py) > 12) {
$sx = \Phpcmf\Service::L('pinyin')->result($name, 0);
if ($sx) {
exit($sx);
}
}
exit($py);
}
/**
* 联动菜单调用
*/
public function linkage() {
$code = dr_safe_replace(\Phpcmf\Service::L('input')->get('code'));
$linkage = dr_linkage_json($code);
if (!$linkage) {
if (CI_DEBUG) {
$linkage = [
[
'value' => 0,
'label' => '请在联动菜单管理,找到【'.$code.'】,点击一键生成按钮',
'children' => [],
]
];
} else {
$linkage = [];
}
}
echo 'var linkage_'.$code.' ='.json_encode($linkage, JSON_UNESCAPED_UNICODE).';';exit;
}
/**
* 联动菜单Api
*/
public function linkage_json() {
$code = dr_safe_replace(\Phpcmf\Service::L('input')->get('code'));
if (!$code) {
$this->_json(0, dr_lang('联动菜单code参数没有值'));
}
$linkage = dr_linkage_json($code);
if (!$linkage) {
$this->_json(0, dr_lang('没有联动菜单数据'));
}
$this->_json(1, $code, $linkage);
}
/**
* 经典样式的联动菜单调用
*/
public function linkage_data() {
$code = dr_safe_replace(\Phpcmf\Service::L('input')->get('code'));
if (!$code) {
$this->_json(0, dr_lang('联动菜单code参数没有值'));
}
$pid = (int)\Phpcmf\Service::L('input')->get('pid');
$linkage = dr_linkage_list($code, $pid);
$json = [];
foreach ($linkage as $v) {
if ($v['pid'] == $pid) {
$json[] = $v;
}
}
if (!$json) {
$this->_json(0, dr_lang('没有联动菜单数据'));
}
$this->_json(1, $code, $json);
}
/**
* 经典样式的联动菜单调用
*/
public function linkage_ld() {
$pid = (int)\Phpcmf\Service::L('input')->get('parent_id');
$code = dr_safe_replace(\Phpcmf\Service::L('input')->get('code'));
$linkage = dr_linkage_list($code, $pid);
$json = [];
$html = '';
foreach ($linkage as $v) {
if ($v['pid'] == $pid) {
$json[] = [
'region_id' => $v['ii'],
'region_code' => $v['id'],
'region_name' => $v['name']
];
}
}
echo json_encode([
'data' => $json,
'html' => $html,
], JSON_UNESCAPED_UNICODE);exit;
}
/**
* Ajax调用字段属性表单
*/
public function field() {
\Phpcmf\Service::L('api')->field();
}
/**
* 动态调用模板
*/
public function template() {
$app = dr_safe_filename(\Phpcmf\Service::L('input')->get('app'));
$file = dr_safe_filename(\Phpcmf\Service::L('input')->get('name'));
$module = dr_safe_filename(\Phpcmf\Service::L('input')->get('module'));
$data = [
'app' => $app,
'file' => $file,
'module' => $module,
];
if (!$file) {
$html = 'name不能为空';
} else {
if ($module) {
$this->_module_init($module);
\Phpcmf\Service::V()->module($module);
} elseif ($app) {
\Phpcmf\Service::V()->module($app);
}
\Phpcmf\Service::V()->assign(\Phpcmf\Service::L('input')->get('', true));
ob_start();
\Phpcmf\Service::V()->display($file);
$html = ob_get_contents();
ob_clean();
$data['call_value'] = \Phpcmf\Service::V()->call_value;
}
$this->_json(1, $html, $data);
}
/**
* 内容关联字段数据读取
*/
public function related() {
$this->_json(0, dr_lang('需要安装最新版的【建站系统】插件'));
}
/**
* 会员关联字段数据读取
*/
public function members() {
$this->_json(0, dr_lang('需要安装最新版的【用户系统】插件'));
}
/**
* 退出前台账号
*/
public function loginout() {
// 注销授权登陆的会员
if ($this->session()->get('member_auth_uid')) {
\Phpcmf\Service::C()->session()->delete('member_auth_uid');
$this->_json(0, dr_lang('当前状态无法退出账号'));
}
$this->_json(1, dr_lang('您的账号已退出系统'), [
'url' => isset($_SERVER['HTTP_REFERER']) ? dr_safe_url($_SERVER['HTTP_REFERER']) : SITE_URL,
'sso' => \Phpcmf\Service::M('member')->logout(),
]);
}
/**
* 电脑和手机网站切换处理接口
*/
public function client() {
$this->_json(0, dr_lang('此功能已废弃'));
}
/**
* 发送验证码
*/
public function send_code() {
$phone = dr_safe_replace(\Phpcmf\Service::L('input')->get('id'));
if (!$phone) {
$this->_json(0, dr_lang('手机号码未填写'), ['field' => 'phone']);
} elseif (!\Phpcmf\Service::L('Form')->check_phone($phone)) {
$this->_json(0, dr_lang('手机号码格式不正确'), ['field' => 'phone']);
}
// 挂钩点 短信验证之前
\Phpcmf\Hooks::trigger('send_phone_before', $phone);
if (!defined('SYS_SMS_IMG_CODE') || SYS_SMS_IMG_CODE == 0) {
$code = dr_safe_replace(\Phpcmf\Service::L('input')->get('code'));
if (!$code) {
$this->_json(0, dr_lang('图片验证码未填写'), ['field' => 'code']);
} elseif (!\Phpcmf\Service::L('Form')->check_captcha_value($code)) {
$this->_json(0, dr_lang('图片验证码不正确'), ['field' => 'code']);
}
}
// 验证操作间隔
if (\Phpcmf\Service::L('Form')->get_mobile_code($phone)) {
$this->_json(1, dr_lang('已经发送稍后再试'));
}
$code = \Phpcmf\Service::L('Form')->get_rand_value();
$rt = \Phpcmf\Service::M('member')->sendsms_code($phone, $code);
if (!$rt['code']) {
$this->_json(0, IS_DEV ? $rt['msg'] : dr_lang('发送失败'));
}
\Phpcmf\Service::L('Form')->set_mobile_code($phone, $code);
$this->_json(1, dr_lang('验证码发送成功'));
}
/**
* 关联字段数据读取
*/
public function join() {
$user = (string)$_SERVER['HTTP_USER_AGENT'];
if (stripos($user, 'spider') !== false or strpos($user, 'bot') !== false) {
$this->goto_404_page('蜘蛛禁止抓取');
}
// 强制将模板设置为后台
\Phpcmf\Service::V()->admin();
// 登陆判断
//if (!$this->uid) {
// $this->_json(0, dr_lang('会话超时,请重新登录'));
//}
// 参数判断
$fid = intval(\Phpcmf\Service::L('input')->get('fid'));
if (!$fid) {
$this->_json(0, dr_lang('fid参数不存在'));
}
$field = \Phpcmf\Service::M()->table('field')->get($fid);
if (!$field) {
$this->_json(0, dr_lang('字段(%s)不存在', $fid));
}
$field['setting'] = dr_string2array($field['setting']);
$pagesize = $field['setting']['option']['pagesize'];
if (!$pagesize) {
$pagesize = 10;
}
// 模块缓存判断
$table = $field['setting']['option']['table'];
if (!$table) {
$this->_json(0, dr_lang('未设置关联表'));
}
$param = $data = \Phpcmf\Service::L('input')->get('', true);
$name = $field['fieldname'];
if (IS_POST) {
$ids = \Phpcmf\Service::L('input')->get_post_ids();
if (!$ids) {
$this->_json(0, dr_lang('没有选择项'));
}
$id = [];
foreach ($ids as $i) {
$id[] = (int)$i;
}
$builder = \Phpcmf\Service::M()->db->table($table);
$builder->whereIn('id', $id);
$mylist = $builder->orderBy('id DESC')->get()->getResultArray();
if (!$mylist) {
$this->_json(0, dr_lang('没有相关数据'));
}
$ids = [];
foreach ($mylist as $t) {
$ids[] = $t['id'];
}
$file = \Phpcmf\Service::V()->code2php(
file_get_contents(is_file(MYPATH.'View/api_join_field_'.$field['fieldname'].'.html') ? MYPATH.'View/api_join_field_'.$field['fieldname'].'.html' : COREPATH.'View/api_join_field.html')
);
ob_start();
require $file;
$code = ob_get_clean();
$html = explode('<!--list-->', $code);
$this->_json(1, dr_lang('操作成功'), ['ids' => $ids, 'html' => $html[1]]);
}
$where = [];
if ($data['search']) {
$data['keyword'] = dr_safe_replace(urldecode($data['keyword']));
if ($data['keyword']) {
$where[] = 'id LIKE "%'.$data['keyword'].'%"';
foreach ($field['setting']['option']['field'] as $t) {
if ($t['field']) {
$where[] = $t['field'].' LIKE "%'.$data['keyword'].'%"';
}
}
}
}
$rules = $data;
$rules['page'] = '{page}';
\Phpcmf\Service::V()->assign([
'table' => $table,
'param' => $data,
'field' => $field,
'where' => $where ? urlencode('('.implode(' OR ', $where).')') : '',
'search' => dr_form_search_hidden(['search' => 1, 'is_iframe' => 1, 'fid' => $fid]),
'urlrule' => '/index.php?s=api&c=api&m=join&'.http_build_query($rules),
'pagesize' => $pagesize,
]);
if (is_file(MYPATH.'View/api_join_'.$field['fieldname'].'.html')) {
\Phpcmf\Service::V()->display('api_join_'.$field['fieldname'].'.html');
} else {
\Phpcmf\Service::V()->display('api_join.html');
}
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
$file = dr_get_app_dir('pay').'Controllers/Buy.php';
if (is_file($file)) {
require_once $file;
} else {
\dr_exit_msg(0, '没有安装「支付系统」插件');
}
// 交易下单
class Buy extends \Phpcmf\Controllers\Buy {
}
File diff suppressed because it is too large Load Diff
+121
View File
@@ -0,0 +1,121 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 文件操作
class File extends \Phpcmf\Common
{
// 验证权限脚本
public function _check_upload_auth($editor = 0) {
return \Phpcmf\Service::L('api')->check_upload_auth($editor);
}
/**
* 文件上传
*/
public function upload() {
\Phpcmf\Service::L('api')->upload();
}
/**
* 输入一个附件
*/
public function input_file_url() {
\Phpcmf\Service::L('api')->input_file_url();
}
/**
* 浏览文件
*/
public function input_file_list() {
\Phpcmf\Service::L('api')->input_file_list();
}
/**
* 浏览文件
*/
public function file_list() {
\Phpcmf\Service::L('api')->file_list();
}
/**
* 删除文件
*/
public function file_delete() {
$rt = \Phpcmf\Service::M('Attachment')->file_delete(
$this->member,
(int)\Phpcmf\Service::L('input')->get('id')
);
$this->_json($rt['code'], $rt['msg']);
}
/**
* 下载文件
*/
public function down() {
\Phpcmf\Service::L('api')->down();
}
/**
* 百度编辑器处理接口
*/
public function ueditor() {
require ROOTPATH.'api/ueditor/php/controller.php';exit;
}
/**
* base64图片上传
*/
public function upload_base64_image() {
\Phpcmf\Service::L('api')->upload_base64_image();
}
/**
* 图片编辑
*/
public function image_edit() {
\Phpcmf\Service::L('api')->image_edit();
}
/**
* 附件改名
*/
public function name_edit() {
\Phpcmf\Service::L('api')->name_edit();
}
/**
* 下载远程图片
*/
public function down_img_list() {
\Phpcmf\Service::L('api')->down_img_list();
}
/**
* 下载远程图片
*/
public function down_img_url() {
\Phpcmf\Service::L('api')->down_img_url();
}
/**
* 下载远程图片
*/
public function down_img() {
\Phpcmf\Service::L('api')->down_img();
}
/**
* 编辑器视频外链解析
*/
public function video() {
\Phpcmf\Service::L('api')->video_link();
}
}
+51
View File
@@ -0,0 +1,51 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 接口处理
class Home extends \Phpcmf\Common
{
public function index() {
if (IS_API === 'pay') {
// 支付接口部分
$info = pathinfo($_SERVER['PHP_SELF']);
$name = basename($info['dirname']);
$path = trim($info['dirname'], '/');
$file = str_replace('_url.php', '_api.php', $info['basename']);
$apifile = WEBPATH . $path . '/' . $file;
if (!is_file($apifile)) {
if (IS_DEV) {
exit('支付接口文件('.$apifile.')不存在');
}
exit('支付接口文件不存在');
}
// 接口配置参数
$config = $this->member_cache['payapi'][$name];
require $apifile;
} elseif (IS_API === 'cron') {
// 任务脚本
$cron = new \Phpcmf\Control\Api\Run($this);
$cron->index();
} elseif (is_file(IS_API)) {
// 自定义任意目录的api
require IS_API;
} else {
$myfile = MYPATH.'Api/'.ucfirst(IS_API).'.php';
if (!is_file($myfile)) {
if (IS_DEV) {
exit('Api接口文件('.$myfile.')不存在');
}
exit('api file is error');
}
require $myfile;
exit;
}
exit;
}
}
+104
View File
@@ -0,0 +1,104 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本代码基于MIT开源协议,协议规定此处版权信息不可去除
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 模块ajax操作接口
class Module extends \Phpcmf\Common {
private $siteid;
private $dirname;
private $tablename;
public $content_model;
public function __construct() {
parent::__construct();
// 初始化模块
$this->siteid = (int)\Phpcmf\Service::L('input')->get('siteid');
!$this->siteid && $this->siteid = SITE_ID;
$this->dirname = dr_safe_filename(\Phpcmf\Service::L('input')->get('app'));
if ($this->dirname == 'MOD_DIR') {
$this->_msg(0, dr_lang('app参数存在问题'));
} elseif (!$this->dirname || !dr_is_app_dir(($this->dirname))) {
$this->_msg(0, dr_lang('模块目录[%s]不存在', $this->dirname));
exit;
}
$this->tablename = $this->siteid.'_'.$this->dirname;
$this->content_model = \Phpcmf\Service::M('Content', $this->dirname);
$this->_module_init($this->dirname, $this->siteid);
$user = (string)$_SERVER['HTTP_USER_AGENT'];
if (strpos($user, 'spider') !== false or strpos($user, 'bot') !== false) {
$this->goto_404_page('蜘蛛禁止抓取');
}
}
public function index() {
exit('module api');
}
/**
* 阅读数统计
*/
public function hits() {
$id = (int)\Phpcmf\Service::L('input')->get('id');
if (!$id) {
$this->_jsonp(0, dr_lang('阅读统计: id参数不完整'));
}
$rt = $this->content_model->update_hits($id, (int)\Phpcmf\Service::L('input')->get('qx'));
if (isset($_GET['format']) && $_GET['format'] == 'json') {
$this->_json($rt['code'], $rt['msg'], $rt['data']);
} else {
$this->_jsonp($rt['code'], $rt['msg'], $rt['data']);
}
}
/**
* 收藏模块内容
*/
public function favorite() {
if (!dr_is_app('favorite')) {
$this->_json(0, dr_lang('应用[模块内容收藏]未安装'));
}
$rt = \Phpcmf\Service::M('op', 'favorite')->run($this->tablename, $this->dirname);
$this->_json($rt['code'], $rt['msg'], $rt['data']);
}
/**
* 是否收藏模块内容
*/
public function is_favorite() {
if (!dr_is_app('favorite')) {
$this->_json(0, dr_lang('应用[模块内容收藏]未安装'));
}
$rt = \Phpcmf\Service::M('op', 'favorite')->is_favorite($this->tablename, $this->dirname);
$this->_json($rt['code'], $rt['msg'], $rt['data']);
}
/**
* 模块内容支持与反对
*/
public function digg() {
if (!dr_is_app('zan')) {
$this->_json(0, dr_lang('应用[模块内容点赞]未安装'));
}
$rt = \Phpcmf\Service::M('op', 'zan')->run($this->tablename, $this->dirname);
$this->_json($rt['code'], $rt['msg'], $rt['data']);
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 快捷登录接口
class Oauth extends \Phpcmf\Common
{
/**
* 快捷登录
*/
public function index() {
$name = dr_safe_filename(\Phpcmf\Service::L('input')->get('name'));
$type = dr_safe_replace(\Phpcmf\Service::L('input')->get('type'));
$back = dr_safe_replace(\Phpcmf\Service::L('input')->get('back'));
$action = dr_safe_replace(\Phpcmf\Service::L('input')->get('action'));
// 非授权登录时必须验证登录状态
if ($type != 'login' && !$this->uid) {
$this->_msg(0, dr_lang('你还没有登录'));
} elseif (!$name) {
$this->_msg(0, dr_lang('未知接入商'));
}
// 请求参数
$appid = $this->member_cache['oauth'][$name]['id'];
$appkey = $this->member_cache['oauth'][$name]['value'];
$callback_url = OAUTH_URL.'index.php?s=api&c=oauth&m=index&action=callback&name='.$name.'&type='.$type;
if ($back) {
$callback_url.= '&back='.urlencode(dr_redirect_safe_check($back));
}
$file = FCPATH.'ThirdParty/OAuth/'.ucfirst($name).'/Run.php';
if (is_file($file)) {
require $file;
} else {
$this->_msg(0, IS_DEV ? dr_lang('没有找到接入商(%s)执行程序', $file) : dr_lang('没有找到接入商的执行程序'));
}
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
$file = dr_get_app_dir('pay').'Controllers/Home.php';
if (is_file($file)) {
require_once $file;
} else {
\dr_exit_msg(0, '没有安装「支付系统」插件');
}
// 付款
class Pay extends \Phpcmf\Controllers\Home
{
}
+54
View File
@@ -0,0 +1,54 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 系统默认伪静态处理
class Rewrite extends \Phpcmf\Common
{
// test
public function test() {
$this->_jsonp(1, '服务器支持伪静态功能,可以自定义URL规则和解析规则了');
}
/**
* 跳转地址
*/
public function url() {
$url = urldecode(\Phpcmf\Service::L('input')->get('url'));
$arr = [ 0 => [], 1 => []];
for ($i = 1 ; $i < 10; $i ++) {
$arr[0][] = urldecode(\Phpcmf\Service::L('input')->get('p'.$i));
$arr[1][] = '$'.$i;
}
dr_redirect(dr_url_prefix(str_replace($arr[1], $arr[0], $url)), 'location', '301');
}
public function license() {
$license = \Phpcmf\Service::R(MYPATH.'Config/License.php');
if (isset($license['oem']) && $license['oem']) {
echo $license['name'].' '.$license['cms'].''.$license['type'].' V'.$this->cmf_version['version'] . ' <span style="display: none">'.$license['license'].'</span>';exit;
}
echo 'XunRuiCMS V'.$this->cmf_version['version'].'<hr>';
if (is_file(WEBPATH.'LICENSE')) {
$file = WEBPATH.'LICENSE';
} elseif (is_file(ROOTPATH.'LICENSE')) {
$file = ROOTPATH.'LICENSE';
} elseif (is_file(dirname(WEBPATH).'/LICENSE')) {
$file = dirname(WEBPATH).'/LICENSE';
} else {
exit('<font color="red">LICENSE许可证文件不存在,请遵守迅睿MIT开源协议</font>');
}
echo nl2br((string)file_get_contents($file));
exit;
}
}
+243
View File
@@ -0,0 +1,243 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
/**
* 运行任务接口
*/
class Run extends \Phpcmf\Common
{
/**
* 初始化
*/
public function __construct($object = NULL)
{
parent::__construct();
if ($object) {
foreach ($object as $var => $value) {
$this->$var = $value;
}
}
}
public function index() {
// 验证运行权限
if (!IS_DEV) {
if (defined('SYS_CRON_AUTH') && SYS_CRON_AUTH) {
if (is_cli()) {
// cli模式
} else {
// url模式
if (SYS_CRON_AUTH == 'cli') {
exit('限制CLI模式执行任务');
}
$ip = \Phpcmf\Service::L('input')->ip_address();
if (!$ip) {
if (CI_DEBUG) {
log_message('error', '任务执行失败:无法获取执行客户端的IP地址');
}
exit('无权限执行任务');
return;
}
if (SYS_CRON_AUTH != $ip) {
if (CI_DEBUG) {
log_message('error', '任务执行失败:后台设置的服务端ip('.SYS_CRON_AUTH.')与客户端ip'.$ip.')不一致');
}
exit('限制固定IP执行任务');
return;
}
}
}
$run_time = 0;// 上次执行的时间
if (is_file(WRITEPATH.'config/cron_run_time.php')) {
$run_time = file_get_contents(WRITEPATH.'config/cron_run_time.php');
if ($run_time && SYS_TIME - $run_time < 100) {
exit('未到任务执行时间');
}
} else {
file_put_contents(WRITEPATH.'config/cron_run_time.php', SYS_TIME);
}
$fp = fopen ( WRITEPATH.'config/cron_run_time.php' , "r" );
//加锁
if ( flock ( $fp ,LOCK_EX | LOCK_NB)) {
// 写入新的时间
file_put_contents(WRITEPATH.'config/cron_run_time.php', SYS_TIME);
} else {
fclose( $fp );
exit('任务正在执行中');
}
if (isset($_GET['is_ajax'])) {
// 后台脚本自动任务时
} else {
// 服务器自动任务时
// 自动任务锁定
if (!is_file(WRITEPATH.'config/run_lock.php')) {
file_put_contents(WRITEPATH.'config/run_lock.php', 'true');
}
}
} else {
$fp = false;
}
// 批量执行站点动作
foreach ($this->site_info as $siteid => $site) {
// 删除网站首页
if ($site['SITE_INDEX_HTML']) {
$time = (isset($site['SITE_INDEX_TIME']) && $site['SITE_INDEX_TIME'] ? $site['SITE_INDEX_TIME'] : 10) * 3600;
foreach ([
\Phpcmf\Service::L('html')->get_webpath($siteid,'site', 'index.html'),
\Phpcmf\Service::L('html')->get_webpath($siteid,'site', 'mobile/index.html'),
] as $file) {
$ft = filemtime($file);
if ($ft && SYS_TIME - $ft > $time) {
unlink($file);
}
}
}
}
// 执行队列
$i = \Phpcmf\Service::M('cron')->run_cron(intval($_GET['num']));
// 最少100秒调用本程序
//\Phpcmf\Service::L('input')->set_cookie('cron', 1, 100);
// 定义后台执行任务的时效
//\Phpcmf\Service::L('input')->set_cookie('admin_cron', 1, 600);
// 任务计划
\Phpcmf\Hooks::trigger('cron');
// 清理缓存数据
if (!is_file(WRITEPATH.'config/run_auto_cache_time.php')) {
$time = SYS_TIME;
file_put_contents(WRITEPATH.'config/run_auto_cache_time.php', $time);
} else {
$time = file_get_contents(WRITEPATH.'config/run_auto_cache_time.php');
}
// 多少天清理一次系统缓存
$day = max(3, SYS_CACHE_CRON);
if (SYS_TIME - $time > 3600 * 24 * $day) {
// 缓存清理
\Phpcmf\Service::M('cache')->update_data_cache(true);
file_put_contents(WRITEPATH.'config/run_auto_cache_time.php', SYS_TIME);
// 清理日志
$map = dr_file_map(WRITEPATH.'error/');
if ($map) {
foreach ($map as $file) {
if (strpos($file, 'log-') !== false) {
$file = WRITEPATH.'error/'.$file;
$time = filectime($file);
if ($time && SYS_TIME - $time > 3600 * 24 * 30) {
@unlink($file);
}
}
}
}
}
// 项目计划
if (is_file(MYPATH.'Config/Cron.php')) {
require MYPATH.'Config/Cron.php';
}
// 为插件单独执行计划
$local = \Phpcmf\Service::Apps();
if ($local) {
foreach ($local as $dir => $path) {
if (is_file($path.'Config/Cron.php')
&& is_file($path.'Config/App.php')
&& is_file($path.'install.lock')) {
require $path.'Config/Cron.php';
}
}
}
// 自动任务执行时间
file_put_contents(WRITEPATH.'config/run_time.php', dr_date(SYS_TIME));
if ($fp) {
flock ( $fp ,LOCK_UN);
fclose( $fp );
}
exit('任务执行成功:Run '.($i ? $i : 'Ok'));
}
/**
* 线程任务接口
*/
public function cron() {
$file = WRITEPATH.'thread/'.dr_safe_filename(\Phpcmf\Service::L('input')->get('auth')).'.auth';
if (!is_file($file)) {
//log_message('error', '线程任务auth文件不存在:'.dr_now_url());
exit('线程任务auth文件不存在'.$file);
}
$time = (int)file_get_contents($file);
unlink($file);
if (SYS_TIME - $time > 500) {
// 500秒外无效
log_message('error', '线程任务auth过期:'.dr_now_url());
exit('线程任务auth过期');
}
switch (\Phpcmf\Service::L('input')->get('action')) {
case 'oauth_down_avatar': // 快捷登录下载头像
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$oauth = \Phpcmf\Service::M()->table('member_oauth')->get($id);
if (!$oauth) {
exit('oauth不存在');
} elseif (!$oauth['uid']) {
exit('oauth没有绑定账号');
}
list($cache_path) = dr_avatar_path();
$path = $cache_path.dr_avatar_dir($oauth['uid']);
$file = $path.$oauth['uid'].'.jpg';
if (is_file($file)) {
\Phpcmf\Service::M()->db->table('member_data')->where('id', $oauth['uid'])->update(['is_avatar' => 1]);
exit('头像已经存在');
}
$avatar = dr_catcher_data($oauth['avatar']);
if ($avatar) {
if (!is_dir($path)) {
dr_mkdirs($path);
}
if (file_put_contents($file, $avatar)) {
\Phpcmf\Service::M()->db->table('member_data')->where('id', $oauth['uid'])->update(['is_avatar' => 1]);
}
}
break;
case 'cron': // 队列任务
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$rt = \Phpcmf\Service::M('cron')->do_cron_id($id);
if (!$rt['code']) {
log_message('debug', '任务执行失败('.$rt['msg'].'):'.$rt['data']['value']);
exit('任务执行失败('.$rt['msg'].'');
}
break;
}
exit('ok');
}
}
+115
View File
@@ -0,0 +1,115 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 同步登陆接口
class Sso extends \Phpcmf\Common {
public function index() {
switch (\Phpcmf\Service::L('input')->get('action')) {
case 'logout': // 前台退出登录
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
\Phpcmf\Service::L('input')->set_cookie('member_uid', 0, -30000);
\Phpcmf\Service::L('input')->set_cookie('admin_login_member', 0, -30000);
\Phpcmf\Service::L('input')->set_cookie('member_cookie', 0, -30000);
break;
case 'login': // 前台同步登录
$code = dr_authcode(\Phpcmf\Service::L('input')->get('code'), 'DECODE');
if (!$code) {
$this->_jsonp(0, '解密失败');
}
list($uid, $salt) = explode('-', $code);
if (!$uid || !$salt) {
$this->_jsonp(0, '格式错误');
}
$member = \Phpcmf\Service::M()->db->table('member')->where('id', $uid)->get()->getRowArray();
if (!$member) {
$this->_jsonp(0, '账号不存在');
} elseif ($salt != $member['salt']) {
$this->_jsonp(0, '账号验证失败');
}
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
\Phpcmf\Service::M('member')->save_cookie($member, \Phpcmf\Service::L('input')->get('remember'));
break;
case 'alogin': // 后台登录授权
$code = dr_authcode(\Phpcmf\Service::L('input')->get('code'), 'DECODE');
if (!$code) {
$this->_jsonp(0, '解密失败');
}
list($uid, $password) = explode('-', $code);
$admin = \Phpcmf\Service::L('cache')->get_data('admin_login_member');
if (!$admin) {
$this->_jsonp(0, '缓存失败');
} elseif ($password != md5($admin['id'].$admin['password'])) {
$this->_jsonp(0, '验证失败');
}
// 存储状态
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
\Phpcmf\Service::L('input')->set_cookie('admin_login_member', $uid.'-'.$admin['id'], 3600);
$this->session()->set('admin_login_member_code', md5($uid.$admin['id'].$admin['password']));
break;
case 'slogin': // 后台登录其他站点
exit('功能废弃');
break;
}
return $this->_jsonp(1, 'ok', [], true);
}
public function login() {
if (!IS_USE_MEMBER) {
$this->_json(0, '没有安装用户系统插件');
}
require IS_USE_MEMBER.'Controllers/Login.php';
$ci = new \Phpcmf\Controllers\Login($this);
$ci->index();
}
public function sms() {
if (!IS_USE_MEMBER) {
$this->_json(0, '没有安装用户系统插件');
}
require IS_USE_MEMBER.'Controllers/Login.php';
$ci = new \Phpcmf\Controllers\Login($this);
$ci->sms();
}
public function oauth() {
if (!IS_USE_MEMBER) {
$this->_json(0, '没有安装用户系统插件');
}
require IS_USE_MEMBER.'Controllers/Login.php';
$ci = new \Phpcmf\Controllers\Login($this);
$ci->oauth();
}
public function register() {
if (!IS_USE_MEMBER) {
$this->_json(0, '没有安装用户系统插件');
}
require IS_USE_MEMBER.'Controllers/Register.php';
$ci = new \Phpcmf\Controllers\Register($this);
$ci->index();
}
}
+40
View File
@@ -0,0 +1,40 @@
<?php namespace Phpcmf\Control\Api;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 测试信息
class Test extends \Phpcmf\Common
{
// test
public function https() {
echo 'xunruicms';
}
public function index() {
$license = \Phpcmf\Service::R(MYPATH.'Config/License.php');
if (isset($license['oem']) && $license['oem']) {
echo $license['name'].' '.$license['cms'].' V'.$this->cmf_version['version'] . ' <span style="display: none">'.$license['license'].'</span>';exit;
}
echo 'XunRuiCMS V'.$this->cmf_version['version'].'<hr>';
if (is_file(WEBPATH.'LICENSE')) {
$file = WEBPATH.'LICENSE';
} elseif (is_file(ROOTPATH.'LICENSE')) {
$file = ROOTPATH.'LICENSE';
} elseif (is_file(dirname(WEBPATH).'/LICENSE')) {
$file = dirname(WEBPATH).'/LICENSE';
} else {
exit('<font color="red">LICENSE许可证文件不存在,请遵守迅睿MIT开源协议</font>');
}
echo nl2br((string)file_get_contents($file));
exit;
}
}
+89
View File
@@ -0,0 +1,89 @@
<?php namespace Phpcmf\Control;
/**
* https://www.besyun.com
* BESCMS
* 本代码基于MIT开源协议,协议规定此处版权信息不可去除
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Category extends \Phpcmf\Home\Module {
public function index() {
if (IS_POST) {
$this->_json(0, '禁止提交,请检查提交地址是否有误');
}
$id = (int)\Phpcmf\Service::L('input')->get('id');
$dir = trim(dr_safe_replace(\Phpcmf\Service::L('input')->get('dir')), '/');
$page = max(1, (int)\Phpcmf\Service::L('input')->get('page'));
$module = \Phpcmf\Service::L('cache')->get('module-'.SITE_ID.'-share');
if (!$module) {
$module = \Phpcmf\Service::L('cache')->get_file('module-'.SITE_ID.'-share');
if (!$module) {
$this->_msg(0, dr_lang('共享栏目缓存不存在'));
return;
}
}
// 挂钩点
$rt2 = \Phpcmf\Hooks::trigger_callback('module_category_share');
if ($rt2 && isset($rt2['code']) && $rt2['code']) {
$id = $rt2['data'];
}
if ($id) {
$cat = $module['category'][$id];
if (!$cat) {
$this->goto_404_page(dr_lang('栏目(%s)不存在', $id));
}
} elseif ($dir) {
$id = intval($module['category_dir'][$dir]);
$cat = $module['category'][$id];
if (!$cat) {
if (isset($module['category_dir'][$dir])) {
$id = (int)$module['category_dir'][$dir];
$cat = $module['category'][$id];
} else {
// 无法通过目录找到栏目时,尝试多及目录
foreach ($module['category'] as $t) {
if ($t['setting']['urlrule']) {
$rule = \Phpcmf\Service::L('cache')->get('urlrule', $t['setting']['urlrule']);
$rule['value']['catjoin'] = '/';
if ($rule['value']['catjoin'] && strpos($dir, $rule['value']['catjoin'])) {
$dir = trim(strchr($dir, $rule['value']['catjoin']), $rule['value']['catjoin']);
if (isset($module['category_dir'][$dir])) {
$id = (int)$module['category_dir'][$dir];
$cat = $module['category'][$id];
break;
}
}
}
}
// 返回无法找到栏目
if (!$id) {
$this->goto_404_page(dr_lang('栏目(%s)不存在', $dir));
}
}
}
} else {
$this->goto_404_page(dr_lang('栏目参数不存在'));
}
// 初始化模块
if ($cat['tid'] == 1) {
if ($cat['mid']) {
$this->_module_init($cat['mid']);
} else {
$this->goto_404_page(dr_lang('栏目所属模块不存在'));
}
} else {
$this->_module_init('share');
}
// 调用栏目方法
$this->_Category($id, $dir, $page);
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php namespace Phpcmf\Control;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Home extends \Phpcmf\Common {
// 首页显示
public function index() {
if (IS_POST) {
$this->_json(0, '禁止提交,请检查提交地址是否有误');
}
// 挂钩点 网站首页时
$rs = \Phpcmf\Hooks::trigger_callback('index_page');
if ($rs && isset($rs['code'])) {
// 存在返回动作不加载模板
} else {
\Phpcmf\Service::L('Router')->is_redirect_url(dr_url_prefix('/'), 1);
\Phpcmf\Service::V()->assign([
'indexc' => 1,
'fix_html_now_url' => SITE_URL,
]);
\Phpcmf\Service::V()->assign([
'meta_title' => SITE_NAME,
'meta_keywords' => SITE_NAME,
'meta_description' => SITE_NAME
]);
\Phpcmf\Service::V()->display('index.html');
}
}
/**
* 404 页面
*/
public function s404() {
if (IS_DEV) {
$uri = \Phpcmf\Service::L('input')->get('uri', true);
$msg = '没有找到这个页面: '.$uri;
} else {
$msg = dr_lang('没有找到这个页面');
}
$this->goto_404_page($msg);
}
}
+170
View File
@@ -0,0 +1,170 @@
<?php namespace Phpcmf\Control;
/**
* https://www.besyun.com
* BESCMS
* 本代码基于MIT开源协议,协议规定此处版权信息不可去除
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
// 生成静态
class Html extends \Phpcmf\Home\Module {
private $is_html;
// 首页动作
public function _index_page() {
ob_start();
\Phpcmf\Service::V()->assign([
'is_cms' => 1,
'indexc' => 1,
'fix_html_now_url' => defined('IS_MOBILE') && IS_MOBILE ? SITE_MURL : SITE_URL,
]);
\Phpcmf\Service::V()->assign($this->_index_seo());
\Phpcmf\Service::V()->display('index.html');
$html = ob_get_clean();
// 开启过首页静态时
if ($this->site_info[SITE_ID]['SITE_INDEX_HTML'] && !defined('SC_HTML_FILE')) {
if (IS_CLIENT) {
// 自定义终端
$file = dr_is_app('chtml') ? \Phpcmf\Service::L('html', 'chtml')->get_webpath(SITE_ID, 'site', IS_CLIENT.'/index.html') : WEBPATH.IS_CLIENT.'/index.html';
$rt = file_put_contents($file, $html);
!$rt && CI_DEBUG && log_message('error', '首页终端('.IS_CLIENT.')生成失败:'.$file);
} elseif (defined('IS_MOBILE') && IS_MOBILE) {
// 移动端,当移动端独立域名情况下才生成静态
if (defined('SITE_IS_MOBILE_HTML') && SITE_IS_MOBILE_HTML && SITE_MURL == dr_now_url()) {
$mfile = dr_is_app('chtml') ? \Phpcmf\Service::L('html', 'chtml')->get_webpath(SITE_ID, 'site', SITE_MOBILE_DIR.'/index.html') : WEBPATH.SITE_MOBILE_DIR.'/index.html';
$mobile = file_put_contents($mfile, $html);
!$mobile && CI_DEBUG && log_message('error', '首页移动端生成失败:'.$mfile);
}
} else {
// pc
$file = dr_is_app('chtml') ? \Phpcmf\Service::L('html', 'chtml')->get_webpath(SITE_ID, 'site', 'index.html') : WEBPATH.'index.html';
$pc = file_put_contents($file, $html);
!$pc && CI_DEBUG && log_message('error', '首页PC端首页生成失败:'.$file);
}
}
echo $html;
}
// 首页显示
public function index() {
if (IS_POST) {
$this->_json(0, '禁止提交,请检查提交地址是否有误');
}
// 挂钩点 网站首页时
\Phpcmf\Hooks::trigger_callback('cms_index');
\Phpcmf\Service::L('Router')->is_redirect_url(dr_url_prefix('/'), 1);
$this->_index_page();
}
// 生成静态
public function html() {
// 判断权限
if (!dr_html_auth()) {
$this->_json(0, '权限验证超时,请重新执行生成');
}
// 标识变量
!defined('SC_HTML_FILE') && define('SC_HTML_FILE', 1);
// 开启ob函数
ob_start();
$this->is_html = 1;
\Phpcmf\Service::V()->init('pc');
\Phpcmf\Service::V()->assign([
'fix_html_now_url' => SITE_URL, // 修复静态下的当前url变量
]);
$this->_index_page();
$html = ob_get_clean();
$file = dr_is_app('chtml') ? \Phpcmf\Service::L('html', 'chtml')->get_webpath(SITE_ID, 'site', 'index.html') : WEBPATH.'index.html';
$pc = file_put_contents($file, $html, LOCK_EX);
!$pc && CI_DEBUG && log_message('error', '首页PC端首页生成失败:'.$file);
if (SITE_MURL != SITE_URL) {
// 开启ob函数
ob_start();
$this->is_html = 1;
\Phpcmf\Service::V()->init('mobile');
\Phpcmf\Service::V()->assign([
'fix_html_now_url' => SITE_MURL, // 修复静态下的当前url变量
]);
$this->_index_page();
$html = ob_get_clean();
$mfile = dr_is_app('chtml') ? \Phpcmf\Service::L('html', 'chtml')->get_webpath(SITE_ID, 'site', SITE_MOBILE_DIR.'/index.html') : WEBPATH.SITE_MOBILE_DIR.'/index.html';
$mobile = file_put_contents($mfile, $html, LOCK_EX);
!$mobile && CI_DEBUG && log_message('error', '首页移动端生成失败:'.$mfile);
} else {
CI_DEBUG && log_message('error', '首页移动端生成失败:移动端未绑定域名');
}
$this->_json(1, dr_lang('电脑端 %s),移动端 %s', dr_format_file_size($pc), dr_format_file_size($mobile)));
}
private function _index_seo() {
$seo = [
'meta_title' => \Phpcmf\Service::C()->get_cache('site', SITE_ID, 'seo', 'SITE_TITLE'),
'meta_keywords' => \Phpcmf\Service::C()->get_cache('site', SITE_ID, 'seo', 'SITE_KEYWORDS'),
'meta_description' => \Phpcmf\Service::C()->get_cache('site', SITE_ID, 'seo', 'SITE_DESCRIPTION')
];
if (IS_CLIENT) {
// 终端模式下
$cdata = \Phpcmf\Service::R(WRITEPATH.'config/app_client_seo_'.SITE_ID.'.php');
if ($cdata && isset($cdata[IS_CLIENT]) && $cdata[IS_CLIENT]) {
$seo = [
'meta_title' => $cdata[IS_CLIENT]['SITE_TITLE'],
'meta_keywords' => $cdata[IS_CLIENT]['SITE_KEYWORDS'],
'meta_description' => $cdata[IS_CLIENT]['SITE_DESCRIPTION']
];
}
}
!$seo['meta_title'] && $seo['meta_title'] = SITE_NAME;
if ($seo['meta_title'] && strpos($seo['meta_title'], '{page}') !== false) {
$page = max(1, intval($_GET['page']));
if ($page > 1) {
$seo['meta_title'] = str_replace(array('[', ']'), '', $seo['meta_title']);
$seo['meta_title'] = str_replace('{join}', SITE_SEOJOIN, $seo['meta_title']);
$seo['meta_title'] = str_replace('{page}', $page, $seo['meta_title']);
} else {
$seo['meta_title'] = preg_replace('/\[.+\]/U', '', $seo['meta_title']);
}
}
return \Phpcmf\Service::L('Seo')->get_seo_value([], $seo);
}
// 生成栏目
public function category() {
parent::_Category_Html();
}
// 生成内容
public function show() {
parent::_Show_Html();
}
// 生成栏目单页
public function categoryfile() {
parent::_Category_Html_File();
}
// 生成内容单页
public function showfile() {
parent::_Show_Html_File();
}
}
+987
View File
@@ -0,0 +1,987 @@
<?php namespace Phpcmf\Control;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
define('IS_INSTALL', 1);
set_time_limit(0);
// 安装程序
class Install extends \Phpcmf\Common {
public $db;
private $lock;
/**
* 初始化共享控制器
*/
public function __construct()
{
parent::__construct();
define('SITE_LANGUAGE', is_file(WRITEPATH.'lang.default') ? file_get_contents(WRITEPATH.'lang.default') : 'zh-cn');
define('SITE_ID', 1);
define('SITE_URL', '/');
define('SITE_MURL', '/');
define('IS_API_HTTP', 0);
define('SITE_TEMPLATE', 'default');
define('THEME_PATH', '/static/');
define('ROOT_THEME_PATH', '/static/');
define('LANG_PATH', '/api/language/'.SITE_LANGUAGE.'/');
if (is_file(MYPATH.'Config/Version.php')) {
$app = require MYPATH.'Config/Version.php';
} else {
$app = [
'id' => 1,
'name' => 'XunRui',
'version' => 'dev',
];
}
define('DR_CMS', $app['id']);
define('DR_NAME', $app['name']);
define('DR_VERSION', $app['version']);
define('SITE_NAME', $app['name']);
define('CMF_UPDATE_TIME', SYS_TIME);
\Phpcmf\Service::V()->init('pc');
\Phpcmf\Service::V()->admin();
}
public function index() {
$this->lock = WRITEPATH.'install.lock';
if (!IS_XRDEV && is_file($this->lock)) {
exit(dr_lang('安装程序已经被锁定,重新安装请删除%s', 'cache/install.lock'));
}
$data = [];
$step = intval($_GET['step']);
if (!$step && SITE_LANGUAGE != 'zh-cn') {
$step = 1;
}
$error = '';
$admin = 'admin';
switch ($step) {
case 0:
$gsname = '四川迅睿云软件开发有限公司';
if (is_file(MYPATH.'Config/License.php')) {
$ls = require MYPATH.'Config/License.php';
if (isset($ls['name']) && $ls['name']) {
$gsname = $ls['name'];
}
}
\Phpcmf\Service::V()->assign([
'gsname' => $gsname,
]);
break;
case 1:
$error = 0;
// 目录权限检查
$dir = [
WRITEPATH,
WRITEPATH.'data/',
WRITEPATH.'file/',
WRITEPATH.'config/',
WRITEPATH.'session/',
WRITEPATH.'template/',
WRITEPATH.'database/', CONFIGPATH,
WEBPATH.'uploadfile/',
];
$path = [];
foreach ($dir as $t) {
$path[$t] = dr_check_put_path($t);
if (!$path[$t]) {
$error = 1;
}
}
$php = [
[
'name' => dr_lang('PHP扩展%s', 'mbstring'),
'code' => function_exists('mb_substr'),
'help' => 'http://www.xunruicms.com/doc/742.html',
],
[
'name' => dr_lang('PHP扩展%s', 'curl'),
'code' => function_exists('curl_init'),
'help' => 'http://www.xunruicms.com/doc/743.html',
],
];
$db_ext = [
[
'name' => dr_lang('PHP扩展%s', 'mysqli').'MySQLi',
'code' => function_exists('mysqli_init'),
'help' => 'http://www.xunruicms.com/doc/741.html',
],
[
'name' => dr_lang('PHP扩展%s', 'sqlite3').'SQLite3',
'code' => extension_loaded('sqlite3'),
'help' => '',
],
];
// 数据库扩展:mysqli / sqlite3 至少启用一个即可
$has_db_ext = function_exists('mysqli_init') || extension_loaded('sqlite3');
if (!$has_db_ext) {
$error = 1;
}
\Phpcmf\Service::V()->assign([
'php' => $php,
'db_ext' => $db_ext,
'has_db_ext' => $has_db_ext,
'path' => $path,
'error' => $error,
]);
break;
case 2:
// 安装信息填写
$is_demo = is_file(MYPATH.'Config/demo.sql') && !is_file(MYPATH.'Config/Install.sql');
if (IS_AJAX_POST) {
$data = $_POST['data'];
if (empty($data['name'])) {
$this->_json(0, dr_lang('项目名称不能为空'));
} elseif (empty($data['username'])) {
$this->_json(0, dr_lang('创始人账号不能为空'));
} elseif (empty($data['password'])) {
$this->_json(0, dr_lang('创始人密码不能为空'));
} elseif (empty($data['email'])) {
$this->_json(0, dr_lang('创始人邮箱不能为空'));
}
// 数据库驱动:扫描 System/Database 下可用驱动(目录不存在则默认 MySQLi)
$drivers = $this->_scan_database_drivers($this->_my_install_sql_requires_mysql());
$rawDriver = isset($data['db_driver']) ? trim((string) $data['db_driver']) : '';
$selected = null;
foreach ($drivers as $d) {
if (strcasecmp($d['name'], $rawDriver) === 0) {
$selected = $d;
break;
}
}
if (!$selected) {
// 默认优先 MySQLi
foreach ($drivers as $d) {
if ($d['enabled']) {
$selected = $d;
if ($d['name'] === 'MySQLi') {
break;
}
}
}
}
if (!$selected || !$selected['enabled']) {
$this->_json(0, dr_lang('不支持的数据库驱动:%s', $rawDriver !== '' ? $rawDriver : '-'));
}
$data['db_driver'] = $selected['name'];
// 自定义包 Install.sql 含 SQL 时仅允许 MySQLi
if ($this->_my_install_sql_requires_mysql() && $data['db_driver'] !== 'MySQLi') {
$this->_json(0, dr_lang('当前安装包存在自定义 Install.sql,仅支持 MySQLi 安装'));
}
if (empty($data['db_prefix'])) {
$this->_json(0, dr_lang('数据表前缀不能为空'));
}
if ($data['db_driver'] === 'SQLite3') {
// 路径与随机文件名由 _install_db_bootstrap 生成
$data['db_host'] = isset($data['db_host']) ? $data['db_host'] : '';
$data['db_user'] = isset($data['db_user']) ? $data['db_user'] : '';
$data['db_pass'] = isset($data['db_pass']) ? $data['db_pass'] : '';
} else {
if (empty($data['db_host'])) {
$this->_json(0, dr_lang('数据库地址不能为空'));
} elseif (empty($data['db_user'])) {
$this->_json(0, dr_lang('数据库账号不能为空'));
} elseif (empty($data['db_name'])) {
$this->_json(0, dr_lang('数据库名称不能为空'));
} elseif (!isset($data['db_pass'])) {
$this->_json(0, dr_lang('数据库密码不能为空'));
}
// 允许空密码(部分本地环境)
if (is_numeric(substr($data['db_name'], 0, 1))) {
$this->_json(0, dr_lang('数据库名称(%s)不能是数字开头', $data['db_name']));
} elseif (strpos($data['db_name'], '.') !== false) {
$this->_json(0, dr_lang('数据库名(%s)不能存在.号', $data['db_name']));
}
$data['db_name'] = dr_safe_filename($data['db_name']);
}
$rt = $this->_install_db_bootstrap($data);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
// SQLite 可能规范化了相对路径(如补全 database/ 前缀)
if (!empty($rt['data']) && is_array($rt['data'])) {
$data = array_merge($data, $rt['data']);
}
$data['db_prefix'] = strtolower($data['db_prefix']);
// 存储缓存文件中
$size = file_put_contents(WRITEPATH.'install.info', dr_array2string($data));
if (!$size || $size < 10) {
$this->_json(0, dr_lang('临时数据存储失败,cahce目录无法写入'));
}
// 写入数据库配置(显式 DBDriver,供驱动层 DDL/方言转换使用)
$rt = $this->_write_database_config($data);
if (!$rt['code']) {
$this->_json(0, $rt['msg']);
}
$this->_json(1, 'index.php?c=install&m=index&is_install_db='.(!$is_demo ? 0 : intval($_POST['is_install_db'])).'&step='.($step+1));
}
$force_mysqli = $this->_my_install_sql_requires_mysql();
$db_drivers = $this->_scan_database_drivers($force_mysqli);
$default_driver = 'MySQLi';
$db_dir_missing = !is_dir(FRAMEPATH.'Database/');
foreach ($db_drivers as $d) {
if (!empty($d['enabled'])) {
$default_driver = $d['name'];
if ($d['name'] === 'MySQLi') {
break;
}
}
}
$data = [
'do_url' => '/index.php?c=install&m=index&is_install_db='.(!$is_demo ? 0 : intval($_POST['is_install_db'])).'&step=2',
'is_demo' => $is_demo,
'db_driver' => $default_driver,
'db_drivers' => $db_drivers,
'db_dir_missing' => $db_dir_missing,
'db_host' => defined('INSTALL_DB_HOST') ? INSTALL_DB_HOST : '127.0.0.1',
'db_user' => defined('INSTALL_DB_USER') ? INSTALL_DB_USER : '',
'db_pass' => defined('INSTALL_DB_PASS') ? INSTALL_DB_PASS : '',
'db_name' => defined('INSTALL_DB_NAME') ? INSTALL_DB_NAME : '',
'db_prefix' => defined('INSTALL_DB_PREFIX') ? INSTALL_DB_PREFIX : 'dr_',
'sqlite_name' => 'database/SQLite3/'.dr_lang('安装时随机生成'),
'force_mysqli' => $force_mysqli,
];
\Phpcmf\Service::V()->assign($data);
break;
case 3:
$page = intval($_GET['page']);
$data = dr_string2array(file_get_contents(WRITEPATH.'install.info'));
$error = '';
file_put_contents(WRITEPATH.'install.error', '');
if (empty($data)) {
$error = dr_lang('临时数据获取失败,请返回前一页重新执行');
} else {
$this->db = \Phpcmf\Service::M()->db;
// 检查数据库是否存在
if (!$this->db->connect(false)) {
// 链接失败,尝试创建数据库
$error = dr_lang('数据库连接失败,请返回前一页重新执行');
} elseif (!isset($_GET['doin']) && $this->db->tableExists($data['db_prefix'].'cron')) {
// 判断是否安装过
if (isset($data['db_driver']) && $data['db_driver'] === 'SQLite3') {
$error = dr_lang('指定的数据库文件(%s)已经安装过表前缀(%s),你可以尝试修改数据库文件名或者数据表前缀', $data['db_name'], $data['db_prefix']);
} else {
$error = dr_lang('指定的数据库(%s)已经安装过表前缀(%s),你可以尝试修改数据库名或者数据表前缀', $data['db_name'], $data['db_prefix']);
}
} else {
// 导入数据结构
if ($page) {
// 优先规范化 SchemaConfig/Install.php);自定义包仍可用 MYPATH Install.sql
$schema_file = '';
if (!is_file(MYPATH.'Config/Install.sql') && is_file(CMSPATH.'Config/Install.php')) {
$schema_file = CMSPATH.'Config/Install.php';
}
if ($schema_file) {
if ((int)$page === 1) {
$schema = require $schema_file;
if (!is_array($schema) || empty($schema['tables'])) {
$this->_json(0, dr_lang('安装 Schema 无效:%s', $schema_file));
}
$rt = \Phpcmf\Service::M('table')->install_schema($schema);
if (!$rt['code']) {
$error = '**************************************************************************'
.PHP_EOL.$rt['msg'].PHP_EOL
.'**************************************************************************'.PHP_EOL;
file_put_contents(WRITEPATH.'install.error', $error.PHP_EOL, FILE_APPEND);
$this->_json(0, $rt['msg']);
}
$this->_json(1, dr_lang('表结构安装完成(%s张表)', intval($rt['data']['tables'] ?? 0)), ['page' => 99]);
}
$this->_json(1, dr_lang('执行完成,即将安装数据信息...'), ['page' => 99]);
}
if (is_file(MYPATH.'Config/Install.sql')) {
$sql = file_get_contents(MYPATH.'Config/Install.sql');
if (strlen($sql) < 100) {
$sql = file_get_contents(CMSPATH.'Config/Install.sql');
}
} else {
$sql = file_get_contents(CMSPATH.'Config/Install.sql');
}
$sql = str_replace('{dbprefix}', $data['db_prefix'], $sql);
// 每批条数过少会导致超大 Install.sql 需要数百次 AJAX,易中途超时;可按环境酌情调大
$rows = $this->query_rows($sql, 40);
$key = $page - 1;
if (isset($rows[$key]) && $rows[$key]) {
// 安装本次结构
$last_sql = '';
foreach ($rows[$key] as $statement) {
if (!$statement) {
continue;
}
$statement = trim($statement);
if ($statement === '') {
continue;
}
$last_sql = $statement;
if (!$this->db->simpleQuery($statement)) {
$rt = $this->db->error();
$error = '**************************************************************************'
.PHP_EOL.$statement.PHP_EOL.$rt['message'].PHP_EOL;
$error.= '**************************************************************************'.PHP_EOL;
file_put_contents(WRITEPATH.'install.error', $error.PHP_EOL, FILE_APPEND);
$this->_json(0, 'SQL执行错误:'.$rt['message']);
}
}
$this->_json(1, dr_lang('正在执行:%s', dr_strcut($last_sql, 70)), ['page' => $page + 1]);
} else {
$this->_json(1, dr_lang('执行完成,即将安装数据信息...'), ['page' => 99]);
}
}
}
}
\Phpcmf\Service::V()->assign([
'do_url' => 'index.php?c=install&m=index&step=3&doin=1&is_install_db='.intval($_GET['is_install_db']),
]);
break;
case 4:
$data = dr_string2array(file_get_contents(WRITEPATH.'install.info'));
if (empty($data)) {
$error = dr_lang('临时数据获取失败,请返回前一页重新执行');
} else {
$this->db = \Phpcmf\Service::M()->db;
// 检查数据库是否存在
if (!$this->db->connect(false)) {
// 链接失败,尝试创建数据库
$error = dr_lang('数据库连接失败,请返回前一页重新执行');
} else {
// 导入默认安装数据
$errorlog = file_get_contents(WRITEPATH.'install.error');
if ($errorlog && strlen($errorlog) > 10) {
// 出现错误了
$error = $errorlog;
} else {
if (!\Phpcmf\Service::M()->is_table_exists('member')) {
if (is_file(MYPATH.'Config/Install.sql')) {
$sql = MYPATH.'Config/Install.sql';
} elseif (is_file(CMSPATH.'Config/Install.php')) {
$sql = CMSPATH.'Config/Install.php';
} else {
$sql = CMSPATH.'Config/Install.sql';
}
$error = dr_lang('安装文件:%s', $sql);
$error.= '<br>'.dr_lang('关键数据表member结构不完整,检查安装包结构文件是否合理');
} else {
// 创建账号
$pwd = md5(dr_safe_password($data['password']));
$salt = substr(md5(rand(0, 999)), 0, 10);
$prefix = \Phpcmf\Service::M()->prefix;
if (\Phpcmf\Service::M()->table('member')->get(1)) {
\Phpcmf\Service::M()->table('member')->update(1, [
'email' => $data['email'],
'username' => $data['username'],
'password' => md5($pwd.$salt.$pwd),
'salt' => $salt,
'name' => dr_lang('创始人'),
'phone' => '',
'money' => 1000000,
'freeze' => 0,
'spend' => 0,
'score' => 1000000,
'experience' => 1000000,
'regip' => '',
'regtime' => SYS_TIME,
'randcode' => 0,
]);
$id = 1;
} else {
$this->db->table('member')->insert([
'email' => $data['email'],
'username' => $data['username'],
'password' => md5($pwd.$salt.$pwd),
'salt' => $salt,
'name' => dr_lang('创始人'),
'phone' => '',
'money' => 1000000,
'freeze' => 0,
'spend' => 0,
'score' => 1000000,
'experience' => 1000000,
'regip' => '',
'regtime' => SYS_TIME,
'randcode' => 0,
]);
$id = $this->db->insertID();
$this->db->table('member_data')->insert([
'id' => $id,
'is_lock' => 0,
'is_admin' => 1,
'is_verify' => 1,
'is_mobile' => 1,
'is_complete' => 1,
]);
}
// 加入管理员表
if (!\Phpcmf\Service::M()->table('admin')->where('uid', $id)->counts()) {
$this->db->table('admin')->insert([
'uid' => $id,
'setting' => '',
'usermenu' => '',
]);
// 加入角色表
$this->db->table('admin_role_index')->insert([
'uid' => $id,
'roleid' => 1,
]);
}
// 创建站点
if (\Phpcmf\Service::M()->table('site')->get(1)) {
\Phpcmf\Service::M()->table('site')->update(1, [
'name' => $data['name'],
'domain' => DOMAIN_NAME,
]);
} else {
$this->db->table('site')->replace([
'id' => 1,
'name' => $data['name'],
'domain' => DOMAIN_NAME,
'setting' => '',
'disabled' => 0,
'displayorder' => 0,
]);
}
\Phpcmf\Service::M()->site = $this->site = [ 1 => 1 ];
$ssl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443') ? 1 : 0;;
if (isset($_GET['protocol']) && trim($_GET['protocol'], ':') == 'https') {
$ssl = 1;
}
// 写配置文件
$sys = [
'SYS_DEBUG' => '1',
'SYS_ADMIN_CODE' => '0',
'SYS_ADMIN_LOG' => '0',
'SYS_AUTO_FORM' => '0',
'SYS_ADMIN_PAGESIZE' => '10',
'SYS_SMS_IMG_CODE' => '0',
'SYS_NOT_ADMIN_CACHE' => '0',
'SYS_URL_ONLY' => '0',
'SYS_THEME_ROOT_PATH' => '1',
'SYS_URL_REL' => '1',
'SYS_CRON_AUTH' => '0',
'SYS_CSRF' => '0',
'SYS_CSRF_TIME' => '0',
'SYS_301' => '1',
'SYS_NOT_UPDATE' => '1',
'SYS_KEY' => 'PHPCMF'.md5($data['name'].rand(1, 999999)), //安全密匙
'SYS_HTTPS' => $ssl,
'SYS_ATTACHMENT_DB' => '',
'SYS_ATTACHMENT_PATH' => '',
'SYS_ATTACHMENT_URL' => '',
'SYS_API_TOKEN' => '',
];
if (is_file(MYPATH.'Config/License.php')) {
$ls = require MYPATH.'Config/License.php';
if (isset($ls['oem']) && $ls['oem']) {
$sys['SYS_DEBUG'] = 0;
}
}
\Phpcmf\Service::M('System')->save_config($sys, $sys);
// 删除app的install.lock
$local = \Phpcmf\Service::Apps();
foreach ($local as $dir => $path) {
if (is_file($path.'install.lock')) {
unlink($path.'install.lock');
}
}
// 执行安装程序废除
/*
$sql = '';
if (is_file(MYPATH.'Config/Install.sql')) {
$sql = file_get_contents(MYPATH.'Config/Install.sql');
$sql = str_replace('{dbprefix}', $data['db_prefix'], $sql);
}
if (is_file(MYPATH.'Config/Install_site.sql')) {
$s = file_get_contents(MYPATH.'Config/Install_site.sql');
$sql.= PHP_EOL.str_replace('{dbprefix}', $data['db_prefix'].'1_', $s);
}
$this->query($sql);*/
// 运行自定义安装脚本
if (is_file(MYPATH.'Config/Install.php')) {
require MYPATH.'Config/Install.php';
}
// 运行自定义安装脚本②
if (is_file(MYPATH.'Config/Install_tpl.php')) {
require MYPATH.'Config/Install_tpl.php';
}
$errorlog = file_get_contents(WRITEPATH.'install.error');
if ($errorlog && strlen($errorlog) > 10) {
// 出现错误了
$error = $errorlog;
} else {
// 安装完成
file_put_contents($this->lock, time());
file_put_contents(WRITEPATH.'update.txt', time());
file_put_contents(WRITEPATH.'install.test', time());
unlink(WRITEPATH.'install.info');
unlink(WRITEPATH.'install.error');
// 重命名后台入口
$admin = 'admin'.substr(md5(SYS_TIME.rand(1, 999999)), 0, 12);
$afile = WEBPATH.$admin.'.php';
if (is_file(WEBPATH.'admin.php')) {
copy(WEBPATH.'admin.php', $afile);
}
if (!is_file($afile)) {
file_put_contents($afile, "<?php
define('IS_ADMIN', TRUE);
define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));
require('index.php');");
}
if (is_file($afile)) {
unlink(WEBPATH.'admin.php');
} else {
$admin = 'admin';
}
}
}
}
}
}
break;
}
\Phpcmf\Service::V()->assign([
'data' => $data,
'step' => $step,
'error' => $error,
'admin' => $admin,
'pre_url' => 'index.php?c=install&m=index&step='.($step-1).'&is_install_db='.intval($_GET['is_install_db']),
'next_url' => 'index.php?c=install&m=index&step='.($step+1).'&is_install_db='.intval($_GET['is_install_db']),
]);
\Phpcmf\Service::V()->display('install/'.$step.'.html');
exit;
}
/**
* 扫描 FRAMEPATH/Database 目录,列出可识别的数据库驱动
*
* @param bool $forceMysqli 自定义 Install.sql 时仅启用 MySQLi
* @return array [['name','label','ext_ok','installable','enabled','form','tip'], ...]
*/
private function _scan_database_drivers($forceMysqli = false)
{
$base = FRAMEPATH.'Database/';
$list = [];
// 无 System/Database 目录时,默认仅 MySQLMySQLi)模式
if (!is_dir($base)) {
$extOk = function_exists('mysqli_init');
return [[
'name' => 'MySQLi',
'label' => 'MySQLi',
'ext_ok' => $extOk,
'installable' => true,
'enabled' => $extOk,
'form' => 'server',
'tip' => $extOk ? '' : dr_lang('PHP 未启用对应扩展'),
]];
}
// PHP 扩展检测
$extMap = [
'MySQLi' => function_exists('mysqli_init'),
'SQLite3' => extension_loaded('sqlite3'),
'Postgre' => extension_loaded('pgsql'),
'SQLSRV' => extension_loaded('sqlsrv'),
'OCI8' => extension_loaded('oci8'),
];
// 表单类型:sqlite 用文件表单,其余用服务器表单
$formMap = [
'SQLite3' => 'sqlite',
];
// 安装引导已实现的驱动(其余目录有驱动文件但安装流程未接好)
$bootstrapOk = ['MySQLi' => true, 'SQLite3' => true];
$dirs = @scandir($base);
if (!is_array($dirs) || $dirs === []) {
$extOk = function_exists('mysqli_init');
return [[
'name' => 'MySQLi',
'label' => 'MySQLi',
'ext_ok' => $extOk,
'installable' => true,
'enabled' => $extOk,
'form' => 'server',
'tip' => $extOk ? '' : dr_lang('PHP 未启用对应扩展'),
]];
}
foreach ($dirs as $name) {
if ($name === '.' || $name === '..' || !is_dir($base.$name)) {
continue;
}
$conn = $base.$name.'/Connection.php';
if (!is_file($conn)) {
continue;
}
// 迅睿安装要求驱动实现 formatCreateSql;未实现的不展示在安装界面
$code = @file_get_contents($conn);
$hasDdl = is_string($code) && strpos($code, 'function formatCreateSql') !== false;
if (!$hasDdl) {
continue;
}
$extOk = isset($extMap[$name]) ? (bool) $extMap[$name] : true;
$installable = !empty($bootstrapOk[$name]);
$enabled = $installable && $extOk;
if ($forceMysqli && $name !== 'MySQLi') {
$enabled = false;
}
$tip = '';
if (empty($bootstrapOk[$name])) {
$tip = dr_lang('安装引导暂未支持该驱动');
} elseif (!$extOk) {
$tip = dr_lang('PHP 未启用对应扩展');
} elseif ($forceMysqli && $name !== 'MySQLi') {
$tip = dr_lang('自定义 Install.sql 仅支持 MySQLi');
}
$list[] = [
'name' => $name,
'label' => $name,
'ext_ok' => $extOk,
'installable' => $installable,
'enabled' => $enabled,
'form' => isset($formMap[$name]) ? $formMap[$name] : 'server',
'tip' => $tip,
];
}
// 目录存在但未扫到任何驱动时,同样回退 MySQLi
if (!$list) {
$extOk = function_exists('mysqli_init');
return [[
'name' => 'MySQLi',
'label' => 'MySQLi',
'ext_ok' => $extOk,
'installable' => true,
'enabled' => $extOk,
'form' => 'server',
'tip' => $extOk ? '' : dr_lang('PHP 未启用对应扩展'),
]];
}
// MySQLi / SQLite3 排前面,其余按名称
usort($list, static function ($a, $b) {
$order = ['MySQLi' => 0, 'SQLite3' => 1];
$oa = isset($order[$a['name']]) ? $order[$a['name']] : 50;
$ob = isset($order[$b['name']]) ? $order[$b['name']] : 50;
if ($oa === $ob) {
return strcmp($a['name'], $b['name']);
}
return $oa - $ob;
});
return $list;
}
/**
* 是否存在自定义 My/Config/Install.sql 且含有效 SQL(此时禁止选 SQLite3
*/
private function _my_install_sql_requires_mysql()
{
$file = MYPATH.'Config/Install.sql';
if (!is_file($file)) {
return false;
}
$sql = @file_get_contents($file);
if ($sql === false || trim($sql) === '') {
return false;
}
// 去掉注释与空白后判断是否还有语句
$lines = preg_split("/\r\n|\n|\r/", $sql);
$buf = '';
if (is_array($lines)) {
foreach ($lines as $line) {
$trim = ltrim($line);
if ($trim === '' || strpos($trim, '--') === 0 || strpos($trim, '#') === 0) {
continue;
}
$buf .= $trim;
}
}
$buf = trim(preg_replace('/\/\*.*?\*\//s', '', $buf) ?? '');
if ($buf === '') {
return false;
}
// 至少像一条 SQL(含关键字或分号)
return (bool) preg_match('/\b(CREATE|INSERT|REPLACE|ALTER|DROP|UPDATE|DELETE|SET)\b/i', $buf);
}
/**
* 生成 SQLite3 库文件路径:cache/database/SQLite3/{随机}.db
*
* @return array{rel:string,abs:string,name:string}
*/
private function _sqlite3_make_db_file()
{
try {
$name = bin2hex(random_bytes(16)).'.db';
} catch (\Throwable $e) {
$name = md5(uniqid((string) mt_rand(), true).microtime(true)).'.db';
}
$rel = 'database'.DIRECTORY_SEPARATOR.'SQLite3'.DIRECTORY_SEPARATOR.$name;
// 配置与展示统一用正斜杠相对路径(WRITEPATH 拼接时再转系统分隔符)
$rel_slash = 'database/SQLite3/'.$name;
return [
'name' => $name,
'rel' => $rel_slash,
'abs' => WRITEPATH.str_replace('/', DIRECTORY_SEPARATOR, $rel_slash),
];
}
/**
* 安装阶段数据库引导连接。
* 支持 MySQLi / SQLite3;配置写出后再由 CI 驱动执行 Schema/Install.sql。
*
* @param array $data
* @return array
*/
private function _install_db_bootstrap(array $data)
{
$driver = isset($data['db_driver']) ? $data['db_driver'] : 'MySQLi';
if ($driver === 'SQLite3') {
if (!extension_loaded('sqlite3') || !class_exists('SQLite3', false)) {
return dr_return_data(0, dr_lang('PHP环境必须启用SQLite3扩展'));
}
// cache/database/SQLite3/{随机名}.db,避免固定路径被猜测
$info = $this->_sqlite3_make_db_file();
$data['db_name'] = $info['rel'];
$file = $info['abs'];
$dir = dirname($file);
if (!is_dir($dir) && !@mkdir($dir, 0755, true)) {
return dr_return_data(0, dr_lang('无法创建数据库目录:%s', $dir));
}
if (!is_writable($dir)) {
return dr_return_data(0, dr_lang('数据库目录不可写:%s', $dir));
}
// 禁止目录浏览
if (!is_file($dir.DIRECTORY_SEPARATOR.'index.html')) {
@file_put_contents($dir.DIRECTORY_SEPARATOR.'index.html', '');
}
try {
$flags = SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE;
$pass = isset($data['db_pass']) ? (string) $data['db_pass'] : '';
$db = ($pass !== '')
? new \SQLite3($file, $flags, $pass)
: new \SQLite3($file, $flags);
$db->close();
} catch (\Throwable $e) {
return dr_return_data(0, dr_lang('无法创建或打开SQLite数据库:%s', $e->getMessage()));
}
return dr_return_data(1, '', $data);
}
if ($driver !== 'MySQLi') {
return dr_return_data(0, dr_lang('暂不支持的数据库驱动:%s', $driver));
}
if (!function_exists('mysqli_init')) {
return dr_return_data(0, dr_lang('PHP环境必须启用Mysqli扩展'));
}
$mysqli = mysqli_init();
if (!$mysqli) {
return dr_return_data(0, dr_lang('PHP环境必须启用Mysqli扩展'));
}
if (!@mysqli_real_connect($mysqli, $data['db_host'], $data['db_user'], $data['db_pass'])) {
if (SITE_LANGUAGE == 'zh-cn') {
return dr_return_data(0, '['.mysqli_connect_errno().'] - 无法连接到数据库服务器('.$data['db_host'].'),请检查用户名('.$data['db_user'].')和密码('.$data['db_pass'].')是否正确');
}
return dr_return_data(0, mysqli_connect_errno().' '.mysqli_connect_error());
}
if (!mysqli_select_db($mysqli, $data['db_name'])) {
if (!mysqli_query($mysqli, 'CREATE DATABASE `'.$data['db_name'].'` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci')) {
return dr_return_data(0, dr_lang('指定的数据库(%s)不存在,系统尝试创建失败,请通过其他方式建立数据库', $data['db_name']));
}
if (!mysqli_select_db($mysqli, $data['db_name'])) {
return dr_return_data(0, dr_lang('指定的数据库(%s)不存在,系统尝试创建失败,请通过其他方式建立数据库', $data['db_name']));
}
}
if (!mysqli_set_charset($mysqli, 'utf8mb4')) {
return dr_return_data(0, dr_lang('当前MySQL不支持utf8mb4编码(%s)建议升级MySQL版本', mysqli_error($mysqli)));
}
return dr_return_data(1);
}
/**
* 写出 config/database.php(显式包含 DBDriver
*
* @param array $data
* @return array
*/
private function _write_database_config(array $data)
{
$driver = isset($data['db_driver']) && $data['db_driver'] ? $data['db_driver'] : 'MySQLi';
$prefix = dr_safe_filename($data['db_prefix']);
if ($driver === 'SQLite3') {
// 相对 WRITEPATHdatabase/SQLite3/{随机}.db
$rel = isset($data['db_name']) ? (string) $data['db_name'] : '';
if ($rel === '' || (strpos($rel, 'SQLite3/') === false && strpos($rel, 'SQLite3'.DIRECTORY_SEPARATOR) === false)) {
$info = $this->_sqlite3_make_db_file();
$rel = $info['rel'];
$data['db_name'] = $rel;
}
$rel_fs = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $rel);
$rel_php = str_replace('\\', '\\\\', $rel_fs);
$pass = str_replace("'", "\\'", (string) (isset($data['db_pass']) ? $data['db_pass'] : ''));
$database = '<?php
/**
* 数据库配置文件(SQLite3)
* 库文件目录:cache/database/SQLite3/(文件名安装时随机生成)
*/
$db[\'default\'] = [
\'hostname\' => \'\',
\'username\' => \'\',
\'password\' => \''.$pass.'\',
\'database\' => WRITEPATH.\''.$rel_php.'\',
\'DBPrefix\' => \''.$prefix.'\',
\'DBDriver\' => \'SQLite3\',
\'charset\' => \'utf8\',
\'DBCollat\' => \'\',
];';
} else {
$database = '<?php
/**
* 数据库配置文件
*/
$db[\'default\'] = [
\'hostname\' => \''.str_replace("'", "\\'", $data['db_host']).'\',
\'username\' => \''.str_replace("'", "\\'", $data['db_user']).'\',
\'password\' => \''.str_replace("'", "\\'", $data['db_pass']).'\',
\'database\' => \''.str_replace("'", "\\'", $data['db_name']).'\',
\'DBPrefix\' => \''.$prefix.'\',
\'DBDriver\' => \'MySQLi\',
\'charset\' => \'utf8mb4\',
\'DBCollat\' => \'utf8mb4_general_ci\',
];';
}
$size = file_put_contents(CONFIGPATH.'database.php', $database);
if (!$size || $size < 10) {
return dr_return_data(0, dr_lang('数据库配置文件创建失败,config目录无法写入'));
}
return dr_return_data(1);
}
/**
* 将安装 SQL 拆成单条语句。
* Install.sql 以 MySQL 方言为源,经 dr_format_create_sql → 驱动 formatCreateSql 转换。
* 先统一为 \n 再占位,避免 Windows 换行在 Linux 下经 PHP_EOL 替换后出现双占位符,导致无法按 ; 拆分、多条语句粘成一条执行失败。
* 拆分后还原真实换行交给数据库解析,避免逐行剔除 #/-- 时误伤多行字符串内的合法内容。
*/
private function split_install_sql_statements($sql)
{
if (!$sql) {
return [];
}
$sql = dr_format_create_sql($sql);
$sql = str_replace(["\r\n", "\r"], "\n", $sql);
$ph = 'SQL_FINECMS_EOL';
$sql = str_replace("\n", $ph, $sql);
$sql_data = explode(';'.$ph, trim($sql));
$rt = [];
foreach ($sql_data as $chunk) {
$chunk = trim($chunk);
if ($chunk === '') {
continue;
}
$rt[] = str_replace($ph, "\n", $chunk);
}
return $rt;
}
// 数据分组
private function query_rows($sql, $num = 0)
{
if (!$sql) {
return [];
}
$rt = $this->split_install_sql_statements($sql);
return $num ? array_chunk($rt, $num) : $rt;
}
// 数据执行
private function query($sql)
{
if (!$sql) {
return '';
}
foreach ($this->split_install_sql_statements($sql) as $ret) {
if (!$this->db->simpleQuery($ret)) {
$rt = $this->db->error();
$error = '**************************************************************************'
.PHP_EOL.$ret.PHP_EOL.$rt['message'].PHP_EOL;
$error.= '**************************************************************************'.PHP_EOL;
file_put_contents(WRITEPATH.'install.error', $error.PHP_EOL, FILE_APPEND);
}
}
}
}
+40
View File
@@ -0,0 +1,40 @@
<?php namespace Phpcmf\Control;
/**
* https://www.besyun.com
* BESCMS
* 本代码基于MIT开源协议,协议规定此处版权信息不可去除
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Show extends \Phpcmf\Home\Module
{
public function index() {
if (IS_POST) {
$this->_json(0, '禁止提交,请检查提交地址是否有误');
}
// 共享模块通过id查找内容
$id = (int)\Phpcmf\Service::L('input')->get('id');
$row = \Phpcmf\Service::M()->table(SITE_ID.'_share_index')->get($id);
// 挂钩点
$rt2 = \Phpcmf\Hooks::trigger_callback('module_show_share', $row);
if ($rt2 && isset($rt2['code']) && $rt2['code']) {
$row = $rt2['data'];
$id = $row['id'];
}
$mid = $row['mid'];
if (!$mid) {
$this->goto_404_page(dr_lang('无法通过id找到共享模块的模块目录'));
}
// 初始化模块
$this->_module_init($mid);
// 调用内容方法
$this->_Show($id, null, max(1, (int)\Phpcmf\Service::L('input')->get('page')));
}
}