Files

543 lines
17 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php namespace Phpcmf;
/**
* https://www.besyun.com
* BESCMS
* 本文件是框架系统文件,二次开发时不可以修改本文件
**/
class Service {
static private $instances = [];
static private $help = [];
static private $logs = [];
static private $view;
static private $model;
static private $require;
static private $apps = [
1 => [],
0 => [],
];
static private $mwhere_apps = [];
static private $filters = [
'home' => [
'install/index',
'api/ueditor',
],
'member' => [
'api/ueditor',
],
'admin' => [
'api/ueditor',
],
];
static private $license = [];
// 获取应用自动加载
public static function Auto($auto) {
$auto->psr4 = array_merge($auto->psr4, [
'Phpcmf\Controllers' => APPPATH.'Controllers',
'Phpcmf\Control' => CMSPATH.'Control',
'Phpcmf\Extend' => FRAMEPATH.'Extend',
'Phpcmf\Library' => CMSPATH.'Library',
'Phpcmf\Field' => CMSPATH.'Field',
'Phpcmf\ThirdParty' => FCPATH.'ThirdParty',
'My\Field' => MYPATH.'Field',
'My\Library' => MYPATH.'Library',
'My\Model' => MYPATH.'Model',
]);
$classmap = [
'Phpcmf\App' => CMSPATH.'Core/App.php',
'Phpcmf\Table' => CMSPATH.'Core/Table.php',
'Phpcmf\Model' => CMSPATH.'Core/Model.php',
'Phpcmf\View' => CMSPATH.'Core/View.php',
'Phpcmf\Common' => CMSPATH.'Core/Common.php',
];
if (IS_USE_MODULE) {
$classmap['Phpcmf\Home\Module'] = IS_USE_MODULE.'Extends/Home/Module.php';
$classmap['Phpcmf\Admin\Config'] = IS_USE_MODULE.'Extends/Admin/Config.php';
$classmap['Phpcmf\Admin\Module'] = IS_USE_MODULE.'Extends/Admin/Module.php';
$classmap['Phpcmf\Model\Content'] = IS_USE_MODULE.'Models/Content.php';
$classmap['Phpcmf\Model\Search'] = IS_USE_MODULE.'Models/Search.php';
$classmap['Phpcmf\Admin\Category'] = IS_USE_MODULE.'Extends/Admin/Category.php';
if (IS_USE_MEMBER) {
$classmap['Phpcmf\Member\Module'] = IS_USE_MODULE.'Extends/Member/Module.php';
}
}
$auto->classmap = array_merge($auto->classmap, $classmap);
$local = \Phpcmf\Service::Apps();
if ($local) {
foreach ($local as $dir => $path) {
if (!is_file($path.'install.lock')) {
continue;
}
if (is_file($path.'Config/Auto.php')) {
$app_auto = require $path.'Config/Auto.php';
isset($app_auto['psr4']) && $app_auto['psr4'] && $auto->psr4 = array_merge($auto->psr4, $app_auto['psr4']);
isset($app_auto['classmap']) && $app_auto['classmap'] && $auto->classmap = array_merge($auto->classmap, $app_auto['classmap']);
unset($app_auto);
}
// 加载钩子
if (is_file($path.'Config/Hooks.php')) {
require $path.'Config/Hooks.php';
}
// 判断是否存在自定义where
if (is_file($path.'Config/Mwhere.php')) {
\Phpcmf\Service::Set_Mwhere_App($dir);
}
// 判断是否存在CSRF白名单
if (is_file($path.'Config/Filters.php')) {
$Filters = require $path.'Config/Filters.php';
if ($Filters) {
$Filters['home'] && static::$filters['home'] = array_merge(static::$filters['home'], $Filters['home']);
$Filters['member'] && static::$filters['member'] = array_merge(static::$filters['member'], $Filters['member']);
$Filters['admin'] && static::$filters['admin'] = array_merge(static::$filters['admin'], $Filters['admin']);
}
}
}
}
return $auto;
}
// 获取应用目录
public static function Apps($is_install = 0) {
$is_install = $is_install ? 1 : 0;
if (isset(static::$apps[$is_install]) && static::$apps[$is_install]) {
return static::$apps[$is_install];
}
static::$apps[$is_install] = [];
$source_dir = dr_get_app_list();
if ($fp = opendir($source_dir)) {
while (FALSE !== ($file = readdir($fp))) {
$path = dr_get_app_dir($file);
if ($file === '.'
OR $file === '..'
OR $file === 'Module'
OR $file[0] === '.'
OR !is_dir($path)) {
continue;
}
if ($is_install && !is_file($path . 'install.lock')) {
continue;
}
static::$apps[$is_install][$file] = $path;
}
closedir($fp);
}
if (function_exists('dr_get_app_extend')) {
$extend = dr_get_app_extend($is_install);
if ($extend) {
foreach ($extend as $i => $t) {
static::$apps[$is_install][$i] = $t;
}
}
}
return static::$apps[$is_install];
}
// 设置mwhere的插件名称
public static function Set_Mwhere_App($dir) {
static::$mwhere_apps[] = $dir;
}
// 读取mwhere插件名称列表
public static function Mwhere_Apps() {
return static::$mwhere_apps;
}
// 读取Filters白名单
public static function Filters($type = 'auto') {
if ($type == 'auto') {
if (IS_ADMIN) {
$type = 'admin';
} elseif (IS_MEMBER) {
$type = 'member';
} else {
$type = 'home';
}
} elseif ($type == '') {
return static::$filters;
}
return isset(static::$filters[$type]) ? static::$filters[$type] : [];
}
// 是否是电脑端模板
public static function IS_PC_TPL() {
return static::V()->is_pc();
}
public static function IS_PC() {
return static::V()->is_pc();
}
// 是否是移动端模板
public static function IS_MOBILE_TPL() {
return static::V()->is_mobile();
}
public static function IS_MOBILE() {
return static::V()->is_mobile();
}
// 当前客户端是否是移动端访问
public static function IS_MOBILE_USER() {
return dr_is_mobile();
}
public static function _is_mobile() {
return dr_is_mobile();
}
// 当前客户端是否是PC端访问
public static function IS_PC_USER() {
return !dr_is_mobile();
}
// 错误日志记录
public static function Log($level, $message, array $context = []) {
if ($level == 'debug' && defined('IS_FB_DEBUG') && IS_FB_DEBUG) {
return;
}
if (is_object($message)) {
$msg = substr((string)$message->getMessage(), 0, 1048576);
$code = md5($msg);
if (is_array( static::$logs) && in_array($code, static::$logs)) {
return;
}
static::$logs[] = $code;
$context['trace'] = $message->getTraceAsString();
$context['sql'] = \Phpcmf\Service::M()->get_sql_query();
$context['url'] = FC_NOW_URL;
$context['user'] = dr_safe_replace($_SERVER['HTTP_USER_AGENT']);
$context['referer'] = dr_safe_url($_SERVER['HTTP_REFERER'], true);
return \Phpcmf\Service::L('input')->log($level, $msg."\n#SQL{sql}\n#URL{url}\n#AGENT{user}\n".($context['referer'] ? "#REFERER{referer}\n" : "")."{trace}\n", $context);
}
$message.= '---'.FC_NOW_URL.PHP_EOL;
return \Phpcmf\Service::L('input')->log($level, $message, $context);
}
/**
* 模型类对象实例
*
* @var object
*/
public static function model() {
if (!is_object(static::$model)) {
static::$model = new \Phpcmf\Model();
}
return static::$model;
}
/**
* 控制器对象实例
*
* @var object
*/
public static function C() {
return class_exists('\Phpcmf\Common') ? \Phpcmf\Common::get_instance() : null;
}
public static function LIC($type = '') {
if (defined('IS_XRDEV') && IS_XRDEV) {
return $type ? 'DR-DEV' : 'DR-DEV';
}
$version = static::R(MYPATH.'Config/Version.php');
if ($version && is_array($version)) {
if (isset($version['version']) && isset($version['id'])
&& is_string($version['version'])
&& intval(substr($version['version'], -1)) % 2 == 1
&& in_array($version['id'], [18, 16])
) {
$lic = static::R(MYPATH.'Config/License.php');
if ($lic && is_array($lic)) {
if (isset($lic['type']) && $lic['type']) {
return $type ? (stripos($lic['type'], $type) === false ? '' : $lic['type']) : $lic['type'];
}
}
}
}
return $type ? '' : 'MIT-LICENSE';
}
/**
* 获取文件内容
*
* @var object
*/
public static function R($file, $clear = false) {
$_cname = md5($file);
if (!$clear) {
if (isset(static::$require[$_cname])) {
return static::$require[$_cname];
} elseif (!is_file($file)) {
//CI_DEBUG && log_message('debug', '引用文件不存在:'.$file);
return false;
}
}
static::$require[$_cname] = require $file;
return static::$require[$_cname];
}
/**
* 模板视图对象实例
*
* @var object
*/
public static function V() {
if (!is_object(static::$view)) {
static::$view = new \Phpcmf\View();
}
return static::$view;
}
/**
* 类对象实例
*
* @var object
*/
public static function L($name, $namespace = '') {
if (IS_USE_CMS && $namespace == 'module') {
$namespace = 'cms';
}
list($classFile, $extendFile, $appFile) = self::_get_class_file($name, $namespace, 'Library');
$_cname = md5($classFile.$extendFile.$appFile);
$className = ucfirst($name);
if (!isset(static::$instances[$_cname]) or !is_object(static::$instances[$_cname])) {
require_once $classFile;
// 自定义继承类
if ($extendFile && is_file($extendFile)) {
if ($namespace && is_file($appFile)) {
require $appFile;
$newClassName = '\\Phpcmf\\Library\\'.ucfirst($namespace).'\\'.$className;
} else {
require $extendFile;
$newClassName = '\\My\\Library\\'.$className;
}
} else {
$newClassName = '\\Phpcmf\\Library\\'.$className;
// 多个应用引用同一个类名称时的区别
if ($namespace) {
$newClassName2 = '\\Phpcmf\\Library\\'.ucfirst($namespace).'\\'.$className;
if (class_exists($newClassName2)) {
static::$instances[$_cname] = new $newClassName2();
return static::$instances[$_cname];
}
}
}
static::$instances[$_cname] = new $newClassName();
}
return static::$instances[$_cname];
}
/**
* 模型对象实例
*
* @var object
*/
public static function M($name = '', $namespace = '') {
if (!$name) {
return static::model();
}
$className = ucfirst($name);
if (!$namespace) {
switch ($className) {
case 'Content':
if (!IS_USE_MODULE) {
\dr_exit_msg(0, '没有安装「建站系统」插件');
}
$namespace = 'cms';
break;
case 'Search':
if (!IS_USE_MODULE) {
\dr_exit_msg(0, '没有安装「建站系统」插件');
}
$namespace = 'cms';
break;
case 'Category':
if (!IS_USE_MODULE) {
\dr_exit_msg(0, '没有安装「建站系统」插件');
}
$namespace = 'cms';
break;
case 'Module':
if (!IS_USE_MODULE) {
\dr_exit_msg(0, '没有安装「建站系统」插件');
}
$namespace = 'cms';
break;
case 'Pay':
if (!dr_is_app('pay')) {
\dr_exit_msg(0, '没有安装「支付系统」插件');
}
$namespace = 'pay';
break;
}
} else {
if (IS_USE_MODULE && in_array($className, ['Content', 'Search'])
&& !is_file(dr_get_app_dir($namespace).'Models/'.$className.'.php')) {
$namespace = 'cms';
}
}
if (IS_USE_CMS && $namespace == 'module') {
$namespace = 'cms';
}
list($classFile, $extendFile, $appFile) = self::_get_class_file($name, $namespace, 'Model');
$_cname = md5($classFile.$extendFile.$appFile);
if (!isset(static::$instances[$_cname]) or !is_object(static::$instances[$_cname])) {
require_once $classFile;
// 自定义继承类
if ($extendFile && is_file($extendFile)) {
if ($namespace && is_file($appFile)) {
require_once $appFile;
$newClassName = '\\Phpcmf\\Model\\'.ucfirst($namespace).'\\'.$className;
} else {
require $extendFile;
$newClassName = '\\My\\Model\\'.$className;
}
} else {
$newClassName = '\\Phpcmf\\Model\\'.$className;
// 多个应用引用同一个类名称时的区别
if ($namespace) {
$newClassName2 = '\\Phpcmf\\Model\\'.ucfirst($namespace).'\\'.$className;
if (class_exists($newClassName2)) {
static::$instances[$_cname] = new $newClassName2();
return static::$instances[$_cname];
}
}
}
static::$instances[$_cname] = new $newClassName();
}
return static::$instances[$_cname];
}
/**
* 引用应用的helper
*/
public static function H($name, $namespace) {
if (IS_USE_CMS && $namespace == 'module') {
$namespace = 'cms';
}
$file = dr_get_app_dir($namespace).'Helpers/'.ucfirst($name).'.php';
$_cname = md5($file);
if (isset(static::$help[$_cname])) {
return;
}
if (!is_file($file)) {
self::_error('函数文件:'.str_replace(FCPATH, '', $file).'不存在');
}
static::$help[$_cname] = 1;
require $file;
}
// 获取类文件路径
private static function _get_class_file($name, $namespace, $class) {
$className = ucfirst($name);
$classFile = CMSPATH.$class.'/'.$className.'.php';
// 自定义继承类文件
$extendFile = MYPATH.$class.'/'.$className.'.php';
// 当前是app时优先考虑本级继承目录文件
if ($namespace) {
if (IS_USE_CMS && $namespace == 'module') {
$namespace = 'cms';
}
$appFile = dr_get_app_dir($namespace).($class == 'Library' ? 'Librarie' : $class ).'s/'.$className.'.php';
} else {
$appFile = '';
}
if (!is_file($extendFile) && $namespace) {
// 当前是app时优先考虑本级继承目录文件
$extendFile = $appFile;
}
if (!is_file($classFile)) {
// 相对于APP目录
if ($namespace) {
$classFile = $appFile;
$extendFile = '';
} else if (is_file($extendFile)) {
$classFile = $extendFile;
$extendFile = '';
}
// 都不存在就报错
if (!$classFile || !is_file($classFile)) {
self::_error('类文件:'.str_replace(FCPATH, '', $classFile).'不存在');
}
}
return [$classFile, $extendFile, $appFile];
}
// 错误输出
private static function _error($msg) {
if (defined('IS_API_HTTP') && IS_API_HTTP) {
log_message('error', $msg . ''.FC_NOW_URL.'');
\Phpcmf\Service::C()->_json(0, $msg); // api输出格式
} else {
// 报系统故障
dr_show_error($msg);
}
}
}